writeup-CGfsb-pwn

麻了,pwn好难哈哈哈哈哈哈

本题目是利用字符串格式化漏洞来更改pwnme变量的值。

image-20220226170521013

先看看pwnme变量存在哪了?

image-20220226170644707

image-20220226170741811

简单地说,就是一个会自动初始化为0的可读写区段。

那么,到底什么是字符串格式化漏洞?

printf函数含有的参数构造是由一个固定的format字符串和多个输出表列组成的,他们在函数调用时被一起推入内存,当我们在format字符串中形如填了%啥的东西后,他就会自动在内存中寻找参数(也就是我们推入的输出表项);

在printf函数中,有一个带有赋值功能的格式化字符串是%n,其功能就是记录在%n之前输出的字符数,然后将此值赋给一个变量。那赋值给哪一个变量呢?我们就需要传入这个变量的指针,也就是使用&变量名来接收参数,即类似于下图中的语法:

image-20220226173819436

这样一来,我们就可以利用printf进行赋值了。

那么,我们要赋值给pwnme这个变量,要怎么做呢。

我们只能传入一个参数,因此需要手动设定在format字符串中%n这个赋值操作的偏移量,他并不是直接指向下一个地址,而是指向了某一个存了目标(即pwnme)变量的指针的地址,那么这个指针肯定也是由我们通过前面的输入(就是format字符串中有一个地址,我们用控制%n的偏移,让他赋值的时候赋给format中含有的那个地址)传入的内容啦。

那么,控制偏移要怎么做?

%n:将%n 之前 printf 已经打印的字符个数赋值给偏移处指针所指向的地址 位置,如%100×10$n 表示将 0x64 写入偏移 10 处保存的指针所指向的地址(4 字节),而%$hn 表示写入的地址空间为 2 字节,%$hhn 表示写入的地址空间为 1 字节,%$lln 表示写入的地址空间为 8 字节,在 32bit 和 64bit 环境下一样。有时, 直接写 4 字节会导致程序崩溃或等候时间过长,可以通过%$hn 或%$hhn 来适时 调整。

就是这样,我们模仿这样的语法去调用就可以。。。

然后呢,我们现在需要知道的就是,我们通过scanf输入的那个地址存在哪里,我们用printf去往那个地址上赋值就可以了。

那么,我们需要知道printf函数的调用地址相较scanf输入的偏移量,可以有两种方法:

其一,用格式化字符串进行输出测试

image-20220226220040384

可以看到,在红圈处圈起来的就是aaaa的十六进制码,除了aaaa以外,在第十的位置。

其二,用gdb进行调试

真难用,换edb吧还是。。。

image-20220226222728483

差十个地址。

然后我们知道了偏移值后,就可以构造脚本了

image-20220226223030843

不能说不费劲,只能说是非常费劲。。。

cyberpeace{79366eb910334f932677401355a7f418}