ACProtect Professional 1.3C 主程序脱壳(3)(图)

运行程序,crashedL。直接用修复完stolen code的dumped_.exe看看。从EP的第1个call进去就有问题。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图1500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图2500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

在OllyDbg中可以看到:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图3500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

有部分IAT在壳中。这部分代码前面是跟到了的(在第6次int 3以后),原来认为这只是loader自己需要的API。实际上正常的程序代码也使用了这个IAT。

如果用ImportRec把这部分也取出来,属于不同dll的api混排了,ImportRec不能处理。

这些地址是在736643处理的。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图4500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

而且有一个不能识别(这个实际上是Hooked MessageBoxA)。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图5500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

估计这是加壳时做的手脚。当发现主程序使用了与壳代码同样的API时,修改了对应的调用代码,使其调用到壳中的IAT。这样可以加强与壳的联系。反过来看,这里大部分API(除了只有壳使用的),在前面避开IAT加密处理后,都已经import了。

在ACProtect_Fixed中已经有解好的api名。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图6500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

紧临的函数指针:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图7500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

注意函数名及指针与7339A9附近的代码并不完全对应。有的函数名或指针在别处。

可以在程序入口自己调用LoadLibrary,GetProcAddress进行处理,填入相应的地址。或者把Loader的代码搬过来。也可以修改主程序的代码,使其调用前面得到的干净的IAT而不是壳中的IAT(这样要处理的地方太多,很麻烦)。

注意ACProtected_Fixed中,import了几个基本的API:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图8500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

在加载API时壳代码会使用这些函数。这几个地址直接填入007300D8开始的IAT中了。修改dumped_.exe的EP,从壳代码开始(可以看到dump出来的代码,这部分已经解开了),

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图9500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图10500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

注意Loader代码中用的几个API(GetModuleHandleA,GetProcAddress)改为使用避开IAT加密后得到的主程序的IAT。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图11500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

原来在壳代码import的4个API,从主程序的IAT直接取。结束处理后跳回前面的OEP 409DE4。用pushad,pushad保存寄存器值。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图12500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

注意最后一项7301CC实际是MessageBoxA,被ACProtect用做SDK的接口。 不要填入MessageBox的真正地址。

下面的73013C在跟原程序的过程中始终为0,可能是注册版才有?

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图13500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

处理完后,位于壳空间的IAT已经赋上了正确值。

7. 修复Replaced code (1)

用前面的OllyScript脚本,停下后对Code section设内存访问断点。忽略所有异常。断下后,在抽取代码的共同入口722416设断,运行。第1次调用在004047E5。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图14500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

里面还有SMC,解出后贴到ACProtect_Fixed中对照跟踪。这部分的处理与低版本基本相同。

1) 查返回地址表

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图15500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

7225CC后ebx指向返回地址表,里面是RVA:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图16500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

上一页12 3 下一页 阅读全文

找到匹配地址后,ecx等于表项的offset,第1项为0x2A。

2) 查opcode表

用1中的到的offset查opcode数据表(007262ED):

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图17500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

密文opcode表:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图18500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

counter表(记录每个地址的调用次数,超出0x20次将使用新的地址解码):

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图19500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

第1次解出的变形码:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图20500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

3) 调整stack以便正确调用变形码及返回

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图21500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

4) 破坏解出的代码,ret到变形码

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图22500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

5) 执行变形码,返回到原程序

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图23500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

6) Patch

先把解出的代码binary copy到dumped_.exe(直接copy 722416 – 7226B0的代码即可)。

关闭722579的解码(解出7225C1 – 7226B0):

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图24500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

关闭7226A8处对前面代码的破坏:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图25500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

patch 72260C: jnz->jmp,无论执行多少次都使用同一解码地址

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图26500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

copy正确的ImageBase值,这里为0,改72FC1F为400000

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图27500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图28500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

copy 正确的10 bytes key(第1 byte为0)

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图29500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

执行,仍然crashedL。

8. 修复Replaced code (2)

还有replaced code,在这里出异常:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图30500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

->

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图31500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

