Flare-on 8 WriteUp(二)
说来惭愧,来 52pojie 这么久了,看各路师傅剁 app 发技术文章、给大家分享破解好的工具、软件,我还是只能做一做题,一方面是目前重心放在 CTF 上,需要更多做题经验,另一方面也是水平不足,还难以分析巨量逻辑的汇编代码。
过年这段时间疏于练习,去上海苏州长沙武汉郑州遍览祖国风光,好不容易回来了苏州疫情把我的行程卡直接加上了一个小星星,正好趁这段健康观察的时间集训自己
之前逛论坛的时候没见大家发过 Flare-on 的 Writeup,可能 CTF 逆向圈子以外的人没有听过这一系列的比赛,FLARE 是 Fireeye 旗下的一个小组
每年会办一场高质量的逆向工程比赛,至 2021 年已经是第八届 Flare-on 比赛了。
Flare-on 每年约有 10 道题,一般来讲是以 Windows 为中心(事实上,现在 CTF 的竞赛环境中,还是 Windows 题目更多一些),考察的范围也比较广,除了一般的二进制分析,也会涉及到 PHP、Js、Docker 等知识点。每年通过整个挑战的逆向工程师会得到一个徽章或类似的奖励,并会进入 Flare-on 的名人堂,同时会按时间排名。
这一系列的 Writeup 并不能保证题目解题过程完全由我自己完成,我也暂时没有独立完成整个比赛的水平,比赛时是被奇安信的源哥拉着玩,但是当时比较忙,也没有好好看,趁这个时间会仔细研究一下,Flare-on 8 共有 341 位工程师完成了整个挑战,其中来自中国大陆的仅有13 位,排名第七,这低于以色列(18),新加坡(32),越南(33),也希望有更多的师傅能关注到这样比较优秀的比赛。
废话就到这儿,下面开始贴 Writeup,期望用四天完成所有的题目,每天的题目会单独发一个帖子
01 - CredChecker
打开HTML,一个页面登录器,是一个js逆向
function checkCreds() {
if (username.value == "Admin" && atob(password.value) == "goldenticket")
{
var key = atob(encoded_key);
var flag = "";
for (let i = 0; i < key.length; i++)
{
flag += String.fromCharCode(key.charCodeAt(i) ^ password.value.charCodeAt(i % password.value.length))
}
document.getElementById("banner").style.display = "none";
document.getElementById("formdiv").style.display = "none";
document.getElementById("message").style.display = "none";
document.getElementById("final_flag").innerText = flag;
document.getElementById("winner").style.display = "block";
}
else
{
document.getElementById("message").style.display = "block";
}
}
没有什么技术含量,btoa("goldenticket")
就是密码
Flag: enter_the_funhouse@flare-on.com
02 - known
32位PE,丢IDA里看一眼。
执行一下,发现File下的文件被解锁了,但是是乱码。猜测可能是根据固定的解锁方式爆破密码。
程序函数不多,从start跟一遍。401000是strlen,401030是strcpy,401070是数字分解,4010C0是错误输出,401370是读取解密,因为它循环调用了401220,猜到401220应该是解密函数。参数是文件名、文件名和输入。
创建了两个文件对象,猜一个读一个写,我们关心读,应该是把读入的放到4011F0,结合输入进行移位和异或,最后输出。
回头看一下读入,用的是ReadConsoleA, 读一个八字节秘钥。
flag不一定是在TXT还是什么里,思考了一下打算尝试爆破前两位,看看能不能识别到PNG头 0x89,0x50.
写完python脚本觉得太慢,换成了c脚本
写完C脚本发现我太蠢,都想到PNG头了为什么不干脆反算。。。
不过还是贴一下,毕竟是思路过程
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main() {
for(int i = 0; i < 0xFF; i ++ ) for(int j = 0; j < 0xFF; j ++ ) {
FILE* fp = fopen("tt.in", "wb");
fprintf(fp, "%c%c", i, j);
printf("%x%x\n", i, j);
system("tt.exe < tt.in > tt.out");
FILE* png = fopen("Files/capa.png", "rb");
char t1, t2;
fscanf(png, "%c%c", &t1, &t2);
if(t1 == 0x89 && t2 == 0x50) {
exit(0);
}
fclose(png);
fclose(fp);
}
}
加密过程是这样的
for ( i = 0; i < 8; i ++ ) {
a1[i] = __ROL1__(*(_BYTE *)(i + a2) ^ a1[i], i) - i;
}
每8个一组,将第i位和密码的第i位的内容异或之后,循环左移i位,再减i
所以逆向应当是+i之后循环右移i位,再与密码的第i位异或。
但是本题要求的不太一样,相当于已知明文和密文求解密码
那就应当是密文+i然后循环右移i位,再与明文的第i位异或。
编写exp...等等,又犯蠢了,这哪是加密过程,这是解密过程,不过不影响
最后脚本没写出来,感觉是循环位移没写对,但是八位可以手算,按上面的过程,一位位算的。(
秘钥是 No1Trust
Flag :You_Have_Awakened_Me_Too_Soon_EXE@flare-on.com