最近一直在分析路由器和linux漏洞,所以linux下的工具用的比较多,特别是gdb调试器,一直都是用什么学什么,但是总感觉不是很系统,系统学习工具,框架,书籍一直是自己的一个学习习惯,因此总结了一下linux下的逆向分析工具和基础使用方法,在忘记的时候方便自己查看。
Linux 命令
1. 文件目录
1.1 特殊符号:
1.1.1 . 当前目录
1.1.2 .. 上级目录
1.1.3 ~ 用户的home目录
1.2 cd - 切换目录
1.3 ls - 查看目录/文件属性
1.4 mv/cp/rm 剪切/拷贝/删除文件
1.5 rmdir 删除空目录
1.6 touch 创建新文件
1.7 查看文件内容 more(按页查看)/less(部分查看)/cat(查看全部)/head(查看前x行)/tail(查看后x行)
1.8 hexdump 以十六进制查看文件
hexdump -C 文件名
hexdump -C 文件名 | less
1.9 ln 创建文件链接
1.10 file - 查看文件类型
1.11 grep - 查找文件内容
1.12 find/whereis/whois
2. 用户/权限
2.1 useradd(命令)/adduser(脚本) 添加目录
2.1 passwd 修改用户登陆密码
2.3 userdel 删除用户
2.4 usermod 修改用户信息(用户名/主目录/用户组/登陆密码)
2.4 chmod 修改文件权限
2.5 chown 修改文件拥有者
2.6 groupadd/groupdel 添加用户组/删除用户组
3. 进程/任务
3.1 ps/top 查看当前进程信息
3.2 kill 结束进程
4. 磁盘
4.1 df/du 查看磁盘使用信息
5. 其它
clear - 清屏
source - 强行让一个脚本去立即影响当前的环境(不重启而更新配置)
apt - 软件包管理
更新源 sudo apt update
更新软件 sudo apt upgrade
安装软件 : sudo apt install 软件名
卸载软件 : sudo apt remove / sudo apt autoremove
6. 常见配置文件
6.1 vimrc,bashrc . /etc目录下的配置文件
Linux 命令
1. 文件目录
1.1 特殊符号:
1.1.1 . 当前目录
1.1.2 .. 上级目录
1.1.3 ~ 用户的home目录
1.2 cd - 切换目录
1.3 ls - 查看目录/文件属性
1.4 mv/cp/rm 剪切/拷贝/删除文件
1.5 rmdir 删除空目录
1.6 touch 创建新文件
1.7 查看文件内容 more(按页查看)/less(部分查看)/cat(查看全部)/head(查看前x行)/tail(查看后x行)
1.8 hexdump 以十六进制查看文件
hexdump -C 文件名
hexdump -C 文件名 | less
1.9 ln 创建文件链接
1.10 file - 查看文件类型
1.11 grep - 查找文件内容
1.12 find/whereis/whois
2. 用户/权限
2.1 useradd(命令)/adduser(脚本) 添加目录
2.1 passwd 修改用户登陆密码
2.3 userdel 删除用户
2.4 usermod 修改用户信息(用户名/主目录/用户组/登陆密码)
2.4 chmod 修改文件权限
2.5 chown 修改文件拥有者
2.6 groupadd/groupdel 添加用户组/删除用户组
3. 进程/任务
3.1 ps/top 查看当前进程信息
3.2 kill 结束进程
4. 磁盘
4.1 df/du 查看磁盘使用信息
5. 其它
clear - 清屏
source - 强行让一个脚本去立即影响当前的环境(不重启而更新配置)
apt - 软件包管理
更新源 sudo apt update
更新软件 sudo apt upgrade
安装软件 : sudo apt install 软件名
卸载软件 : sudo apt remove / sudo apt autoremove
6. 常见配置文件
6.1 vimrc,bashrc . /etc目录下的配置文件
VIM常用命令
1.1 退出
1.2 移动光标 :
k
<-h l->
j
1.2.1 w 下一个单词
1.2.2 b 上一个单词
1.2.3 $ 直接定位到行末
1.2.4 ^ 直接定位到行首
1.3 开始编辑
1.3.1 i在当前光标下插入
1.3.2 A在行尾插入
1.3.3 I在行首插入
1.3.4 o在另起一行插入
1.3.5 O在上一行插入
1.4 保存: w
1.5 删除/撤销
1.5.1 x - 删除一个字符
1.5.2 dd - 删除一行字符
1.5.3 u - 撤销一次删除
1.6 复制/粘贴
1.6.1 y
1.6.2 p
1.7 命令执行次数 : 在任何命令之前输入一个数字,可以让命令重复执行多次. 例如要删除5行的内容可以输入: 5dd
1.8 ctrl + v 选中多行多列
1.1 退出
1.2 移动光标 :
k
<-h l->
j
1.2.1 w 下一个单词
1.2.2 b 上一个单词
1.2.3 $ 直接定位到行末
1.2.4 ^ 直接定位到行首
1.3 开始编辑
1.3.1 i在当前光标下插入
1.3.2 A在行尾插入
1.3.3 I在行首插入
1.3.4 o在另起一行插入
1.3.5 O在上一行插入
1.4 保存: w
1.5 删除/撤销
1.5.1 x - 删除一个字符
1.5.2 dd - 删除一行字符
1.5.3 u - 撤销一次删除
1.6 复制/粘贴
1.6.1 y
1.6.2 p
1.7 命令执行次数 : 在任何命令之前输入一个数字,可以让命令重复执行多次. 例如要删除5行的内容可以输入: 5dd
1.8 ctrl + v 选中多行多列
1. GCC 常用编译选项
编译器将源文件生成成obj中间文件.
然后再由链接器将多个obj文件打包成可执行文件格式.
2.1 -c : 只编译成中间文件,不链接
2.2 -S : 编译成汇编文件
2.3 -masm=intel : 生成intel masm格式的汇编
2.4 -m32 : 编译成32位的目标文件/可执行文件
2.5 -g : 支持调试
2.6 -o : 设置目标文件的文件名
2.7 -O0/-O1/-O2/-O3 : 优化级别,0最低,3最高
2.8 -static : 静态编译
2.9 -share : 动态编译
2.10 -shared : 编译成so文件(动态链接库文件)
1. GCC 常用编译选项
编译器将源文件生成成obj中间文件.
然后再由链接器将多个obj文件打包成可执行文件格式.
2.1 -c : 只编译成中间文件,不链接
2.2 -S : 编译成汇编文件
2.3 -masm=intel : 生成intel masm格式的汇编
2.4 -m32 : 编译成32位的目标文件/可执行文件
2.5 -g : 支持调试
2.6 -o : 设置目标文件的文件名
2.7 -O0/-O1/-O2/-O3 : 优化级别,0最低,3最高
2.8 -static : 静态编译
2.9 -share : 动态编译
2.10 -shared : 编译成so文件(动态链接库文件)
1. GDB 常用命令
4.1 命令行参数系列
4.1.1 set args
4.1.2 show args
4.2 运行系列:
4.2.1 r - 运行
4.2.2 n - 单步步过(源码)
4.2.3 s - 单步步入
4.2.4 u - 运行到循环退出
4.2.5 c - 继续运行
4.2.6 si/ni - 汇编级单步步入/步过
4.2.7 jump - 设置eip到指定位置
4.3 断点系列
4.3.1 b 行号/函数名 - 设置断点
4.3.2 info b - 查看断点
4.3.3 d 断点号 - 删除断点
4.3.4 dis 断点号 - 禁用断点
4.3.5 enable 断点号 - 启用断点
4.4 信息查看系列
4.4.1 print 变量名 - 查看变量的值
4.4.2 set 变量名=VAL - 修改变量的值
4.4.3 set disassembly-flavor intel 以intel方式查看反汇编
4.4.4 list [函数名] - 查看源码
1. GDB 常用命令
4.1 命令行参数系列
4.1.1 set args
4.1.2 show args
4.2 运行系列:
4.2.1 r - 运行
4.2.2 n - 单步步过(源码)
4.2.3 s - 单步步入
4.2.4 u - 运行到循环退出
4.2.5 c - 继续运行
4.2.6 si/ni - 汇编级单步步入/步过
4.2.7 jump - 设置eip到指定位置
4.3 断点系列
4.3.1 b 行号/函数名 - 设置断点
4.3.2 info b - 查看断点
4.3.3 d 断点号 - 删除断点
4.3.4 dis 断点号 - 禁用断点
4.3.5 enable 断点号 - 启用断点
4.4 信息查看系列
4.4.1 print 变量名 - 查看变量的值
4.4.2 set 变量名=VAL - 修改变量的值
4.4.3 set disassembly-flavor intel 以intel方式查看反汇编
4.4.4 list [函数名] - 查看源码
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 - 调试相关
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表示按照十六进制显示。
程序运行
然后 b main,再 r
程序会断在main函数入口处
下面是寄存器窗口
汇编代码窗口
堆栈窗口
当前执行信息
栈回溯
i r
i r a
i r esp
i r pc
(gdb) x /wx 0x80040000 # 以16进制显示指定地址处的数据
(gdb) x /8x $esp
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)