一个Xposed和基于adbi的模块,它能够钩住针对Android操作系统的Java和本机方法。挂接方法的相关信息将记录为输出。
使用Android EagleEye完全由您自己承担风险
特征
- 能够钩住Java和本机方法
- 仅配置挂接自定义Java方法所需的文件
- 通过DexClassLoader动态加载钩子自定义Java方法
- 从系统库和应用程序库中钩住本机方法
- 采用反仿真器方法
目录
- EagleEye:Android EagleEye的源代码
- eagleeetest:eagleeeye的一个测试应用程序
- testcase配置:配置需要挂接的定制Java系统api、应用程序方法和本机lib(用于EagleEyeTest)
用法
确保您具有根访问权限并已安装XposedInstaller
遵循以下步骤:
- 安装EagleEye.apk并在XposedInstaller中启用此模块
- 重新启动Android设备
- 将属性rw.eagleeye.fr.uids设置为要为Java方法挂接的应用程序的uid,而对于本机挂接,请设置属性rw.eagleeye.nt.uids,例如:adb shell su-c setprop rw.eagleeye.fr.uids“10076 | 10078”用于Java挂接(uid由“|”分隔),adb shell su-c setprop rw.eagleeye.nt.uids“10076 | 10078”用于本地钩住
- adb shell su-c setprop rw.eagleeye.fr.uids“10076 | 10078”用于Java挂接(uid由“|”分隔)
- 亚洲开发银行外壳su-c setprop rw.eagleeye.nt.uids“10076 | 10078”,用于本地挂钩
- 重新启动要挂接的应用程序(每当加载应用程序时,EagleEye将读取rw.EagleEye.fr.uids和rw.EagleEye.nt.uids属性,因此如果要挂接其他应用程序,只需将这两个属性设置为适当的值并重新启动应用程序)
- 使用adb logcat-s EagleEye:I查看日志信息
如何钩住更多的JAVA方法
EagleEye默认钩住一些Java系统api(参考jni目录下com.mindmac.EagleEye.hookclass包和hooks/hook_api.c下的类),如果要钩住其他Java系统api或应用程序的方法,可以配置如下:
- Java系统api可以通过fr_sys_APIs.config定制(有关详细信息,请参阅配置文件格式部分)。请将此配置文件推送到Android设备的目录/data/local/tmp/。您可以自定义的默认api数量限制为500,您可以将属性rw.eagleeye.fr.sys_api_num设置为所需的值。
- Java应用程序的方法可以由fr_app_api.config自定义(有关详细信息,请参阅配置文件格式部分)。请将此配置文件推送到Android设备的目录/data/data/<package name of the application you want to hook>/。您可以自定义的默认方法数限制为500,您可以将属性rw.eagleeye.fr.app_api_num设置为所需的值。
- 重新启动要挂接的应用程序(EagleEye将在加载应用程序时重新加载配置文件)。
请确保挂接的应用程序可以读取fr_sys_apis.config和fr_app_apis.config(如果需要,请使用chmod)。
如何钩住更多本机方法
EagleEye使用adbi钩住本机方法(不需要注入部分),默认情况下钩住系统库中的一些本机方法(请参阅jni目录下的hook_api.c)。目前,您需要添加额外的本机代码来钩住所需的方法。请按照以下步骤挂接更多本机方法。唯一需要接触的文件是hook_api.c。
- 声明要替换目标方法的方法(参数类型和返回类型应与原始方法相同)。
- 初始化HOOK_INFO结构时,对于系统库中的方法,变量名应以system_HOOK_INFO开头,而对于应用程序自身库中的方法,变量名应以custom_HOOK_INFO开头。第二个成员是要挂接的方法的库名称(需要开头的关键字lib);第三个成员是目标方法;第四个和最后一个成员可以在步骤1中设置为已声明的方法。
- 实现步骤1中声明的方法。具体实现方案请参考hook_api.c。
- 在EagleEye项目目录下执行ndk build以重新生成本机代码。
- 将修改后的EagleEye应用程序重新安装到设备上。
- 要挂接应用程序自身库中的本机方法,需要额外的配置文件。请在本机lib.config中指定库名称(每行一个库名称,库名称应以lib关键字和.so开头,不需要),并将其推送到要挂接的应用程序的/data/data/<package name>。请确保挂接的应用程序可以读取本机的lib.config。
反仿真器
一些Android应用程序将检查运行时环境,看看它们是否在Android模拟器上运行。针对这种反仿真器技术,EagleEye采用了一些基于运行时钩子的方法。以Tim Strazzere编写的反仿真器项目为例,部署EagleEye后输出如下:
V/反仿真器(2226):检查污点跟踪…V/反仿真器(2226):hasAppAnalysisSpackage:falseV/反仿真器(2226):hasTaintClass:falseV/反仿真器(2226):hasTaintMemberVariables:falseV/反仿真器(2226):未检测到污点跟踪。V/反仿真器(2226):检查猴子用户…V/反仿真器(2226):isUserAMonkey:falseV/AntiEmulator(2226):未检测到Monkey用户。V/AntiEmulator(2226):正在检查调试器…V/AntiEmulator(2226):未检测到调试器。V/AntiEmulator(2226):正在检查QEmu env…V/AntiEmulator(2226):hasKnownDeviceId:falseV/AntiEmulator(2226):hasKnownPhoneNumber:falseV/AntiEmulator(2226):isOperatorNameAndroid:falseV/AntiEmulator(2226):hasKnownImsi:falseV/AntiEmulator(2226):hasEmulatorBuild:falseV/AntiEmulator(2226):hasPipes:falseV/AntiEmulator(2226):hasQEmuDriver:trueV/AntiEmulator(2226):hasQEmuFiles:falseV/AntiEmulator(2226):hasEmulatorAdb:trueV/AntiEmulator检测。
目前,EagleEye还没有考虑几种反仿真器方法。
配置文件格式
fr_sys_apis.config和fr_app_apis.config的格式相同。如下所述:
- 要挂接的api或方法由行分隔。
- EagleEye将读取的api或方法的数量受属性rw.EagleEye.fr.sys_api_num或rw.EagleEye.fr.app_api_num的限制。默认值设置为500。
- 每个API或方法都是smali格式的。例如,如果您想挂接[Intent.putExtra()](http://developer.android.com/reference/android/content/Intent.html#putExtra(java.lang.String,java.lang.String)),内容行将如下所示:Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
- Landroid/content/Intent;->putExtra(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
- 参数和返回类型可以留空,以挂接具有相同方法名的所有api或方法。例如,您可以如下配置内容行,以挂接Intent类下的所有putExtra方法:Landroid/content/Intent;->putExtra
- Landroid/内容/意图;->putExtra
- 要挂接构造函数,方案类似于Lpackage/name/class_name;->class_name(参数类型)。例如,如果要挂接Intent构造函数Intent(字符串操作),可以指定如下配置:Landroid/content/Intent;->Intent(Ljava/lang/String;)或Landroid/content/Intent;->Intent挂接所有Intent构造函数。
本机的lib.config格式非常简单。库名称用行分隔。每个库名称都应该以关键字lib和.开头,因此不需要。
有关更多详细信息,请参阅testcase\u configs下的配置文件。
日志格式
EagleEye将以JSON格式记录挂接方法的参数和返回值。挂接的应用程序的uid、挂接类型(framework system api-0x00、framework app method-0x01、native system api-0x10、native app method-x011)以及是否自定义了该方法将被记录。对于预定义的Java系统API和本机方法,将记录参数名称而不是参数类型。
典型的日志如下所示,“10078”表示目标应用程序的uid;“16”表示钩子类型,这里是本机系统api;“false”值表示此方法不是自定义的。
{“Basic”:[“10078”,“16”,“false”],“InvokeApi”:{“open”:{“filename”:“/data/data/com.mindmac.eagleeye/lib/libeagleyenative.so”,“access”:“0”,“permission”:“8”},“return”:{“int”:“50”}}
由于Android的Logcat会将超过1024字节的日志截短,EagleEye会将文件读写操作的内容分为多个部分,你可以根据id值重构内容。目标文件路径和文件内容都是十六进制字节。文件操作记录如下:
{“Basic”:[“10078”,“0”,“false”],“FdAccess”:{“path”:“2f73746f726167652f656d756c617465642f302f44796e616d69632e61706b”,“id”:“1577699679”}
{“Basic”[“10078”,“0”,“false”],“FileRW”:{“operation”:“write”,“数据”:EEDDC07E213F185F846FC2042032C1177D832B76D8F6A8EDEB78D0171AAD6B336EE81E813219C934C236953D3AD71376D7bff0caae08b149bfc7f45bc706eeeab7796c025c655bf58ca91113449738263c1863B930645FC3FCD947C9D6A864F3BF6CEB967895AD57F2886645B954B36835C68917D8FF79F1AE3835CBAE4BFCC161CBE7A8E5FCDFAD51CBFECBA842F659F690F0E54C9D127E317366095FCDDC5B93E1937BFE07504B07083100C38DAF0200000FC06000040B03040A0000080000568A,“id”:“1577699679”}
{“Basic”[“10078”,“0”,“false”],“FileRW”:{“operation”:“write”,“数据”:8C8DCB29DB31210976E2251A6F0A107A4180555aa6aa12760d1010280c7b78fcfec7ef2c8ae2cb5bf7266e5f48db73f7e51d01da4507bb0229DAAF8AC7BAF1F5E19DE1EC56AEB9983A7FE25EB2EDCF22BD96E1DE228D76D836C2208BF695FA43BA14509221510A408C214458420A1118161A87902003c3003010b6b0d6927169c59a992bc302c9d295f1b70787fa67c7be59850861f080779c2fa6ccab43983dbd1f239fa0a8f9b6580f840a054a3050ca00fa722c410081104,“id”:“1577699679”}
{“Basic”:[“10078”,“16”,“false”],“InvokeApi”:{“read”:{“handle”:“49”,7b01a0821720068e628ca6f56b40ed97d30a3173d2643e264832c748ac63e47ea8a93“:”1444149052“,“path”:“2f73746f726167652f656d756c617465642f302f44796e616d69632e61706b”},“return”:{“int”:“65557”}}
{“Basic”:[“10078”,“16”,“false”],“InvokeApi”:{“read”:{“handle”:“49”,FB8A1263E5FE8A9268E545D074EE49EF7DCAC6AF03F826F9369FEC267A4E1E5C1C4“:”1444149052“,“path”:“2f73746f726167652f656d756c617465642f302f44796e616d69632e61706b”},“return”:{“int”:“65557”}}