记录一下,以免难以查找
期间走了很多弯路,想直接看破解部分的,请跳到13小节,以下:
1
od载入,断在C语言运行时的入口
2 稍微向下拉一点,就到了Window窗口程序的入口 WinMain,即下图的 0059173B
3 F7单步进入,005BE120处的Call是进入AfxWinMain
4 再往下一点, 005C7480处就是进入CWinApp.InitInstance()了
上图 005C7472处的call是进入CWinApp.InitApplication()
以上的逻辑是程序进入 start->_WinMain -> WinMain-> CWinApp.InitInstance ()。 然后并没有任何卵用,因为都不是跟这个程序相关的,这是MFC的框架部分,进入CWinApp.InitInstance()后就被易语言的核心库接管了,在这里追了好几天,对比了MFC的Dialog,SDI,MDI类型的程序,始终不一样,都快放弃了,结果发现这个程序目录里会释放出krnl这种东西,百度了一下才发现这是易语言……被自己蠢哭了。以下再跟下去,可以发现释放各种核心库和支持库,校验库md5的代码,这里就不展开了,初始化流程是这样,点了一个按钮之后,怎么知道这个按钮对应的处理函数在哪里呢?这里就要祭出神器了,有大神分析过易语言消息分发的机制,http://bbs.pediy.com/showthread.php?t=195626,
易语言派发事件的特征码FF55FC5F5E
5 直接在Od Ctrl+B, 确定后,来到易语言分派消息的地方
00519F7D
6 F2 下断,然后F7单步进入,我们就来到了点击 登录后 处理登录的代码了,
看到那个 ASC字符串么,说明我们来对了,因为没有勾选那个协议的话,要弹个框,要求先勾选那个协议。往下拉一点,有个判断 登录成功 的字符串,说明登录网络操作的代码应该在前面,于是我们在前面一个call处下断,0047B0EA。这里我作为一个新手,犯了个自以为是的错误,看到判断
登录成功 的地方,按照惯性思维,把判断后的jmp代码nop掉不就行了么,nop掉之后运行,崩掉了。教程上边都是这样写的啊?怎么不对呢,教程是教程,实际应用中哪会这么简单,师傅领进门,修行靠个人啊。实际上这里登录成功和登录失败服务器返回的内容和格式都是不一样的,这点后面细说。
7 F7单步进入,这里就是拼接url,网络验证,解析服务器返回的内容了,这里是重点,我们的破解也在这里。向下大概翻阅一下,翻到ret,大概浏览一下这个函数,估计一下函数完成的内容。前半部分各种获取随机数,HardDiskCode,拼接url,然后网络操作,接下来判断服务器返回的内容,前半部分略过不提,接下来需要压入30个参数的函数,就是网络操作了,00404655处的call就是网络操作,有兴趣可以跟进入看看,不过这里我们没必要,因为我跟进入读完了发现跟我们的目的没有任何关系,摔……
8 完了之后又开始释放调用之前分配的各种参数,说优化不好也确实是这样,很少见到过需要30个参数的函数,call前一堆Alloc,call后一堆Free,这种风格在代码里大量出现。刚刚我们网络操作的call后 我们单步一下看看是什么情况,F7单步到00404743处的代码后
9 寄存器eax里出现了服务器返回的内容
10 然后接下来的代码就不贴图了,主要逻辑是
判断返回的内容中是否有 !DOCTYPE ,如果有说明服务器出错了,
判断返回值是否为空,空说明服务器连接失败,
判断返回内容左边4个字是否是登录成功 ,
如果是,开始解析内容
解析内容的方法是将返回的内容 使用\r\n分割,分割的代码在这里。
11 因为需要了解分割的内容格式是什么样的,继续往下读代码。接下来两段是判断分割后的内容,分割后应该是返回一个数组,数组分为3部分,第一部分是int值表示第二部分有几个int,第二部分是多个int值,表示第三部分有多少,第二部分的多个int值乘积结果就是第三部分的个数,第三部分就是多个指针,指向分割后的字符串。判断的代码在下面:
12 看00404910那个地方,分割后的结果有9个字符串啊,这下明白了我们为什么不能直接nop掉前面判断登录成功登录失败的代码了吧,因为根本没用,登录成功后还有一些其他的操作需要用到这里的数据。再往下就是将分割后的字符串保存到传入这个函数的参数arg1中,arg1应该是个对象,接下来分别将9个参数存入对应的位置,
00404991 arg1+1c处存放第一个
004049EF arg1+0x8处存放第二个等等,其中第1个和第4个参数是字符串,其他的都是int值。然后这个函数就完了……然后我们就开始我们的破解之路啦,以上都是胡乱分析,接下来才是真正的破解。
13 然后也并不知道这9个参数分别是什么,只知道第一个参数是“登录成功”不管它,先试一下,先构造一个返回值 登录成功\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8,先跑一下,看看是什么结果。
od重新载入,断点下载00404739处,F9运行
14 来到断点处后,点EAX右键,数据窗口跟随,
15 可以看到这里就是服务器返回的内容,双击02EC6E38处,也即是图上D3的那个位置,我们要修改这里的数据,复制一下代码B5C7C2BCB3C9B9A60D0A310D0A320D0A330D0A340D0A350D0A360D0A370D0A3800
粘贴到
Hex + 00处,粘贴之前取消保持大小处的勾,修改02EC6E34处即图上0d处的值为21,为什么要复制上面的代码呢,因为0D0A就是\r\n,B5C7C2BCB3C9B9A60就是“登录成功”的GBK编码了,31就是1,32就是2,33就是3,38就是8,方便我们判断下面不同的字段是什么意思,修改完成后,上图02EC6E30处010000表示第二部分1个字节,02EC6E30处21表示第三部分33个字节,第三部分就是我们粘贴进去的代码啦
16 然后F9运行,然后看到什么了,神奇的登录成功,点击确定后我们就进入主界面啦,从图上我们可以看出来,9个字段分别是什么意思,当然4个和第6个还是不知道是什么意思,字段2是上次登录ip,字段3是上次登录时间的Stamp,字段5是在线时长的秒数,字段7是历史购票数,字段8是账号到期时间的Stamp,我把用户名抹掉了……
19 这只是在内存中运行,我们要怎么破解呢,根据上面的跟踪,我们只要把下图中eax固定为我们的值就可以了
20 首先我们先在程序里边找个地方存放我们的返回内容
Od-插件-中文搜索引擎-搜索asc,找出代码中所有需要字符串的地方
21 我们看0056B9D0处那里应该是个说明性的文字,一般不会用到,我们就把我们的字符串放在这里,这里调用的是0xA8D44C处的字符串,在OD的数据窗口ctrl+G跳转到0xA8D44C,看到内容是0x00A8DBDC, 因为是小端序,内容在内存中是DCDBA800,顺序是反的
22 再ctrl+G跳转到0x00A8DBDC ,就可以看到字符串了
23 点击00A8DBDC处即图上D3的位置,粘贴下面的代码到OD的窗口
010000003B000000B5C7C2BCB3C9B9A60D0A310D0A322E322E322E320D0A313435303530373837300D0A340D0A3535350D0A360D0A300D0A3134363135303738373000
这里我解释一下上边的数据,
01000000表示第二部分1个int
3B000000表示第三部分3B个字节,即59
下面是第三部分
B5C7C2BCB3C9B9A60D0A登录成功
310D0A字段1,不知道含义
322E322E322E320D0A字段2,上次登录ip,内容是2.2.2.2
313435303530373837300D0A字段3 上次登录时间,内容是1450507870,表示2015年12月19日 14:51:10
340D0A 字段4,这个其实是用户等级的意思
3535350D0A字段5,在线时长,内容是555秒
360D0A 字段6,未知
300D0A 字段7 历史购票总数,内容是0
3134363135303738373000字段8,账号过期时间,内容是1461507870,表示2016年04月24日 22:24:30
24 然后再来到我们上面的要赋值的EAX处,修改成下图的代码,这样不管服务器返回什么,最后都是我们填写的内容了
任意处点 右键 复制到可执行文件 ,在弹出的框里 复制-全选,然后点保存文件。我们就破解好了,好了么?还没有,双击破解后的exe,竟然检测到修改了文件,妈蛋,继续OD载入,插件-中文搜索-搜索ASC 找到 “检测到您的……”字符串,点击就来到检测文件修改的代码处了。
25 004037B9处,eax里保存了判断md5的结果,0为相等,1为不等。全部nop掉
然后保存即可。
最后附上一张图: