(本书是按OD分析的)
从第一个程序开始分析:
快速查找代码的四种方法:
1.代码执行法:
根据代码的特征:
假如有提示小窗口,可知道是MessageBox函数调用,通过一步步执行,就能找到显示窗口的位置
适合于代码量不大,程序功能明确的情况
2.字符串检索法:
点鼠标右键——>search for——>All referenced text strings
找到字符串,点击进入就行
3.API检索法:在调试代码中设置断点
鼠标右键——>Search for——>All intermodular calls
找到函数,点击进入
4.API检索法:在API代码中设置断点
鼠标右键——>Search for——>Name in all calls
当dll代码库加载进进程以后,可以向dll代码库添加断点
当位于system中的dll,如果我们写代码实现调用时,必须使用OS提供的API向OS发出请求,然后与被调用API对应的系统dll文件就会被加载到应用程序的进程内存中
使用“打补丁”方式修改字符串:
1.直接修改字符串缓冲区:(不建议)
找到字符串所在的缓冲区,进行修改
如果新字符串比原字符串长,就容易使数据遭到破环
2.在其他内存区新建字符串并传递给消息函数:
找一块新的区域,在此处写下字符串,然后通过调用这一区域,实现字符串打印
但是这种如果只是简单的保存,就无法正常运行,这里出现的问题留到PE文件学了就懂了
启动函数:
启动函数不是用户添加,而是编译器任意添加的
小端序标记法:
字节序是多字节数据在计算机存储或网络传输时各字节的顺序,分小端序和大端序
[][][][]
12 34 56 78这种称大端序,78 56 34 12称小端序
当字节为1时,两种没区别。而字符串保存在数组中,字符数组在内存中是连续的,向里存放数据,无论大小端序都一样
网络协议经常采用大端序,而进行算术运算和扩展/缩小数据。小端序效率高
IA-32寄存器基本讲解:
寄存器分通用寄存器、段寄存器、程序状态与控制寄存器、指令指针寄存器。
1.通用寄存器:
大小都是32位,即四个字节,主要保存地址和常量,特定汇编来操作特定寄存器
EAX:(针对操作数和结果数据)累加器
EBX:(DS段中的数据指针)基址寄存器
ECX:(字符串和循环操作)寄存器
EDX:(I/O指针)寄存器
Win32函数会将返回值保存在EAX再返回,在win32函数内部调用ECX和EDX,要先保存里面的值
EBP:(ss段中栈内数据指针)扩展基址指针寄存器
ESI:(字符串操作源指针)源变址寄存器
EDI:(字符串操作目标指针)目的变址寄存器
ESP:(ss段中栈指针)栈指针寄存器
这四个保存地址用的
2.段寄存器:
段是一种内存保护技术,每个段都都赋予起始地址、范围、访问权限,还同分页技术一起用于虚拟内存变更为实际物理内存,段内存记录在SDT(段描述符表),段寄存器持有这些SDT的索引
CS:代码段寄存器
SS:栈段寄存器
DS:数据段寄存器
ES:附加段寄存器
FS: 数据段寄存器
GS:数据段寄存器
FS这个寄存器会经常用到,用于计算SEH(结构化异常处理机构)、TEB(线程环境块)、PEB(进程环境块)。
3.程序状态与控制寄存器:
EFLAGS:标志寄存器
我们需要掌握的标志寄存器,ZF(零标志)、OF(溢出标志)、CF(进位标志)
4.指令指针寄存器:
EIP,CPU读取一条指令后,EIP寄存器会自动加1
JMP、jcc、CAll、、RET指令可间接修改EIP,还可以通过中断和异常来修改
栈:
栈是用来存储局部变量、传递函数参数、保存函数返回地址等
栈是一种数据结构,先进先出
栈顶指针(ESP)初始状态指向栈底端。栈是由高地址到低地址扩展的数据结构
栈帧:
栈帧就是利用EBP(栈帧指针),寄存器访问栈内局部变量、参数、函数返回地址等
基准点(函数起始地址)的ESP值保存在EBP,以EBP的值作为基址能够安全访问局部变量、参数和返回地址
最新编译器的“优化”功能,使该选项编译简单的函数不会生成栈帧
栈保存返回地址是系统安全隐患之一,攻击者使用缓冲区溢出技术能够把保存在栈内存的返回地址更改为其他地址
函数调用约定:
函数调用约定是对函数调用时如何传递参数的一种约定
主要的函数调用约定:
cdecl stdcall fsatcall
讲这之前,先知道调用者和被调用者
调用者,调用函数的一方;被调用者,被调用的函数
1.cdecl:
调用者处理栈
2.stdcall:
被调用者处理栈,RETN 8是RETN+POP8字节
3.fastcall:
该方式通常使用寄存器(非栈)去传递那些需要传递参数的部分参数(前两个),若参数为4个。前两个参数使用是ECX、EDX,因为寄存器调用很快,所以这种方式快,如果函数调用前ECX和EDX保存有重要数据,需要先保存。