脱壳破解

脱壳破解【脱壳破解】在一些电脑软体里有一段专门负责保护软体不被非法修改或反编译的程式 。它们一般都是先于程式运行拿到控制权,然后完成它们保护软体的任务 。就像动植物的壳一般都是在身体外面一样理所当然(但后来也出现了所谓的“壳中带籽”的壳) 。由于这段程式和自然界的壳在功能上有很多相同的地方,基于命名的规则,大家就把这样的程式称为“壳”了 。就像电脑病毒和自然界的病毒一样,其实都是命名上的方法罢了 。从功能上抽象,软体的壳和自然界中的壳相差无几 。无非是保护、隐蔽壳内的东西 。而从技术的角度出发,壳是一段执行于原始程式前的代码 。原始程式的代码在加壳的过程中可能被压缩、加密…… 。当加壳后的档案执行时,壳这段代码先于原始程式运行,他把压缩、加密后的代码还原成原始程式代码,然后再把执行权交还给原始代码 。软体的壳分为加密壳、压缩壳、伪装壳、多层壳等类,目的都是为了隐藏程式真正的OEP(入口点,防止被破解) 。关于“壳”以及相关软体的发展历史请参阅吴先生的《一切从“壳”开始》 。
基本介绍中文名:脱壳破解
外文名:Shelling crack
解决方法:忽略所有异常,隐藏好OD
变化:多种组合
近日对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,将空数据改为如下代码:00401000 60 pushad00401001 9C pushfd00401002 68 A0FD1200 push xxxx (注:此处的 xxxx为断下后mutex name前的数值 。) 00401007 33C0 xor eax,eax00401009 50 push eax0040100A 50 push eax0040100B E8 E694A677 call KERNEL32.CreateMutexA00401010 9D popfd00401011 61 popad00401012 - E9 8F9FA777 jmp 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返回,修改前两个位元组为加壳程式载入时的前两个位元组 。下断点bp GetModuleHandleA,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,将空数据改为如下代码:00401000 60 pushad00401001 9C pushfd00401002 68 A0FD1200 push xxxx (注:此处的 xxxx为断下后name前的数值 。) 00401007 33C0 xor eax,eax00401009 50 push eax0040100A 50 push eax0040100B E8 E694A677 call KERNEL32.CreateMutexA00401010 9D popfd00401011 61 popad00401012 - E9 8F9FA777 jmp 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)用Imprec1.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、用Imprec修复,无效指针CUT 。6、如果有类似自校验的,则用AMINLINE工具中的nanomites选项修复 。