[摘要]近日对Armadillo壳很感兴趣, 缘于它的多种组合的变化, 但仔细看来, 其保护的解决方法又有相对固定。 方法无外乎那么几种脱壳方法(当然排除有key和cc), 本人在本论 坛已对标准壳... 近日对Armadillo壳很感兴趣, 缘于它的多种组合的变化, 但仔细看来, 其保护的解决方法又有相对固定。 方法无外乎那么几种脱壳方法(当然排除有key和cc), 本人在本论 坛已对标准壳的脱壳方法发贴, 但后来有所更新, 干脆总结在一块吧, 以方便大家。 大家可以复制下来, 放在手边, 脱壳时按步骤来。 我还是 一小鸟, 同大家一样在逐渐成长中, 有不对的地方和不成熟的地方, 望大家批评指正, 共同进步。 一、基本知识: 该壳有如下保护: (1)Debug-Blocker(阻止调试器)--解决方法就是忽略所有异常, 隐藏好OD, 如果加载时, 老出错, 就多换几个OD试试。 (2)CopyMem-II(双进程保护)---解决方法是:用手动或者脚本使双变单。 (3) Enable Import Table Elimination(IAT保护) –解决方法是用工具ArmaDetach再次载入加壳程序, 记下子进程ID, 用另一OD载入, 利用断 点GetModuleHandleA, 找到Magic Jump, 修改Magic Jump, 得到正确的IAT。 (4)Enable Strategic Code Splicing(远地址跳) , 解决方法就是用Arminline工具。 (5) Enable Nanomites Processing(简称CC), 就是把一些retn代码变成CC(INT型), 解决方法:用Arminline工具或Enjoy工具。 (6)Enable Memory-Patching Protections(内存保护) 二、脱此类壳常用的断点: 1、WaitForDebugEvent(用于寻找非标准OEP和做补丁用) 2、WriteProcessMemory(用于寻找非标准OEP) 3、DebugActiveProcess(找子程) 4、OpenMutexA(双进程转单进程) 5、GetSystemTime(补丁KEY) 6、VirtualProtect(用于5.x) 7、CreateFileMappingA(用于5.x) 8、GetModuleHandleA/LoadLibraryA (用于找Magic Jump) 9、CreateThread(寻找OEP) 三、种类及脱壳方法 说明:对于此壳一般要隐藏OD。 如果按以下方法下断OD断不下来, 出错, 就多换几个OD试试, 在我脱壳中, 就有个情况, 下断点后, 老断不下 来, 多换了几个OD就成功了。 (一)单线程标准方式 具体方法:2次断点法加修改Magic Jump。 1、找Magic Jump 方法有二: 方法一、下断点Bp GetModuleHandleA/he GetModuleHandleA/bp GetModuleHandleA+5/he GetModuleHandleA+5, 按shift+f9运行, 当经过一个 call缓冲有点大时, 一般是在堆栈窗口出现ASCII "kernel32.dll"和ASCII "VirtualFree“后, 再运行一次, 出现"kernel32.dll", 就是返回 时机, 取消断点, 按alt+f9执行到返回。 方法二、也可以下bp LoadLibraryA断点, 当在堆栈窗口出现MSVBVM60.Dll函数时, 返回时机, 在kernel32.LoadLibraryA下面有一个跳转, 一 般情况下, 这个跳转比较大的话, 就改为jmp, 而跳转比较小的话, 就改nop)。 [注:下此断点的目的是找到Magic Jump, 修改Magic Jump目的 是避开的IAT的加密。 ] 2、找OEP 下断点bp GetCurrentThreadId/bp CreateThread, shift+f9运行, 中断后, 取消断点, Alt+F9返回, 单步执行, 看到一个call edi之类的。 F7 进入, 即到oep。 OD不要关!打开import--选择进程--OEP输入va--自动搜索IAT--获取输入表--显示无效函数--CUT! (二) 双线程的标准壳 总体步骤:1、要双变单;2、处理IAT, 修改Magic Jump;3、寻找OEP;4、修复 1、双变单, 方法有三。 方法一:PATCH代码法 下断bp OpenMutexA, 断下后, ctrl+g到00401000, 将空数据改为如下代码: 0040100060 pushad 004010019C pushfd 00401002 68 A0FD1200 push xxxx(注:此处的xxxx为断下后mutex name前的数值。 ) 0040100733C0 xor eax,eax 0040100950 push eax 0040100A50 push eax 0040100BE8 E694A677call KERNEL32.CreateMutexA 004010109D popfd 0040101161 popad 00401012- E9 8F9FA777jmp KERNEL32.OpenMutexA 点右键选择重建eip,f9运行, 断下后,取消断点, ctrl+g到00401000, 恢复修改。 方法二, 下断点:bp OpenMutexA, SHIFT+F9, 断下后, ALT+F9返回, 返回后, 将返回代码下面的第一个跳转改为相反跳转, 再次SHIFT+F9, 断下后, ALT+F9返回, 再次将返回代码下面的第一个跳转改为相反跳转。 然后再一次SHIFT+F9,取消断点, 至此,同样,双进程转单进程完毕! 方法三、除了用双变单的脚本外, 还可以用一个工具ARMADETACH, 将带壳的程序拖入, 记下子进程的ID。 2、处理IAT, 修改Magic Jump。 用OD附加该子进程, 加载后, ALT+F9返回, 修改前两个字节为加壳程序载入时的前两个字节。 下断点bpGetModuleHandleA, Shift+F9运行, 一般是在堆栈窗口出现ASCII "kernel32.dll"和ASCII "VirtualFree“后, 再运行一次, 出现 "kernel32.dll", 就是返回时机, 中断后alt+f9返回,在KERNEL32.LoadLibraryA下面找到Magic Jump!修改为jmp。 再下断点bp GetCurrentThreadId/bp CreateThread(或往下拉找到两个salc, 在其上面的jmp上下断, Shift+F9, 断下!如果文件有校验, 则要撤消Magic Jump处的修改!打开内存镜像, 在00401000段下断。 运行, 中断后, 删除断点, alt+f9返回), F8单步走, 到第一个CALL ECX之类的东西时, F7进入。 到oep。 注:(对于有些OD有一个字符串溢出漏洞, 尽量用一些修正些错误的OD, 有些程序需要处理Anti, 方法如下:下断点he OutputDebugStringA 断下后, 选中%s%之类的字符, 在数据窗口跟随, 点右键->二进制->使用00填充, 中断2次!都如上修改, 删除此断点!) 3、修复。 (三)CopyMem-ll +Debug-Blocke保护方式 1、先找OEP, 两个断点。 (1)断点bp WaitForDebugEvent,运行, 中断后看堆栈, 在一行有“pDebugEvent”字样的那一行右键点击“数据窗口 跟随”, 取消断点。 (2)bp WriteProcessMemory,运行, 中断后, 在数据窗口(要地址显示)发现oep。 2、patch代码, 解码。 方法:重新载入, bp WaitForDebugEvent,运行, 中断, 取消断点, alt+f9返回, CTRL+F搜索命令:or eax, 0FFFFFFF8 , 找到后, 先往上看, 可以看到两个CMP, 一个是“cmp dword ptr ss:[XXXX],0”在这里下硬件执行断点, Shift+F9运行, 中断后取消断点。 这时看信息窗口:SS[XXXXX]=00000000, 如果这个值不为0的话, 需要将其清0, 如果为0就不用了。 第二个CMP, cmp ecx,dword ptr ds:[XXXX] , 下面开始解码。 在这里要记下几个地址:(1)cmp dword ptr ss:[XXXX],0前的地址和[]内的值。 (2)第二个CMP中[]中的值。 接着or eax , 0FFFFFFF8处往下, 可以找到一处为and eax, 0FF的代码, 从这里开始Patch, 代码如下: inc dword ptr ds:[] //第一个CMP内的值 mov dword ptr ds:[XXXX+4],1//XXXX为第二个CMP[]内的值 jmp XXXX//第一个CMP前的地址 修改好后, 去掉所有断点, 向下找到第一个CMP下面的跳转所跳到的地址, 来到这个地址, 下硬件执行断点, Shift+F9运行, 此时代码解压完毕 , 可以脱壳。 3、脱壳。 运行LordPE,将子进程dump出来, 这里的子进程就是LordPE第2个进程(有2个同名进程)。 Dump后用LordPE修改入口点为在第一步中查 到的OEP。 4、修复输入表、IAT的寻找 脱壳后不要急着去修复输入表, 得先把RVA数据获取, 用OD载入Dump出来的程序, 右键搜索二进制字符串, 输入FF25, 找到一个函数, 在数据窗 口跟随, 在数据窗口向上找到全是0的地方, 记下地址, 再向下找到全是0的地方, 记下地址。 5、加载子程序。 (1)找子程序pid的方法有二: 方法一:用OD载入原程序(脱壳前的程序), 下断点:bp DebugActiveProcess, 中断后看堆栈, 记下Processid后面的值(这个值不是每次都 相同的)。 OD不要关。 第二种方法就是用工具ArmaDetach, 将加壳程序拖入。 记下子程序的pid和前两个字节。 (2)另开一个OD, 附加Processid后面的值进程或用工具ArmaDetach所记下的进程id, 附加后, ALT+F9返回程序, 将前两个字节改为原程序载 入时的前两个字节。 6、下面的做法就和标准壳的一样了, 在附加的OD中: 双变单:方法有二。 其一:patch法。 其二修改跳转法。 方法一:下断点BP OpenMutexA(双变单), F9运行, 断下后, ctrl+g到00401000, 将空数据改为如下代码: 0040100060 pushad 004010019C pushfd 00401002 68 A0FD1200 push xxxx(注:此处的xxxx为断下后name前的数值。 ) 0040100733C0 xor eax,eax 0040100950 push eax 0040100A50 push eax 0040100BE8 E694A677call KERNEL32.CreateMutexA 004010109D popfd 0040101161 popad 00401012- E9 8F9FA777jmp KERNEL32.OpenMutexA 点右键选择重建eip,f9运行, 断下后,取消断点, ctrl+g到00401000, 恢复修改。 方法二:下断点BP OpenMutexA, SHIFT+F9运行, 断下后, ALT+F9返回, 返回后, 将返回代码下面的第一个跳转改为相反跳转, 再次SHIFT+F9 , 断下后, ALT+F9返回, 再次将返回代码下面的第一个跳转改为相反跳转。 然后再一次SHIFT+F9,取消断点, 至此,同样,双进程转单进程完毕! 此法相对简单, 另外适用于00401000空数据不能修改的程序。 (2)修改Magic Jump 。 下断BP GetModuleHandleA+5, 运行, 一般是在堆栈窗口出现ASCII "kernel32.dll"和ASCII "VirtualFree后, 再运行一次, 就是返回时机, 中 断后alt+f9返回,在KERNEL32.LoadLibraryA下面找到Magic Jump!修改为jmp。 清除所有断点, 再直接按F9运行, 出现暂停。 这时大功告成。 (3)用Imdivc1.6f选择进程附加的那个进程, 填入OEP地址, 填第4步所记下的RAV, SIZE=1000, 不要按自动搜索IAT, 直接按获取输入表, 再 按显示无效地址, 剪掉修复抓取文件就OK了。 (四)全保护脱壳脱壳方法 1、双变单可以用以下方法, 也可以用脚本, 目的是双变单。 记下程序加载时的前两个字节。 运行脚本后, 记下OEP的前两个字节, OEP地址和子 进程ID。 2、用OD附加子进程, 加载后, ALT+F9返回, 修改前两个字节为脚本记载的OEP的前两个字节。 3、处理IATL输入表 方法:(1)用工具ARMADETACH, 将带壳的程序拖入, 记下子进程的ID。 (2)另开一OD, 附加该子进程, 加载后, ALT+F9返回, 修改前两个字 节为加壳程序载入时的前两个字节。 (3)修改Magic Jump , CTRL+G, 输入GetModuleHandleA, 在其下面的第一个跳转下硬件执行断点, Shift+F9运行, 一般是在堆栈窗口出现ASCII "kernel32.dll"和ASCII "VirtualFree后, 再运行一次, 就是返回时机, 中断后alt+f9返回,在 KERNEL32.LoadLibraryA下面找到Magic Jump!修改为jmp。 往下拉找到两个salc, 在其上面的jmp上下断, Shift+F9, 断下!撤消Magic Jump处 的修改!CTRL+G, 输入GetCurrentThreadId/ CreateThread, 下断, 运行, 中断后, 删除断点, alt+f9返回, F8单步走, 到第一个CALL ECX之 类的东西时, F7进入。 (此时的OEP是伪OEP, 但此时的IAT是正确的。 先开的OEP是对的, 但IAT是错误的)。 (4)打开先前的OD, CTRL+B, 搜 索FF25, 在数据窗口跟随, 找到函数的起始位置, 选定1-3个, 二进制复制, 打开后面所开的OD, 打开内存镜像, 在此界面中点一下, 二进制搜 索, 将刚才复制的粘贴, 找到后, 在转存窗口, 找到函数的起始地址, 选定到末尾, 将选定的函数复制到先前开的OD的数据窗口, 要对整齐( 起点要一样), 这时, 后开的OD的任务完成(目的就是将未加密的IAT找到)。 4、用AMINLINE工具修复, 选择第一个OD所用的子进程, 在Code Splicing中开始Code的地址自动给填好了, 但长度需要设置一下, 大一些, 20000左右就可以了, 修复。 在IAT的长度要根据实际情况, 一般选1000即可, 依次进行修复, 修复后, 在OD中修复的地方都变成红色。 5、用Imdivc修复, 无效指针CUT。 6、如果有类似自校验的, 则用AMINLINE工具中的nanomites选项修复。
上面是电脑上网安全的一些基础常识,学习了安全知识,几乎可以让你免费电脑中毒的烦扰。
|