首页
社区
课程
招聘
[原创]第七题
2017-6-15 10:47 4123

[原创]第七题

2017-6-15 10:47
4123

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虚拟机自动化脱壳的方法

收藏
点赞1
打赏
分享
最新回复 (2)
雪    币: 112
活跃值: (27)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
伊邪那美 2017-6-15 13:12
2
0
谢谢分享
雪    币: 598
活跃值: (282)
能力值: ( LV13,RANK:330 )
在线值:
发帖
回帖
粉丝
Fpc 4 2017-6-15 14:34
3
0
用idc脚本调试比较方便
游客
登录 | 注册 方可回帖
返回