本帖最后由 JoyChou 于 2014-4-10 16:46 编辑
第一题:餐前甜点
描述:nc 218.2.197.236 2009
溢出点 get,不判断输入字符的长度,导致覆盖v2,并执行v2
堆栈中是这样存放的(堆栈地址越大,就越往下)
result
v1 0x80个字节大小 0x9c-0x1c
v2 4个字节
ebp
ret
思路:输入长度为0x80后面加上bindshell的shellcode。
但是,shellcode总是执行不成功。
用checksec.sh脚本看下
原来有dep保护。
搜索字符串发现,程序本身是要读取flag的,所以后面的shellcode只需换成下面这个函数的地址即可
最后的poc
[Python] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 | import socket
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(( '218.2.197.236 ' , 2009 ))
print s.recv( 4096 )
str = struct.pack( "I" , 0x0804855C )
s.send( "1" * 128 + str + '\n' )
while ( 1 ):
print s.recv( 4096 )
s.close()
|

第二题:杀猪吃肉
描述:nc 218.2.197.236 2010
0x1. 基础储备 函数调用: 可以发现,参数调用顺序为rdi(edi) rsi(esi) edx ,即如果只有一个参数,那就用rdi传递参数。以此类推 具体是用rdi和edi就是看参数类型大小。
即rdi rsi edx分别为参数1,2,3,顺序为edx rsi rdi (相当于从右往左压栈)
比如下图,就可以这样理解,edx第三个参数,esi第二个参数,rdi第一个参数。
指针申请
在linux中(x64下)x86的没测试过。free掉重新申请,发现指针是一样的。
如果没有free重新申请,申请的指针相差0x20
当分配长度大于等于25的时候,就又相差0x20了。好神奇的linux~
最短24字节,相差0x20
字符输入长度
在linux上,
用fgets是要接收回车字符的。假如输入123,长度为4
gets是不会接收回车字符的。假如输入123,长度为3
0x2. IDA分析
killPig 中的操作:
比较输入的前8个字节是否为killPig (注意有个空格)。
如果是,就malloc分配8个字节大小的内存给cs:auth,并且初始化为0。
并且将第9位以后的内容拷贝到cs:auth里面。如果输入的字符串长度一共大于0x1E+8 = 0x26,就不执行拷贝操作。直接执行下面的reset操作
reset中的操作:
比较输入的前5个字节是否为reset。
如果是,就free掉cs:auth里面的内容。(相当于cs:auth没有内容)
不是,就跳到feedPig操作
feedPig中的操作:
比较输入的前7个字节是否为feedPig。
如果是,就用strdup从第输入的地址+8(即第9个字节),分配一个另外的指针给cs:service。但是没有free(不过没有影响)。
最后的正确判断:
判断cs:auth偏移0x20处的值是否为0,如果不为0即得到flag
0x3. 解题思路
所以就有两个思路:
1. 使用reset。由于使用reset,cs:auth会被free,所以下次再feedPig中申请的地址和cs:auth是一样的。
根据这个图就知道,feedPig只需要输入24个字节+1个回车即可。
构造出来为:feedPig0 + 01234567890123456789012+回车(25位一共,这是最短的)
此时的cs:auth+0x20指向的内容是01234567890123456789012
2. 不使用reset。由于不使用reset,cs:auth没有被free,所以下次feedPig用strdup申请的地址是cs:auth偏移0x20处。
这样,只需保证strdup能申请成功即可。最短长度为,feedPig+1个字符+1个回车。
附件:bin+checksec.sh+idb文件:
pwn.zip
(52.66 KB, 下载次数: 26)
|