1、处理int3反调试,可以看到:
0040F2CA |> \68 E2DE4000 PUSH 7-不问少.0040DEE2 ; /pTopLevelFilter = 7-不问少.0040DEE2
0040F2CF |. FF15 F83C4500 CALL DWORD PTR DS:[<&KERNEL32.SetUnhandledExceptio>; \SetUnhandledExceptionFilter
0040DEE2 为程序处理异常的函数:
0040DEE2 /. 55 PUSH EBP
0040DEE3 |. 8BEC MOV EBP,ESP
0040DEE5 |. 56 PUSH ESI
0040DEE6 |. 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
0040DEE9 |. 8B06 MOV EAX,DWORD PTR DS:[ESI]
0040DEEB |. 8138 03000080 CMP DWORD PTR DS:[EAX],80000003 比较是不是int3
0040DEF1 |. 75 25 JNZ SHORT 7-不问少.0040DF18
0040DEF3 |. 6A 00 PUSH 0 ; /lParam = 0
0040DEF5 |. 6A 00 PUSH 0 ; |wParam = 0
0040DEF7 |. FF35 302C4000 PUSH DWORD PTR DS:[402C30] ; |Message = MSG(464)
0040DEFD |. FF35 00264500 PUSH DWORD PTR DS:[452600] ; |hWnd = 9303D4
0040DF03 |. FF15 E03D4500 CALL DWORD PTR DS:[<&USER32.PostMessageW>] ; \PostMessageW //发送窗口消息,执行正常的流程
0040DF09 |. 8B46 04 MOV EAX,DWORD PTR DS:[ESI+4]
0040DF0C |. 8380 B8000000>ADD DWORD PTR DS:[EAX+B8],9
0040DF13 |. 83C8 FF OR EAX,FFFFFFFF
0040DF16 |. EB 02 JMP SHORT 7-不问少.0040DF1A
0040DF18 |> 33C0 XOR EAX,EAX
0040DF1A |> 5E POP ESI
0040DF1B |. 5D POP EBP
0040DF1C \. C2 0400 RETN 4
通过PostMessageW发送消息,可以推断出,最终会执行到0040E3ED :
0040E3ED |. 8D45 1C LEA EAX,DWORD PTR SS:[EBP+1C]
0040E3F0 |. C745 1C 01000>MOV DWORD PTR SS:[EBP+1C],1
0040E3F7 |. 50 PUSH EAX
0040E3F8 |. FF75 14 PUSH DWORD PTR SS:[EBP+14]
0040E3FB |. 8BCB MOV ECX,EBX
0040E3FD |. 56 PUSH ESI
0040E3FE |. 57 PUSH EDI
0040E3FF |. E8 C9200000 CALL 7-不问少.004104CD 这里就是效验key的函数
然而每次按下按钮会执行到:
0040E478 |. 8D45 1C LEA EAX,DWORD PTR SS:[EBP+1C]
0040E47B |. 897D 1C MOV DWORD PTR SS:[EBP+1C],EDI
0040E47E |. 50 PUSH EAX
0040E47F |. FF75 14 PUSH DWORD PTR SS:[EBP+14]
0040E482 |. 51 PUSH ECX
0040E483 |. 6A 00 PUSH 0
0040E485 |. 8BCB MOV ECX,EBX
0040E487 |. E8 F91D0000 CALL 7-不问少.00410285 这个为执行int3反调试
00410285如下:
00410285 CC INT3 跳到0040DEE2
00410286 6A 01 PUSH 1 ; /ExitCode = 1
00410288 |. FF15 343E4500 CALL DWORD PTR DS:[<&USER32.PostQuitMessage>] ; \PostQuitMessage
0041028E |. 33C0 XOR EAX,EAX
00410290 \. C2 1000 RETN 10
正常来说,在调试的情况,int3会被调试器接管,不会执行到0040DEE2,然后执行PostQuitMessage退出,达到反调试的目的;
下面说下我咋处理这个int3,不难发现0040E478和0040E3ED 是处于同一个函数下,所以只要是 执行到0040E478,改变eip到0040E3ED就可以简单pass
2、具体key效验过程:
key经过一个算法得到一个buffer,然后在和 g_result比较,如果相等就用这个key和一个加密的call进行循环异或解密得到正常call,然后执行这个call
具体爆破key的算法如下:
#include "stdafx.h"
#include <vector>
#include <ctype.h>
#define _DWORD unsigned int
#define _BYTE unsigned char
#define CROL(value, bits) ((value << bits) | (value >> (8 - bits)))
#define CROR(value, bits) ((value >> bits) | (value << (8 - bits)))
unsigned char g_table[64] = {
0x89, 0xBC, 0x95, 0xFC, 0xFB, 0xBA, 0xED, 0x9A, 0xBB, 0xAE, 0xFE, 0x99, 0xA2, 0x98, 0xB9, 0xF9,
0x9F, 0x84, 0x9C, 0xFD, 0x83, 0xAD, 0xB6, 0xA9, 0xA5, 0xF5, 0x8C, 0xA7, 0x9E, 0x96, 0x8A, 0xF4,
0x85, 0xBE, 0xA8, 0x8F, 0x86, 0xAF, 0x88, 0x9D, 0x87, 0xBF, 0xFF, 0xA1, 0x8B, 0x81, 0xA0, 0xAB,
0x8E, 0xBD, 0xB5, 0xAA, 0x82, 0x94, 0xA4, 0x8D, 0xA3, 0xF8, 0xB4, 0xFA, 0x9B, 0xA6, 0xB8, 0x80
};
unsigned char g_result[80] = {
0x02, 0x02, 0x00, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x02, 0x00, 0x00, 0x02,
0x02, 0x00, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x01, 0x00, 0x02, 0x02, 0x02, 0x01, 0x02, 0x03,
0x02, 0x02, 0x02, 0x01, 0x02, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x00, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x02, 0x02, 0x02, 0x03, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03
};
void encode(unsigned char *lpKey,unsigned char *lpOut,unsigned int len)
{
unsigned int v8; // esi@1
unsigned int v16; // ecx@13
unsigned char *v17; // edi@14
unsigned int v18; // eax@15
unsigned int v19; // eax@17
unsigned int v20; // ecx@17
bool v21; // zf@18
unsigned char v22; // al@18
unsigned char v23; // bl@19
bool v24; // sf@21
unsigned int v25; // edi@23
char v26; // al@27
unsigned int v32; // [sp-Ch] [bp-Ch]@1
unsigned char *t;
unsigned int v34;
unsigned int v35;
v8 = (unsigned int)g_table;
v16 = 0;
v17 = lpOut;
t = v17;
v34 = 0;
v35 = 0;
while ( 1 )
{
v18 = (unsigned int)lpKey;
v32 = v16 + v18;
v19 = (unsigned int)memchr((void*)v8, *(unsigned char *)(v16 + v18),sizeof(g_table));
v20 = v19;
if ( v19 != 0 )
{
v22 = v19 - v8;
v21 = (v20 == v8);
*v17 = v22;
if ( v21 )
v23 = 1;
else
v23 = v22;
v24 = (v16 < 0);
*v17 = v23;
if ( !v24 )
{
v35 = v35 + 1;
v34 = v35;
do
{
v25 = 0;
do
{
if ( ++v20 == (v8 + sizeof(g_table)) )
v20 = v8;
++v25;
}
while ( v25 != (signed int)v23 / 5 + 5 );
v17 = t;
v26 = v20 - v8;
v21 = (v20 == v8);
*v17 = v26;
if ( v21 )
v23 = 1;
else
v23 = v26;
v34--;
v21 = (v34 == 0);
*v17 = v23;
}
while ( !v21 );
}
*v17 = *(_BYTE *)(*v17 + v8);
}
v16 = v16 + 1;
++v17;
t = v17;
if ( v16 >= len )
break;
}
}
void HexStrToByte(const char* source, unsigned char* dest, int sourceLen)
{
short i;
unsigned char highByte, lowByte;
for (i = 0; i < sourceLen; i += 2)
{
highByte = toupper(source[i]);
lowByte = toupper(source[i + 1]);
if (highByte > 0x39)
highByte -= 0x37;
else
highByte -= 0x30;
if (lowByte > 0x39)
lowByte -= 0x37;
else
lowByte -= 0x30;
dest[i / 2] = (highByte << 4) | lowByte;
}
return ;
}
void PrintKey(char keyTable[0x14][0x10],char *lpKey,unsigned int i,unsigned int j)
{
if (i==0x14)
{
if (strstr(lpKey,"Pediy2017")&&strstr(lpKey,"Bwns")) //加了这个限制,解缩减到200多个
{
printf("%s\n",lpKey);
}
//i=0;
}
else
{
for (int a=i;a<0x14;a++)
{
for (int b=0;b<0x10;b++ )
{
if (keyTable[a][b]!=0)
{
lpKey[a] = keyTable[a][b];
PrintKey(keyTable,lpKey,a+1,0);
}
else
{
//PrintKey(keyTable,lpKey,a+1,0);
return;
}
}
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
char szResult[260] = "";
char szTable[] = "0123456789ABCDEF";
int len = sizeof(g_result)/2;
int i = 0,j=0,k=0,a=0,b=0;
unsigned short index = 0;
unsigned char szTemp[260] = {NULL};
unsigned short t = 0;
unsigned char szKey[260] = {NULL};
unsigned char szOut[260] = {NULL};
memset(szResult,0,sizeof(szResult));
for (i=0;i<len;i++)
{
index = g_result[2*i]*4 + g_result[2*i+1];
szResult[i] = szTable[index];
}
HexStrToByte(szResult,szTemp,len);
for (i=0;i<len/2;i++)
{
szTemp[i] = CROR(szTemp[i],3);
szTemp[i] = szTemp[i] ^ 0xCC;
}
char keyTable[0x14][0x10] = {NULL};
memset(keyTable,0,sizeof(keyTable));
for (i=0;i<len/2;i++)
{
printf("\n%d:",i);
k=0;
for (j=0;j<0x100;j++)
{
szKey[i] = j;
encode(szKey,szOut,0x14);
if (szOut[i] == szTemp[i])
{
t = szKey[i]^0xCC;
if ((t >='0' && t <='9')||(t >='a' && t <='z')||(t >='A' && t <='Z'))
{
keyTable[i][k++]=t;
printf("%c",t);
}
//break;
}
}
}
printf("\n");
char kk[0x20] = {NULL};
PrintKey(keyTable,kk,0,0);
return 0;
}
一打印,我的妈,有好多的解,是作者变态还是我哪里分析得不够,在这多个解找一个key,和最终加密call进行解密,然后执行,很是蛋疼,这里纠结很久,还好作者在key上面给了些提示最终在key里肉眼发现了一组可疑的key:
BwnsAtPediy2017KXIOF
BwnsAtPediy2017KXIOk
BwnsAtPediy2017KXDOF
BwnsAtPediy2017KXDOk
BwnsAtPediy2017KX9OF
BwnsAtPediy2017KX9Ok //这个尝试了一下弹出 well done
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法