一、不同架构下寄存器传参的方式
64位x86架构
- RDI (Destination Index): 用于传递第一个整数参数。
- RSI (Source Index): 用于传递第二个整数参数。
- RDX (Data Register): 用于传递第三个整数参数。
- RCX (Counter Register): 用于传递第四个整数参数。
- R8: 用于传递第五个整数参数。
- R9: 用于传递第六个整数参数。
如果函数的参数个数超过6个,则超过的参数直接使用栈来传递
32位架构
所有参数直接使用栈来传递
return address
在执行call sum
的时候,会将sum
的下一条命令的执行地址0x8048438
压入栈中,然后程序进入 sum片段进行执行,此时,0x8048438
地址就是sum
函数的返回地址,即 return address。
二、IDA
常用快捷键
IDA中的快捷键都是和菜单栏的各个功能选项一一对应的,基本上你只要能在菜单栏上找到某个功能,也就能看到相应的快捷键,这里记录几个常用的:
a:将数据转换为字符串
f5:一键反汇编
esc:回退键,能够倒回上一部操作的视图(只有在反汇编窗口才是这个作用,如果是在其他窗口按下esc,会关闭该窗口)
shift+f12:可以打开string窗口,一键找出所有的字符串,右击setup,还能对窗口的属性进行设置
ctrl+w:保存ida数据库
ctrl+s:选择某个数据段,直接进行跳转
ctrl+鼠标滚轮:能够调节流程视图的大小
x:对着某个函数、变量按该快捷键,可以查看它的交叉引用
g:直接跳转到某个地址
n:更改变量的名称
y:更改变量的类型
/ :在反编译后伪代码的界面中写下注释
\ :在反编译后伪代码的界面中隐藏/显示变量和函数的类型描述,有时候变量特别多的时候隐藏掉类型描述看起来会轻松很多
;:在反汇编后的界面中写下注释
ctrl+shift+w:拍摄IDA快照
u:undefine,取消定义函数、代码、数据的定义
特殊情况
postive sp value has been found
栈内出现负指针,打开工具栏的options->general,勾上stack pointer,选中负数=指针ATL+K修改value
三、构造ROP传参
多数函数并不会直接将“shell = '/bin/sh'”这种危险字符串和system函数放在一起,此时就需要传参
32位中构造ROP传参
利用溢出覆盖返回地址进入func函数内部,再将参数一指向“/bin/sh”的储存地址即可。其中要注意的是r处需要我们进行垃圾数据的填充。
64构造ROP传参
对x64的参数,大部分情况下,前六个参数储存在寄存器内,无法直接使用简单的栈溢出修改寄存器内容,这时候我们需要解除ROPgadget工具进行辅助。
ROP(Return Oriented Programming),即返回导向编程,通过栈溢出内容覆盖返回地址,使其跳转到可执行文件中已有的片段代码中执行我们选择的代码段。
知道了ROP工具的功能,我们需要做的是
- 修改rdi的值(可使用代码pop rdi ; ret)
- 在栈中放入‘bin/sh’经由pop提交给rdi
- 进入func函数内调用system函数
利用ROPgadget查找需要的代码行--pop rdi ; ret
ROPgadget --binary ret2text_func2_x64 --only 'pop|ret'
也可用ropper查询。
ropper --file 文件名 --search "pop|ret"