“ 奶妈式教学,从BUFF App开始进入Android应用逆向分析的世界。 ”
具体App以及本系列文章内容涉及的资源存放在百度云中,链接如下:https://pan.baidu.com/s/12VldUiBWFcfvOSqM0RE-Ng 提取码:d5ku。
01
—
写作风格
我的女友梁雅是个美丽可爱又傻fufu的女孩,我会尽自己最大的能力写清楚写详细每一个步骤,好让她和你们都能听懂。
02
—
逆向分析的思路
我写的所有的文章都会以实战为导向,在逆向学习的初期,新手很需要跟着详尽的实战文章一步步去做,这会大大增加学习者的经验和成就感。但需要提醒大家,千万不要只追求实战而忽略基础与开发,否则逆向就是无根之水,只能停留在脚本小子的地步。在教程中,我会尝试兼顾原理与实战,采用“遇到问题——探索原理——举一反三——解决问题”的思路,同大家一起踏上逆向之旅。首先看一下基本的分析思路,在入门阶段,最好每个App按照这个思路去研究和破解。 再放一下之前CSDN博客中画的图,和这儿关系不大,但胜在好看。
03
—
前置知识
你只需拥有以下的知识和环境即可开始这趟逆向之旅:
-
一台内存8G及以上的Windows电脑,Mac等也可;
-
正确配置Java和Android开发环境,安装有Android Studio(3.0以上)
-
熟悉通过Fiddler/Charles工具抓App数据包;
-
电脑安装逍遥/雷电模拟器,或者有一台已Root的真机;
-
安装Xposed,熟悉安装和激活Xposed模块的流程;
-
熟悉JADX等反编译工具的安装和操作,不了解的可以看我的这篇文章
我不假设你熟悉Java/Android开发,或者C语言,但在实战之前,或者逆向的旅途中,时时翻看下面这三本书,会给你带来极大的帮助。
-
《第一行代码(第二版)》郭霖——Android入门第一书
-
《Java 核心技术 卷一》——Java入门经典
-
《C Primer Plus(第6版)中文版》——C语言入门第一书
在理想的状态下,Android逆向工作者需要熟悉java和C/C++ 语言,有开发大型或成熟Android软件的经验,熟悉JVM虚拟机,了解Android底层,清楚应用运行机理。但是,这并不意味着我们得到这个地步才能开始Android逆向的旅程。你应该先从一个比较系统的角度了解Android逆向的全貌,然后跟着教程学习逆向和分析的思路,并使用一些成熟的工具和技巧进行破解,完成几次简单但充实的实战,之后就可以在实际问题中不断去学习和补充知识。但这也只是建议而已,万流如海,殊途同归,只要你热爱这门技术,并能忍受纷扰的诱惑潜心研究,逆向之旅会越走越开阔和明朗。
04
—
抓包分析
具体App请下载百度云资源自行测试,我们这里用BUFF指代它。我使用的抓包软件是Fiddler,测试机为雷电模拟器,建议读者使用雷电Android 5 抓包,如果使用真机,系统版本尽量不要超过7。BUFF只能通过验证码登录,我们从发送验证码的包开始说起。 请求是post请求,Header和Url都非常干净,没有任何敏感信息,Post的内容是Params和Id,返回结果是一个请求成功的消息码。 重复抓两次包,观察一下字段的长度和内容特征,ID由96位十六进制数组成,每次清除App数据后ID发生变化,所以我们得不出什么东西,可能是标识之类的东西。再看一下Params,它长度不定,我抓了两次包,长度分别为896和832,能推断的东西十分少。
-
Params是密文(这不是废话嘛)
-
Param的原文可能是一堆参数,类似{“a”:2;”b”:3,“c”:123456}
-
Params采用的加密方式肯定不是MD5,SHA-1等哈希算法,因为哈希算法的长度往往很短,MD5——32个十六进制数,SHA-1——40个十六进制数,而且哈希算法单向不可逆,无法通过密文推导出原文,因此它常常用于较小型App的签名验证(sign),而不用于信息的传输,这儿可能采用了RSA或者AES一类的算法。
接下来拖拽Apk进Jadx的界面(之所以要提这个,是因为有读者反馈他一直以为Jadx只能反编译Dex,所以他每次都会解压Apk得到Dex,再一个一个dex拖进去看)可以用于搜索的敏感字符串有三处(params,id,这条url),出于保险起见,我们搜“login1”,因为App可能出于复用的考虑,将“sdk.reg.163.com/interfaces’作为常量拼接使用。
双击“str2 = "/interfaces/yd/login1.do"所在的像素区域,查看具体代码。这里有一个题外话,程序员似乎拼错了单词,少了一个c。acquire意为获得、得到,Aquire is misspelling of acquire。 我们来理解一下这个方法,它需要传入一个数字,一个字符串,如果传入数字不为8,进入一个switch选择语句,在switch条件语句中,如果传入数字为1,str2就赋值我们获取验证码的网址,如果数字为2,str2=f.x,我们只要将鼠标停在x上,然后按住Ctrl+鼠标左键,就可以查看这个变量的具体定义处。前进和返回按钮可以方便你在各个类中跳转。 我们发现似乎在这种情况下,str2会被赋值一个用于注册账号的网址,而如果i既不为1也不为2就抛出异常,而当i=8时你可以如法炮制查看具体的字符串资源。我们可以猜测,发送验证码时,我们的逻辑中i为1,str2接下来经过了拼接等操作后发送请求验证码的操作。最后一句代码非常长,我们看一下str2参与的这个方法,因为我们只对str2的值熟悉。post(str2, new b(str)),看函数名很像发送Post请求的方法,它的入参是str2和一个b对象。b对象的构造函数传入了我们函数中神秘的str参数。看一下b对象,它继承自f。 那post方法呢,post是一个接口方法,我们需要找到实现post(str2, new b(str))的那个具体的方法。Java基础比较差的小伙伴可能会有些头疼。天呐,静态分析Android App代码真烦啊。而且如果我们猜错了,str2并不是发送验证码请求的地方,那么我们之后一堆分析就全错了。
如果你想单凭阅读反编译代码来分析程序,这是完全可以的,只不过你需要拿出陪女朋友去游乐场,或者陪老婆孩子吃晚餐的时间来陪一个几十M大小的Apk罢了。 其实定位加密处往往只是逆向的热身步骤,它不应该耗费我们太多时间。为了避免这种情况的发生,我们需要升级一下技术,下一篇中我们使用动态分析的方法和技术来寻找加密处。
推荐阅读
添加微信[gopython3].回复:加群,加入Python交流群