Debugging Android Libraries using IDA

During a recent test, Iencountered a native JNI library used by an Androidapplication. I needed to understand this library and what it did, so the firststep was to load the library in IDA to see what it looked like. It did not takelong until I realized I was looking at obfuscated code that was doing a lot ofmanipulation on the stack. Understanding the library through static analysisalone would take a long time, so the best way forward would be to combinestatic and dynamic analysis.

Having debugged a lotof iOS apps using GDB, I started looking at debugging Android apps with GDB.Until this point, DEX2JARSmali and some other tools had been sufficient formy Android reversing requirements.

Some research lead meto a discussion at xda-developers about Android debugging through the remotedebugging functionality in IDA.

Below is a descriptionof the steps I had to take before I could start debugging the library in question. In this case I used the Android emulator, but this should work justas well on a rooted device.

  1. Create anAndroid Virtual Device (AVD) for use in the emulator and make sure it works. 

  2. Start theemulator, and when the emulator is running, use the command "adb devices" tomake sure the Android Debug Bridge (adb) is working properly. You should seethe emulator listed if it works. It is also best if only one device isconnected, so if you see multiple devices, disconnect the extra ones.

  3. Start theemulator again using the following command: "emulator –avd [AVD_NAME] –partition-size512". It is possible to use a partition size lower(or higher) than 512 although I did not test this. 

  4. Run thefollowing commands.

    adb remount
    adb push android_server /system/
    adb shell
    su (probably not needed for the emulator but is necessary if doing this on a rooted device)
    cd /system
    chmod 755 android_server
    ./android_server

    The commands above will begin by mounting the system partitionas read-write, and then push the file android_server to the /system folder. This file can be found in the dbgsrv folder of IDA. Next, it willcreate a shell, make the android_server file executable andthen run it.

  5. Minimizethe windows where android_server is running and open a new command prompt /terminal, and type this command: "adb forward tcp:23946 tcp:23946". This willallow connections to localhost:23946 and forward those to the emulator.

    In my case, I wanted to debug specific functions in the library. Therefore, I used a custom library loader that loaded the library and then stopped execution. I then attached IDA to the running process, movedthe instruction pointer to the next instruction to get past the breakpoint, and thenjump directly into the function I wanted to debug. This part will be describedin detail in upcoming post.

  6. To attach IDAto a running process, just load the library in IDA, go into the debuggeroptions and select the "Remote ARM Linux/Android debugger", go into "ProcessOptions" in the debugger menu, and set the hostname to localhost. If you usedthe same ports as above, you should not need to change anything else.

  7. Go intothe debugger menu again, this time choose "Attach to process…" and you shouldsee a list of all running processes. Select the one you are interested in,attach and start debugging.

Depending on what isbeing analyzed, it is possible to do a memory dump from the process into IDAand save the IDB. This may be good for future analysis, and there is always arisk of a crash somewhere that can terminate the debug session.

Also, if you have thelibrary or file to be analyzed open in IDA before the debugger is attached, IDAshould identify the memory address shift (due to ASLR) and ask if you want torebase the file / library.

Smali代码

Android Killer V1.3.1.0

1、打印Log

2、加载SO

3、打印Toast

4、弹出提示框

使用 mitmproxy + python 做拦截代理

https://blog.wolfogre.com/posts/usage-of-mitmproxy/

本文是一个较为完整的 mitmproxy 教程,侧重于介绍如何开发拦截脚本,帮助读者能够快速得到一个自定义的代理工具。

本文假设读者有基本的 python 知识,且已经安装好了一个 python 3 开发环境。如果你对 nodejs 的熟悉程度大于对 python,可移步到 anyproxy,anyproxy 的功能与 mitmproxy 基本一致,但使用 js 编写定制脚本。除此之外我就不知道有什么其他类似的工具了,如果你知道,欢迎评论告诉我。

本文基于 mitmproxy v4,当前版本号为 v4.0.1

mitmproxy 是什么

image

