首页
论坛
专栏
课程

[原创]Themida 2.3.5.5分析

2019-3-23 18:54 5157

[原创]Themida 2.3.5.5分析

2019-3-23 18:54
5157
这几天在看关于壳子的文章 在这里得感谢qqmcc大佬的两篇文章链接我放出来

Sure大的链接 :
看了他的这两篇文章,大概就明白了themida保护函数,IAT表的一些手段,最近又逛学破解论坛看到Sure大佬发的一个这个版本的壳子的脚本,感觉强壳的脚本很多但是分析有点少,于是我就手动的分析了一下,在这里发出来算是记录一下吧,要不然还是会丢~

【使用工具】:冷小黑OD

【操作平台】: win xp 虚拟机

关于Themida研究了这三个版本,感觉核心技术就是[esi]表,这个表的大概结构我贴出来

006F912B                          7B 8E 39 F8 2B 04 92 8F          ?拸
006F913B  78 7B 00 20 FF FF FF FF DD DD DD DD 4D 1C DB 55  x{. 葺葺M踀
006F914B  2B 04 92 AF 79 7B 00 C0 FF FF FF FF DD DD DD DD  +挴y{.?葺葺
006F915B  00 78 7A 92 2B 04 92 CF 89 7B 00 20 FF FF FF FF  .xz?捪墈. 
006F916B  DD DD DD DD D2 6E 05 7B 2B 04 92 EF 8A 7B 00 60  葺葺襫{+掞妠.`
006F917B  FF FF FF FF DD DD DD DD 4F 1B 2E D7 2C 04 92 0F  葺葺O.??
006F918B  BA 7A 00 A0 FF FF FF FF DD DD DD DD 98 A8 22 73  簔.?葺葺槰"s
006F919B  2C 04 92 2F B2 7A 00 00 FF FF FF FF DD DD DD DD  ,?瞶..葺葺
006F91AB  7E 4F E6 12 2C 04 92 4F B7 7A 00 20 FF FF FF FF  ~O?,扥穤. 
006F91BB  DD DD DD DD EE 72 DF 46 2C 04 92 6F 0E 52 00 A0  葺葺顁逨,抩R.
006F91CB  FF FF FF FF DD DD DD DD AC 85 52 4B 2C 04 92 8F  葺葺瑓RK,拸
006F91DB  12 52 00 60 FF FF FF FF DD DD DD DD D7 11 33 E0  R.`葺葺?3
006F91EB  2C 04 92 AF 1E 52 00 60 24 52 00 E0 FF FF FF FF  ,挴R.`$R.?
006F91FB  DD DD DD DD 38 C8 E1 23 2C 04 92 CF 02 52 00 20  葺葺8柔#,捪R.
006F920B  2E 52 00 00 FF FF FF FF DD DD DD DD 4A 62 49 E1  .R..葺葺JbI
006F921B  2C 04 92 EF 39 53 00 60 FF FF FF FF DD DD DD DD  ,掞9S.`葺葺
006F922B  28 57 A9 3A 2D 04 92 0F FF FF FF FF DD DD DD DD  (W?-?葺葺
006F923B  EE EE EE EE                                      铑铑葺葺

一个DWORD看成是一个元素  这个表中的FF FF FF FF DD DD DD DD看成是一组元素的结尾 而 FF FF FF FF DD DD DD DD EE EE EE EE 是一个表的结束
一般来说一个[esi]表是有三个可用元素,但是当按照这个步骤进去以后会发现这个[esi]表是有四个元素
程序放到OD里边 在代码段下写入断点到这个循环,然后F7 F8 shift+F9跑起来
006F72C8    F3:A4           rep movs byte ptr es:[edi],byte ptr ds:[esi]
到这个地方
007095C8     890A                 mov dword ptr ds:[edx],ecx                ; 写入IAT
007095CA     5A                   pop edx                                   ; 第二个元素还是去IAT填充API这里的IAT 的基址是487600
007095CB     F5                   cmc
007095CC     AD                   lods dword ptr ds:[esi]                   ; 取第三个元素
007095CD     F9                   stc
007095CE     50                   push eax                                  ; v2_3_5_1.00487600
007095CF     B8 00000000          mov eax,0x0
007095D4     50                   push eax                                  ; v2_3_5_1.00487600
007095D5     810424 6B65E465      add dword ptr ss:[esp],0x65E4656B
007095DC     8F46 FC              pop dword ptr ds:[esi-0x4]
007095DF     816E FC 6B65E465     sub dword ptr ds:[esi-0x4],0x65E4656B     ; 元素3置零
007095E6     58                   pop eax                                   ; v2_3_5_1.00487600
007095E7     F8                   clc
007095E8     89B5 8C35AD0A        mov dword ptr ss:[ebp+0xAAD358C],esi      ; 保存当前esi指针位置
007095EE     60                   pushad                                    ; 无用代码
007095EF     81C8 4979F419        or eax,0x19F47949
007095F5     66:81E2 EF0D         and dx,0xDEF
007095FA     61                   popad
007095FB     83F8 FF              cmp eax,-0x1                              ; 跟FFFFFFFF比较 看看是不是到末尾
007095FE     0F85 B5000000        jnz v2_3_5_1.007096B9
接着按F7单步慢慢走慢慢分析
007096B9    C1C0 03         rol eax,0x3
007096BC    F9              stc
007096BD    0385 550EAD0A   add eax,dword ptr ss:[ebp+0xAAD0E55]     ; v2_3_5_1.00400000
007096C3    60              pushad                                   ; 拿到偏移+基址
007096C4    60              pushad                                   ; 处理NOP指令
这个地方拿到的基址+偏移是00429C2D  我们到这个位置看一下
00429C2D    90              nop
00429C2E    90              nop
00429C2F    90              nop
00429C30    90              nop
00429C31    90              nop
00429C32    90              nop

070971C    813E AAAAAAAA   cmp dword ptr ds:[esi],0xAAAAAAAA        ; 判断是不是需要处理的FF15数据
这里比较AAAAAAAA需要说明一下,它实际上是TMD判断原来代码中的FF15(“CALL 地址”)和FF25(”JMP 地址”),
我们在修复的时候也需要判断,至于判断的方法也不一定要从这里,知道了流程,脚本的方法是很多的.
00709875    B9 057F447D     mov ecx,0x7D447F05
0070987A    D1E1            shl ecx,1
0070987C    81E1 976FEE6F   and ecx,0x6FEE6F97
00709882    F7D1            not ecx                                  ; winmm.midiStreamOut
00709884    F7D1            not ecx                                  ; winmm.midiStreamOut
00709886    81F1 5A19005C   xor ecx,0x5C00195A
0070988C    89CB            mov ebx,ecx                              ; winmm.midiStreamOut
0070988E    59              pop ecx                                  ; v2_3_5_1.00709E74
0070988F    81F3 0C5E8200   xor ebx,0x825E0C
00709895    81C3 7B76182A   add ebx,0x2A18767B
0070989B    C1EB 05         shr ebx,0x5
0070989E    81EB FE140103   sub ebx,0x30114FE
007098A4    89D8            mov eax,ebx
007098A6    5B              pop ebx                                  ; 这一段的目的是EAX清零操作



00709997    803F 90         cmp byte ptr ds:[edi],0x90               ; 比较是不是需要处理的NOP指令




00709A75    57              push edi
00709A76    BF B2606917     mov edi,0x176960B2
00709A7B    BB B2606917     mov ebx,0x176960B2                       ; mov ebx,0
00709A80    29FB            sub ebx,edi
00709A82    8B3C24          mov edi,dword ptr ss:[esp]               ; pop edi
00709A85    83C4 04         add esp,0x4


00709AB5    83F8 50         cmp eax,0x50                             ; 判断是否是需要处理的push指令


00709B0A    AA              stos byte ptr es:[edi]                   ; 填充一个E8


00709C26    51              push ecx                                 ; winmm.midiStreamOut
00709C27    B9 04000000     mov ecx,0x4
00709C2C    2D 5614BE78     sub eax,0x78BE1456
00709C31    29C8            sub eax,ecx                              ; winmm.midiStreamOut
00709C33    05 5614BE78     add eax,0x78BE1456                       ; 当前API往后移动四个字节
00709C38    59              pop ecx                                  ; winmm.midiStreamOut


00709C55    AB              stos dword ptr es:[edi]                  ; 将移动后的API地址填充进E8后边 也就是429C2D处


00709C91     AD                   lods dword ptr ds:[esi]            ; 取[esi]表中元素 这时候取得是第四个元素
00709C92     0F85 09000000        jnz v2_3_5_1.00709CA1
00709C98     60                   pushad
00709C99     F8                   clc
00709C9A     0F82 00000000        jb v2_3_5_1.00709CA0
00709CA0     61                   popad
00709CA1     52                   push edx                           ; v2_3_5_1.006F90E3
00709CA2     BA FCFFFFFF          mov edx,-0x4
00709CA7     01F2                 add edx,esi
00709CA9     56                   push esi
00709CAA     BE 3A0A8D4B          mov esi,0x4B8D0A3A
00709CAF     C702 3A0A8D4B        mov dword ptr ds:[edx],0x4B8D0A3A  ; 当前[esi]表清零
00709CB5     3132                 xor dword ptr ds:[edx],esi
00709CB7     5E                   pop esi                            ; v2_3_5_1.006F90E7


007095E8     89B5 8C35AD0A        mov dword ptr ss:[ebp+0xAAD358C],e>; 保存当前esi指针位置
007095EE     60                   pushad                             ; 无用代码
007095EF     81C8 4979F419        or eax,0x19F47949
007095F5     66:81E2 EF0D         and dx,0xDEF
007095FA     61                   popad
007095FB     83F8 FF              cmp eax,-0x1                       ; 跟FFFFFFFF比较 看看是不是到末尾
007095FE     0F85 B5000000        jnz v2_3_5_1.007096B9


007096B9     C1C0 03              rol eax,0x3                                ; 第三个元素左移拿到的是一个偏移值
007096BC     F9                   stc
007096BD     0385 550EAD0A        add eax,dword ptr ss:[ebp+0xAAD0E55]       ; v2_3_5_1.00400000
007096C3     60                   pushad                                     ; 拿到偏移+基址
007096C4     60                   pushad                                     ; 处理NOP指令
第四个元素发现又把之前填充NOP的代码重新执行了一遍   看一下现在的偏移是00429EB5 而之前的是00429C2D  我们到这个429EB5看一下
发现是
00429EB0     8B56 1C              mov edx,dword ptr ds:[esi+0x1C]
00429EB3     51                   push ecx                                   ; winmm.midiStreamOut
00429EB4     52                   push edx
00429EB5     90                   nop
00429EB6     90                   nop
00429EB7     90                   nop
00429EB8     90                   nop
00429EB9     90                   nop
00429EBA     90                   nop
00429EBB     3BC7                 cmp eax,edi                                ; v2_3_5_1.00429C32

而且当前寄存器存放的API地址还是这个winmm.midiStreamOut既然他是同样的处理流程就可以猜测这个参数的作用就是把相同API的调用的地方再去处理一下。
我们去之前的4429C2D看一下是不是调用的相同的API
00429C2D     E8 BC087076          call winmm.midiStreamOut

结果发现是这个API 那我们就放着这个流程执行 看一下填充完成以后是不是同样的API

00429EB3     51                   push ecx                                   ; winmm.76B20633
00429EB4     52                   push edx
00429EB5     90                   nop
00429EB6     E8 33067076          call winmm.midiStreamOut
00429EBB     3BC7                 cmp eax,edi                                ; v2_3_5_1.00429EBB
结果发现是填充了相同的API,如果把一组[ESI]表的规定为三个有效参数那么多出来的就是去相同的调用的地方填充同一个参数。
接着就是到了这一组[esi]的结尾了
00709C91     AD                   lods dword ptr ds:[esi]                    ; 取[esi]表中元素 这时候取得是第四个元素
00709C92     0F85 09000000        jnz v2_3_5_1.00709CA1

同样取完以后清零
00709CAA     BE 3A0A8D4B          mov esi,0x4B8D0A3A
00709CAF     C702 3A0A8D4B        mov dword ptr ds:[edx],0x4B8D0A3A          ; 当前[esi]表清零
00709CB5     3132                 xor dword ptr ds:[edx],esi                 ; v2_3_5_1.006F90EB


当前取出来的是FFFFFFFF 意味着到了结束了 

007095E8     89B5 8C35AD0A        mov dword ptr ss:[ebp+0xAAD358C],esi       ; 保存当前esi指针位置
007095EE     60                   pushad                                     ; 无用代码
007095EF     81C8 4979F419        or eax,0x19F47949
007095F5     66:81E2 EF0D         and dx,0xDEF
007095FA     61                   popad
007095FB     83F8 FF              cmp eax,-0x1                               ; 跟FFFFFFFF比较 看看是不是到末尾
007095FE     0F85 B5000000        jnz v2_3_5_1.007096B9
00709604     60                   pushad
00709605     60                   pushad
00709606     66:81EB 8AAD         sub bx,0xAD8A
0070960B     B8 07DC1C28          mov eax,0x281CDC07
00709610     61                   popad
00709611     0F88 05000000        js v2_3_5_1.0070961C
00709617     66:81DB C08D         sbb bx,0x8DC0
0070961C     61                   popad
0070961D     813E DDDDDDDD        cmp dword ptr ds:[esi],0xDDDDDDDD          ; 比较当前的值是否是DDDD

如果取出来的数据是FFFFFFF  而且他的下一个是DDDDDDDD  那么就是当前这一组[esi]数据处理完成,单步走就会来到循环尾了

0070969C     89B5 8C35AD0A        mov dword ptr ss:[ebp+0xAAD358C],esi       ; 保存当前ESI地址
007096A2     FC                   cld
007096A3   ^ E9 7ACAFFFF          jmp v2_3_5_1.00706122                      ; 循环尾
     ------------------------------------------------------------------------------- 分割线-------------------------------------------------

00706122     C785 0439AD0A 000000>mov dword ptr ss:[ebp+0xAAD3904],0x0       ; 循环头
0070612C     C785 C438AD0A 000000>mov dword ptr ss:[ebp+0xAAD38C4],0x0
00706136     83BD BE1ACD0A 00     cmp dword ptr ss:[ebp+0xACD1ABE],0x0
0070613D     74 06                je short v2_3_5_1.00706145
0070613F     FF95 371EAD0A        call dword ptr ss:[ebp+0xAAD1E37]          ; v2_3_5_1.006D2F98
00706145     FF85 F116AD0A        inc dword ptr ss:[ebp+0xAAD16F1]
0070614B     0F8F 08000000        jg v2_3_5_1.00706159
00706151     0F85 02000000        jnz v2_3_5_1.00706159
00706157     60                   pushad
00706158     61                   popad
00706159     0F88 01000000        js v2_3_5_1.00706160
0070615F     F9                   stc
00706160     83BD F116AD0A 64     cmp dword ptr ss:[ebp+0xAAD16F1],0x64      ; 比较导入模块是否是大于0x64大于64进行校验



关于这个校验qqmcc大佬讲的很明白了,就不过多赘述了,接着往下看

0070634B     AD                   lods dword ptr ds:[esi]                    ; 取第一个元素当前的这一组数据中可用参数是三个
0070634C     F5                   cmc
0070634D     89B5 8C35AD0A        mov dword ptr ss:[ebp+0xAAD358C],esi       ; 保存当前[esi]指针位置
00706353     60                   pushad
00706354     8BF0                 mov esi,eax
00706356     66:81F2 0895         xor dx,0x9508
0070635B     61                   popad
0070635C     E9 08000000          jmp v2_3_5_1.00706369
00706361     26:9c                pushfd
00706363     9F                   lahf
00706364     DBBD B376F953        fstp tbyte ptr ss:[ebp+0x53F976B3]
0070636A     68 C1049676          push 0x769604C1
0070636F     5B                   pop ebx                                    ; mov ebx,0x769604C1
00706370     81F3 25489B1D        xor ebx,0x1D9B4825
00706376     81C3 3775006E        add ebx,0x6E007537
0070637C     81F3 1BC20DD9        xor ebx,0xD90DC21B                         ; 第一个元素置零
00706382     895E FC              mov dword ptr ds:[esi-0x4],ebx             ; mov dword ptr ds:[esi-0x4],0

00706398     3D EEEEEEEE          cmp eax,0xEEEEEEEE                         ; 判断是否是处理完一个[esi]表
0070639D     0F85 92000000        jnz v2_3_5_1.00706435


007064CD     899D EB76C30A        mov dword ptr ss:[ebp+0xAC376EB],ebx       ; 保存元素

接下来就是[esi]表中的第一个元素的使用,他的作用是在一个数组中找到对应的数据然后记录下表用来作为偏移莱寻找制定的API
007067CA     8B95 CC38AD0A        mov edx,dword ptr ss:[ebp+0xAAD38CC]       ; 2A40000出现一个基址
007067D0     60                   pushad
007067D1     80D7 00              adc bh,0x0
007067D4     80C5 80              add ch,0x80
007067D7     61                   popad
007067D8     3B02                 cmp eax,dword ptr ds:[edx]                 ; 出现一个数组了 用莱寻找偏移
007067DA     0F84 BA000000        je v2_3_5_1.0070689A
007067E0    |0F8B 01000000        jpo v2_3_5_1.007067E7
007067E6    |F9                   stc
007067E7    |55                   push ebp
007067E8    |57                   push edi                                   ; v2_3_5_1.00429EBB
007067E9    |BF 3E354E70          mov edi,0x704E353E
007067EE    |81C7 011C8544        add edi,0x44851C01
007067F4    |81CF B4070A6B        or edi,0x6B0A07B4
007067FA    |81EF BB57DBFF        sub edi,0xFFDB57BB
00706800    |89FD                 mov ebp,edi                                ; v2_3_5_1.00429EBB
00706802    |5F                   pop edi                                    ; 数组指针位置+4
00706803    |01EA                 add edx,ebp
00706805    |5D                   pop ebp

00706818     F8                   clc
00706819     52                   push edx
0070681A     BA 32643D47          mov edx,0x473D6432
0070681F     81C2 037DDE45        add edx,0x45DE7D03
00706825     81E2 1840E15C        and edx,0x5CE14018
0070682B     81F2 1140010C        xor edx,0xC014011
00706831     01D1                 add ecx,edx                                ; inc ecx
00706833     5A                   pop edx                                    ; 02A40004


0070683B     3B8D A87FC10A        cmp ecx,dword ptr ss:[ebp+0xAC17FA8]       ; 数组长度是D1

其实这一段真正有用的代码我提取一下就是下边这几句

mov edx,dword ptr ss:[ebp+0xAAD38CC]
add edx,0x4
inc ecx
cmp ecx,dword ptr ss:[ebp+0xAC17FA8] 

我们跑出这个循环在这下个断点
0070689A     898D 5037AD0A        mov dword ptr ss:[ebp+0xAAD3750],ecx       ; 将寻找到的偏移存放在一个局部变量

007068CE     C785 B31BCD0A 000000>mov dword ptr ss:[ebp+0xACD1BB3],0x0
007068D8     B9 01000000          mov ecx,0x1
007068DD     85C9                 test ecx,ecx
007068DF     74 51                je short v2_3_5_1.00706932                 ; 这个地方有个3F0000  数据窗口跟一下会发现是所有导入模块的基址
007068E1     8B8D 7527AD0A        mov ecx,dword ptr ss:[ebp+0xAAD2775]
007068E7     8B09                 mov ecx,dword ptr ds:[ecx]                 ; 开始比较基址
007068E9     3B8D 471AAD0A        cmp ecx,dword ptr ss:[ebp+0xAAD1A47]       ; user32.77D10000
007068EF     74 10                je short v2_3_5_1.00706901
007068F1     3B8D AB26AD0A        cmp ecx,dword ptr ss:[ebp+0xAAD26AB]       ; advapi32.77DA0000
007068F7     74 08                je short v2_3_5_1.00706901
007068F9     3B8D 2D17AD0A        cmp ecx,dword ptr ss:[ebp+0xAAD172D]       ; kernel32.7C800000
数据窗口内容:
003F0000  00 00 B1 76 00 00 A2 71 00 00 80 7C 00 00 D1 77  ..眝....€|..褀
003F0010  00 00 EF 77 00 00 F7 72 00 00 DA 77 00 00 59 7D  ..飛..鱮..趙..Y}
003F0020  00 00 99 76 00 00 0F 77 00 00 17 5D 00 00 32 76  ..檝..w..]..2v
007069D6     8B85 5037AD0A        mov eax,dword ptr ss:[ebp+0xAAD3750]       ; 用到了ecx存放的偏移
007069DC     FC                   cld
007069DD     D1E0                 shl eax,1
007069DF     0F89 09000000        jns v2_3_5_1.007069EE
007069E5     60                   pushad
007069E6     66:8BD8              mov bx,ax
007069E9     66:BF 6693           mov di,0x9366
007069ED     61                   popad
007069EE     0385 FC57C70A        add eax,dword ptr ss:[ebp+0xAC757FC]       ; 这里边存放的是对应模块的基址这个地方应该是定位的对应模块的导出表
007069F4     0F8B 1B000000        jpo v2_3_5_1.00706A15



00706A4A     31F0                 xor eax,esi                                ; winmm.76B11AD6
00706A4C     31C6                 xor esi,eax
00706A4E     31F0                 xor eax,esi                                ; xchg eax,esi
00706A50     E9 0A000000          jmp v2_3_5_1.00706A5F
00706A55     4A                   dec edx
00706A56     AC                   lods byte ptr ds:[esi]
00706A57     71 07                jno short v2_3_5_1.00706A60
00706A59     93                   xchg eax,ebx
00706A5A   ^ 75 CA                jnz short v2_3_5_1.00706A26
00706A5C     86D3                 xchg bl,dl
00706A5E     630F                 arpl word ptr ds:[edi],cx
00706A60     8311 00              adc dword ptr ds:[ecx],0x0
00706A63     0000                 add byte ptr ds:[eax],al
00706A65     0F8F 0B000000        jg v2_3_5_1.00706A76
00706A6B     E9 06000000          jmp v2_3_5_1.00706A76
00706A70     3e:be cca462de       mov esi,0xde62a4cc
00706A76     66:AD                lods word ptr ds:[esi]                     ; 拿到导出函数序号


00706A90     C1E0 02              shl eax,0x2
00706A93     60                   pushad
00706A94     80D2 C7              adc dl,0xC7
00706A97     B4 FE                mov ah,0xFE
00706A99     61                   popad
00706A9A     0385 49F7C70A        add eax,dword ptr ss:[ebp+0xAC7F749]       ; winmm.76B11384
00706AA0     FC                   cld
00706AA1     50                   push eax
00706AA2     81EC 04000000        sub esp,0x4
00706AA8     893424               mov dword ptr ss:[esp],esi                 ; winmm.76B11518
00706AAB     58                   pop eax                                    ; v2_3_5_1.006F90F3
00706AAC     5E                   pop esi                                    ; v2_3_5_1.006F90F3
00706AAD     0F8F 14000000        jg v2_3_5_1.00706AC7                       ; xchg eax,esi


00706AC7     AD                   lods dword ptr ds:[esi]                    ; 根据导出序号拿到了API得偏移


00706AED     81C1 8FD0C722        add ecx,0x22C7D08F
00706AF3     5F                   pop edi                                    ; v2_3_5_1.006F90F3
00706AF4     61                   popad
00706AF5     0F88 01000000        js v2_3_5_1.00706AFC
00706AFB     F8                   clc
00706AFC     05 C2237533          add eax,0x337523C2
00706B01     2D CB28C32D          sub eax,0x2DC328CB
00706B06     01C8                 add eax,ecx                                ; winmm.76B10000
00706B08     05 CB28C32D          add eax,0x2DC328CB
00706B0D     2D C2237533          sub eax,0x337523C2
00706B12     F9                   stc                                        ; 这一大段的意思是去现在装载的模块中根据导出序号找到偏移然后找到函数
00706B13     8138 E8000000        cmp dword ptr ds:[eax],0xE8                ; 比较开头是不是E8


00706C77     8138 6970686C        cmp dword ptr ds:[eax],0x6C687069          ; 比较的硬编码

往下会有这么几句指令我把它摘出来
00706DBC     8B9D 2D17AD0A        mov ebx,dword ptr ss:[ebp+0xAAD172D]       ; kernel32.7C800000
00706DDD     29CB                 sub ebx,ecx                                ; winmm.76B10000

这样的指令应该是检测模块位置是否填充正确 我对这个也不确定因为这些都不影响脱壳


00706E6C     8D9D 608ECD0A        lea ebx,dword ptr ss:[ebp+0xACD8E60]
00706E72     E9 08000000          jmp v2_3_5_1.00706E7F
00706E77     76 51                jbe short v2_3_5_1.00706ECA
00706E79     006F 00              add byte ptr ds:[edi],ch
00706E7C     D216                 rcl byte ptr ds:[esi],cl
00706E7E     46                   inc esi                                    ; v2_3_5_1.006F90F3
00706E7F     FFD3                 call ebx                                   ; 通过这个call 确定API的正确性
00706E81     60                   pushad                                     ; 它是通过判断函数头几个字节

00706EA1     61                   popad                                      ; 覆盖存放的上一个API地址
00706EA2     8985 C426AD0A        mov dword ptr ss:[ebp+0xAAD26C4],eax       ; winmm.midiOutPrepareHeader
这时候取得是第二个元素:
00709452     AD                   lods dword ptr ds:[esi]                    ; 取第二个元素

0070946C     893C24               mov dword ptr ss:[esp],edi
0070946F     BF 6D4D6663          mov edi,0x63664D6D
00709474     81E7 EE30706C        and edi,0x6C7030EE
0070947A     C1E7 08              shl edi,0x8
0070947D     81C7 C779DE03        add edi,0x3DE79C7
00709483     81F7 C7E5DE63        xor edi,0x63DEE5C7
00709489     897E FC              mov dword ptr ds:[esi-0x4],edi             ; 第二个元素清零
0070948C     5F                   pop edi                                    ; winmm.midiOutPrepareHeader



0070956B     51                   push ecx                                   ; winmm.midiOutPrepareHeader
0070956C     B9 9FF0C70D          mov ecx,0xDC7F09F
00709571     05 E22F547B          add eax,0x7B542FE2
00709576     01C8                 add eax,ecx                                ; winmm.midiOutPrepareHeader
00709578     2D E22F547B          sub eax,0x7B542FE2
0070957D     59                   pop ecx                                    ; 这一段执行完成就会拿到IAT的偏移
0070957E     0F8A 05000000        jpe v2_3_5_1.00709589
00709584     60                   pushad
00709585     F9                   stc
00709586     60                   pushad
00709587     61                   popad
00709588     61                   popad
00709589     0385 550EAD0A        add eax,dword ptr ss:[ebp+0xAAD0E55]       ; 拿到代码段中IAT的基址+偏移
0070958F     FC                   cld
00709590     8B8D C426AD0A        mov ecx,dword ptr ss:[ebp+0xAAD26C4]       ; winmm.midiOutPrepareHeader

007095BB     83EC 04              sub esp,0x4
007095BE     891424               mov dword ptr ss:[esp],edx                 ; v2_3_5_1.00487604
007095C1     BA 00000000          mov edx,0x0
007095C6     01C2                 add edx,eax                                ; v2_3_5_1.00487604
007095C8     890A                 mov dword ptr ds:[edx],ecx                 ; winmm.midiOutPrepareHeader
007095CA     5A                   pop edx                                    ; 第二个元素还是去IAT填充API这里的IAT 的基址是487600
到这里就跟文章头部呼应起来了,大体流程就是这些,这样一份Themida加密IAT得流程就分析完成了当我们拉到下边的找到最后一个EEEEEEEEDDDDDDD结构下一个内存访问断点一直单步到这个地方
00706420    /E9 BF380000          jmp v2_3_5_1.00709CE4                      ; 运行到这可以直接代码段下内存访问断点到达OEP
代码段内存访问断点以后shift+F9
到这
直接就到了OEP
00466C98     55                   push ebp
00466C99     8BEC                 mov ebp,esp
00466C9B     6A FF                push -0x1
00466C9D     68 283A4B00          push v2_3_5_1.004B3A28
00466CA2     68 749A4600          push v2_3_5_1.00469A74
00466CA7     64:A1 00000000       mov eax,dword ptr fs:[0]
00466CAD     50                   push eax
00466CAE     64:8925 00000000     mov dword ptr fs:[0],esp
00466CB5     83EC 58              sub esp,0x58
00466CB8     53                   push ebx                                   ; v2_3_5_1.00708D28
00466CB9     56                   push esi                                   ; v2_3_5_1.0070ACF3
00466CBA     57                   push edi

但是这个Sure大可能是没有加虚拟机选项之类的保护,也没有StolenCode所以脱壳还是比较轻松的
到这里手动拖也可以,脚本脱也行了就不赘述了。

最后我只放上Sure大的加壳程序,毕竟是从人家那里学的还是要尊重原创嘛。
因为还不是很会写脚本写出来烂乎乎的,还是用的Sure大的。
最后就是最近看这三个版本的THemida感觉对于TMD来说不去看Anti之类的东西核心技术好像就是这个[esi]表了,掌握了这个表,对于脱壳来说是事半功倍的。
新人贴,如有不对,望指正。


[招聘]欢迎市场人员加入看雪学院团队!

上传的附件:
打赏 + 2.00
打赏次数 1 金额 + 2.00
收起 
赞赏  Editor   +2.00 2019/03/26
最新回复 (20)
nevinhappy 1 2019-3-23 19:23
2
0
感谢分享,学习!!!
xie风腾 2019-3-23 20:01
3
0

新人就玩这么强的壳
tonydebug 2019-3-23 20:51
4
0
厉害了,膜拜会搞强壳的大牛
jgs 2019-3-24 08:49
5
0
收藏,学习,谢谢楼主分享
Editor 2019-3-24 09:22
6
0
厉害~感谢分享~
1lu29e 1 2019-3-24 12:36
7
0
nevinhappy 感谢分享,学习!!!
只要不会误导就好了
1lu29e 1 2019-3-24 12:37
8
0
xie风腾 [em_81] 新人就玩这么强的壳
我觉得其实真正难得地方在于你对它的恐惧……
1lu29e 1 2019-3-24 12:37
9
0
tonydebug 厉害了,膜拜会搞强壳的大牛
大牛啥啊 菜逼一个
xiaohang 3 2019-3-25 21:02
10
0
嗯,其实tmd的IAT处理这块已经好久没有变动了,之前论坛里面已经有不少的帖子讲关于这块的,现在的tmd,难度主要还是集中在了VM上边
xiaohang 3 2019-3-25 21:03
11
0
精华还是要给的,现在愿意玩pe脱壳的实在是不多啊
1lu29e 1 2019-3-25 22:48
12
0
xiaohang 精华还是要给的,现在愿意玩pe脱壳的实在是不多啊
嘿嘿嘿  终于等到精华了,研究研究VM争取甘特娘的~
挽梦雪舞 2019-3-26 06:16
13
1
ilyzqe 嘿嘿嘿 终于等到精华了,研究研究VM争取甘特娘的~
大冷门
1lu29e 1 2019-3-26 11:17
14
0
挽梦雪舞 [em_14]大冷门[em_85]
起这么早?小老弟
挽梦雪舞 2019-3-27 00:04
15
1
ilyzqe 起这么早?小老弟
不早了
邓dg 2019-3-27 02:28
16
0
牛逼
cxfzaysb 2019-3-27 06:55
17
0
学习了,感谢分享
最爱季节 2019-4-10 15:51
18
0
太难脱了,兼容性还不好
西北望西 2019-4-14 22:14
19
0
大牛,你能看下这个程序吗  到找ab特征 这里就进行不下去了~~~~~~
上传的附件:
pushmop 2019-4-30 14:38
20
0
难得有TMD的文章了,支持一下。
pushmop 2019-4-30 14:39
21
0
写的很不错
游客
登录 | 注册 方可回帖
返回