23-11-13
本周学习总结
总算看完了入门视频。
很好的堆题,使我的exp旋转。
全局常量声明:新手上路,文章内容仅是由教程观点和自己总结获得,仅供参考。
一、fmt字符串格式化漏洞–来自原始纯粹的力量–x32
你是否见过如下代码:
1 | |
某个粗心大意的程序员将程序写成了这样,虽然一般来说可以正常运行,但是其实这样会出现意想不到的漏洞。因为没有了“”,导致程序会将变量c中的字符串自动用“”括起来,然后输出。这个时候我们在C语言里面学的看似不怎么引人注意的到的格式化字符串(%c,%s,%p,%d 等)就起了作用。
如果你在以前使用过%p就知道,他会输出参数变量的地址。那么如果没有参数变量地址给他输出会怎么样?他就会被迫找栈上的地址输出,至于从哪里开始输出…
你在输入时使用了一定数量的%p,比如%p%p%p%p%p%p%p%p%p%p%p%p…我们就知道了整个栈上的内容,有人可能要问了,这有什么用呢?
但是这里不得不提printf函数的另外一个特性,如果printf函数没有参数可输出,他会将第一个被输入的字符串当成参数内容输出(什么抽象意思)。
比如你输入:AAAABBBB%p,%p,%p,%p,%p,%p,%p,%p,%p,%p…
程序将会输出比如:
AAAABBBB0xffbd9c48,0x50,0xf7c7cda2,0xf7e1eda0,nil,0x41414141,0x42424242,0x252c7025,0x70252c70,0x2c70252c…
我们可以看到在输出的时候AAAABBBB被输出后出现了一堆不可描述的16进制,但是我们可以看到0x41和0x42这两个连续的16进制,他们分别是A的16进制和B的16进制,现在我们可以知道printf的第一个参数的位置在栈中的相对位置,从第一个16进制开始数,最后得到的位置是6。
这个时候我们另外的船新格式化字符串就来了,他就是%$n。他可以将数值输入到参数中(关于输出函数还有输入这一功能的事)。%n原本的功能是将printf输出字符串的个数的数值输入到后面的参数中。而%$n的作用就是输入到指定位置的参数中。比如上面我们得到的相对位置是6,我们就需要写成%6$n,然后在将AAAA改为需要改变值的地址,就可以造成一种地址任意写的情况。
比如在编写exp时将payload写成:p32(0x114514)+b”%14c%6$n”,此时你就会神奇的发现,addr的值变成了18(格式化字符串不被输出不计数,32位中一个地址占4个字节,所有最终输入的值是14+4=18)。
如果addr需要1000,我们不可能输入1000个字符吧,这个时候我们就需要%c,%1000c相当于输出了1000个字符,还不占输入的位置。
除了%n还有%hn和%hnn,分别对应了以4字节,2字节,1字节写入,视情况更改。
如果已经理解了上面的原理,我们就可以使用%s和%p来实现更离谱的功能,比如你是否还在不知道函数的真实地址而烦恼,你是否在为了不知道canary的值而烦恼。fmt!–为你排忧解难。
二、easy–Format
下载得到程序Format,老样子上一套。



在函数Input发现主要逻辑,发现字符串格式化漏洞。

发现shell在shell函数中,现在我们只要将n的值修改为4就行。

观察到n在.data段,且值为3
测试printf第一个参数的位置

发现位置为6$
编写exp脚本:

因为32位的地址就占了4个字节,都不用填充字符了。

得到flag
三、baby–sandbox–学了pwn的孔乙己:你知道shell一共有几种写法吗?
下载得到程序sandbox,老样子来一套。



在box函数中发现主要逻辑,程序会调用系统执行你输入的指令,但是指令中不得包含”s”,”h”,”cat”,”flag,”-“。这样字符或字符串,不能说不合理吧,只能说屏蔽了我99%的办法。
后来经过资料查询,发现一个特殊的命令”$0”。他的作用是调用当前系统的第一个shell。这个字符串满足程序要求,直接手搓题目。

四、easy–ret2syscall
下载后得到程序ret2syscall,老样子来一套

裸奔是吧。


程序中没有system

但是发现了/bin/sh的存在。
我们可以使用execv的手段来执行shell
首先我们要找齐eax ebx ecx edx int 0x80
在程序输出我们可以知道系统调用号为0xb



我们需要保证eax中为系统调用号,ebx为bin的地址
编写脚本如下:

主要full_ret的顺序

获得flag
下周学习计划
应该要做的事情
开始准备上强度题
找新的进阶资料学习
学习感受
学堆前:不就是堆吗,能有多难?
学堆后:他……刚刚是不是用了一种很离谱的手法拿到了shell?