• 逆向与反汇编实战(一)--PEiD分析复现


    准备

    简介:

    PEiD(PE Identifier)是一款著名的查壳工具,其功能强大,几乎可以侦测出所有的壳,其数量已超过470 种PE 文档 的加壳类型和签名。

    整个过程需要测试文件成品:https://www.lanzous.com/b07r7qu0d

    首先使用PEiD检测之前做的一个异常捕捉测试程序。源码在下面,编译器为VC++ 6.0,编译方法为 Win32 Release

    #include <stdio.h>
    
    class CExcepctionBase {
    public:
        virtual const char* GetExcepctionInfo() = 0;
    };
    
    class CDiv0Excepction :public CExcepctionBase {
    public:
        CDiv0Excepction() {
            printf("CExcepctionDiv0()
    ");
        }
        virtual ~CDiv0Excepction() {
            printf("~CDiv0Excepction()
    ");
        }
        virtual const char* GetExcepctionInfo() {
            return "div zero excepction";
        }
    };
    
    class CAccessExcepction :public CExcepctionBase {
    public:
        CAccessExcepction() {
            printf("CAccessExcepction()
    ");
        }
        virtual ~CAccessExcepction() {
            printf("~CAccessExcepction()
    ");
        }
        virtual const char* GetExcepctionInfo() {
            return "access excepction";
        }
    };
    
    void TestExcepction(int n) {
        try {
            if (1 == n) {
                throw 3;
            }
            if (2 == n) {
                throw 3.0f;
            }
            if (3 == n) {
                throw '3';
            }
            if (4 == n) {
                throw 3.0;
            }
            if (5 == n) {
                throw CDiv0Excepction();
            }
            if (6 == n) {
                throw CAccessExcepction();
            }
            if (7 == n) {
                CAccessExcepction excAccess;
                throw& excAccess;
            }
        }
        catch (int n) {
            printf("catch int %d
    ", n);
        }
        catch (float f) {
            printf("catch float %f
    ", f);
        }
        catch (char c) {
            printf("catch char %c
    ", c);
        }
        catch (double d) {
            printf("catch double %f
    ", d);
        }
        catch (CExcepctionBase &exc) {
            printf("catch error %s
    ", exc.GetExcepctionInfo());
        }
        catch (CAccessExcepction *pExc) {
            printf("catch error %s
    ", pExc->GetExcepctionInfo());
        }
        catch (...) {
            printf("catch ... ...");
        }
        printf("Test End!
    ");
    }
    
    int main()
    {
        for (int i = 1; i <= 8; ++i) {
            TestExcepction(i);
        }
    
        return 0;
    }

    使用PEiD检测情况

    文件判定分析

    函数定位

    从PEiD的分析情况,可以看到“Microsoft Visual C++ 6.0”的字符串,使用OD打开PEiD,找到字符串位置后下断点

    00438FF6  |> 8BAC24 9C0400>mov ebp,dword ptr ss:[esp+0x49C]
    00438FFD  |>  6A 18         push 0x18
    00438FFF  |.  68 285A4000   push upPEiD.00405A28                     ;  ASCII "Microsoft Visual C++ 6.0"
    00439004  |>  8D4D 04       lea ecx,dword ptr ss:[ebp+0x4]
    00439007  |.  E8 04D4FFFF   call upPEiD.00436410

    实际上,运行到此处时,已经结束了文件判断分析阶段,得到了结果,在上一条指令(红线指引),我们可以返回到跳转之前的函数,即是文件判定函数。

    文件判定函数分析

    接着向上查找,找到函数的入口处,设置断点,开始文件判定函数的分析

    00438C20  /$  81EC 88040000 sub esp,0x488
    00438C26  |.  53            push ebx
    00438C27  |.  55            push ebp
    00438C28  |.  56            push esi
    00438C29  |.  57            push edi
    00438C2A  |.  B0 72         mov al,0x72                              ;  定义特征码
    00438C2C  |.  884424 2F     mov byte ptr ss:[esp+0x2F],al
    00438C30  |.  884424 31     mov byte ptr ss:[esp+0x31],al
    00438C34  |.  884424 34     mov byte ptr ss:[esp+0x34],al
    00438C38  |.  884424 39     mov byte ptr ss:[esp+0x39],al
    00438C3C  |.  884424 3D     mov byte ptr ss:[esp+0x3D],al
    00438C40  |.  B0 63         mov al,0x63                              ;  定义特征码
    00438C42  |.  884424 40     mov byte ptr ss:[esp+0x40],al
    00438C46  |.  884424 41     mov byte ptr ss:[esp+0x41],al
    00438C4A  |.  B0 73         mov al,0x73                              ;  定义特征码
    00438C4C  |.  884424 43     mov byte ptr ss:[esp+0x43],al
    00438C50  |.  884424 44     mov byte ptr ss:[esp+0x44],al
    00438C54  |.  B0 6C         mov al,0x6C                              ;  定义特征码
    00438C56  |.  884424 47     mov byte ptr ss:[esp+0x47],al
    00438C5A  |.  884424 48     mov byte ptr ss:[esp+0x48],al
    00438C5E  |.  8BB424 A00400>mov esi,dword ptr ss:[esp+0x4A0]
    00438C65  |.  8B46 0C       mov eax,dword ptr ds:[esi+0xC]           ;  PE首地址,即IMAGE_NT_HEADERS
    00438C68  |.  8B56 18       mov edx,dword ptr ds:[esi+0x18]          ;  ".text"节首地址
    00438C6B  |.  B1 6D         mov cl,0x6D                              ;  定义特征码
    00438C6D  |.  884C24 36     mov byte ptr ss:[esp+0x36],cl
    00438C71  |.  884C24 3E     mov byte ptr ss:[esp+0x3E],cl
    00438C75  |.  B3 41         mov bl,0x41                              ;  定义特征码
    00438C77  |.  C64424 2C 7B  mov byte ptr ss:[esp+0x2C],0x7B
    00438C7C  |.  C64424 2D 4F  mov byte ptr ss:[esp+0x2D],0x4F
    00438C81  |.  C64424 2E 75  mov byte ptr ss:[esp+0x2E],0x75
    00438C86  |.  C64424 30 50  mov byte ptr ss:[esp+0x30],0x50
    00438C8B  |.  C64424 32 6F  mov byte ptr ss:[esp+0x32],0x6F
    00438C90  |.  C64424 33 67  mov byte ptr ss:[esp+0x33],0x67
    00438C95  |.  C64424 35 61  mov byte ptr ss:[esp+0x35],0x61
    00438C9A  |.  C64424 37 44  mov byte ptr ss:[esp+0x37],0x44
    00438C9F  |.  C64424 38 69  mov byte ptr ss:[esp+0x38],0x69
    00438CA4  |.  C64424 3A 7D  mov byte ptr ss:[esp+0x3A],0x7D
    00438CA9  |.  C64424 3B 5C  mov byte ptr ss:[esp+0x3B],0x5C
    00438CAE  |.  885C24 3C     mov byte ptr ss:[esp+0x3C],bl
    00438CB2  |.  885C24 3F     mov byte ptr ss:[esp+0x3F],bl
    00438CB6  |.  C64424 42 65  mov byte ptr ss:[esp+0x42],0x65
    00438CBB  |.  C64424 45 2E  mov byte ptr ss:[esp+0x45],0x2E
    00438CC0  |.  C64424 46 64  mov byte ptr ss:[esp+0x46],0x64
    00438CC5  |.  C64424 18 4D  mov byte ptr ss:[esp+0x18],0x4D
    00438CCA  |.  C64424 19 53  mov byte ptr ss:[esp+0x19],0x53
    00438CCF  |.  C64424 1A 43  mov byte ptr ss:[esp+0x1A],0x43
    00438CD4  |.  C64424 1B 46  mov byte ptr ss:[esp+0x1B],0x46
    00438CD9  |.  0FB740 06     movzx eax,word ptr ds:[eax+0x6]          ;  eax中为IMAGE_NT_HEADERS首地址,[eax+0x6]为Section Number(节数目) = 3
    00438CDD  |.  8D0C80        lea ecx,dword ptr ds:[eax+eax*4]         ;  节数目乘5
    00438CE0  |.  8B6CCA E8     mov ebp,dword ptr ds:[edx+ecx*8-0x18]    ;  得到".data"所占大小
    00438CE4  |.  8D44CA D8     lea eax,dword ptr ds:[edx+ecx*8-0x28]    ;  保存".data"节的首地址
    00438CE8  |.  8B78 14       mov edi,dword ptr ds:[eax+0x14]          ;  ".data"在磁盘中的偏移
    00438CEB  |.  8B46 04       mov eax,dword ptr ds:[esi+0x4]           ;  第二个参数指向结构中的第二项数据
    00438CEE  |.  03FD          add edi,ebp                              ;  ".data"偏移地址+".data"节所占大小=".data"节末尾
    00438CF0  |.  8BAC24 9C0400>mov ebp,dword ptr ss:[esp+0x49C]         ;  获取第一个参数
    00438CF7  |.  8D8F 00390000 lea ecx,dword ptr ds:[edi+0x3900]        ;  .data节在内存中的位置
    00438CFD  |.  3BC1          cmp eax,ecx                              ;  判断第二个参数是否不小于.data节(.data之后就是OEP),如果成功,跳过OEP检查
    00438CFF  |.  73 1A         jnb XupPEiD.00438D1B                     ;  跳过OEP检查
    00438D01  |.  8B55 20       mov edx,dword ptr ss:[ebp+0x20]          ;  获取到程序入口地址
    00438D04  |.  85D2          test edx,edx                             ;  检查OEP
    00438D06  |.  74 13         je XupPEiD.00438D1B
    00438D08  |.  8B4E 18       mov ecx,dword ptr ds:[esi+0x18]          ;  .text节首地址
    00438D0B  |.  8B79 14       mov edi,dword ptr ds:[ecx+0x14]          ;  .text节文件偏移
    00438D0E  |.  0379 10       add edi,dword ptr ds:[ecx+0x10]          ;  .text节文件偏移+.text节大小=.text节末尾
    00438D11  |.  3BD7          cmp edx,edi                              ;  判断OEP是否在.text节中
    00438D13  |.  0F82 E4020000 jb upPEiD.00438FFD                       ;  如果在,跳转,检查结束

    通过,分析实际上这个函数就做了两件事,一是判定第二个参数是否在.data节中,二是判断OEP是否在.text节中。对于节区以及对应位置功能的判断,可以使用PEView,010 Editor以及结合OD寄存器区判断,这里不给出判定过程了。但是,在这里却没有用到特征码,我们将最后一步的跳转命令nop。分析OEP检查错误情况的代码。

    OEP检查错误和编译器判断

    00438D13      90              nop                                      ;  如果在,跳转,检查结束
    00438D14      90              nop
    00438D15      90              nop
    00438D16      90              nop
    00438D17      90              nop
    00438D18      90              nop                                      ;  ************下面的代码是OEP检查失败的情况************
    00438D19  |.  8BFA            mov edi,edx                              ;  OEP偏移地址存入EDI,0x1634
    00438D1B  |>  2BC7            sub eax,edi                              ;  保存.data节的末尾地址
    00438D1D  |.  83F8 09         cmp eax,0x9                              ;  判断OEP是否在.data节中
    00438D20  |.  0F82 D7020000   jb upPEiD.00438FFD                       ;  不在就跳转
    00438D26  |.  8B16            mov edx,dword ptr ds:[esi]               ;  edx保存IMAGE_DOS_HEADER首地址
    00438D28  |.  8D0C3A          lea ecx,dword ptr ds:[edx+edi]           ;  得到OEP的地址
    00438D2B  |.  8B11            mov edx,dword ptr ds:[ecx]               ;  将OEP前四个直接存入edx中,edx=0x6AEC8B55
    00438D2D  |.  81FA 496E7374   cmp edx,0x74736E49                       ;  OEP与特征码比较
    00438D33  |.  75 15           jnz XupPEiD.00438D4A                     ;  条件成立,跳转,不成立则继续比较OEP后双字的数据
    00438D35  |.  8179 04 616C6C5>cmp dword ptr ds:[ecx+0x4],0x536C6C61    ;  OEP与特征码比较
    00438D3C  |.  75 0C           jnz XupPEiD.00438D4A                     ;  成立则跳转
    00438D3E  |.  6A 17           push 0x17                                ;  压入字符串长度
    00438D40  |.  68 B45A4000     push upPEiD.00405AB4                     ;  ASCII "InstallShield 2003 Stub"
    00438D45  |.  E9 BA020000     jmp upPEiD.00439004                      ;  跳转到显示字符串函数处
    00438D4A  |>  81FA 64617461   cmp edx,0x61746164                       ;  OEP与特征码比较
    00438D50  |.  75 27           jnz XupPEiD.00438D79
    00438D52  |.  8179 04 312E636>cmp dword ptr ds:[ecx+0x4],0x61632E31    ;  下面实际上就是一些其他版本的特征码比较了
    00438D59  |.  75 1E           jnz XupPEiD.00438D79
    00438D5B  |.  68 B45A4000     push upPEiD.00405AB4                     ;  ASCII "InstallShield 2003 Stub"
    00438D60  |.  8D4D 04         lea ecx,dword ptr ss:[ebp+0x4]
    00438D63  |.  E8 38E9FFFF     call upPEiD.004376A0
    00438D68  |.  5F              pop edi
    00438D69  |.  5E              pop esi
    00438D6A  |.  C645 00 01      mov byte ptr ss:[ebp],0x1
    00438D6E  |.  5D              pop ebp
    00438D6F  |.  B0 01           mov al,0x1
    00438D71  |.  5B              pop ebx
    00438D72  |.  81C4 88040000   add esp,0x488
    00438D78  |.  C3              retn
    00438D79  |>  3D 00020000     cmp eax,0x200
    00438D7E  |.  BD 00020000     mov ebp,0x200
    00438D83  |.  77 02           ja XupPEiD.00438D87
    00438D85  |.  8BE8            mov ebp,eax
    00438D87  |>  6A 1D           push 0x1D
    00438D89  |.  8D4424 30       lea eax,dword ptr ss:[esp+0x30]
    00438D8D  |.  50              push eax
    00438D8E  |.  8D8C24 98000000 lea ecx,dword ptr ss:[esp+0x98]
    00438D95  |.  E8 26E5FFFF     call upPEiD.004372C0
    00438D9A  |.  8B16            mov edx,dword ptr ds:[esi]
    00438D9C  |.  8D4C24 10       lea ecx,dword ptr ss:[esp+0x10]
    00438DA0  |.  51              push ecx
    00438DA1  |.  55              push ebp
    00438DA2  |.  03D7            add edx,edi
    00438DA4  |.  52              push edx
    00438DA5  |.  8D8C24 9C000000 lea ecx,dword ptr ss:[esp+0x9C]
    00438DAC  |.  E8 4FE6FFFF     call upPEiD.00437400
    00438DB1  |.  84C0            test al,al
    00438DB3  |.  74 26           je XupPEiD.00438DDB
    00438DB5  |.  8BB424 9C040000 mov esi,dword ptr ss:[esp+0x49C]
    00438DBC  |.  6A 1B           push 0x1B
    00438DBE  |.  68 985A4000     push upPEiD.00405A98                     ;  ASCII "Silicon Realms Install Stub"
    00438DC3  |.  8D4E 04         lea ecx,dword ptr ds:[esi+0x4]
    00438DC6  |.  E8 45D6FFFF     call upPEiD.00436410
    00438DCB  |.  5F              pop edi
    00438DCC  |.  C606 01         mov byte ptr ds:[esi],0x1
    00438DCF  |.  5E              pop esi
    00438DD0  |.  5D              pop ebp
    00438DD1  |.  B0 01           mov al,0x1
    00438DD3  |.  5B              pop ebx
    00438DD4  |.  81C4 88040000   add esp,0x488
    00438DDA  |.  C3              retn
    00438DDB  |>  8B46 04         mov eax,dword ptr ds:[esi+0x4]
    00438DDE  |.  2BC7            sub eax,edi
    00438DE0  |.  3D 00400000     cmp eax,0x4000
    00438DE5  |.  BD 00400000     mov ebp,0x4000
    00438DEA  |.  77 02           ja XupPEiD.00438DEE
    00438DEC  |.  8BE8            mov ebp,eax
    00438DEE  |>  6A 04           push 0x4
    00438DF0  |.  8D4424 1C       lea eax,dword ptr ss:[esp+0x1C]
    00438DF4  |.  50              push eax
    00438DF5  |.  8D8C24 98000000 lea ecx,dword ptr ss:[esp+0x98]
    00438DFC  |.  E8 BFE4FFFF     call upPEiD.004372C0
    00438E01  |.  8B16            mov edx,dword ptr ds:[esi]
    00438E03  |.  8D4C24 10       lea ecx,dword ptr ss:[esp+0x10]
    00438E07  |.  51              push ecx
    00438E08  |.  55              push ebp
    00438E09  |.  03D7            add edx,edi
    00438E0B  |.  52              push edx
    00438E0C  |.  8D8C24 9C000000 lea ecx,dword ptr ss:[esp+0x9C]
    00438E13  |.  E8 E8E5FFFF     call upPEiD.00437400
    00438E18  |.  84C0            test al,al
    00438E1A  |.  74 24           je XupPEiD.00438E40
    00438E1C  |.  8BB424 9C040000 mov esi,dword ptr ss:[esp+0x49C]
    00438E23  |.  68 845A4000     push upPEiD.00405A84                     ;  ASCII "InstallShield AFW"
    00438E28  |.  8D4E 04         lea ecx,dword ptr ds:[esi+0x4]
    00438E2B  |.  E8 70E8FFFF     call upPEiD.004376A0
    00438E30  |.  5F              pop edi
    00438E31  |.  C606 01         mov byte ptr ds:[esi],0x1
    00438E34  |.  5E              pop esi
    00438E35  |.  5D              pop ebp
    00438E36  |.  B0 01           mov al,0x1
    00438E38  |.  5B              pop ebx
    00438E39  |.  81C4 88040000   add esp,0x488
    00438E3F  |.  C3              retn
    00438E40  |>  8B46 0C         mov eax,dword ptr ds:[esi+0xC]           ;  eax为IMAGE_NT_HEADERS地址=0x64800D8
    00438E43  |.  8B40 28         mov eax,dword ptr ds:[eax+0x28]          ;  eax为代码段的地址
    00438E46  |.  50              push eax
    00438E47  |.  8BCE            mov ecx,esi
    00438E49  |.  E8 32A40100     call upPEiD.00453280                     ;  计算偏移位置,得到正确的OEP
    00438E4E  |.  8BF8            mov edi,eax
    00438E50  |.  8B46 18         mov eax,dword ptr ds:[esi+0x18]          ;  获取.text节首地址,0x064801D0
    00438E53  |.  8B48 14         mov ecx,dword ptr ds:[eax+0x14]          ;  .text节文件偏移地址
    00438E56  |.  0348 10         add ecx,dword ptr ds:[eax+0x10]          ;  .text节文件偏移地址+.text节大小=.text节末尾偏移地址
    00438E59  |.  3BF9            cmp edi,ecx                              ;  比较OEP是否在.text节中
    00438E5B  |.  0F82 95010000   jb upPEiD.00438FF6                       ;  跳转到显示编译器版本处,此处即显示"Microsoft Visual C++ 6.0”

     因为在第一部分对OEP的检测中,已经完成的跳转,实际上是不会执行这一段代码的,因此对于真正的文件判定代码,是会调用上面这段函数的。

    要找到函数的调用处,因为函数在最后ret时,都会出栈函数调用处的调用地址,所以直接在函数结尾设置断点,执行观察栈区。

    转到0x452F46

    存放数据处

    "真"文件分析函数

    对上面分析函数进行分析

    00452E90  /$  64:A1 00000000  mov eax,dword ptr fs:[0]                 ;  入口地址
    00452E96  |.  6A FF           push -0x1
    00452E98  |.  68 C8CD4600     push upPEiD.0046CDC8                     ;  异常处理
    00452E9D  |.  50              push eax
    00452E9E  |.  64:8925 0000000>mov dword ptr fs:[0],esp
    00452EA5  |.  83EC 10         sub esp,0x10                             ;  局部变量空间
    00452EA8  |.  56              push esi
    00452EA9  |.  8B7424 24       mov esi,dword ptr ss:[esp+0x24]          ;  第一个参数
    00452EAD  |.  8B46 14         mov eax,dword ptr ds:[esi+0x14]
    00452EB0  |.  8B40 10         mov eax,dword ptr ds:[eax+0x10]          ;  获取起始相对虚拟偏移地址
    00452EB3  |.  57              push edi                                 ;  压入参数一
    00452EB4  |.  8BF9            mov edi,ecx                              ;  获取this指针
    00452EB6  |.  50              push eax                                 ;  压入代码起始RVA
    00452EB7  |.  8BCE            mov ecx,esi
    00452EB9  |.  E8 C2030000     call upPEiD.00453280                     ;  检查PE文件格式,将OEP的RWA与RVA进行转换
    00452EBE  |.  3B46 04         cmp eax,dword ptr ds:[esi+0x4]           ;  函数返回调整之后的OEP
    00452EC1  |.  72 15           jb XupPEiD.00452ED8                      ;  条件成立,跳转到分析阶段
    00452EC3  |.  5F              pop edi                                  ;  =============分析失败代码===========
    00452EC4  |.  32C0            xor al,al
    00452EC6  |.  5E              pop esi
    00452EC7  |.  8B4C24 10       mov ecx,dword ptr ss:[esp+0x10]
    00452ECB  |.  64:890D 0000000>mov dword ptr fs:[0],ecx
    00452ED2  |.  83C4 1C         add esp,0x1C
    00452ED5  |.  C2 0800         retn 0x8                                 ;  =======================================
    00452ED8  |>  53              push ebx
    00452ED9  |.  8B5C24 30       mov ebx,dword ptr ss:[esp+0x30]
    00452EDD  |.  8943 20         mov dword ptr ds:[ebx+0x20],eax          ;  保存调整之后的OEP
    00452EE0  |.  8B4E 04         mov ecx,dword ptr ds:[esi+0x4]
    00452EE3  |.  8B16            mov edx,dword ptr ds:[esi]
    00452EE5  |.  2BC8            sub ecx,eax
    00452EE7  |.  51              push ecx
    00452EE8  |.  03D0            add edx,eax
    00452EEA  |.  52              push edx                                 ;  载入内存后的程序入口地址
    00452EEB  |.  8D4C24 14       lea ecx,dword ptr ss:[esp+0x14]
    00452EEF  |.  51              push ecx
    00452EF0  |.  8BCF            mov ecx,edi
    00452EF2  |.  E8 E9740000     call upPEiD.0045A3E0                     ;  将OEP代码与特征码进行对比--PEiD可以检查出分析程序是否在可识别的编译器范围内
    00452EF7  |.  8B4424 14       mov eax,dword ptr ss:[esp+0x14]
    00452EFB  |.  8B4C24 10       mov ecx,dword ptr ss:[esp+0x10]
    00452EFF  |.  8BD0            mov edx,eax
    00452F01  |.  2BD1            sub edx,ecx
    00452F03  |.  C1FA 02         sar edx,0x2
    00452F06  |.  52              push edx
    00452F07  |.  50              push eax
    00452F08  |.  51              push ecx
    00452F09  |.  C74424 30 00000>mov dword ptr ss:[esp+0x30],0x0
    00452F11  |.  E8 9AF5FFFF     call upPEiD.004524B0                     ;  根据函数0x45A3E0对OEP处特征码的对比结果,将特征匹配的处理流程的函数指针,在数组中的下标值都存放在地址ESP+1C的数组中
    00452F16  |.  8B7C24 1C       mov edi,dword ptr ss:[esp+0x1C]
    00452F1A  |.  8B4424 20       mov eax,dword ptr ss:[esp+0x20]
    00452F1E  |.  83C4 0C         add esp,0xC
    00452F21  |.  3BF8            cmp edi,eax
    00452F23  |.  74 37           je XupPEiD.00452F5C                      ;  没有匹配的特征函数,结束分析
    00452F25  |>  8B07            /mov eax,dword ptr ds:[edi]
    00452F27  |.  50              |push eax
    00452F28  |.  56              |push esi
    00452F29  |.  53              |push ebx
    00452F2A  |.  FF15 8C1E4000   |call dword ptr ds:[0x401E8C]            ;  检查.rdata节是否存在
    00452F30  |.  83C4 0C         |add esp,0xC
    00452F33  |.  84C0            |test al,al
    00452F35  |.  75 48           |jnz XupPEiD.00452F7F                    ;  如果不存在,结束查询分析
    00452F37  |.  8B07            |mov eax,dword ptr ds:[edi]
    00452F39  |.  50              |push eax
    00452F3A  |.  56              |push esi
    00452F3B  |.  8D0C40          |lea ecx,dword ptr ds:[eax+eax*2]
    00452F3E  |.  53              |push ebx
    00452F3F  |.  FF148D 8C1E4000 |call dword ptr ds:[ecx*4+0x401E8C]      ;  调用分析函数,存放数据的首地址在0x401E8C
    00452F46  |.  83C4 0C         |add esp,0xC
    00452F49  |.  84C0            |test al,al
    00452F4B  |.  75 32           |jnz XupPEiD.00452F7F
    00452F4D  |.  8B4424 14       |mov eax,dword ptr ss:[esp+0x14]
    00452F51  |.  83C7 04         |add edi,0x4
    00452F54  |.  3BF8            |cmp edi,eax
    00452F56  |.^ 75 CD           jnz XupPEiD.00452F25                    ;  循环跳转。一直循环到匹配到对应的处理函数

    上面的函数,整个过程:

    1. 对OEP的特征码比较
    2. 通过比较结果匹配储存函数指针的数组中的过程,将下标存储到数组
    3. 检测程序中是否存在.rdata节
    4. 从存储下标的数组中取出下标,调用对应的函数。

    在第一步中,会产生一个使用OEP的哪些机器码作为特征码进行比较的问题(特征码的定义)。因此,我们进一步分析函数0x45A3E0

    00452EF2  |.  E8 E9740000     call upPEiD.0045A3E0                     ;  将OEP代码与特征码进行对比--PEiD可以检查出分析程序是否在可识别的编译器范围内

    特征码分析

    0045A3E0  /$  6A FF           push -0x1
    0045A3E2  |.  68 38D24600     push upPEiD.0046D238                     ;  SE 处理程序安装
    0045A3E7  |.  64:A1 00000000  mov eax,dword ptr fs:[0]
    0045A3ED  |.  50              push eax
    0045A3EE  |.  64:8925 0000000>mov dword ptr fs:[0],esp
    0045A3F5  |.  83EC 14         sub esp,0x14
    0045A3F8  |.  53              push ebx
    0045A3F9  |.  55              push ebp
    0045A3FA  |.  33DB            xor ebx,ebx
    0045A3FC  |.  56              push esi
    0045A3FD  |.  57              push edi
    0045A3FE  |.  8BF1            mov esi,ecx                              ;  获取this指针
    0045A400  |.  895C24 10       mov dword ptr ss:[esp+0x10],ebx          ;  将数组清零
    0045A404  |.  895C24 18       mov dword ptr ss:[esp+0x18],ebx
    0045A408  |.  895C24 1C       mov dword ptr ss:[esp+0x1C],ebx
    0045A40C  |.  895C24 20       mov dword ptr ss:[esp+0x20],ebx
    0045A410  |.  8B7C24 38       mov edi,dword ptr ss:[esp+0x38]          ;  获取OEP,保存到EDI
    0045A414  |.  0FB607          movzx eax,byte ptr ds:[edi]              ;  获取OEP地址处的数据
    0045A417  |.  8B4486 14       mov eax,dword ptr ds:[esi+eax*4+0x14]    ;  对this指针偏移计算
    0045A41B  |.  83F8 FF         cmp eax,-0x1
    0045A41E  |.  8B6C24 3C       mov ebp,dword ptr ss:[esp+0x3C]          ;  OEP差值
    0045A422  |.  895C24 2C       mov dword ptr ss:[esp+0x2C],ebx          ;  EBX=0,将局部变量清0
    0045A426  |.  74 0F           je XupPEiD.0045A437
    0045A428  |.  55              push ebp
    0045A429  |.  57              push edi
    0045A42A  |.  50              push eax
    0045A42B  |.  8D4C24 20       lea ecx,dword ptr ss:[esp+0x20]          ;  获取数组首地址
    0045A42F  |.  51              push ecx
    0045A430  |.  8BCE            mov ecx,esi                              ;  将ECX赋值为this指针
    0045A432  |.  E8 99FDFFFF     call upPEiD.0045A1D0                     ;  检查OEP处代码是否与特征码相同(将OEP处的字节码与特征码对比,从而比较OEP处的机器码)
    0045A437  |>  8B86 14040000   mov eax,dword ptr ds:[esi+0x414]
    0045A43D  |.  83F8 FF         cmp eax,-0x1
    0045A440  |.  74 0F           je XupPEiD.0045A451
    0045A442  |.  55              push ebp
    0045A443  |.  57              push edi
    0045A444  |.  50              push eax
    0045A445  |.  8D5424 20       lea edx,dword ptr ss:[esp+0x20]
    0045A449  |.  52              push edx
    0045A44A  |.  8BCE            mov ecx,esi
    0045A44C  |.  E8 7FFDFFFF     call upPEiD.0045A1D0                     ;  检查OEP处代码是否与特征码相同(将OEP处的字节码与特征码对比,从而比较OEP处的机器码)

    机器码和特征码的介绍与关系:https://www.cnblogs.com/qiumingcheng/p/5400265.html

    在上面的函数中通过0x45A1D0比较OEP的机器码与特征码,提取出具有相同特性的编译器版本。

    例如

    这是OEP的部分数据

    05551634  55 8B EC 6A FF 68 F0 80 40 00 68 40 41 40 00 64  U嬱jh饊@.h@A@.d
    05551644  A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 10  ?...Pd?....冹
    05551654  53 56 57 89 65 E8 FF 15 0C 80 40 00 33 D2 8A D4  SVW塭?.€@.3見?
    05551664  89 15 6C BA 40 00 8B C8 81 E1 FF 00 00 00 89 0D  ?l篅.嬋佱...?
    05551674  68 BA 40 00 C1 E1 08 03 CA 89 0D 64 BA 40 00 C1  h篅.玲蕢.d篅.?

    使用数据拼接成机器码指令

    0x55 0x8b 0xec 0x6a 0xff

    0045A3E0      55              push ebp
    0045A3E1      8BEC            mov ebp,esp
    0045A3E3      6A FF           push -0x1

    PEiD解析流程

    1. PEiD解析编译器的流程总结:
    2. 读取文件,分析出PE结构,保存。
    3. 检查OEP,修正OE,再次检查OEP
    4. 使用OEP处的机器码与特征码比较
    5. 通过比较结果匹配储存函数指针的数组中的过程,将下标存储到数组
    6. 检查文件是否存在rdata节
    7. 循环,从存储下标的数组中取出下标,调用对应的函数。
    8. 在处理函数中再次检查OEP的机器码与特征码
    9. 获取并显示编译器版本

    开发环境伪造

    在第一次文件判定中,我们知道会检测OEP是否在.text节中,因此,我们只需要将伪造OEP写入.text节后,使用HEX Editor改变原来OEP即可

    55 8B EC 6A FF 68 F0 80 40 00 68 40 41 40 00 64
    A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 10
    53 56 57 89 65 E8 5F 5E 5B 83 C4 10 58 64 A3 00
    00 00 00 58 58 58 58 E8 76 FA FF FF 00 00 00 00

    使用一个简单的Hello World程序进行伪造OEP

    1.初始的OEP地址在0xF012C2处,写入伪造OEP数据

    2.保存修改后的文件后,OD打开,起始偏移地址为1810

    3.HEX Editor定位到偏移地址0x110处

    将原OEP偏移地址0x12C2改为0x1810即可

    本次实战复现主要是对程序特征码的识别,日后可以用于病毒程序,游戏外挂的识别判断。迟到了...wokao...

  • 相关阅读:
    005.SQLServer AlwaysOn可用性组高可用简介
    004.Windows Server 故障转移群集 (WSFC)简介
    003.SQLServer数据库镜像高可用部署
    附008.Kubernetes TLS证书介绍及创建
    附007.Kubernetes ABAC授权
    附006.Kubernetes RBAC授权
    附005.Kubernetes身份认证
    附004.Kubernetes Dashboard简介及使用
    附003.Kubeadm部署Kubernetes
    附002.Minikube介绍及使用
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11960703.html
Copyright © 2020-2023  润新知