最近一直在分析路由器和linux漏洞,所以linux下的工具用的比较多,特别是gdb调试器,一直都是用什么学什么,但是总感觉不是很系统,系统学习工具,框架,书籍一直是自己的一个学习习惯,因此总结了一下linux下的逆向分析工具和基础使用方法,在忘记的时候方便自己查看。
PE的组成
1. 头部
1.1 DOS头
1.2 NT头
1.2.1 文件头
1.2.2 扩展头
1.3 区段头
2. 区段数据
2.1 代码段: .text
2.2 数据段: .data
2.3 只读数据段: .rdata
2.3.1 导入表的数据
2.3.2 导出表的数据
2.4 重定位数据段: .reloc
ELF文件格式
ELF的组成部分
1. ELF头
1.1 id数组
1.1.1 前4位是魔数 0x74"elf"
1.1.2 ELF文件种类(32位/64位)
1.1.3 ELF文件数据的字节序(小端/大端)
1.1.4 版本 : 1. 文件版本,2. 系统ABI版本
1.2 文件类型 : 可重定位文件/可执行文件/动态库文件
2. 程序头
2.1 段类型 : 决定了段的作用,以及段是否被加载到内存中. 一个ELF文件中,至少存在一个LOAD类型的段. ELF一般都有解释器段,这个段用于保存解释器的文件路径. 有可能也会存在动态链接段(用于链接外部模块)
2.2 段数据的文件偏移/文件大小/内存地址/内存中的大小
2.3 加载到内存中后的分页属性
2.4 段的对齐粒度
3. 区段头
3.1 区段名
3.2 区段类型
3.3 Link和info
3.4 区段数据的文件偏移和大小,元素大小.
4. 区段数据
4.1 符号表
4.1.1 记录本模块的符号(导出)
记录在.symtab符号表中
记录一个符号的名字(例如函数名),记录了符号
的绑定类型(LOCAL,GLOBAL),还记录了符号的类型(函数,区段),记录符号的值(根据符号的不同,有不同的值,例如函数是符号类型,值就是函数的地址)
4.1.2 记录了导入的符号
记录在.dynsym符号表
4.2 重定位表
4.2.1 重定位类型, 决定了修复重定位的方法
可执行文件类型的ELF和共享库的ELF文件的重定位是不一样的.
4.2.2 重定位的偏移(根据重定位类型决定)
elf的加载
do_execve();
1. 其它
5.1 PLT和GOT表
call printf ==> jmp [GOT表项地址] =第二次以后=> printf真正的地址
push XX
jmp xxx ==> 加载printf所在的so文件,修复printf函数地址
5.2 构造函数数组,析构函数数组
5.2.1 全局对象的初始化和析构.
5.3 ptrace - 调试相关
程序运行
然后 b main,再 r
程序会断在main函数入口处
基本界面
下面是寄存器窗口
汇编代码窗口
堆栈窗口
当前执行信息
栈回溯
查看寄存器
i r
i r a
i r esp
i r pc
查看内存
(gdb) x /wx 0x80040000 # 以16进制显示指定地址处的数据
(gdb) x /8x $esp
(gdb) x /16x $esp+12
(gdb) x /16s 0x86468700 # 以字符串形式显示指定地址处的数据
(gdb) x /24i 0x8048a51 # 以指令形式显示指定地址处的数据(24条)
修改寄存器的值
(gdb) set $v0 = 0x004000000
(gdb) set $epc = 0xbfc00000
修改内存的值
(gdb) set {unsigned int}0x8048a51=0x0
(gdb) set *(unsigned int*)0x8048a54=0x55aa55aa
内存搜索
Usage: find <start> <end> <count> <value>
(gdb) define find
set $ptr = $arg0
set $cnt = 0
while ( ($ptr<=$arg1) && ($cnt<$arg2) )
if ( *(unsigned int *)$ptr == $arg3 )
x /wx $ptr
set $cnt = $cnt + 1
end
set $ptr = $ptr + 4
end
end
断点、监测点
(gdb) b *0x80400000
(gdb) watch *(unsigned int *)0xbffff400==0x90909090
其他重要命令
查看当前程序栈的内容: **$**x/10x $sp-->打印stack的前10个元素
查看当前程序栈的信息: **$**info frame----list general info about the frame
查看当前程序栈的参数: **$**info args---lists arguments to the function
查看当前程序栈的局部变量: **$**info locals---list variables stored in the frame
查看当前寄存器的值:**$**info registers(不包括浮点寄存器) info all-registers(包括浮点寄存器)
查看当前栈帧中的异常处理器:**$**info catch(exception handlers)
用于详细查看内存信息:
x/ (n,f,u为可选参数)
n: 需要显示的内存单元个数,也就是从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义,比如1,2,3,4,5,。。。
f:显示格式,比如:
x(hex) 按十六进制格式显示变量。
d(decimal) 按十进制格式显示变量。
u(unsigned decimal) 按十进制格式显示无符号整型。
o(octal) 按八进制格式显示变量。
t(binary) 按二进制格式显示变量。
a(address) 按十六进制格式显示变量。
c(char) 按字符格式显示变量。
f(float) 按浮点数格式显示变量
u:每个单元的大小,按字节数来计算。默认是4 bytes。GDB会从指定内存地址开始读取指定字节,并把其当作一个值取出来,并使用格式f来显示
b:1 byte h:2 bytes w:4 bytes g:8 bytes
比如x/3uh 0x54320表示从内存地址0x54320读取内容,h表示以双字节为单位,3表示输出3个单位,u表示按照十六进制显示。