这是杭州电子科技大学信息安全竞赛(HDUSEC CTF)一个比较坑爹的题目,运行程序之后电脑就自动关了,如果直接在真机测试,那丢点数据也在所难免了,呵呵~ (注:本文是在比赛结束后发的)
这个时候,你很可能拿起你的OD准备动手了,可是当你刚载入OD的那一瞬间,屏幕又黑了,看了看主机箱,擦,灯灭了,电脑有关了,这尼玛不是坑爹么!
别哭,开机继续搞!把程序载入PEiD,看,有TLS呢!当然啦,大概就猜TLS里面有坑爹的代码。这个TLS可以看也可以不看的,但是出于好奇心,我还是忍不住看了下。那还是用IDA看一下这个样本吧。载入IDA分析,看一下导出表,有个TlsCallback_0,就是这货调用了sub_4013B0函数,对调试器进行了检测。
其实在检测进程之前就注定要关机了:通过调用RtlAdjustPrivilege和ZwShutdownSystem两个函数实现瞬间关机,可以自己去网上找一下相关介绍,ZwShutdownSystem这个字符串是解密出来的,和后面的一种解密方法一致(后文提到的内联汇编代码)。
还是先看下Main函数吧,在start函数中,如果你熟悉运行库的启动代码,你就可以快速确定sub_4010A0就是main函数,不知道也没关系,可以看一下《MSVC CRT运行库启动代码分析》。
分析一下main函数,发现这货会解密两个字符串,就是Kernel32.dll和IsDebuggerPresent了,动态获取函数地址然后调用一下看看是不是被爆菊ing:
我们去看sub_401240这个函数,进去看看发现又是在解密,还在打印key呢,好开森啊!
写个程序算一下,输出的结果是这样的:
18118806718727666771776122771028512219102806977728066103767266872929
怎么发现不太对呢?这不是key啊,你他妈在逗我!!!
擦擦擦!再用IDA看一下字符串,发现还有点问题:
I am the Key!! 好像有点意思!去看看在哪里被引用了。通过IDA的交叉引用功能找到sub_401390,然后继续往上找到sub_4012E0,而在sub_4012E0中又发现了sub_401320,尼玛这货又在解密。
解密方式还不是简单的异或运算,稍微变换了下。还是看汇编代码吧:
.text:00401333 loc_401333: ; .text:00401333 xor ecx, ecx .text:00401335 .text:00401335 loc_401335: ; .text:00401335 mov dl, byte_403078[ecx] .text:0040133B mov al, cl .text:0040133D mov bl, 2Bh .text:0040133F imul bl .text:00401341 add dl, 80h .text:00401344 add al, 4 .text:00401346 xor dl, al .text:00401348 mov byte_403988[ecx], dl .text:0040134E inc ecx .text:0040134F cmp ecx, 5A9h .text:00401355 jl short loc_401335 .text:00401357 movsx eax, byte_40303A .text:0040135E movsx edx, byte_40302C .text:00401365 push offset byte_403988 .text:0040136A mov byte_403988[ecx], 0 .text:00401371 movsx ecx, byte_403026 .text:00401378 push eax ; y .text:00401379 push ecx ; e .text:0040137A push edx ; k .text:0040137B push offset aCCCS ; "%c%c%c:%s" .text:00401380 call ds:printf |
可以看到前面是对数据块byte_403078的解密操作,大小为0x5A9,解密完之后输出key:解密后的内容。现在去byte_403078提取0x5A9大小的数据,然后内联汇编解密吧:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #include <iostream> using namespace std; int main(int argc, char **argv) { const int size = 0x5A9; unsigned char src[size] = { 0 }; unsigned char dst[size] = { 0 }; FILE *fp = fopen("data.bin", "rb"); fread(src, size, 1, fp); fclose(fp); __asm { xor ecx, ecx doDecrypt : mov dl, src[ecx] mov al, cl mov bl, 2Bh imul bl add dl, 80h add al, 4 xor dl, al mov dst[ecx], dl inc ecx cmp ecx, 5A9h jl short doDecrypt } printf("%s\n", dst); return 0; } |
打印出来是个啥?是KEY吗?显然不是,没图说个JB,看图:
又是一堆16进制数据,复制出来转成文件吧(就是让文件的16进制内容就是长这个样子),C32Asm有个特别粘贴功能(ASCII Hex),很好用!看一下文件内容,凭感觉判断吧:
看到Key.txt以及那个感叹号,你应该自信的想到这个是个RAR文件(你凭什么这么自信?不好意思我用了飘柔),那就加上Rar标志吧,然后保存为rar文件,尼玛又怒了,要密码啊,爆破都不行,你TM又在逗我!
等等,Key.txt很小的样子,RAR后还附加有数据,你还看到了IHDR和IEND以及那个‰符号,你又应该自信的想到这是一个PNG图片:
那就把第2、3、4字节改成PNG吧,把附加数据段单独提取出来保存。图片显示7.20,这货难道就是解压密码?真的是,这回没有逗我了,拿到KEY为cbklgcdm43ch96dsfCJ5dnGLQOnzfiS
至此,终于戳穿了对方的各种伎俩!纯静态分析实现本题Crack。收工?等等,做个广告《5月1日前注册的GitHub账号可领取20元》
本博客很少转载他人文章,如未特别标明,均为原创,转载请注明出处:
本文出自程序人生 >> [HDUSEC CTF]逆向分析Final
作者:代码疯子