顾名思义,mitmproxy 就是用于 MITM 的 proxy,MITM 即中间人攻击(Man-in-the-middle attack)。用于中间人攻击的代理首先会向正常的代理一样转发请求,保障服务端与客户端的通信,其次,会适时的查、记录其截获的数据,或篡改数据,引发服务端或客户端特定的行为。

不同于 fiddler 或 wireshark 等抓包工具,mitmproxy 不仅可以截获请求帮助开发者查看、分析,更可以通过自定义脚本进行二次开发。举例来说,利用 fiddler 可以过滤出浏览器对某个特定 url 的请求,并查看、分析其数据,但实现不了高度定制化的需求,类似于:“截获对浏览器对该 url 的请求,将返回内容置空,并将真实的返回内容存到某个数据库,出现异常时发出邮件通知”。而对于 mitmproxy,这样的需求可以通过载入自定义 python 脚本轻松实现。

但 mitmproxy 并不会真的对无辜的人发起中间人攻击,由于 mitmproxy 工作在 HTTP 层,而当前 HTTPS 的普及让客户端拥有了检测并规避中间人攻击的能力,所以要让 mitmproxy 能够正常工作,必须要让客户端(APP 或浏览器)主动信任 mitmproxy 的 SSL 证书,或忽略证书异常,这也就意味着 APP 或浏览器是属于开发者本人的——显而易见,这不是在做黑产,而是在做开发或测试。

那这样的工具有什么实际意义呢?据我所知目前比较广泛的应用是做仿真爬虫,即利用手机模拟器、无头浏览器来爬取 APP 或网站的数据,mitmproxy 作为代理可以拦截、存储爬虫获取到的数据,或修改数据调整爬虫的行为。

事实上,以上说的仅是 mitmproxy 以正向代理模式工作的情况,通过调整配置,mitmproxy 还可以作为透明代理、反向代理、上游代理、SOCKS 代理等,但这些工作模式针对 mitmproxy 来说似乎不大常用,故本文仅讨论正向代理模式。

安装

“安装 mitmproxy”这句话是有歧义的,既可以指“安装 mitmproxy 工具”,也可以指“安装 python 的 mitmproxy 包”,注意后者是包含前者的。

如果只是拿 mitmproxy 做一个替代 fiddler 的工具,没有什么定制化的需求,那完全只需要“安装 mitmproxy 工具”即可,去 mitmproxy 官网 上下载一个 installer 便可开箱即用,不需要提前准备好 python 开发环境。但显然,这不是这里要讨论的,我们需要的是“安装 python 的 mitmproxy 包”。

安装 python 的 mitmproxy 包除了会得到 mitmproxy 工具外,还会得到开发定制脚本所需要的包依赖,其安装过程并不复杂。

首先需要安装好 python,版本需要不低于 3.6,且安装了附带的包管理工具 pip。不同操作系统安装 python 3 的方式不一,参考 python 的下载页,这里不做展开,假设你已经准备好这样的环境了。

安装开始。

在 linux 中:

在 windows 中,以管理员身份运行 cmd 或 power shell:

安装结束。

完成后,系统将拥有 mitmproxymitmdumpmitmweb 三个命令,由于 mitmproxy 命令不支持在 windows 系统中运行(这没关系,不用担心),我们可以拿 mitmdump 测试一下安装是否成功,执行:

应当可以看到类似于这样的输出:

运行

要启动 mitmproxy 用 mitmproxymitmdumpmitmweb 这三个命令中的任意一个即可,这三个命令功能一致,且都可以加载自定义脚本,唯一的区别是交互界面的不同。

mitmproxy 命令启动后,会提供一个命令行界面,用户可以实时看到发生的请求,并通过命令过滤请求,查看请求数据。形如:

image

mitmweb 命令启动后,会提供一个 web 界面,用户可以实时看到发生的请求,并通过 GUI 交互来过滤请求,查看请求数据。形如:

image

mitmdump 命令启动后——你应该猜到了,没有界面,程序默默运行,所以 mitmdump 无法提供过滤请求、查看数据的功能,只能结合自定义脚本,默默工作。

由于 mitmproxy 命令的交互操作稍显繁杂且不支持 windows 系统,而我们主要的使用方式又是载入自定义脚本,并不需要交互,所以原则上说只需要 mitmdump 即可,但考虑到有交互界面可以更方便排查错误,所以这里以 mitmweb 命令为例。实际使用中可以根据情况选择任何一个命令。

启动 mitmproxy:

应当看到如下输出:

mitmproxy 绑定了 *:8080 作为代理端口,并提供了一个 web 交互界面在 127.0.0.1:8081

现在可以测试一下代理,让 Chrome 以 mitmproxy 为代理并忽略证书错误。为了不影响平时正常使用,我们不去改 Chrome 的配置,而是通过命令行带参数起一个 Chrome。如果你不使用 Chrome 而是其他浏览器,也可以搜一下对应的启动参数是什么,应该不会有什么坑。此外示例仅以 windows 系统为例,因为使用 linux 或 mac 开发的同学应该更熟悉命令行的使用才对,应当能自行推导出在各自环境中对应的操作。

由于 Chrome 要开始赴汤蹈火走代理了,为了方便继续在 web 界面上与 mitmproxy 交互,我们委屈求全使用 Edge 或其他浏览器打开 127.0.0.1:8081。插一句,我用 Edge 实在是因为机器上没其他浏览器了(IE 不算),Edge 有一个默认禁止访问回环地址的狗屁设定,详见解决方案

接下来关闭所有 Chrome 窗口,否则命令行启动时的附加参数将失效。打开 cmd,执行:

前面那一长串是 Chrome 的的安装路径,应当根据系统实际情况修改,后面两参数设置了代理地址并强制忽略掉证书错误。用 Chrome 打开一个网站,可以看到:

image

同时在 Edge 上可以看到:

image

脚本

完成了上述工作,我们已经具备了操作 mitmproxy 的基本能力 了。接下来开始开发自定义脚本,这才是 mitmproxy 真正强大的地方。

脚本的编写需要遵循 mitmproxy 规定的套路,这样的套路有两个,使用时选其中一个套路即可。

第一个套路是,编写一个 py 文件供 mitmproxy 加载,文件中定义了若干函数,这些函数实现了某些 mitmproxy 提供的事件,mitmproxy 会在某个事件发生时调用对应的函数,形如:

第二个套路是,编写一个 py 文件供 mitmproxy 加载,文件定义了变量 addons,addons 是个数组,每个元素是一个类实例,这些类有若干方法,这些方法实现了某些 mitmproxy 提供的事件,mitmproxy 会在某个事件发生时调用对应的方法。这些类,称为一个个 addon,比如一个叫 Counter 的 addon:

这里强烈建议使用第二种套路,直觉上就会感觉第二种套路更为先进,使用会更方便也更容易管理和拓展。况且这也是官方内置的一些 addon 的实现方式。

我们将上面第二种套路的示例代码存为 addons.py,再重新启动 mitmproxy:

当浏览器使用代理进行访问时,就应该能看到控制台里有类似这样的日志:

这就说明自定义脚本生效了。

事件

上述的脚本估计不用我解释相信大家也看明白了,就是当 request 发生时,计数器加一,并打印日志。这里对应的是 request 事件,那拢共有哪些事件呢?不多,也不少,这里详细介绍一下。

事件针对不同生命周期分为 5 类。“生命周期”这里指在哪一个层面看待事件,举例来说,同样是一次 web 请求,我可以理解为“HTTP 请求 -> HTTP 响应”的过程,也可以理解为“TCP 连接 -> TCP 通信 -> TCP 断开”的过程。那么,如果我想拒绝来个某个 IP 的客户端请求,应当注册函数到针对 TCP 生命周期 的 tcp_start 事件,又或者,我想阻断对某个特定域名的请求时,则