DLL注入
消息钩子Windows操作系统GUI将键盘敲击,鼠标移动和点击,窗口大小和位置改变都看成事件(Event).消息传递过程大致为
事件发生时,首先将这个事件添加到系统的[OS message queue]中
OS判断这个事件是在哪个应用程序中产生的,然后将这个事件添加到应用程序的消息队列中
应用程序对这些消息进行处理
消息钩子就在这个传递链过程中添加一些函数,这些函数可以侦听事件甚至修改事件的参数。
SetWindowsHookEx这个API可以实现消息钩子,它的定义如下HHOOK SetWindowsHookEx{ int idHoook; HOOKPROC lpfn; HINSTANCE hMod;//这个程序所属DLL句柄 DOWRD dwThreadId;//想要挂钩的线程Id}
DLL注入DLL注入指的是想运行中的进程强制插入DLL文件。具体来讲就是让其他进程调用LoadLibrary().
具体方法
创建远程线程
使用注册表
消息勾取
创建远程线程bool inject_dll(DWORD dwPID, LPCTSTR sz ...
PE文件格式
PE文件时windows中的32位可执行文件。在linux中是elf。如exe,dll,scr等都是PE文件
基本结构
PE文件中的RVA(相对虚拟地址)一般不是直接转换到真实的虚拟地址的,还要加上一个基准地址(ImageBase).也就是说VA = RVA + ImageBase
这样做主要是因为DLL,DLL动态链接时如果发现这个虚拟地址已经有其他的dll了,那么就要进行重定位到其他位置,如果没有ImageBase那么重定位是很麻烦的。
PE头DOS头typedef struct _IMAGE_DOS_HEADER{ WORD e_magic; WORD e_cblp; WORD e_cp; WORD e_crlc; WORD e_cpaarhdr; WORD e_minalloc; WORD e_maxalloc; WORD e_ss; WORD e_sp; WORD e_csum; WORD e_ip WORD e_cs; WORD e_lfarlc; WORD e_ovno; ...
红黑树
性质红黑树是一颗二叉搜索树,并且在每个节点上增加一个变量来储存颜色,可以是红或者是黑。红黑树保证了没有一条路径会比其他路径长两倍。
每个节点有五个属性:color、key、left、right、p(parent)。
红黑树满足以下性质:
根节点是黑色
每个叶结点是黑色的。
如果一个节点是红色,则两个子节点是黑色
对于每个节点,从这个节点到所有后代节点的简单路径上,均包含相同数目的黑色节点。
在叶结点中不存在值,可以用一个哨兵节点来代指叶结点。哨兵节点颜色为黑,其他值任意,之后一旦到叶结点就连接到哨兵,这样可以减少空间占用。
从某一节点出发(不包含这个节点)的任意一条简单路径上黑色节点的个数叫这个点的黑高。定义红黑树的黑高是根节点的黑高。
可以证明,节点数为n的红黑树高度至多为2lg(n+1).
旋转插入和删除可能会改变红黑树的性质,这个时候就需要通过旋转来恢复红黑树的性质。
左旋的过程是把y的左边给x,然后x变为y的左儿子。右旋可以类比。
注意: 旋转之后性质不改变并且旋转的两个节点颜色可以互换。
左旋函数:
void left_rotate(node* t, node* x)& ...
内存管理
段式管理段指的是一些有相似功能的程序集合(不是准确描述),例如程序段,代码段,全局变量段等。
段的分配算法固定分区法事先把磁盘分为大小固定的分区,之后有进程来了就将它放入可以容纳的分区中。每个分区大小可以不一样,如4k,8k等。
这种方法最大的问题就是会产生很大的内碎片。例如没有空间使用了,然后来了一个大小为1k的进程,这时一块16k的分区释放了,这个进程只能进这个空间,于是浪费了15k的空间。
还可以对每个大小的分区使用一个列表。列表中存放的是可以被这个空间容纳的进程。进程先是按照大小分配到这些列表中,然后再进行运行。
这种方法可以减小每个分区的内碎片,但是不一定能提高系统总的空间利用率,因为可能进程集中于某一个大小的分区,这样其他的分区就没有得到充分利用。
可变分区法可变分区法就是开始不分区,等进程来了之后再分配它需要的大小给他。这种方法可以使用一个链表进行维护,每次来了一个进程就记录内存起始位置和终止位置。
最先适配:从一个方向进行扫描,找到第一个可以容纳的空间放入进程
下次适配:从上次分配的地方开始扫描,实际上差别并不大
此外还有两种有两种策略,最好匹配和最差匹配。最好匹配 ...
c++函数指针备忘
语法返回值 (*指针名) (参数列表)
例:int add(int x, int y){ return x + y;}int main(){ int (*func)(int a, int b); func = add; cout<< add(1, 2) << endl;}输出: 3这里将add的函数首地址传给了这个函数指针,现在这个指针就指代这个函数,传入参数就可以使这个函数执行。
注意:int(*)(int a, int b)是一个函数指针类型,和int,double类似。而func相当与int a的a。
根据上面这一条,我们可以用typedef测试一下typedef int(*Func)(int a, int b);int main(){ Func fn = add; add(1, 2); return 0;}可以运行
我们也可以直接赋值并运行:(void(*)(void))eip()。这条语句前面是一个void(*)(void)的函数指针,它的值是ei ...
linux指令学习
命令语法一次输入多条命令,可以在命令之间用 ;分割开来
语法: 命令名称 选项 参数
选项有时被称为开关(switches)或标志(flags),选项通常是由一个连字符后面接着一些字母,或者两个连字符后接着一个单词构成。例如 —help,—version(显示版本信息)
使用多个单字符选项时,可以把他们连接在一起,用一个连字符来表示。例如 ls -lF。注意,unix的选项区分大小写
实际上许多长参数有着对应的短参数,但是长参数是一个完整的单词,为了便于记忆,有时也是用长参数,这时就要用两个连字符
输入命令时,必须要把每个选项和参数用空格分隔开
有些命令有默认值,有些命令没有默认值,例如 ls 如果只输入ls的话他会返回当前工作目录下所有文件
手册中提示的语法
方括号中的项是可选的
不再方括号中的项是必选项
黑体字必须原样输入
斜体字可以用适当的值代替
有省略号代表可以重复多次
如果一个单独的选项和参数组合在一起,这二者必须同时出现
由竖线(|)字符分开的两个或者多个项,宝石可以从这个列表中选择任意一项
用户提醒命令
who 用来显示用这个计算机的用户
whoami 用来显示当前用 ...
内联汇编
简介内联汇编是在c语言代码中插入一段汇编语言,这在一些特殊的场合如操作系统中经常使用。有些时候我们想加快速度或者进行某些特殊的操作就可以使用内联汇编。
语法
关键字: asm
例asm volatile( "movl %eax, %ebx");其中,volatile的含义是告诉编译器这段代码不需要优化,原封不动的让他执行。
语法:asm( 汇编语言模板 : output operands /*可选*/ : input operands /*可选*/ : options /*可选*/);可以只有output operands或只有input operands。但是如果有options,那么前面两个冒号都要打.
options表示我们最多使用哪些寄存器。
汇编模板可以使用AT&T语法,也可以使用intel语法(没有测试过)。下面以AT&T模板作为例子。
它的语法和和汇编语言完全类似,同样是寄存器用%,立即数用$, 内存访问用()。
注意:
如果有多行汇编语句,那么语句与语句之间要用\n\t分隔开
如果使用了%0,%1等标 ...
标志寄存器
标志寄存器16位中只有9位有特殊作用
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CF
0
PF
0
AF
0
ZF
SF
TF
IF
DF
OF
0
0
0
0
ZFZF含义是执行完指令后结果是否为0,为0,ZF=1,不为0,ZF=0
例如mov ax,1 ;ZF=0sub ax,1 ;ZF=1
PF奇偶标志位,它记录相关指令执行后,其结果的所有bit为中1的个数是否为偶数,如果1的个数为偶数,pf=1,反之则为0
SF符号标志位,看结果是否为负,如果为负,则SF=1
CF进位标志位,一般情况下,对无符号数运算时,它记录了超过最高位的值
例如 ,add 255,255 这时已经超过最高位了,我们已经知道,超过最高位的数据都会被丢失,实际上它被保存在CF中,但只会保存一位
做减法时,还有可能发生错位,例如,两个8位数据,-4+5,将产生错位。错位后,相当于计算 252+5,超过255,因此会记录,因为无符号数中负数就是255-该值。小的减大的时会产生借位
OF溢出标志位,在有符号数运算时,可能会产生溢出,即小于最小值或大于最大值, ...
Linux重定向与管道
标准输入 标准输出和标准错误基本思想:每个基于文本的程序都可以从任何源接受输入,并向任何目标输出
标准输入指的是一种读取数据的通用办法,标准输出有两种,一种是标准输出,另一种是标准错误
而输入输出其实正常情况下有shell决定。为了保证程序的输出,需要告诉shell将输出目标设置成文件。
重定向标准输出在登陆时,shell会自动将标准输入设置成键盘,将标准输出和标准错误设置成屏幕。
但是每次输入命令时,可以告诉shell在此命令执行期间更换输入输出对象。
如果想把一个命令输出送到一个文件中,例如sort命令 可以写成 sort > names
以这种命令输出时,如果文件不存在,shell会自动创建这个文件。如果文件存在,那他将会把文件内容全部清空然后再把内容输入到里面去
如果我们只想追加内容到这个文件中,可以用 >> 。如果文件不存在,这个命令也会创建新文件,如果存在,那么会追加内容到后面。
如果取消清空文件重新输入的选项,可以设置nonclobber选项。但是设置完之后,如果确实想替换掉这个文件,可以临时忽略掉noclobber,这时需要用>|替换 >
...
Linux文件操作
touch 创建文件创建文件有许多种方式,例如用vi创建文件,利用重定向创建文件。
语法: touch [-acm] [-t time] file…
作用: 创建文件,改变文件的修改时间和访问时间。
-m 改变修改时间
-a 改变访问时间
-t 用一个具体的时间去替换
如果不加参数会将修改时间和访问时间全部修改。
例如: touch * ,这个命令会修改目录下的所有文件的访问时间和修改时间。
如果后面接的文件名不存在,touch将会创建一个文件。
-c 不创建文件。如果文件存在,会修改时间,如果文件不存在,不进行操作。
文件命名要求:
文件名最长是255个字符
文件名可以包含除了/外的任何字符
虽然说创建文件名的时候没有太多的要求,但是最好创建有意义的名字并且不要实用一些特殊字符。例如-,虽然创建的时候不会出现问题,但是使用命令进行操作的时候却会带来麻烦。
cp 复制文件语法: cp [-ip] file1 file2
file1是已有文件 file2是目标文件
例如: cp /etc/passwd ~/pword
这个命令会复制passwd文件到pword中,如果pword不存在 ...