首先来个声明: 本文为论文性质,请勿转载;本文仅学习讨论加密解密技术,勿用于其他任何用途,否则与本人无关!为了避免不必要的麻烦,屏蔽相关软件的名字。
有朋友请我研究一个WX插件的验证机制,一直没找到整块时间,回头想起来这个事花了点时间看了看,很简单,不过插件已经过气了。记录一下逆向过程,开始吧!插件为DEB格式,解压后出现了一个application和三个dylib,安装后会弹出一个UIAlertView,要求输入用户名和验证码,随便输入一个会弹出注册失败。好,就从这个UIAlertView入手,因为它的initWithTitle跟这个DEB包的名字是一样的,根据这个去定位相关函数,把三个dylib和一个application都扔进IDA,查看输入表,找到OBJC_CLASS___UIAlertView的交叉引用,最后确定一个z开头的dylib里负责弹出这个UIAlertView,代码如下:
我用的是IDA6.8,里面的Unicode支持不好,使用相关插件后,会自动在注释中标上对应的中文,但是跟心中期望的直显中文还是有所距离,没有6.9也没办法,我凑合用大家凑合看吧。
再去找消息响应函数,代码如下:
我们来看一下dispatch_after的官方解释 Enqueue a block for execution at the specified time.
可以理解成在指定的时间执行代码块,至于代码块,IDA已经帮我们分析好了,就是这个block_invoke。IDA为了表述方便吧,他重新定义了一个函数表示这个代码块。那就去看这个block吧!
翻译一下:鑜孮1"就是注册失败,看一下text也挺清楚的,左边成功,右边失败。
接下来就是去分析那个V8啥时候为1(注册成功),代码很清楚:checkUID textFieldAtIndex.text encrypt(getuuid())。验证你输入的验证码和一个加密了的uuid。getuuid顾名思义,
接着去看看encrypt
看起来很清晰,uuid先经过utf8编码,然后做MD5,把HASH值打成string再统一大写。这样看下来其实不是加密,编码而已,checkUID的俩参数都搞清楚了,再去看看这个方法
打开一看有些篇幅,分析分析啊,看字符串的样子,明显是base64编码过的,注意代码中的这行 v10 = objc_msgSend(v9, "initWithData:encoding:", v8, 4); 这个4其实是
确定是标准的BASE64解码,解码后其实是一个URL地址,就是验证服务器的。接着往下看,向这个地址发起了一个HTTP请求,把那个“加了密”的UUID和我输入的验证码统统发给服务端验证,然后在response里面找code,这个值就是服务器的验证结果。到这里这个验证机制就分析清楚了,这个插件的验证太简单了,方法名没混淆,连个像样的加密算法也没加,严阵以待的LLDB都没用上,就当给刚刚入门的朋友们增加信心吧。On the last,我顺便看了看其他dylib的代码,发现这套验证也是HOOK了其他人的验证,贵圈真乱啊。。。。
|