AutoHotkey1
运行文件很常规的对话框,貌似用了某种脚本语言
文件加了upx壳,脱之。脱壳后运行失败
不太清除为啥,在IDA中找到"EXE corrupted"字符串,可以看到一个判断
当然上图是我已经标注后的,很明显,sub_4508c7函数里进行了某种检测,进入该函数,反编译结果如下
int __thiscall sub_4508C7(FILE **this, int a2, char *a3)
{
FILE **pfp; // esi
FILE *fp; // eax
signed int k; // eax
signed int v7; // eax
signed int i; // edx
int offset; // eax
FILE *fp_; // ST18_4
int v11; // eax
signed int v12; // eax
signed int v13; // edi
int v14; // edi
int v15; // ecx
signed int v16; // [esp-4h] [ebp-550h]
char v17; // [esp+Ch] [ebp-540h]
CHAR Filename; // [esp+410h] [ebp-13Ch]
char v19[16]; // [esp+518h] [ebp-34h]
char buf1[16]; // [esp+528h] [ebp-24h]
int v21; // [esp+538h] [ebp-14h]
int final4Bytes; // [esp+53Ch] [ebp-10h]
int v23; // [esp+540h] [ebp-Ch]
int offset_; // [esp+544h] [ebp-8h]
char v25; // [esp+54Bh] [ebp-1h]
char *m; // [esp+558h] [ebp+Ch]
pfp = this;
sub_450F56(&v17);
GetModuleFileNameA(0, &Filename, 0x104u);
fp = fopen(&Filename, unk_46651C);
*pfp = fp;
if ( !fp )
return 1;
k = 0;
do
{
buf1[k] = byte_466514[k];
buf1[k + 8] = byte_46650C[k];
++k;
}
while ( k < 8 );
v7 = strlen(a3);
pfp[68] = 0;
for ( i = 0; i < v7; ++i )
pfp[68] = (FILE *)((char *)pfp[68] + a3[i]);
fseek(*pfp, -8, 2);
fread(pfp + 1, 4u, 1u, *pfp);
offset = ftell(*pfp);
fp_ = *pfp;
offset_ = offset;
fread(&final4Bytes, 4u, 1u, fp_);
fseek(*pfp, 0, 0);
m = 0;
v11 = 0;
if ( offset_ > 0 )
{
do
{
if ( (*pfp)->_flag & 0x10 )
break;
fread(&v21, 1u, 1u, *pfp);
v11 = sub_450F95(&v17, v21);
++m;
}
while ( (signed int)m < offset_ );
}
if ( final4Bytes != (v11 ^ 0xAAAAAAAA) )
goto LABEL_25;
fseek(*pfp, (int)pfp[1], 0);
if ( !fread(v19, 0x10u, 1u, *pfp) )
goto LABEL_25;
v12 = 0;
do
{
if ( v19[v12] != buf1[v12] )
break;
++v12;
}
while ( v12 < 16 );
if ( v12 != 16 )
{
LABEL_25:
v16 = 3;
LABEL_19:
v13 = v16;
fclose(*pfp);
return v13;
}
fread(&v25, 1u, 1u, *pfp);
if ( v25 != 3 )
{
v16 = 4;
goto LABEL_19;
}
fread(&v23, 4u, 1u, *pfp);
v14 = v23 ^ 0xFAC1;
fread(pfp + 3, 1u, v23 ^ 0xFAC1, *pfp); // 取32字节
sub_450ABA((int)(pfp + 3), v14, v14 + 0xC3D2);
*((_BYTE *)pfp + v14 + 12) = 0;
v15 = 0;
for ( pfp[68] = 0; v15 < v14; ++v15 )
pfp[68] = (FILE *)((char *)pfp[68] + *((char *)pfp + v15 + 12));
pfp[2] = (FILE *)ftell(*pfp);
return 0;
}
具体细节得慢慢进行分析,要对C语言的文件操作函数比较了解,这里大概说下功能
1.取自身文件最后4字节为final4bytes
2.对文件的一块数据部分进行某种运算,获得一个值v11
3.检测final4bytes == v11 ^ 0xaaaaaaaa
4.再向上取文件4字节为offset
5.以offset作为文件偏移位置开始取值,与一些硬编码进行比较
分析花了一阵时间,还顺便了解了下FILE结构体,最后4字节可以先不管,可以先把其余地方安排好后动态得到v11并替换文件最后4字节。一开始我去将硬编码替换到了+offset的内存之中,结果后面嵌入的脚本又运行不了,我才发现硬编码本就存在文件之中,只是offset变了,因为upx作为一种压缩壳,很大程度上改变了文件的大小,于是搜索硬编码并将偏移位置替换到offset的位置就行了,由于这种自检测的机制,所以到此为止才算是真正脱了壳吧。
本题的提示如下
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
AuthKey = un_md5(DecryptKey) + " " + un_md5(EXE's Key)
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Ex:)
DecryptKey = 1dfb6b98aef3416e03d50fd2fb525600
EXE's Key = c944634550c698febdd9c868db908d9d
=> AuthKey = visual studio
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
By Pyutic
只要分析了程序就会知道,有个md5值会在上面那个函数结尾处全部得到,内存如下
交叉引用到DialogFunc的GetWindowTextA处,下断点开始调试,执行完GetWindowTextA后,对我们的输入下内存断点,运行后会在strcmp函数中断下,栈回溯可以找到两个参数的值,其中一个为
chamd5网站找到两个md5对应字符串,拼接即可
AutoHotkey2
脱壳和过自检测与AutoHotkey1相同,运行后
根据意思搜索Eddard Stark的私生子就是答案了。
PEPassword
给了两个文件,字面意思是原文件和加了某种保护,确实Packed.exe被查出有壳,但不知道是啥。依次运行,效果如下:
packed.exe
original.exe
这貌似完全不是一个东西。。,不管了,先用IDA打开Packed.exe,啥都看不出来,还是动态调试吧,随便跟一下就能看到一些关键的地方
这里就是消息循环了,直接让程序完全跑起来,当我们输入的时候就会触发键盘消息了。很容易找到消息处理函数,分析后代码如下
可以看到,当edit发生改变时,这里将GetText消息发送出去并将输入存入一个缓冲区中,然后调用一次sub_4091D8函数来进行验证,这个函数目测了一会儿是个复杂哈希函数,但该壳的解密还没看到,于是直接爆破继续往下跟踪,程序会在以下地方动态加载API,然后跳转到代码段执行
那想必在0x4090E0处调用的函数就是解密函数了,进入该函数中。
解密过程:
1.将input经过两次hash生成两个初始密钥eax,ebx
2.使用这两个密钥来对代码段解密
仅根据hash值想找到长度未知的input是很难的,但这里若并非想找input,而是仅仅为了解密成功,是可以找出两个密钥的。首先eax可以直接xor orignal_ep, packed_ep来找到,所以问题就是ebx密钥了。在解密过程中,由于下一轮解密的eax是通过这一轮的ebx得到的,而下一轮的eax我们也是已知的,所以从理论上是可以求出ebx的,但这里在过程上不可逆,所以可以考虑蛮力攻击。
枚举空间为2的32次方,貌似有点大,但这里只有几条汇编指令,要跑起来所需要的时间应该不会太久。结果1分钟都没要到就跑完了。。。暴破代码:
#include <cstdlib>
#include <cstdio>
unsigned GetNextEax(unsigned _eax, unsigned _ebx)
{
unsigned ret = 0;
_asm {
mov eax, _eax
mov ebx, _ebx
mov cl, al
rol ebx, cl
xor eax, ebx
mov cl, bh
ror eax, cl
mov ret, eax
}
return ret;
}
int main()
{
unsigned packed_ep = 0xb6e62e17;
unsigned orignal_ep = 0x014cec81;
unsigned packed_next = 0x0d0c7e05;
unsigned orignal_next = 0x57560000;
unsigned _eax = packed_ep ^ orignal_ep;
unsigned eax_next = packed_next ^ orignal_next;
for (unsigned _ebx = 0; _ebx < 0xfffffffff; _ebx++)
{
if (eax_next == GetNextEax(_eax, _ebx))
printf("ebx:0x%x\n", _ebx);
if (_ebx == 0xffffffff)
break;
}
system("pause");
}
待续未完。。。