Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1760032
  • 博文数量: 290
  • 博客积分: 10653
  • 博客等级: 上将
  • 技术积分: 3178
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-24 23:08
文章存档

2013年(6)

2012年(15)

2011年(25)

2010年(86)

2009年(52)

2008年(66)

2007年(40)

分类:

2008-03-28 21:10:34


【文章标题】: 加密解密习题练习
【文章作者】: kanghtta
【作者邮箱】: kanghtta@hotmail.com
【作者主页】: http://kanghtta.cublog.cn
【作者QQ号】: 18381291
【软件名称】: echap512
【软件大小】: 4kb
【下载地址】: 加密解密第二版光盘
【加壳方式】: 五壳
【编写语言】: masm32
【使用工具】: peid  OllyICE
【操作平台】: windows
【软件介绍】: 难度--稍难(不是我说的,出题人给的)
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!


【详细过程】 大家好,有一就有二嘛!昨天做了个我的第一个练习,本想自己练练,但是觉得把自己破解的思路记下来,以后也好温习温习, 还是写一写好,本来昨晚就写得差不多了,可由于在宿舍住,阿姨关电是不是从来不看时间啊,唉。。我写了2小时的文章 就那样灰飞烟灭了,也不想抱怨什么了,这个社会上抱怨是没用的。 (我废话真多,嘿嘿。。jmp short 正文)。 由于题目给的是稍难,但是不用管这个,难不难都试一试吧!    首先,还是老格调,拿到一个程序呢,先运行一下看看,找找提示信息,熟悉熟悉软件环境。好了,看到一个编辑框, 直接 OK它, 熟悉的Messagebox出来了,不过不用高兴,它带来的不是什么好消息: Wrong S/N # 现在,用peid载入看看,主要是看有没有壳,(乌龟盖),还有软件的一些信息。 (其它的不用说了吧。其实也不知道怎么说,你用一下就知道了) 刚才说过了,messagebox跳出来说了句:Wrong S/N #,一般的思路都是用字串参考,不过还是用OD载入看看。 一开始就是GetModuleHandle ,获取程序模块句柄,好了,先不用字串参考了,上下拖拖看。(指滚动条) 窗口产生过程的流程都差不多,获取模块句柄,注册窗口类,创建窗口,更新客户区,消息循环。和昨天不同的是, 昨天的用对话框,今天用CreateWidnowEx 用了三次,分别产生:窗口,编辑框,按钮,(后两个窗口用系统预定义类) 在往下拉拉看,找到关键,嘿嘿,,, 0040118F |. /75 5E jnz short 004011EF 00401191 |. |6A 28 push 28 ; /Count = 28 (40.) 00401193 |. |68 A6204000 push 004020A6 ; |Buffer = echap512.004020A6 00401198 |. |FF35 4C204000 push dword ptr [40204C] ; |hWnd = NULL 0040119E |. |E8 00010000 call ; \GetWindowTextA 004011A3 |. |FF35 44204000 push dword ptr [402044] ; /Arg1 = 00000000 004011A9 |. |E8 5D000000 call 0040120B ; \echap512.0040120B 004011AE |. |83F8 01 cmp eax, 1 004011B1 |. |75 1E jnz short 004011D1 004011B3 |. |6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL 004011B5 |. |68 81204000 push 00402081 ; |Title = "Good For U!" 004011BA |. |68 8D204000 push 0040208D ; |Text = "U Did It!!" 004011BF |. |FF35 48204000 push dword ptr [402048] ; |hOwner = NULL 004011C5 |. |E8 EB000000 call ; \MessageBoxA 004011CA |. |5E pop esi 004011CB |. |5F pop edi 004011CC |. |5B pop ebx 004011CD |. |C9 leave 004011CE |. |C2 1000 retn 10 004011D1 |> |6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL 004011D3 |. |68 98204000 push 00402098 ; |Title = "=)" 004011D8 |. |68 9B204000 push 0040209B ; |Text = "Wrong S/N#" 004011DD |. |FF35 48204000 push dword ptr [402048] ; |hOwner = NULL 004011E3 |. |E8 CD000000 call ; \MessageBoxA 004011E8 |. |5E pop esi 004011E9 |. |5F pop edi 004011EA |. |5B pop ebx 004011EB |. |C9 leave 004011EC |. |C2 1000 retn 10 建议大家如果程序比较大的时候,还是用字串参考,这里先看两个地址, 如果可能,请记下它们. 004011E3 |. E8 CD000000 call ; \MessageBoxA 004011C5 |. E8 EB000000 call ; \MessageBoxA 分别是不成功和成功注册给的提示信息。接下来,我们上下拉拉看,找找有没有Call Jxx 阿什么的跳到这两个地址。 结果不容乐观。但不用担心,如果字串找到了,你一般留心下函数。 看到这个没有 0040119E |. E8 00010000 call ; \GetWindowTextA GetWindowText函数复制一个指定的窗口标题文本(如果它有的话)到一缓冲区中。如果指定的窗口是控件,那么控件文本 被复制。然而,GetWindowText不能获得另一应用程序的控件文本。 原型如下: int GetWindowText( HWND hWnd, // handle to window or control with text 有文本的窗口或是控件的句柄。 LPTSTR lpString, // address of buffer for text 文本缓冲区地址 int nMaxCount // maximum number of characters to copy能复制的最大字符数。 ); 0040119E |. E8 00010000 call ; \GetWindowTextA 004011A3 |. FF35 44204000 push dword ptr [402044] ; /Arg1 = 00000000 004011A9 |. E8 5D000000 call 0040120B ; \echap512.0040120B 004011AE |. 83F8 01 cmp eax, 1 004011B1 |. 75 1E jnz short 004011D1 004011B3 |. 6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL 004011A9 |. E8 5D000000Call 0040120B 初步断定为关键,获取完文本,接下来一般都是对文本做写处理或者是变换。 废话少说 在0040119E处 F2,然后Ctrl +F2 重新载入后,按F9 运行: 窗口出来了,我输入的是 : kanghtta (当然,你可以输入你喜欢的任何字符,要是直接输入注册码,你就神了,嘿嘿。。) 现在我们F8来到004011A9 处F7跟进,哈哈,看下面 0040120B /$ C8 000000 enter 0, 0 0040120F |. 53 push ebx 00401210 |. 52 push edx 00401211 |. 33C0 xor eax, eax 00401213 |. B8 A6204000 mov eax, 004020A6 ; ASCII "kanghtta"( 熟悉吧,我是很熟悉的) 00401218 |. 8038 00 cmp byte ptr [eax], 0 0040121B |. 74 60 je short 0040127D 是否输入的是空字符,如果是,跳走,估计程序也完蛋了,这么说的原因是,我不知道它跳到什么地方,干了什么事 0040121D |. 33DB xor ebx, ebx 0040121F |. 33D2 xor edx, edx ; 接下来两句是:寄存器清0 00401221 |> 8A18 /mov bl, byte ptr [eax] 00401223 |. C1C3 08 |rol ebx, 8 00401226 |. 03D3 |add edx, ebx 00401228 |. 40 |inc eax 00401229 |. 8038 00 |cmp byte ptr [eax], 0 0040122C |.^ 75 F3 \jnz short 00401221 这一段的功能是循环计算输入字符,算法一会下面给出 0040122E |. 52 push edx ; /<%lX> = 7FF45409 0040122F |. 68 54204000 push 00402054 ; |Format = "%lX" 00401234 |. 68 BF204000 push 004020BF ; |s = echap512.004020BF 00401239 |. E8 8F000000 call ; \wsprintfA 0040123E |. BB BF204000 mov ebx, 004020BF ;ebx 为74746168 00401243 |. 803B 38 cmp byte ptr [ebx], 38 第一字节和38比较 00401246 |. 75 35 jnz short 0040127D 结果不为0则跳转,F8跟进,结果程序完蛋.Wrong.... 00401248 |. 807B 01 44 cmp byte ptr [ebx+1], 44 0040124C |. 75 2F jnz short 0040127D 0040124E |. 807B 02 43 cmp byte ptr [ebx+2], 43 00401252 |. 75 29 jnz short 0040127D 00401254 |. 807B 03 41 cmp byte ptr [ebx+3], 41 00401258 |. 75 23 jnz short 0040127D 0040125A |. 807B 04 46 cmp byte ptr [ebx+4], 46 0040125E |. 75 1D jnz short 0040127D 00401260 |. 807B 05 33 cmp byte ptr [ebx+5], 33 00401264 |. 75 17 jnz short 0040127D 00401266 |. 807B 06 36 cmp byte ptr [ebx+6], 36 0040126A |. 75 11 jnz short 0040127D 0040126C |. 807B 07 38 cmp byte ptr [ebx+7], 38 00401270 |. 75 0B jnz short 0040127D 00401272 |. B8 01000000 mov eax, 1 00401277 |. 5A pop edx 00401278 |. 5B pop ebx 00401279 |. C9 leave 0040127A |. C2 0400 retn 4 将运算的结果和 38 44 43 41 46 33 36 38 依次比较,任何一个不等,就跳到0040127D现在我们看看此处代码: 0040127D |> 33C0 xor eax, eax eax 清0 0040127F |. 5A pop edx 恢复现场 00401280 |. 5B pop ebx 00401281 |. C9 leave 恢复现场,和堆栈维护 00401282 \. C2 0400 retn 4 返回到 004011AE |. 83F8 01 cmp eax, 1 eax 和1比 不等则完蛋. ;而eax在040127D处被清0 这就是说,只要跳转到0040127D处,程序就完蛋 004011B1 |. 75 1E jnz short 004011D1 004011B3 |. 6A 30 push 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL 下面我们来分析注册的算法: 这里先留意一个API函数: wsprintf The wsprintf function formats and stores a series of characters and values in a buffer. Wsprintf在缓冲区中格式化并储存一系列的字符和值,任何自变量都能依照在格式串中指定的格式被修改和复制到输出缓冲区中. 这个函数在输入的字符串后面附加一个NUll终结符,但是返回值中并不包含这个终结符的计数. 它可以将数值按指定的格式翻译成字符串: int wsprintf( LPTSTR lpOut, // pointer to buffer for output 指向输出缓冲区的指针 LPCTSTR lpFmt, // pointer to format-control string 指向格式控制字符串的指针 ... // optional arguments 自变量选项,这个参数的类型和大小依赖以在lpFmt参数中指定的格式控制规格. ); lx, lX A long unsigned hexadecimal integer in lowercase or uppercase 程序算法: 1.将由GetWindowText获得的文本从左到右输入一个字符到bl中. 2,bl循环右移8位, 3,将右移后得到的值和edx相加,edx初值为0,结果保存在edx中 4,取下一字符 5,比较,看看取得的字符是否为NULL ,如果是,说明字符串结束,如果不是,回到第1步 6,将计算的到的edx值格式化后输出到缓冲区中 7,缓冲区的字符串依次和38 44 43 41 46 33 36 38比较.,字符串翻译为: 8DCAF368 ebx=00006B00 ebx=006B6100 ebx=6B616E00 ebx=616E676B ebx=6E676861 ebx=6768746E ebx=68747467 ebx=74746168 -------------------------- edx=7FF45409 0040123E |. BB BF204000 mov ebx, 004020BF 取缓冲区地址 ; ASCII "7FF45409" 00401243 |. 803B 38 cmp byte ptr [ebx], 38 缓冲区数据比较 00401246 |. 75 35 jnz short 0040127D 004020BF=004020BF (ASCII "7FF45409") ebx=74746168 我们知道最后比较的字符串为:8D CA F3 68,现在考虑如何逆向它: ebx=00006B00 ebx=006B6100 ebx=6B616E00 ebx=616E676B ebx=6E676861 ebx=6768746E ebx=68747467 ebx=74746168 -------------------------- edx=7FF45409 也就是 最后的edx的结果要是8DCAF368 n个字符经循环移位变换后得n/2个字符,如果要从结果退出注册码,可不可能呢? ( 大家帮忙思考下) , 00k0 0ka0 kan0 ang

【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2008年03月28日 上午 09:57:00
文件:echap512.rar
大小:1KB
下载:下载
阅读(1618) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~