CrackMe调试及算法分析
2016-02-13刘键林
刘键林
(天津现代职业技术学院,天津 300350)
CrackMe调试及算法分析
刘键林
(天津现代职业技术学院,天津300350)
摘要:目前网络上最便利于交流学习的CrackMe,已经被程序人员与Cracker爱好者广泛地流传于相互学习交流的平台上,便利大家共同研究、分析、切磋程序人员的最新思路,以及程序人员之间要准备解决与需要攻克的问题。文本主要论述与分析CrackMe的调试及算法。
关键词:CrackMe分析;脱壳分析;算法分析
一、CrackMe分析
首先分析一下CrackMe,主要条件是需要详细观察其运行条件,是否有注册窗口,是否有人机对话框提示,其次、是否加壳、加何种壳,如何脱壳。何种语言编写等等,这些都是详细分析之前需要掌握的信息。我们双击主程序使其运行,随即出现运行后的主界面。主界面要求在注册框输入注册码。任意输入了一些数字之后点击注册按钮,随即惊人的一幕发生了Windows操作系统被强制注销了。
1.这种情况首先是CrackMe必须获取权限,然后对输入的任意数字“测试码”进行对比,正确即刻弹出现温和的人机互动对话框。反之此CrackMe将在不做任何提示的情况下一律按逆向分析者处理,继而使用获取到的权限调用Windows系统下的ExitWindowsEx函数,此函数为重启或注销操作系统。这种函数调用仅此CrackMe如此使用而已,若为恶意软件使用麻烦肯定是有的。
2.待计算机操作系统重新正常启动之后,注册框内我们什么也没有输入而再次点击注册按钮时Windows系统再次被强制注销。至此我们已经大致清楚了CrackMe的作者为了防止逆向分析其注册机制而设计的调取API来注销系统继而考验耐性,进而阻止利用获取内存镜像方法来获取注册比对信息。至此大致已经清楚CrackMe作者的思路这是反内存注册算法。
二、脱壳分析
1.如果对任何一款软件进行分析,那么首先要利用一些工具软件检测一下该程序是被什么加壳工具加的壳,尤其是那些经验丰富的Cracker在反汇编代码里大致分析段首的特征码即刻确定加的什么壳。然后将其外表的壳脱掉使其还原成未加壳的代码原貌再进行反汇编详尽分析。对于此CrackMe所加壳的种类分析,本文在这里借助一款查壳专业很强的软件PEID来对其进行壳种类的检测。通过PEID?检测结果此CrackMe壳为ASPack?2.12?->?Alexey?Solodovnikov?所加壳,属于比较温和的一款加壳软件。无论任何一款被加壳程序在逆向详细分析前首先是需要脱掉其ASPack的外壳,脱壳的方法有很多、包括现成的效果很棒脱壳软件。或者利用OllyDbg调试器等。方式方法很多诸如OllyDbg软件的脱壳脚本、ESP定律等等。这里将使用OllyDbg调试器插件当中OllyDump来进行手动单步跟踪,进行脱壳过程以及分析ASPack外壳的加密方式。
2.进行脱壳分析。OllyDbg调试器载入CrackMe脱壳过程以及反汇编源代码如下:
004D3001>60pushad:程序入口 (F8)单步执行。
004D3002E8 03000000call004D300A:此call(F7)跟进里面。
004D3007- E9 EB045D45jmp45AA34F7:迷惑人的花指令。
004D300C55pushebp
004D300DC3retn
004D300E E8 01000000call004D3014 :巧妙利用花指令保护上面CALL地址。
(F7)跟进004D3002的call之后来到这里反汇编代码如下:
004D300A5Dpopebp:CrackMe.004D3007。
004D300B45incebp
004D300C55pushebp
004D300DC3retn:执行返回到004D3008。
接上面执行返回之后来到这里反汇编代码如下:
004D3008/EB 04jmpshort 004D300E :无条件跳转跳到004D300E处。
004D300A|5Dpopebp
004D300B|45incebp
004D300C|55pushebp
004D300D|C3retn
004D300E/E8 01000000call004D3014:此call(F7)跟进去。
上面004D300E的call跟进之后来到这里反汇编代码如下:
004D30145Dpopebp CrackMe.004D3013:代码重定位。弹出返回地址ebp=004D3013。
004D3015BB EDFFFFFFmovebx, -13:偏移量为13h字节。
004D301A03DDaddebx, ebp:004D3013-13=004D3000壳代码段起始位置。
004D301C81EB 00300D00subebx, 0D3000:004d3000-3000=00400000(ImageBase)
映射地址。
004D302283BD 220400000>cmpdword ptr [ebp+422], 0
:[ebp+422]=[004D3435]=00000000。
004D3029899D 22040000movdword ptr [ebp+422], ebx
:[ebp+422]存入00400000(ImageBase)。
004D302F0F85 65030000jnz004D339A:初始化为0,进行解压缩、填充IAT表处理,完成后再回到这里判断,如果是00400000就去OEP)jnz条件跳转,转移指令。结果不为零(或不相等)则转移。
004D30358D85 2E040000leaeax, dword ptr [ebp+42E]:然后继续单步跟踪。
004D303B50pusheax
004D303CFF95 4D0F0000calldword ptr[ebp+F4D]
004D30428985 26040000movdword ptr[ebp+426], eax
004D30488BF8movedi, eax
说明:其中这上、下代码之间还有很多相关但是不太重要的代码段在此处已经被忽略若干条。
然后我们继续单步跟踪来到这里反汇编代码如下:
004D30668985 51050000movdword ptr[ebp+551], eax :保存函数地址。
004D306C8D45 77leaeax, dword ptr[ebp+77]:地址=004D308A。
004D306FFFE0jmpeax:跳向目标地址004D308A。
004D307156pushesi:
004D33A00385 22040000addeax, dword ptr[ebp+422]:CrackMe.00400000。
:RVA+ImageBase=OEP。
004D33A659popecx:弹出OEP的RVA。
004D33A70BC9orecx, ecx:OEP的RVA是否为0。
004D33A98985 A8030000movdword ptr [ebp+3A8], eax:修改程序代码,将OEP写入、压栈指令。
004D33AF61popad:
004D33B075 08jnzshort CrackMe 004D33BA :OEP的RVA不为0则跳,否则程序已经运行。
004D33B2B8 01000000moveax, 1:
004D33B7C2 0C00retn0C:
004D33BA68 00000000push0:这里被修改成了push 004B0FE0。
004D33BFC3retn:利用执行到返回前往OEP也就是程序的可以运行的入口处。
承接上面的执行到返回来到下面的反汇编代码到达OEP 入口。汇编代码如下:
004B0FE055pushebp:这里就是程序入口的OEP此处我们可以利用OllyDump进行脱壳了。
004B0FE18BECmovebp, esp
004B0FE383C4 F0addesp, -10
004B0FE6B8 800D4B00moveax, 004B0D80
004B0FEBE8 D85AF5FFcall00406AC8
004B0FF06A 00push0
004B0FF268 58104B00push004B1058:ASCII “CrackMeDialTime”。
004B0FF7E8 9462F5FFcall00407290: jmp user32.FindWindowA。
通过上面详尽的单步跟踪我们顺利的到达了OEP,到达之后本文将使用OllyDbg调试器内的OllyDump功能插件进行脱壳,程序脱壳顺利完成。随之我们双击运行被脱壳后的程序,出现的运行界面显示本软件完全可以正常运行。
3.脱壳分析ASPack 2.12小结。根据ASPack 2.12的特点现作如下分析,该壳非常巧妙的利用了伪输入表动态的调入来满足壳运行时所需要的函数。然后将程序中的每一个段先解压到缓冲区域之后,再进行复制到目标区域的段内,以达到对输入表的保护。如果代码在缓冲区内,可以将所有开头为call和jmp指令的段先行解密到正确的目标地址之后,再复制到目标区域的段内。但是对于我们分析的此CrackMe所加ASPack壳被完整的保留了输入表,脱壳后输入表不需要再行修复。因为它的输入表是利用动态函数获取得到的。利用动态获取函数地址之后再填入IAT表,之后方利用执行到返回的指令跳转向OEP。此ASPack壳运行中且自动完成了修改代码,最后以retn“执行到返回 ”的方式返回到OEP。此壳采用了一些花指令干扰静态调试。对部分的call和jmp的目标地址好像是起到了加密的作用了,但是、不过是解压后在缓冲区域内又解密并复制到代码段中。所以此处好像是略显欠佳,作者在后面的ASPack高版本中已经进行了改变设计。
三、算法及注册机制分析
1.脱壳成功且能够运行之后、首先发现一点既是CrackMe的文件大小发生了变化由脱壳前的305KB增大为脱壳后的864KB换句话说,也就是压缩比还是可以的。但是ASPack 2.12这个版本对于输入表的隐藏与加密还是欠佳的,因此后面高版本的ASPack作者对输入表的隐藏功能改进较大,另外还增加了许多加密功能。脱壳后需要输入表的深入、细心的修复,否则的话逆向分析将为之停止在这里。
2.完成脱壳之后对此CrackMe也有了一个详尽的分析及了解,接下来就要按照轻重顺序、来清除影响阻止我们分析的障碍。接下来需要我们解除CrackMe对调试机器操作系统的强制注销,不然我们将被陷于操作系统往复重启之麻烦当中。也便利对其进行深入细致的分析。当我们运行CrackMe出现主界面之后,在其注册框内输入任意“测试码”点击注册按钮之后系统毫不客气的被注销,也就是所有潜伏的调试软件一律被停止了。分析:首先CrackMe在运行过程中其注册框内如果输入的注册码正确将显示注册成功,解除一切功能限制。若发现注册框内注册码错误首先利用AdjustTokenPrivileges函数获取对操作系统的管理权限,继而调用ExitWindowsEx函数使调试机器的操作系统重新启动,以此达到阻止对其分析,至此我们已经有了一个详尽解除方案了。好了我们等待计算机的操作系统重新启动之后利用OllyDbg调试器载入CrackMe在命令窗口下断点BP ExitWindowsEx过程以及反汇编源代码如下:
命令窗口BP ExitWindowsEx断在这里反汇编代码显示如下:
77D5A275>8BFFmov edi,edi
77D5A27755push ebp
77D5A2788BECmov ebp,esp
77D5A27A83EC 18sub esp,0x18
77D5A27D53push ebx
77D5A27E8B5D 08mov ebx,dword ptr ss:[ebp+0x8]。
分析堆栈汇反编代码显示如下:
0012FD54004AD87F/CALL 到 ExitWindowsEx 来自 CrackMe.004AD87A。
0012FD5800000004 |Options = EWX_FORCE。
0012FD5C00000000/Reserved = 0。
利用快捷键、Ctrl+G 前往004AD87A:
当我们来到004AD87A仔细分析这些汇编代码之后,发现跳转已经无条件实施了所以检测和校验一定是在004AD87A之上这些汇编代码之中。反汇编代码分析显示如下:
004AD860 |.50push eax: /pRetLen。
004AD861 |.6A 00push 0x0:|pPrevState = NULL。
004AD863 |.6A 10push 0x10:|PrevStateSize = 10 (16.)。
004AD865 |.8D4424 20lea eax,dword ptr ss:[esp+0x20] :|
004AD869 |.50push eax:|pNewState。
004AD86A|.6A 00push 0x0:|DisableAllPrivileges = FALSE。
004AD86C|.8B4424 14mov eax,dword ptr ss:[esp+0x14]:|
004AD870 |.50push eax:|hToken = 0000018C (window)。
004AD871E8 8A93F5FFcall CrackMe.00406C00: jmp 到 advapi32.AdjustTokenPrivileges。
004AD8766A 00push 0x0:这个入栈的推手NOP掉。
004AD8786A 04push 0x4:这个入栈的推手NOP掉。
004AD87AE8 019AF5FFcall CrackMe.00407280: jmp 到 user32.ExitWindowsEx。
修改其俩个指令之后,然后我们右键将对其重新修改指令之处复制到可执行文件,保存。至此可以说我们已经完全的解除了该CrackMe将自己提升的的注销系统权限,之后再行测试一切安然。注:关于NOP在反汇编修改其内容或改变其跳转时一定要按照汇编指令规律操作,所以这里只有用NOP来填充其字节数保证CrackMe的完整不受影响。
3.解除注销系统权限之后我们只是简略的分析其注册算法:利用OllyDbg再次载入CrackMe利用ApiBreak插件内的功能下断?PointH这是一个万能断点,点击运行,待CrackMe运行起来我们输入测试码之后点击注册按钮时CrackMe被拦截在这里。
万能断点拦截后反汇编源代码如下:
004AD707 |.8B86 FC020000mov eax,dword ptr ds:[esi+0x2FC]
004AD70D |.E8 1260F9FFcall CrackMe.00443724:获取“测试”码的输入位数。
004AD712|.837D FC 00cmp [local.1],0x0:注册框内是否“空”。
004AD7160F84 A3000000je CrackMe.004AD7BF:如果注册框是空的就开始循环,否则继续。
004AD71C|.8D55 F8lea edx,[local.2]:动态指向0012FDB0“测试码”地址。
004AD71F|.8B86 FC020000mov eax,dword ptr ds:[esi+0x2FC]
:获取的“测试码”与“位数”存入EDX寄存器。
004AD725|.E8 FA5FF9FFcall CrackMe.00443724
004AD72A|.8B45 F8mov eax,[local.2]
004AD72D|.50push eax:测试码入站。
004AD72E|.8D55 F0lea edx,[local.4]
004AD731|.8BC6mov eax,esi
004AD733|.E8 90FBFFFFcall CrackMe.004AD2C8:测试码转成16进制乘:10加4减1重复测试码位数,然后获取CPUID。
004AD738|.8B55 F0mov edx,[local.4]
004AD73B|.8D4D F4lea ecx,[local.3]
004AD73E|.A1 F8334B00mov eax,dword ptr ds:[0x4B33F8]
004AD743|.8B00mov eax,dword ptr ds:[eax]
004AD745|.E8 02A2FDFFcall CrackMe.0048794C
004AD74A|.8B55 F4mov edx,[local.3]
004AD74D|.58pop eax
004AD74E|.E8 5973F5FFcall CrackMe.00404AAC:测试码与注册码对比。
004AD753|.74 14je XCrackMe.004AD769:对比结果相等跳向004AD769,否则将重启机器。
综上所述分析结果,如果根据上面所做的详细分析要得到注册算法已经非常明朗,若利用我们自己编写的程序提取注册码也是很轻松的事情。这里本文不在论述、如何编写程序提取注册码,因为如果论述编写程序提取注册码需要很长的篇幅所以此文不在论述。但是我们可以利用一款现成的内存注册码提取软件来完成此CrackMe的内存注册码的算法提取工作。
内存注册码提取方法如下:
我们首先下载keymake内存注册码算法提取软件,这是一款功能非常强大的软件。它的详细功能我们不在复述,因为作者赋予的功能是超出大家想象的之外。只有但我们亲自试验之后方为得知。
下面首先运行keymake待其正常运行之后,开始填入我们上面详细分析的相关的中断地址、寄存器、中断次数、拦截进程、等。按软件提示填入相关数据之后,该软件将自动生成内存注册码提取软件但是在使用时该软件一定要和CrackMe保存在一个文件夹之下。
关键之处反汇编代码如下:
004AD74A|.8B55 F4mov edx,[local.3]
004AD74D|.58pop eax
004AD74E|.E8 5973F5FFcall CrackMe.00404AAC:测试码与注册码对比。
004AD753|.74 14je XCrackMe.004AD769:对比结果相等跳向004AD769,否则将重启机器。
需要填写代码如下:
地址如下:
中断地址004AD74E。
中断次数 :1。
中断指令:E8。
指令长度:5。
方式:
内存方式:
寄存器:EDX
宽字节:
地址指针:1
拦截所有进程。
然后将指针指向CrackMe所在之处,接下来点击生成。此时一款我们自己分析的内存注册码提取软件已经生成。运行之时内存注册码提取软件首先按我们的指针方向寻找CrackMe,并将其激活。之后我们在注册窗口输入测试码、点击确定按钮之关键之时,我们的内存注册码提取软件将在内存当中获取到正确的注册码,之后将注册码复制填入注册窗口点击确定按钮,温馨的人机对话欣然出现“注册成功”。
再者将此CrackMe脱壳、解除ExitWindowsEx。的调用之后,将004AD753这个关键跳转74若修改为75或者EB。将得到非常轻松的爆破结果,
通过对其CrackMe的脱壳、解除限制、算法分析之后。虽然花费了一些时间,但是从中获益匪浅深感益师无处不在,学无止境。若这种限制方法被恶意使用,解决的难度也是可想的、不过通过分析学习解决的方法也会更加进步。
CrackMe Debugging and Algorithm Analysis
LIU Jian-lin
(TianjinModernVocationalTechnicalCollege,Tianjin, 300350)
Abstract:CrackMe which is most convenient for exchange and communication on the internet has been widely communicated by the programmers and Cracker fans on the platform of mutual learning and exchange, so that everyone can jointly research, analyze and discuss the latest thought of programmers and problems to be solved and tackled among the programmers.This paper mainly discusses and analyzes the debugging and algorithm of CrackMe.
Key words:CrackMe analysis; shell analysis; algorithm analysis
中图分类号:TP311
文献标识码:A
文章编号:1673-582X(2016)04-0106-07
作者简介:刘键林(1959-),男,天津市人,天津现代职业技术学院计算机实验室管理员、工程师,从事计算机加密与解密教学与研究工作。
收稿日期:2015-12-29