将解出的代码贴到ACProtect_Fixed.exe。可以看到,这些实际上是变形的call代码。第1次执行到这里,在buffer中解出的变形码为:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图32500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图33500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

XOR的结果:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图34500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

目前的dumped_.exe,地址72ED83的值为0(这些值是loader写入的)。

406DF8的变形码原来是call GetKeyboardType。原程序的call API 全部被抽掉了。壳代码的动作与前面相似,用返回地址查表,获取相应的指针,生成jmp dword ptr ds:[xxxxxxxx]指令,该地址则指向类似72124C的变形码,调用正确的API。

变形call API的返回RVA地址表:

开始:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图35500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

结束:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图36500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

寻址变形码数组下标表(每项1字节),用于查变形码指针数组:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图37500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

变形码地址表(指向变形码的指针):

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图38500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

上一页 1 23 下一页 阅读全文

开始打算写个inline-patch:

用同样的查表动作,把对应的变形码copy出来,得到对应的API地址,与跳过加密而得到的干净IAT对比。查到匹配值后,修改对应的opcode,使其直接call到IAT中的地址。

用OllyScript脚本跳过IAT加密,得不到变形码(此时从变形码地址表中得到的就是API的真正地址,有46项指针无效,为0xCCCCCCCC)。

另一个问题却是难以解决的,replaced code只有5字节:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图39500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

这里的call是0xE8,调用壳中的绝对地址。InlinePatch写到一定程度才发现,如果要修复代码,使其调用到IAT,需要相对地址调用6 bytesL。真是个低级错误。

现在patch的结果:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图40500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

真正需要的是:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图41500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

这样只有保留变形码。把壳中对应的代码copy过来,OEP前生成正确的变形码。而且脱壳后的程序不能直接看到API名字,很不舒服。

只好把壳的相应代码搬过来。再次修改dumped_.exe入口处代码,在把loader空间中的IAT填好后,跳到处理变形码的位置:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图42500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

loader在处理IAT时需要调用几个API,及判断dll的映射地址、API地址等,先保存需要的数据(我们有干净的IATJ):

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图43500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

由于在前面避开了IAT加密,生成变形码需要的数据已经被正确的API地址覆盖了。用LoadPE把ACProtect的idata section存到文件,然后加到dumped_.exe。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图44500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

把这个section的密文数据copy到dumped_.exe的idata section,覆盖掉干净的IAT,我们已经不需要它了。现在只要伪造好现场J。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图45500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

往下执行loader的IAT处理代码,做几处小小的修改,使其使用刚才保存的API地址等数据。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图46500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

IAT及变形码处理结束后回到OEP。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图47500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

执行。又挂了L。这次是内存访问异常。跟一跟可以知道,是在Hooked MessageBoxA中。这里面的代码还没有仔细看,有几个switch-case分枝。第1次eax为5。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图48500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

进去后有几个查表动作:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图49500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

用调用Hooked MessageBoxA的返回地址查表。这张表在721F25处,dumped_.exe中有,共21项。

注意查表时不是找相等值,而是找大于返回地址值且最接近的值。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图50500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

继续->

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图51500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

这里出现了另外2张表。7220B5的表中数据为size。Dumped_.exe中有:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图52500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

问题出在第3张表:

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图53500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

dump出的数据为0。这段代码要把主程序中的一段数据copy到这张表中数据所指的地址。在loader中执行时,这里填入了指向动态分配内存的指针。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图54500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

显然不能直接复制这些值。有个简单的办法可以骗过loader。从那张size表中可以看到,最大的数据FD5D。用LoadPE再次增加1个section,size为FFFF即可。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图55500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

修改dumped_.exe,设置21项数据,使其全部指向该地址。

ACProtect Professional 1.3C 主程序脱壳(3)(图)插图56500)this.width=500\” title=\”点击这里用新窗口浏览图片\” />

在W2K下运行,显示窗口,但不能响应输入。在WinXP下运行什么也不显示。

下面该与主程序交手了,这需要把板凳坐穿的耐心L。

上一页 1 2 3下一页阅读全文

发表评论

邮箱地址不会被公开。 必填项已用*标注