飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2934|回复: 2

Private exe Protector 1.8 IAT 加密分析

[复制链接]
  • TA的每日心情
    开心
    2017-2-23 16:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2006-7-9 12:39:35 | 显示全部楼层 |阅读模式
    Private exe Protector 1.8 IAT 加密分析
    水平有限,只有IAT加密分析,其他的保护一律没开,也没分析。实例程序用的加密解密光盘里面的MD5calc.加壳方式是可选的加密方式都不开.( IAT加密是默认的)

    加壳后的程序的IAT被完全清空了,运行后,壳直接向IAT中填充壳IAT解密函数的地址。然后,通过计算得到正确的API地址,直接进入API然后返回。
    OD载入,文件被作过手脚。只能停在system breakpoint.   //晕,今天又停在了正常的OEP.不知道是怎么搞得。
    He GetVersion.
    F9运行。第二次断下后。运行到返回。向上看看就是OEP.
    随便找一个call [IAT],在数据窗口中跟随,看到IAT了。
    这是这个例子的IAT
    00405000  004121A6  MD5calcu.004121A6
    00405004  00412221  MD5calcu.00412221
    00405008  00412287  MD5calcu.00412287
    0040500C  004122E8  MD5calcu.004122E8
    00405010  0041231C  MD5calcu.0041231C
    00405014  00412391  MD5calcu.00412391
    00405018  00412415  MD5calcu.00412415
    0040501C  0041248C  MD5calcu.0041248C
    00405020  00412522  MD5calcu.00412522
    00405024  00412589  MD5calcu.00412589
    00405028  00412630  MD5calcu.00412630
    0040502C  0041269E  MD5calcu.0041269E
    00405030  00412709  MD5calcu.00412709
    00405034  00412784  MD5calcu.00412784
    00405038  0041280D  MD5calcu.0041280D
    0040503C  00412887  MD5calcu.00412887
    00405040  004128F8  MD5calcu.004128F8
    00405044  00412928  MD5calcu.00412928
    00405048  004129BD  MD5calcu.004129BD
    0040504C  00412A42  MD5calcu.00412A42
    00405050  00412AC3  MD5calcu.00412AC3
    00405054  00412B69  MD5calcu.00412B69
    00405058  00412BD3  MD5calcu.00412BD3
    0040505C  00412C01  MD5calcu.00412C01
    00405060  00412CA2  MD5calcu.00412CA2
    00405064  00412CF4  MD5calcu.00412CF4
    00405068  00412D8B  MD5calcu.00412D8B
    0040506C  00412DEB  MD5calcu.00412DEB
    00405070  00412E32  MD5calcu.00412E32
    00405074  00412ECE  MD5calcu.00412ECE
    00405078  00412F4D  MD5calcu.00412F4D
    0040507C  00412FD5  MD5calcu.00412FD5
    00405080  00413023  MD5calcu.00413023
    00405084  00413047  MD5calcu.00413047
    00405088  00413097  MD5calcu.00413097
    0040508C  0041312B  MD5calcu.0041312B
    00405090  00000000
    00405094  00411D92  MD5calcu.00411D92
    00405098  00411DE8  MD5calcu.00411DE8
    0040509C  00411E6F  MD5calcu.00411E6F
    004050A0  00411F03  MD5calcu.00411F03
    004050A4  00411F99  MD5calcu.00411F99
    004050A8  0041201F  MD5calcu.0041201F
    004050AC  0041204F  MD5calcu.0041204F
    004050B0  004120C2  MD5calcu.004120C2
    004050B4  0041212E  MD5calcu.0041212E

    可见,全部被壳的函数填充了,每个函数都不一样。
    多跟踪几个解密过程。可以发现如下的规律。

    解密的过程:
    一共有三层
    第一层:
    每个API函数,对应一段相应的解密函数。
    刚进入的这段函数,都是执行下面的过程
    1.push 一个unsigned int立即数。
    2.计算进一步解密函数的地址(第二层解密函数地址).
    3.进入第二层函数。
    其中步骤1有3种实现方式:
    (1)
    push xxxxxxxx
    mov [esp] xxxxxxxx
    (2)
    push r32
    mov [esp] xxxxxxxx
    (3)
    push xxxxxxxx
    步骤2也有若干种实现方式
    但是变化仅仅是使用不同的寄存器。而且总是得到同一个地址(对同一个程序,同一台机器来说)
    步骤3是通过在堆栈上写入步骤2计算出来的地址,通过最后的retn实现的.
    其中一段的实际代码如下:
    push    edi
    mov     [esp+4+var_4], 0B182DFA9h
    push    36F05CB9h
    push    eax
    mov     eax, ds:dword_4081FE
    add     eax, 0C224h
    mov     [esp+0Ch+var_8], eax
    pop     eax
    retn    //进入第二层
    我这里的第二层函数的地址是003AC224
    (注意,刚刚进入第2层的时候,[esp]=上一层步骤1 push的立即数)
    代码如下:
    003AC224    55                 push    ebp
    003AC225    89E5               mov     ebp, esp  
    003AC227    50                 push    eax
    003AC228    53                 push    ebx
    003AC229    51                 push    ecx
    003AC22A    52                 push    edx
    003AC22B    56                 push    esi
    003AC22C    57                 push    edi         //上面的操作相当pushad
    003AC22D    8B45 04            mov     eax, [ebp+4]
    003AC230    50                 push    eax         //第一层步骤1push的立即数
    003AC231    E8 B2FFFFFF        call    003AC1E8   //进入第三层
    003AC236    8945 04            mov     [ebp+4], eax
    003AC239    5F                 pop     edi      
    003AC23A    5E                 pop     esi
    003AC23B    5A                 pop     edx
    003AC23C    59                 pop     ecx
    003AC23D    5B                 pop     ebx
    003AC23E    58                 pop     eax        //相当popad
    003AC23F    5D                 pop     ebp
    003AC240    C3                 retn
    进入第三层函数:
    003AC1E8    55                 push    ebp
    003AC1E9    8BEC               mov     ebp, esp
    003AC1EB    56                 push    esi
    003AC1EC    8B4D 08            mov     ecx, [ebp+8]
    003AC1EF    33F6               xor     esi, esi
    003AC1F1    A1 58003B00        mov     eax, [3B0058]
    003AC1F6    83C0 04            add     eax, 4
    003AC1F9    8B10               mov     edx, [eax]
    003AC1FB    83C0 04            add     eax, 4
    003AC1FE    85D2               test    edx, edx
    003AC200    76 18              jbe     short 003AC21A
    003AC202    3B08               cmp     ecx, [eax]
    003AC204    75 0E              jnz     short 003AC214
    003AC206    83C0 04            add     eax, 4
    003AC209    8B30               mov     esi, [eax]
    003AC20B    A1 58003B00        mov     eax, [3B0058]
    003AC210    3330               xor     esi, [eax]
    003AC212    EB 06              jmp     short 003AC21A
    003AC214    83C0 08            add     eax, 8
    003AC217    4A                 dec     edx
    003AC218  ^ 75 E8              jnz     short 003AC202
    003AC21A    8BC6               mov     eax, esi
    003AC21C    5E                 pop     esi
    003AC21D    5D                 pop     ebp
    003AC21E    C2 0400            retn    4

    通过分析上面的代码知:
    API地址的解密方式如下:
    在[3B0058]== 00BB0000(不同的程序,不同的机器地址不一样)有一个表,结构如下

    表头是下列结构
    struct tablehead
    {
    DWORD MagicNum;
    DWORD count;     //API结构的个数
    }
    表身是一个由下列结构组成的数组
    struct API
    {
    DWORD ID;
    DWORD key;
    }

    在00BB0000存放的方式是表头+表身

    IAT中的正确的API地址为:
    在表中查找第一层步骤1中的立即数。也就是说用找struct API结构中的ID来和第一层步骤1中的那个立即数比较。
    如果相等
    那么
    API Address = Key  xor MagicNum;
    例如:
    下面是我这个程序的表:
    00BB0000  6A55116E
    00BB0004  0000002D
    00BB0008  4844D879
    00BB000C  1D83BD70
    00BB0010  865A2255
    00BB0014  1D86D824
    00BB0018  D4C9B887
    00BB001C  1D84B9C3
    00BB0020  369744FB
    00BB0024  1D87037F
    00BB0028  AC9E8550
    00BB002C  1D87024A
    00BB0030  509362AB
    00BB0034  1D87E2F4
    00BB0038  BB32A0F6
    00BB003C  1D84DAEB
    00BB0040  3B9BF46E
    00BB0044  1D87733E
    00BB0048  6CAACE09
    00BB004C  1D86A072
    00BB0050  BAFA03D7
    00BB0054  16D5D7A1
    00BB0058  C1E6CFF5
    00BB005C  16D43D16
    00BB0060  62F88496
    00BB0064  16D5B5EE
    00BB0068  962C31C7
    00BB006C  16D69DD7
    00BB0070  5752A351
    00BB0074  16D5DFAA
    00BB0078  A3861600
    00BB007C  16D63F45
    00BB0080  72F11E39
    00BB0084  16D58DC3
    00BB0088  3FC1BD8D
    00BB008C  16DD3EAA
    00BB0090  C97C1FFF
    00BB0094  16D5BD46
    00BB0098  B1866570
    00BB009C  6A6FD19E
    00BB00A0  ADE2CB95
    00BB00A4  16D50F80
    00BB00A8  2D66B1C5
    00BB00AC  16D43DE3
    00BB00B0  4CCF1A0F
    00BB00B4  16D405C5
    00BB00B8  251097CC
    00BB00BC  6A6FD032
    00BB00C0  AB40BF8D
    假如第一层中的立即数是 4844D879
    那么API地址就为1D83BD70 xor 6A55116E=77D6AC1E

    修复的方法见附件中的源代码
    这个程序只能修复这个实例程序的IAT,因为那张解密表我是直接写到了程序里面。要修复其他程序,把那张表替换了就可以了。
    发现有些函数 壳是自己实现的,解密出来的函数还是指向壳里,这部分我是手动修复的。正在研究自动修复的方法。

    IAT修复程序使用方法:
    先用OD,跑到OEP或者OEP附近。然后打开程序,填写要求的数据,点修复按钮就可以了。
    源代码有点乱,下个版本改进。

    已知的壳自己实现的API:
    GetModuleHandleA
    ExitProcess
    GetModuleFileNameA

    BTW:ETG和CMIX是什么东西啊?
    PYG19周年生日快乐!
  • TA的每日心情
    无聊
    2018-12-10 18:30
  • 签到天数: 70 天

    [LV.6]常住居民II

    发表于 2006-7-9 20:02:58 | 显示全部楼层
    “He GetVersion       F9运行。第二次断下后。运行到返回。向上看看就是OEP.”

    我这里怎么只能中断一次,第二次根本就不能中断,并且提示进程已终止,退出代码。
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2008-9-27 17:12:07 | 显示全部楼层
    学习啊,多谢分享.
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表