幽雅的心 发表于 2010-12-3 10:43:13

Armadillo SMC 破解教程

以《硕思闪客精灵 企业版》为例子。PEiD载入,看区段,显然是Armadillo,现在用Armadillo Find Protector看一下有啥保护:
<- 02-12-2010 18:17:59 - ->

G:\Program Files\SourceTec\SWFDecompiler_2.exe

Protected Armadillo

<-Find Protect

Protection system (Professional)

<Protection Options>

Standard protection or Minimum protection

Import Table Elimination

Strategic Code Splicing

<Backup Key Options>

Variable Backup Keys

<Compression Options>

Minimal/Fastest Compression

<Other Options>

Disable Monitoring Thread

<-Find Version

Version 7.00 26-10-2009

<- Elapsed Time 00h 00m 00s 453ms ->
复制代码

似乎是单进程的,那就好办了。果断SMC之。
   

我们先找到要爆破的地方,这个地方是lkou版主告诉我的,我自己没调试出来(!-_-)。在程序运行起来之后,需要Patch几个地址:

    ->0x37

    ->0x179E9

    ->0xDE89000
复制代码
试一试,在入口点的时候patch掉这几处的代码果然可以变成了正版。lkou版主说他用了不到十分钟就搞掉了……我硬是没调出来。
   

下面有必要知道一些Armadillo的特点,Armadillo的壳主要是在一个ArmAccess.dll里边,外壳加载的时候首先调用VirtualAlloc分配一段内存,然后模拟PE加载器把DLL加载进去,然后把流程转移到DLL里,DLL完成主要的流程。DLL大概会做一点事情就是,首先是进行文件校验,然后处理IAT,最后解压代码啥的啥的。
SMC的流程是这样的:在DLL加载完毕后劫持流程,因为我们修改了文件,所以要绕过文件校验。之后是在壳解压原始代码之后进行Patch,相当于内存补丁。
所以,我们需要在三个地方插入代码:加载DLL完毕的时候,壳自校验的时候,原始代码解压完毕的时候。
   
首先说一下如何找DLL加载完毕的时机,OD载入程序,搜索字符串“SetFunctionAddresses”,会找到这里:

00BC40EB   |> \6A 00            push    0x0

00BC40ED   |.6A 01            push    0x1

00BC40EF   |.A1 4CC3C200      mov   eax, dword ptr                ;这里就保存着dll的基址

00BC40F4   |.50               push    eax

00BC40F5   |.FF15 50C3C200    call    dword ptr                   ;call DLL 入口

00BC40FB   |.85C0             test    eax, eax

00BC40FD   |.75 11            jnz   short 00BC4110
复制代码

既然在00BC40EF从0xC2C34C处取出dll的基址,就一定有另外一个地方把dll的基址写入0xC2C34C。所以我们搜索常量,可以到这里:
00BC4D3A    .A3 4CC3C200      mov   dword ptr , eax

00BC4D3F       8B45 08          mov   eax, dword ptr

00BC4D42       8BE5             mov   esp, ebp

00BC4D44    .5D               pop   ebp

00BC4D45    .C3               retn
复制代码

很显然,这个时候把DLL的代码解压完毕,并把基址保存到了0xC2C34C里。我一般选择在00BC4D3F处SMC,这样可以更简单,而且不用考虑重定位。SMC代码里面eax就是基址了。记下00BC4D3F,作为第一处Patch的地址。
   
下面我们来找原始的文件校验值,bp OutputDebugStringA,运行两次之后返回,代码是这样的:

0287D82C   FF15 4C928B02      call    dword ptr                    ; kernel32.OutputDebugStringA

0287D832   C705 6C4A8D02 A4F7>mov   dword ptr , 0x28BF7A4

0287D83C   8B0D 1C938D02      mov   ecx, dword ptr             ; SWFDecom.00C1C4E0

0287D842   8B15 1C938D02      mov   edx, dword ptr             ; SWFDecom.00C1C4E0

0287D848   A1 1C938D02      mov   eax, dword ptr

0287D84D   8B40 78            mov   eax, dword ptr

0287D850   3342 58            xor   eax, dword ptr

0287D853   3341 2C            xor   eax, dword ptr

0287D856   3345 F0            xor   eax, dword ptr                ; ***********
复制代码

