本文为看雪论坛精华文章
看雪论坛作者ID:flag0
程序流程
逆向分析
查看基础信息
反调试
APC注入可以让一个线程在它正常的执行路径运行之前执行一些其他的代码,每一个线程都有一个附加的APC队列,他们在线程处于可警告的时候才被处理(WaitForSingObjectEx,SleepEx)。 异步过程调用,apc可以看成就是内核里的定时器,为了给自己一个在本函数返回后还能执行的一次机会,有很多操作是需要在函数返回后才能执行。类似于析构函数但不完全是。
加密后的字符是32位。
在md5函数中有查表相关的操作。
解密函数分析
BEGIN = 0x140015ee0
len = 0x16
for i in range(len):
tmp = Byte(BEGIN + i)
tmp = tmp ^ 0x0c1
PatchByte(BEGIN+i, tmp)
sub_140007DD0(Buffer, v0, (__int64)v10);
v8[0] = 0xFC;
v8[1] = 0xAE;
v8[2] = 0xEB;
v8[3] = 0x6E;
v8[4] = 0x34;
v8[5] = 0xB4;
v8[6] = 0x30;
v8[7] = 0x3E;
v8[8] = 0x99;
v8[9] = 0xB9;
v8[10] = 0x12;
v8[11] = 6;
v8[12] = 0xBD;
qmemcpy(v9, "2_+", sizeof(v9));
type Test.txt >> WinRev.exe:signature
跟进sub_140009200函数内,发现其对输入进行了加密验证,还原正确的输入。
#include <iostream>
int main(int argc)
{
char v6[] = { 0x2F,0x1F,0x20,0x2E,0x34,0x4,0x37,0x2D,0x10,0x39,0x7C,0x22,0x7B,0x75,0x0A,0x38,0x39,0x21, 0};
char v7[0x13] = { 0 };
int v5[] = {1, 5, 4, 2, 3, 0};
char v8[0x12] = {};
for (size_t i = 0; i < 0x13; i++)
{
v6[i] ^= 0x45;
}
for (size_t k = 0; k < 0x12; k++)
{
v7[6 * (k / 6) + v5[k % 6]] = v6[k];
}
for (size_t i = 0; i < 0x12; i++)
{
v8[i] = v7[i] ^ i;
printf("%c", v8[i]);
}
return 0;
}
sub_1400089E0 => 0x100001 key:106
sub_140008A80=> 0x100002 key:0
sub_140008910 => 0x100003 key:Akira_aut0_ch3ss_!
跟进去其添加的函数地址sub_140009850。
查看导入表中的LoadLibrary,然后查看交叉引用,可以发现在sub_140007D80中却有引用。
由此基本可以判定sub_140007D80作为用调用DLL中的函数执行功能的操作,而被加密的数据正是DLL。
#include <iostream>
#include <Windows.h>
#include <io.h>
#define DLLSIZE 19456
int main()
{
FILE* pFile = fopen("WinRev.exe", "rb+");
if (pFile == NULL)
{
return -1;
}
//获取文件大小
DWORD dwFileLen = _filelength(_fileno(pFile));
if (dwFileLen <= 0)
{
return -1;
}
PBYTE pFileBuff = new BYTE[dwFileLen];
ZeroMemory(pFileBuff,dwFileLen);
if (pFileBuff == NULL)
{
return -1;
}
fread(pFileBuff, 1, dwFileLen, pFile);
fclose(pFile);
PBYTE pDllBuff = new BYTE[19456];
ZeroMemory(pDllBuff, 19456);
memcpy(pDllBuff, pFileBuff + 0xEFA0, DLLSIZE);
//解密1001
DWORD pdwKey1001 = 106 ^ 0x33;
for (size_t i = 0; i < DLLSIZE; i++)
{
if (i % 3 == 1)
pDllBuff[i] ^= pdwKey1001; //函数解密
}
//解密1002
for (size_t i = 0; i < DLLSIZE; i++)
{
if (i % 3 == 2)
{
pDllBuff[i] = ((int)(unsigned __int8)pDllBuff[i] >> 4) | (16 * pDllBuff[i]);//函数解密
}
}
//解密1003
PCHAR pKey1003 = (PCHAR)"Akira_aut0_ch3ss_!";
DWORD dwKey1Len = strlen(pKey1003);
for (size_t i = 0; i < DLLSIZE; i++)
{
if (!(i % 3))
{
pDllBuff[i] ^= pKey1003[i / 3 % dwKey1Len];//函数解密
}
}
FILE* pFileNew = fopen("Test.DLL", "wb+");
fwrite(pDllBuff, 1, DLLSIZE, pFileNew);
fclose(pFileNew);
delete pFileBuff;
delete pDllBuff;
return 0;
}
DLL分析
通过CFF来进行FOA=>VA的转换。
解密flag
Src[0] = 0x94;
Src[1] = 0xBF;
Src[2] = 0x7A;
Src[3] = 0xC;
Src[4] = 0xA4;
Src[5] = 0x35;
Src[6] = 0x50;
Src[7] = 0xD1;
Src[8] = 0xC2;
Src[9] = 0x15;
Src[10] = 0xEC;
Src[11] = 0xEF;
Src[12] = 0x9D;
Src[13] = 0x9A;
Src[14] = 0xAA;
Src[15] = 0x56;
memcpy(v7, Src, 0x10ui64);
>>> import base64
>>> strCryptoText = b"\x94\xBF\x7A\x0C\xA4\x35\x50\xD1\xC2\x15\xEC\xEF\x9D\x9A\xAA\x56"
>>> base64.b64encode(strCrypto).decode()
'lL96DKQ1UNHCFezvnZqqVg=='
总结
看雪ID:flag0
https://bbs.pediy.com/user-home-873556.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!