findKey

知识点

  • WIndows逆向

解题

查壳,32位无壳。

打开程序,没发现什么

IDA打开,看可疑字符串发现flag{}

跳到该位置,发现爆红,两行一样的代码,nop掉第二行,按P生成函数,再F5反汇编。看到如下代码,已去除无关代码

LRESULT __stdcall sub_401640(HWND hWndParent, UINT Msg, WPARAM wParam, LPARAM lParam)
{
LoadStringA(hInstance, 0x6Au, Buffer, 100);
v11 = Msg;
if ( Msg > 0x111 )
{
if ( v11 == 517 )
{
if ( strlen((const char *)String1) > 6 )
ExitProcess(0);
if ( strlen((const char *)String1) )
{
memset(v20, 0, sizeof(v20));
v6 = strlen((const char *)String1);
memcpy(v20, String1, v6);
v7 = strlen((const char *)String1);
jiami(String1, v7, (LPSTR)String1); // string加密
strcpy(Str, "0kk`d1a`55k222k2a776jbfgd`06cjjb");
memset(v17, 0, sizeof(v17));
v18 = 0;
v19 = 0;
strcpy(char_S, "SS");
*(_DWORD *)&char_S[3] = 0;
v14 = 0;
v15 = 0;
v8 = strlen(Str);
yihuo(char_S, (int)Str, v8); // Str和s异或
if ( _strcmpi((const char *)String1, Str) )// string和str比较
{
SetWindowTextA(hWndParent, "flag{}"); // 标题
MessageBoxA(hWndParent, "Are you kidding me?", "^_^", 0);// 弹窗
ExitProcess(0);
}
memcpy(v12, byte_423030, 0x32u);
v9 = strlen(v12);
yihuo(v20, (int)v12, v9);
MessageBoxA(hWndParent, v12, 0, 0x32u);
}
++dword_428D54;
}

通过分析可知v12异或后即可出现flag,为得到v12的异或需要得到string1,而string1和Str加密后比较相同

从Str入手

strcpy(Str, "0kk`d1a`55k222k2a776jbfgd`06cjjb");
memset(v17, 0, sizeof(v17));
v18 = 0;
v19 = 0;
strcpy(char_S, "SS");
*(_DWORD *)&char_S[3] = 0;
v14 = 0;
v15 = 0;
v8 = strlen(Str);
yihuo(char_S, (int)Str, v8);

在如下函数中,可看到Str和S异或

得到加密后的string1=c8837b23ff8aaa8a2dde915473ce

看jiami函数(这是已经改了名的函数)

int __cdecl sub_4013A0(BYTE *pbData, DWORD dwDataLen, LPSTR lpString1)
{
int result; // eax
DWORD i; // [esp+4Ch] [ebp-24h]
CHAR String2[4]; // [esp+50h] [ebp-20h] BYREF
BYTE v6[16]; // [esp+54h] [ebp-1Ch] BYREF
DWORD pdwDataLen; // [esp+64h] [ebp-Ch] BYREF
HCRYPTHASH phHash; // [esp+68h] [ebp-8h] BYREF
HCRYPTPROV phProv; // [esp+6Ch] [ebp-4h] BYREF

if ( !CryptAcquireContextA(&phProv, 0, 0, 1u, 0xF0000000) )// 用于获取句柄到一个特定的密钥容器
return 0;
if ( CryptCreateHash(phProv, 0x8003u, 0, 0, &phHash) )// 启动哈希数据流的,0x8003为MD5
{
if ( CryptHashData(phHash, pbData, dwDataLen, 0) )// 将数据添加到指定的哈希对象
{
CryptGetHashParam(phHash, 2u, v6, &pdwDataLen, 0);// 检索实际哈希值
*lpString1 = 0;
for ( i = 0; i < pdwDataLen; ++i )
{
wsprintfA(String2, "%02X", v6[i]); // 打印
lstrcatA(lpString1, String2); // 连接字符串
}
CryptDestroyHash(phHash); // 销毁哈希对象
CryptReleaseContext(phProv, 0); // 释放CSP
result = 1;
}
BOOL CryptCreateHash(
HCRYPTPROV hProv,
ALG_ID Algid, //第二个参数决定了采用什么哈希表(即什么加密)
HCRYPTKEY hKey,
DWORD dwFlags,
HCRYPTHASH *phHash
);

查询API即可知道是MD5加密

将string1字符串MD5解密

然后与v12异或即可

脚本

脚本如下

str = "0kk`d1a`55k222k2a776jbfgd`06cjjb"
# s = [0x00]*32
# for i in range(len(v)):
# s[i] = ord(str[i]) ^ ord('S')
# for i in range(len(v)):
# print(chr(s[i]), end="")
s = "c8837b23ff8aaa8a2dde915473ce" # MD5解密为123321
k = "123321"

v = [0x57, 0x5E, 0x52, 0x54, 0x49, 0x5F, 0x01, 0x6D, 0x69, 0x46,
0x02, 0x6E, 0x5F, 0x02, 0x6C, 0x57, 0x5B, 0x54, 0x4C, 0x00,
0x00, 0x00, 0x00, 0x00, 0x53, 0x53, 0x00, 0x00]

for i in range(len(v)):
v[i] ^= ord(k[i % len(k)])
for i in range(len(v)):
print(chr(v[i]), end="")
# flag{n0_Zu0_n0_die}