注意0287D856,输入dd ebp-0x10,看数据窗口:
0012F30813388778

0012F30C48963C67

0012F310F76562B1

0012F31410181326

0012F31800000000

0012F31C720DAEB2
复制代码

这五个值就是原始文件的校验值,只要我们在这里恢复文件校验,就可以任意的修改文件了。
   
接下来是找一找代码解压的时机,这里是跟他们学的,劫持VirtualProtect然后判断对应地址的数据是不是0就可以了。大家看代码就好了。
   
下面开始SMC。先让00BC4D3F处的代码跳到我们的SMC代码:

00BC4D3F   - E9 BC620400      jmp   00C0B000                              ;跳到00C0B000
复制代码

在00C0B000处补上代码:
00C0B000   60                  pushad                                          ; 保存寄存器

00C0B001   54                  push    esp                                     ; 分配一个栈空间

00C0B002   54                  push    esp                                     ; 修改内存保护

00C0B003   6A 40               push    0x40                                    ; 可读可写可执行

00C0B005   68 00A00F00         push    0xFA000                                 ; buffer的大小

00C0B00A   8B4424 2C         mov   eax, dword ptr                ; 取出dll基址

00C0B00E   50                  push    eax                                     ; 修改dll的属性

00C0B00F   FF15 6CB0C100       call    dword ptr [<&KERNEL32.VirtualProtect>]; kernel32.VirtualProtect

00C0B015   58                  pop   eax

00C0B016   61                  popad                                           ; 堆栈平衡

00C0B017   C780 4C920B00 32B0C>mov   dword ptr , 00C0B032       ; Hook OutputDebugStringA

00C0B021   C780 54910B00 64B0C>mov   dword ptr , 00C0B064       ; Hook VirtualProtect

00C0B02B   8B45 08             mov   eax, dword ptr                 ; 恢复原来的代码

00C0B02E   8BE5                mov   esp, ebp

00C0B030   5D                  pop   ebp

00C0B031   C3                  retn

00C0B032   8B0424            mov   eax, dword ptr                   ; 调用OutputDebugStringA流程会到这里,首先取出返回地址

00C0B035   8178 1E 33425833    cmp   dword ptr , 0x33584233      ; 然后判断是不是到校验的地方

00C0B03C   75 23               jnz   short 00C0B061

00C0B03E   C745 F0 B2AE0D72    mov   dword ptr , 0x720DAEB2      ; 如果是,就恢复校验值

00C0B045   C745 E8 26131810    mov   dword ptr , 0x10181326

00C0B04C   C745 E4 B16265F7    mov   dword ptr , 0xF76562B1

00C0B053   C745 E0 673C9648    mov   dword ptr , 0x48963C67

00C0B05A   C745 DC 78873813    mov   dword ptr , 0x13388778

00C0B061   C2 0400             retn    0x4                                     ; OutputDebugStringA只是一个反调试,返回就好

00C0B064   C74424 0C 40000000mov   dword ptr , 0x40               ; 这里是Hook VirtualProtect,我们修改属性为可读可写可执行。

00C0B06C   803D E3684400 00    cmp   byte ptr , 0x0                ; 判断是否解压完毕

00C0B073   74 1B               je      short <jmp.&KERNEL32.VirtualProtect>

00C0B075   C605 E4684400 37    mov   byte ptr , 0x37               ; 开始补代码

00C0B07C   C705 38674400 E9790>mov   dword ptr , 0x179E9

00C0B086   C705 3C674400 0090E>mov   dword ptr , 0xDE89000

00C0B090   - FF25 6CB0C100       jmp   dword ptr [<&KERNEL32.VirtualProtect>]; kernel32.VirtualProtect,继续执行。
复制代码

其实原来的SMC代码比较麻烦,昨天晚上洗澡的时候突然觉悟了,其实可以写的更简单的。
   
谢谢观赏。

转自 CjwNull

wkxq 发表于 2010-12-3 12:53:56

高手就是不一样, 我看完了还没有明白

葉子 发表于 2011-1-20 18:41:50

学习一下

gadong 发表于 2014-2-10 09:53:30

学习了,感谢。

玩物 发表于 2014-6-3 20:29:53

支持飘云阁!
页: [1]
查看完整版本: Armadillo SMC 破解教程