目录
基础知识
代码分析
逆向分析法
修改应用程序文件或进程内存内容方法
入口点
修改地址方法
区分代码为部分的方法
快速查找制定代码
两个反调试方法
函数调用约定
字符串
字符串编码
修改字符串方法
内存
内存分区
字节序
PE文件
格式
地址映射
PE头
节区头
工具
8086汇编语言
汇编语言依赖于CPU,每个产品用的CPU种类不同,则汇编语言也有略微差异
汇编文件(主)
十六进制文件(辅)
静态分析——分析源码
动态分析——调试分析
推荐方法:先静态分析再动态分析
打补丁——Patch
破解——Crack
调试器停止的地方即为PE文件执行的起始地址
call [地址]
jmp [地址]
goto命令
设置断点
注释
标签
代码执行法
字符串检索法
API检索法
压缩器——修改文件结构、压缩后文件仍为可执行文件
保护器——压缩、反调试、反模拟、反转储
函数执行完毕,ESP需要回滚(用户执行)
字符的编码方式不同,占据位数不同,调试代码要注意
Unicode码中字符长度不够后需要填充NULL
直接修改字符串缓冲区(新字符串长度大于原有字符串,覆盖可能损坏字符串后面的数据)
在其他内存区域生成新字符串并传递给消息函数(注意地址,地址并不是按照规定载入内存,其按一定规律,即其要按一定文件偏移,否则程序出错)。
应用程序被加载到内存有最小内存分配大小,若不够则要填充NULL(一般为1000)
多字节数据在计算机内存中存放的字节顺序(小端序和大端序)
采用大端序存储数据时,内存地址低位存储数据的高位,内存地址的高位存储数据的低位。例如:Unix CPU/网络协议。
采用小端序存储数据时,内存地址低位存储数据的低位,内存地址的高位存储数据的高位。例如:Intel x86 CPU。
PE头:DOS头到节区头
PE体:PE头其下的节区
文件中使用偏移,内存中使用VA(虚拟地址)来表示位置。
文件分为.text(代码)、.data(数据)、.rsrc(资源)节,其分别保存
PE头与各节区的尾部存在一个区域,称为NULL填充(不够最小基本单位则填充NULL)
VA:虚拟内存的绝对地址,RVA:相对虚拟地址,ImageBase:基准地址
ImageBase+RVA=VA
32位Windows OS中,各进程分配有4GB的虚拟内存,VA范围为00000000~FFFFFFFF。
PE头由许多结构体组成(40字节),PE头的最前面添加了一个IMAGE_DOS_HEADER结构,用来扩展已有的DOS EXE头。
IMAGE_DOS_HEADER分为e_magic(DOS签名)、e_lfanew(指示NT头的偏移)。
所有PE文件在开始部分(e_magic)都有DOS签名(“MZ”)。
e_lfanew指向NT头所在位置(NT头:IMAGE_NT_HEADERS)。
DOS存根在DOS头下方,是个可选项,且大小不固定,其由代码和数据混合而成。
NT头结构分为签名、文件头、可选头三部分。
Hex Editor:二进制->十六进制
OllyDbg:汇编逆向工具
字:16bit 字节:8bit
通用寄存器:ax、bx、cx、dx(16位)
高位寄存器:ah、bh、ch、dh(高8位)
低位寄存器:al、bl、cl、dl(低8位)
从CS:IP的内存单元地址中读取指令,执行该指令,之后IP=IP+所读取指令的长度。(CS:IP永远指向当前指令的下一条指令)
CS:段地址寄存器
IP:偏移地址
物理地址=段地址×16+偏移地址
jmp 段地址:偏移地址 修改CS、IP寄存器
jmp 寄存器 仅修改IP寄存器
ds寄存器
ds 段地址
[…] 表示一个内存单元的偏移地址
DS:[…]表示的是内存(保存数据的位置)
数据保存方向:从低地址向高地址保存,数据的高位保存在高地址,数据的低位保存在低地址。
入栈操作:push
出栈操作:pop
SS:SP指向栈顶元素(操作者只能修改SP,一个段最大范围为0~FFFFH,最大容量为64KB)
入栈,栈顶从高地址向低地址移动 SP=SP-2
出栈,栈顶从低地址向高地址移动 SP=SP+2
栈空间由程序声明,CPU没有控制栈空间的概念,意味着栈溢出时可以覆盖其它内存单元数据。
内存信息:①内存单元地址②内存单元长度
[寄存器] 表示一个内存单元,其偏移地址位于寄存器中
loop使用方法:
s:
代码段
loop s
汇编源程序中,数据不能以字母开头(前面补0来解决这一问题)
debug和源程序区别:
debug: mov al,[0]
源程序: mov al,ds:[0]
循环方法:
mov cx,10 #cx为循环计数器
s:
代码段
inc bx
loop s
mov ax,ds:[bx] 相当于 mov ax,[bx]
mov ax,ss:[bx] 段地址寄存器为ss
若不体现:前面的寄存器,默认为ds
寻找到安全的内存空间(其中没有重要数据,不必担心覆盖导致数据丢失)
查看内存空间,找到全为0的连续空间,即为安全空间
DOS系统:0:200~0:2FF一般是安全空间
操作系统:合法通过操作系统取得的安全都为安全空间
源程序的伪指令需要经过编译器编译,由编译器执行
伪指令举例:
assume cs:code
code segment
start(程序入口)
代码段
code ends
end start(程序结束)
dw define word 定义字型数据
dw [数据] 从当前的CS:IP处开始存储数据
dw 0,…,0 声明内存空间,将其用作栈(清空一个数据空间)
编写代码时应注意用多个段存放数据、代码和栈。
si和di和bx功能相近,但不能分成两个8位寄存器使用。
多层循环时,需要通过对cx数据进行保存,恢复来进行。
需要暂存数据的时候,我们都应该使用栈。
没有寄存器名存在情况,用word ptr/byte ptr指明内存单元的大小。
call 实现CS、IP入栈,转移地址执行命令
内中断
外中断