DASCTF复盘 (一)、RE -> CrackMe

 
Crackme

一、查壳

0
32位的MFC无壳程序

二、IDA静态分析

搜索字符串定位到这里
0
代码流程不难,大体上程序就是从文本编辑框中获取flag与key,然后对key进行md5摘要并作为密钥对flag进行AES加密,最后的结果与this指针偏移0x2E4的结果进行对比...

三、解决反调试

当我动态调试的时候,程序会莫名崩掉如图:
0
猜测此处为反调试
IDA搜索导入函数:
0
并没有搜到有关反调试的函数,猜测可能是动态加载dll
搜索有关thread的字符串
0
注意到字符串 ZwSetInformationThread 函数,交叉引用
 
0
这里即为反调试的地方,把这个函数patch掉或修改其第二个参数(这里我已经修改过了)...
再次动态调试,程序不再奔溃,反调试解决
获取this指针指向的值:
this+ 0xdc: 9f77c2a4 ac5c0a67 1321bbe1 e9972af6
this + 0x1e0: D59F8E94 B0E1DE6E 329518A0 C444AA94 DE7C8D44
this + 0x2e4: 5B9CEEB2 3BB7D734 F31B7514 C6B21FE8 DE334474 751B476A D4375188 FC67E660 DA0D5807 814353EA 7B52856C 8665AFB4
 

四、获取key

通过this指向的值直接爆破得到key
代码如下:
import hashlib
gather = "123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"


def md5(i):
    m5 = hashlib.md5()
    m5.update(i.encode(encoding='utf-8'))
    return m5.hexdigest()

def sha1(i):
    sh1 = hashlib.sha1()
    sh1.update(i.encode(encoding='utf-8'))
    return sh1.hexdigest()

ans = 0
for a in gather:
    for b in gather:
        for c in gather:
            for d in gather:
                if ans == 2:
                    exit(0)
                f = ""
                f += a +b +c +d
                if md5(f) == "9f77c2a4ac5c0a671321bbe1e9972af6":
                    print(f)
                    ans += 1
                if(sha1(f) == "D59F8E94B0E1DE6E329518A0C444AA94DE7C8D44".lower()):
                    print(f)
                    ans += 1
#循环次数有点多,要跑上一会儿...
 
0
得到key: NocTuRne

五、获得flag

0
首先对Key进行md5加密
0
得到:5C53A4A41D52437A9FA1E9C26CA59090
然后,按理说应该以md5加密后的Key为密钥对this->0x2e4的值进行解密,但this->0x2e4对应的值是96位的,解不出明文。。。
 
这里,我们换一种思路
既然有 CryptEncrypt 函数,那一定也有 CryptDecrypt函数,我们直接对他进行解密!
代码如下:
#include<stdio.h>
#include <windows.h>
#include <windef.h>
#include <wincrypt.h>

int main()
{
    BYTE pbData[16] = { 0x5c, 0x53, 0xa4, 0xa4, 0x1d, 0x52, 0x43, 0x7a, 0x9f, 0xa1, 0xe9, 0xc2, 0x6c, 0xa5, 0x90, 0x90 };
    DWORD dwDataLen = 16;
    BYTE a3[0x104] ={ 0x5B, 0x9C, 0xEE, 0xB2, 0x3B, 0xB7, 0xD7, 0x34, 0xF3, 0x1B, 0x75, 0x14, 0xC6, 0xB2, 0x1F, 0xE8, 0xDE, 0x33, 0x44, 0x74, 0x75, 0x1B, 0x47, 0x6A, 0xD4, 0x37, 0x51, 0x88, 0xFC, 0x67, 0xE6, 0x60, 0xDA, 0x0D, 0x58, 0x07, 0x81, 0x43, 0x53, 0xEA, 0x7B, 0x52, 0x85, 0x6C, 0x86, 0x65, 0xAF, 0xB4};
    DWORD pdwDataLen = 32;
    DWORD dwBufLen = 0x104;
    BOOL v6; // [esp+4h] [ebp-18h]
    HCRYPTKEY phKey; // [esp+Ch] [ebp-10h] BYREF
    HCRYPTPROV phProv; // [esp+10h] [ebp-Ch] BYREF
    HCRYPTHASH phHash; // [esp+14h] [ebp-8h] BYREF

    phProv = 0;
    phHash = 0;
    phKey = 0;
    v6 = CryptAcquireContextA(&phProv, 0, 0, 0x18u, 0xF0000000);
    if (v6)
    {
        v6 = CryptCreateHash(phProv, 0x8003u, 0, 0, &phHash);
        if (v6)
        {
            v6 = CryptHashData(phHash, pbData, dwDataLen, 0);
            if (v6)
            {
                // 128位AES加密
                v6 = CryptDeriveKey(phProv, 0x660Eu, phHash, 1u, &phKey);
                if (v6)
                    v6 = CryptDecrypt(phKey, 0, 1, 0, a3, &pdwDataLen);
                printf("%s\n", a3);
            }
        }
    }
    if (phKey)
        CryptDestroyKey(phKey);
    if (phHash)
        CryptDestroyHash(phHash);
    if (phProv)
        CryptReleaseContext(phProv, 0);

    getchar();
    return v6;
}
结果如下
0

六、拿到flag

flag即为:
DASCTF{H@sh_a^d_Aes_6y_W1nCrypt}
 
0
 
 
 
 

反思

这场比赛暴露了很多问题,我还是太菜了,安卓逆向仍然不太会,pyc逆向不够熟悉,x64脱壳没有思路。以前刷的题还是太少,而且简单。
以后要多刷攻防世界高分题了,大二了,不能再刷简单题糊弄自己玩了。
太菜了...
明天再去做做"奇怪的交易" 
还要刷几道安卓逆向题
蓝桥杯国赛也必须提上日程了...
posted @ 2022-04-28 23:29  TLSN  阅读(170)  评论(0)    收藏  举报