工欲善其事,必先利其器。要想更好的掌握安全安全技术,首先要把基础打牢,本章将介绍应用安全经常用到的工具和一些基础命令。
Cydia是由Jay Freeman(Saurik)领导,Okori Group以及UCSB大学合作开发为使用 iPhone、iPod touch、iPad等设备的越狱用户提供的类似App Store的软件商店以安装不被App Store接受的程序。它也是一个软件仓库的聚合器,带有几个被社区信任的源,大部分软件包的稳定版本都可以在这些源中找到。不过,用户也可以自定义添加软件添。
要安装Cydia首先需要对苹果设备进行越狱,只有越狱后的设备才能正常使用Cydia。如果对越狱不太了解,推荐使用爱思助手对设备进行越狱,可以通过图形界面引导越狱,如下图所示:
上图是 Cydia 的 Home 首页,和 App Store 有点类似,是一些热门 deb 软件的介绍和说明,右上角的 “ 重建加载 ” 键,用于页面显示不正常时,重刷加载页面。将 Home 页面拉到底,最下面显示的是当前设备类型、系统版本、 Cydia 版本等信息。
Cydia下方的工具栏共五个按键,分别是“Cydia”、“软件源”、“变更”、“已安装”、“搜索”,下面说明其具体功用。先从最重要的源添加,即“管理”讲起
➢ Cydia:Home 首页,和 App Store 有点类似,是一些热门 deb 软件的介绍和说明,右上角的 “ 重建加载 ” 键,用于页面显示不正常时,重刷加载页面。将 Home 页面拉到底,最下面显示的是当前设备类型、系统版本、 Cydia 版本等信息。
➢ 软件源:软件源就是一个 deb 软件库的索引,点右上角的“编辑”,然后点再左上角的“添加”,源地址输入栏中输入正确的源地址,点“添加源”后即可完成软件源的添加。
➢ 变更:显示的是Cydia中已添加的软件源列表中软件的版本变化情况。
➢ 已安装:通过Cydia安装的软件都会展示在此处。可以通过点击对已安装的软件进行管控,如卸载、降级等。
➢ 搜索:用于搜索需要安装的软件名字。如果搜索所需的软件无果,可以在添加包含该软件软件源后重新搜索。
如果设备越狱后依然无法正常使用Cydia,可尝试通过爱思助手安装由Electra越狱团队发布的 Cydia 的替代品Sileo。
Magisk是大神吴泓霖开发的一套开放源代码的Android(5.0以上版本)自定义工具套组,内置了Magisk Manager(图形化管理界面)、Root管理工具、SElinux补丁和启动时认证/dm-verity/强制加密移除等功能。Magisk同时提供了在无需修改系统文件的情况下更改/system或/vendor分区内容的接口,利用与Xposed类似的模块系统,开发者可以对系统进行修改或对所安装的软件功能进行修改等。
本节主要介绍使用Magisk对Android设备进行Root。对设备进行Root首先需要对设备的Bootloader 进行解锁,只有解锁后才可以通过刷机等一系列操作完成Root。现在国内大部分手机厂商已经彻底关闭了Bootloader解锁方式。因此这里使用Google出产 pixel 系列手机进行Root演示。
将手机的 BootLoader 状态进行解锁,开发者模式下,开启 OEM unlocking,如下图所示:
进入BootLoader模式
1
|
adb reboot bootloader
|
BootLoader 状态下,解锁 BL,根据屏幕显示进行操作
1
|
fastboot flashing unlock 或 fastboot oem unlock
|
在Google官网下载设备对应的系统镜像https://developers.google.com/android/images#taimen 解压缩镜像文件,将其中的boot.img推送到手机的SDCard中,安装Magsik,并对boot.img进行patch。Magsik会将处理后的boot.img存放在/sdcard/Download目录中,并重命名为magisk_patched-xxxx.img,具体操作流程如下图:
将patch后的boot.img拷贝到本地,然后将其刷入需要Root的设备:
1
2
3
|
adb pull
/
sdcard
/
Download
/
magisk_patched
-
23000_T5HA4
.img .
adb reboot bootloader
fastboot boot magisk_patched
-
23000_T5HA4
.img
|
重启后进入系统,Magisk已经成功安装(如果依然显示为安装,可能为获取失败,可按之前流程操重新尝试)。但此时的Root权限为临时root,需要转位永久Root。进入 Magisk Manager,选择安装(Install)——(直接安装)Direct Install,安装完成后选择(重启设备)Reboot。完成重启受设备的临时 root将转换为永久 root。
至此已经彻底完成了设备的Root工作。可以在此设备上肆意妄为的安装任何需要的工具。
备注:Root时刷入的patch后的boot.img需要和目标设备的系统版本保持一致,否则将导致系统无法开启wifi等问题。
EdXposed是适用于Android系统的Hook框架。基于 Riru 的 ART hook 框架 (最初用于 Android Pie) ,使用 YAHFA (或 SandHook) 进行 hook, 支持Android 8.0到Android11的系统。其提供了与原版 Xposed 相同的 XposedBridge API,可在Android高权限模式下运行的框架服务,可以在不修改APP文件的情况下修改程序的运行,基于它可以制作出许多功能强大的Xposed模块,且在功能不冲突的情况下同时运作。
上一节中对Android设备Root时已经安装了Magisk。EdXposed可通过Magisk进行安装,在其模块功能中搜索Riru和EdXposed模块并选择适配自己系统的进行安装。同时安装EdXposedManager客户端方便后续管理EdXposed插件。打开EdXposedManager软件首页中展示EdXposed框架已激活,说明EdXposed框架已经完美安装到当前的设备中。如果显示的未激活,可能是因为选择Riru和EdXposed模块与当前系统不匹配,在Magisk中删除之前安装的模块,重新下载对应版本的模块即可。EdXposed正确安装成功后,如下图所示:
EdXposed框架提供了与原版 Xposed框架相同的 XposedBridge API, 因此基于该 框架编写的模块与原版 Xposed 框架编写的模块是完全兼容的。因两个Hook框架使用的API相同所以使用方法和Xposed框架也是一致的。如果之前已有Xposed模块的开发经验,可以略过后面的的教程,直接进行EdXposed模块开发。
创建Xposed的模块时可根据交互情况选择创建的工程模版。此处为了让大家快速上手Xposed模块的开发,通过简单的无需交互的范例进行讲解。首先通过Android Studio 创建一个No Activity的工程,如下图所示:
此时创建的为普通Android 应用项目,需要在项目的AndroidManifest.xml文件中增加以下三个属性值,用于将该应用转化为xposed模块。
1
2
3
4
5
6
7
8
|
# 标记该应用为xposed模块,用于xposed框识别
<meta
-
data android:name
=
"xposedmodule"
android:value
=
"true"
/
>
# 对该xposed模块的描述
<meta
-
data
android:name
=
"xposeddescription"
android:value
=
"Edxposed demo!"
/
>
# 模块支持的最低API版本
<meta
-
data android:name
=
"xposedminversion"
android:value
=
"54"
/
>
|
添加完属性值的AndroidManifest.xml如下图所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?xml version
=
"1.0"
encoding
=
"utf-8"
?>
<manifest xmlns:android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.hook.xposed"
>
<application
android:icon
=
"@mipmap/ic_launcher"
android:label
=
"@string/app_name"
>
<meta
-
data
android:name
=
"xposedmodule"
android:value
=
"true"
/
>
<meta
-
data
android:name
=
"xposeddescription"
android:value
=
"Edxposed Xposed Test"
/
>
<meta
-
data
android:name
=
"xposedminversion"
android:value
=
"54"
/
>
<
/
application>
<
/
manifest>
|
两种添加Xposedbridge Api开发依赖的方式。方式一:通过gradle添加,即在项目的app目录下的build.gradle文件中添加开发时所需的Xposedbridge Api环境,如下图所示:
1
2
3
4
|
dependencies {
compileOnly
'de.robv.android.xposed:api:82'
compileOnly
'de.robv.android.xposed:api:82:sources'
}
|
项目根目录的settings.gradle的repositories属性中增加配置项,如下图所示:
1
2
3
|
repositories {
jcenter()
}
|
方式二:下载XposedBridgeApi-82.jar,将jar包放置到项目app目录下的libs目录中文件中添加开发时所需的Xposedbridge Api环境,同时在build.gradle文件进行配置,如下图所示:
1
2
3
|
dependencies {
compileOnly files(
'libs/XposedBridgeApi-82.jar'
)
}
|
配置Hook模块的入口,即通知EdXposed框架该模块的是从哪里开始启动。在该项目的main目录下新建assets目录,并在该目录下创建名为xposed_init的文件。将做为入口的class完整路径写入该文件即可,如下所示:
1
|
com.hook.xposed.InitHook
|
以上配置完成后可以正式开始使用EdXposed框架来进行hook操作。Hook操作主要就是使用到了Xposed中的两个比较重要的方法,handleLoadPackage获取包加载时候的回调并拿到其对应的classLoader;findAndHookMethod对指定类的方法进行Hook。它们的详细定义如下所示:
具体使用场景参考模块入口类InitHook中的的代码,如下图所示:
现在所有开发Hook模块的准备工作已经完成,正式开始实战操作。我们先准备一款慕目标应用,界面展示一个按钮,点击显示返回值。运行效果如下图所示:
下图则为该应用的核心代码,当点击“开始点击”按钮程序会调用getTextViewShowData函数获取需要展示的数据。我们的目标是通过Hook的方式将该数据拦截替换其返回数据。
开始编写Hook代码,首先确认目前函数名和其在类的全路径,在此演示示例中目标函数没有接收参数,因此不用关心参数问题。
将Hook模块应用用打包后安装纸装有目标应用的设备,在EdXposedManager客户端的模块管理中启用该模块,并重启设备使该Hook模块生。具体操作参考下图:
设备完成重启后,Hook模块的功能已经正常生效。打开目标应用点击按钮,界面上展示的内容已经是被我们替换后的内容。具体效果如下图所示:
实际使用中目标应用代码量通常比较大,此类应用在打包的时候dex中的引用方法已经超过65536,则会拆分成多个dex文件。Hook框架默认情况下是对应用中的主dex文件进行操作,因此会出现类的路径和和方法名都正确,却出现找不到方法的情况。android加载dex文件后会创建一个application类,然后会调用attach方法,attach方法的接收的参数是context,通过context可以获取相应dex文件的classloader。只要Hook了attach方法通过其获取classloader就能搜索到目标类就能解决该问题,具体实现代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/
/
Multi
-
dex support
findAndHookMethod(
"android.app.Application"
,
loadPackageParam.classLoader,
"attach"
,
Context.
class
,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
Context context
=
(Context) param.args[
0
];
ClassLoader classLoader
=
context.getClassLoader();
/
/
此处开始正常进行hook操作
.....
}
}
);
|
备注:此方法不仅对多dex应用有效,在针对加壳应用Hook时也能收到意想不到的效果。
在真实环境对函数进行hook操作时,目标函数往往都是带有参数的,刚才示例中的函数是无参,下面介绍一下带参数函数Hook。假设之前Hook的函数带有两个参数,如下所示:
1
2
3
4
5
|
......
public String getTextViewShowData(String
input
,
int
count) {
return
"Hello, welcome to here!!!"
;
}
......
|
Java语言是支持函数重载的,即可以在同一个类中存在多个函数名称相同但参数列表不同的函数。编写Hook代码时如果仅指定目标方法名,未指定该方法接受的参数类型,将导致Hook模块无法准确定位到该函数。因此在Hook带参数的目标方法时必须指定匹配的参数类型,以刚才函数为例,带参数Hook如下图所示。
1
2
3
4
5
6
7
|
XposedHelpers.findAndHookMethod(
"com.demo.app.MainActivity"
, lpparam.classLoader,
"getTextViewShowData"
, String.
class
,
int
.
class
, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
/
/
在getTextViewShowData方法执行前拦截并修改
param.setResult(
"this function is be hooked!!!"
);
}
});
|
刚才的例子中函数接受的参数都是标准类型中,正在工作或学习中需要通过反编译的方式确定目标函数名和其所在类,然后编写hook模块。这时就会经常遇到函数的参数是自定义类型,不是标准数据类型。针对此种情况Xposed也提供了解决方案,具体代码时如下图所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Class<?> customClass
=
XposedHelpers.findClass(
"自定义变量的的完整路径"
, classLoader);
findAndHookMethod(
"目标类名"
,
classLoader,
"目标方法名"
,
String.
class
,
customClass,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
}
}
);
|
当熟练掌握本节时你已经从一个Hook开发小白成长为一个中级开发工程师。
Frida是面向开发人员、逆向工程师和安全研究人员的支持多平台的动态测试工具包。使用者可以通过该工具将 JavaScript代码片段或自定义的库注入到 Windows、macOS、Linux、iOS、Android平台的应用程序中,注入的JavaScript代码在执行时可以完全访问宿主程序的内存、hook函数,甚至可在进程内调用本地函数 。同时Frida 还为使用者提供了一系列的基于 Frida API 构建的简单工具。 使用者可以按原样使用这些API,也可根据具体的场景按需对这些API进行调整。
Frida分为客户端和服务端,需要两者配合才能正常使用。下面将以Mac和Android平台为例对该工具的安装和使用进行介绍。官网推荐使用pip进行安装,Python的版本最好为3.0以上的版本。
1
|
$ pip3 install frida
-
tools
|
安装Frida服务端到Android手机,首先到https://github.com/frida/frida/releases 下载相应版本的服务端程序,然后通过下列命令进行安装并启动。
1
2
3
4
5
|
adb push frida
-
server
/
data
/
local
/
tmp
adb shell
/
/
进入到Android的命令行模式
$ su
/
/
切换到root模式
# chemod a+x /data/local/tmp/frida-server
# ./data/local/tmp/frida-server
|
为保证客户端和服务端正常通讯需要进行端口映射
1
2
|
adb forward tcp:
27042
tcp:
27042
adb forward tcp:
27043
tcp:
27043
|
可通过frida-ps -U命令验证之前部署的frida服务是否正常,该命令用于查询出当前Android设备中所有正在运行的进程。
1
2
3
4
5
6
7
8
9
10
11
|
# 查询usb连接的设备上的进程信息
$ frida
-
ps
-
U
PID Name
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
5805
com.google.android.gms
5366
com.google.android.gms.persistent
11067
com.google.android.gms.ui
7371
com.google.android.gms.unstable
5649
com.google.android.googlequicksearchbox
5592
com.google.android.googlequicksearchbox:interactor
5628
android.process.media
|
Frida提供了六个对新手用户非常友好的的命令行工具frida-ls-devices,frida-trace,frida-ps,frida,frida-discover,frida-kill。这些工具可以让使用者在不用自己开发注入模块的情况下快速上手frida。
frida-ls-devices用于列出附加设备的命令行工具,在与多个设备交互时非常有用。
1
2
3
4
5
6
|
$ frida
-
ls
-
devices
Id
Type
Name
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
local local Local System
CVH7N15A20001095 usb Nexus
6P
socket remote Local Socket
|
frida-trace工具可以用来追踪指定的函数的调用,传入的参数都是可以使用通配符的,在分析程序时非常用帮助。
1
2
3
4
5
6
7
8
|
# 跟踪进程中的recv* 和 send* API调用
$ frida
-
trace
-
i
"recv*"
-
i
"send*"
<进程名>
# 在应用程序中跟踪ObjC方法调用
$ frida
-
trace
-
m
"ObjC"
<进程名>
# 在设备中打开应用程序并跟踪函数call的调用
$ frida
-
trace
-
U
-
f <进程名>
-
I
"call"
# 在Android设备上的指定应用程序中跟踪所有JNI函数的调用
$ frida
-
trace
-
U
-
i
"Java_*"
<进程名>
|
备注:参数中的-U代表的是USB,当参数重加入-U参数说明刚命令的操作对象是通过USB连接的设备。
frida-ps是一个用于列出进程的命令行工具,在与远程系统交互时非常有用。
1
2
3
4
5
6
|
# 显示通过usb连接的设备上的进程信息
$ frida
-
ps
-
U
# 显示通过usb连接的设备上活跃的进程信息
$ frida
-
ps
-
Ua
# 显示通过usb连接的设备上安装的应用信息
$ frida
-
ps
-
Uai
|
frida可以模拟出类似IPython(或 Cycript)的交互窗口,让使用者可以实现对进程快速和轻松的调试。
1
2
|
# Frida连接到usb连接的设备上的Chrome,并在调试模式下加载 test.js
$ frida
-
U Chrome
-
l test.js
-
-
debug
|
frida-discover 是一个用于发现程序内部函数的工具,经常配合 frida-trace使用。通过frida-discover发现程序中的函数,然后可以使用 frida-trace 对发现的函数进行跟踪。
1
2
3
|
# 发现应用程序中的内部函数
$ frida
-
discover
-
n <进程名>
$ frida
-
discover
-
p <进程
id
>
|
frida-kill这是一个用于杀死进程的命令行工具。需要配合frida-ls-devices和frida-ps工具中识别的设备id和进程id使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
$ frida
-
kill
-
D <DEVICE
-
ID
> <PID>
# 查询当前连接的设备
$ frida
-
ls
-
devices
Id
Type
Name
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
local local Local System
CVH7N15A20001095 usb Nexus
6P
socket remote Local Socket
# 列出指定设备上活跃的进程信息
$ frida
-
ps
-
D CVH7N15A20001095
-
a
PID Name
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
5805
com.google.android.gms
5366
com.google.android.gms.persistent
11067
com.google.android.gms.ui
7371
com.google.android.gms.unstable
5649
com.google.android.googlequicksearchbox
5592
com.google.android.googlequicksearchbox:interactor
5628
android.process.media
# 杀死制定设备上的进程
$ frida
-
kill
-
D CVH7N15A20001095
5805
|
frida框架支持python语言,可以通过python语言实现更多复杂的需求。在使用python开发frida模块前需要了解frida的attach和spawn两种模式,具体区别如下:
attach模式附加已经运行的进程
1
2
3
4
5
|
# Attach 到目标进程
process
=
frida.attach(target_process)
# 加载jscode 到目标进程
script
=
process.create_script(script_code)
script.load()
|
spawn模式启动调试进程
1
2
3
4
5
6
7
8
9
10
|
# 启动指定的进程
pid
=
device.spawn([packename])
# attach到新创建的进程
process
=
device.attach(pid)
# 加载jscode 到目标进程
script
=
process.create_script(jscode)
script.on(
'message'
, on_message)
script.load()
# 新创建的进程为挂起状态,调用resume将进程恢复
device.resume(pid)
|
正式开始开发前还需要了解python中怎么frida连接到目标设备,frida提供三种获指定设备方式。
1
2
3
4
5
6
7
|
# 获取指定设备id的设备
device
=
frida.get_device_manager().get_device(
"device id"
)
# 获取远程的设备
manager
=
frida.get_device_manager()
device
=
manager.add_remote_device(
"30.128.25.128:8080"
)
# 获取通过usb连接的设备
device
=
frida.get_usb_device()
|
frida使用python和加载JavaScript代码 Hook Java层的示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import
sys
import
frida
# 获取通过usb连接的设备
device
=
frida.get_usb_device()
# 启动指定的进程
pid
=
device.spawn([
"com.frida.test"
])
# attach到新创建的进程
session
=
device.attach(pid)
# 新创建的进程为挂起状态,调用resume将进程恢复
device.resume(pid)
jscode
=
"""
Java.perform(function(){
var main=Java.use("com.frida.test.MainActivity");
main.test.implementation = function()
{
console.log("You have been Hooked");
}
});
"""
def
on_message(message,data):
# message的类型为map,取出key payload 的value
print
(message[
"payload"
])
script
=
session.create_script(jscode)
# 设置message回调函数为on_message。js代码调用send就会发到on_message
script.on(
"message"
,on_message)
script.load()
sys.stdin.read()
|
frida是一个非常强大的Hook框架,不但可以Hook Java层的代码,还可以对Native层进行Hook。Hook Native层的代码示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import
frida
import
sys
# 获取通过usb连接的设备
device
=
frida.get_usb_device()
# 启动指定的进程
pid
=
device.spawn([
"com.frida.test"
])
# attach到新创建的进程
session
=
device.attach(pid)
# 新创建的进程为挂起状态,调用resume将进程恢复
device.resume(pid)
jscode
=
"""
var openPtr = Module.findExportByName("libc.so", "open");
Interceptor.attach(openPtr, {
onEnter : function(args){
var pathPtr = args[0];
send("open called ! path=" + pathPtr.readUtf8String());
},
onLeave : function(retval){
send("open leave.....");
}
});
"""
def
on_message(message, data):
# message的类型为map,取出key payload 的value
print
(message[
"payload"
])
script
=
session.create_script(jscode)
# 设置message回调函数为on_message。js代码调用send就会发到on_message
script.on(
"message"
, on_message)
script.load()
sys.stdin.read()
|
至此你已经熟练掌握frida的基本操作,赶紧去找个目标应用去实际操作一下吧。
objection是基于Frida框架开发的自动化hook工具包,该工具支持Android和IOS平台。如果你不擅长进行代码开发,但又想使用frida进行一些复杂的hook操作,那objection将是一个非常不错的工具。
frida依赖python 3.x的版本,安装objection可使用以下命令:
1
|
pip3 install objection
|
完成安装后在终端命令中输入objection命令。执行结果显示如下图,说明已经安装成功。正式使用objection前需在手机端启动frida-server,并进行端口转发。
通过应用的包名或者bundleID附加需要调试的目标应用,进入到objection提供的交互界面,类似于ipython的交互环境。
1
|
objection
-
g [packageName
/
bundleID] explore
|
obejction采用attach附加模式进行Hook。如果我们需要在应用启动时就进行Hook可以通过如下的方式启动objection。
1
|
objection
-
g packageName explore
-
-
startup
-
command
'android hooking watch class_method xxxx'
|
查看目标应用程序在设备内的存储路径,直接在交互界面输入“env”命令即可,结果如图所示:
如目标应用为Android应用,可通过以下命令查看该应用的的组件信息:
1
2
3
4
5
6
|
# 查看应用的activity组件信息
android hooking
list
activities
# 查看应用的service组件信息
android hooking
list
services
# 查看应用的broadcast receiver组件信息
android hooking
list
receivers
|
既然能查看目标应用的组件信息,亦可启动目标应用的组件:
1
2
3
4
|
# 启动指定的activity组件
android intent launch_activity [class_activity]
# 启动指定的service组件
android intent launch_service [class_service]
|
目标应用已加载到内存中的类和方法的相关操作
1
2
3
4
5
6
7
8
|
# 查看内存中所有的类
android
/
ios hooking
list
classes
# 查看指定类中所有的方法
android
/
ios hooking
list
class_methods <class_name>
# 查找指定特征的类
android
/
ios hooking search classes <class_name>
# 查找指定特征的方法
android
/
ios hooking search methods <method_name>
|
使用objection进行hook操作
1
2
3
4
5
6
7
8
9
10
11
|
# hook指定类下所有的方法
android
/
ios hooking watch
class
[class_name]
# hook指定类中的指定方法
# --dump-args : 打印参数
# --dump-backtrace : 打印调用栈
# --dump-return : 打印返回值
android
/
ios hooking watch class_method [class_name]
-
-
dump
-
args
-
-
dump
-
backtrace
-
-
dump
-
return
# 设置返回值,目前仅支持bool类型
android
/
ios hooking
set
return_value [class_name] false
# 生成frida的hook代码
android
/
ios hooking generate simple [class_name]
|
调用执行目标应用中的方法
1
2
3
4
|
# 搜索指定类的实例, 获取该类的实例id
search instances search instances [class_name]
# 通过实例id直接调用该类中的方法
android heap execute [instance_id] [method_name]
|
如果目标应用启用SSL校验,可通过objection进行关闭
1
|
android
/
ios sslpinning disable
|
目标应用内存操作
1
2
3
4
5
6
7
8
|
# 枚举当前进程模块
memory
list
modules
# 查看指定模块的导出函数
memory
list
exports [lib_name]
# 将导出函数的结果保存到指定的文件
memory
list
exports [lib_name]
-
-
json result.json
# 搜索内存
memory search
-
-
string
-
-
offsets
-
only
|
其它常用命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 尝试对抗root检测
android root disable
# 尝试模拟root环境
android root simulate
# 截图
android
/
ios ui screenshot [image.png]
# 对抗越狱检测
ios jailbreak disable
# dump keychain中的内容
ios keychain dump
# 尝试关闭ios生物特征认证
ios ui biometrics_bypass
# 执行shell命令
android shell_exec [command]
|
Tweak是一款依赖Cydia Substrate框架的越狱插件开发工具,该工具通过创建dylib动态库注入到宿主进程,完成各种Hook操作,让开发者在无需要破解iOS系统的情况下,快速开发出功能强大的tweak插件。
进行Tweak开发前需要安装配theos环境,theos提供了一组工具和库,可以帮助开发者快速创建、编译和部署tweak。具体环境配置命令如下所示:
1
2
3
4
5
6
7
|
# 将theos 下载安装到指定目录中
git clone
-
-
recursive https:
/
/
github.com
/
theos
/
theos.git
/
opt
/
theos
# 将theos添加到环境变量中
export THEOS
=
/
opt
/
theos
export PATH
=
"$THEOS/bin:$PATH"
# 安装签名工具,用于对编译完成后的文件签名
brew install ldid
|
Theos环境搭建完成后就可以开始创建Tweak项目。在终端中执行"nic.pl"命令,根据输出的提示信息选择tweak模版进行创建。然后按着提示依此输入工程名称、包名、作者名称等信息即可完成创建,具体命令如下图所示:
命令执行成功后将在当前目录下创建一个名为testtweak的工程目录。工程目录中默认共生成四个文件,具体文件信息如下图所示:
control:该文件中是当前工程的配置信息介绍,如果工程名称、包名、作者名称、版本号依赖等。
Makefile:主要作用是自动化构建项目,文件中指定待编译的源代码、依赖信息和编译配置信息等。
TestTweak.plist:此文件用于存储的配置信息。配置信息中的Bundle ID决定了当前项目对哪些些应用生效。具体配置信息如下所示:
1
|
{
Filter
=
{ Bundles
=
(
"com.test.demo"
,
"com.test.demo1"
); }; }
|
Tweak.x:是Theos生成的源代码文件,该文件中的代码使用Logos语法进行开发。具体代码示例如下图所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
%
hook ClassName
/
/
Hooking a
class
method
+
(
id
)sharedInstance {
return
%
orig;
}
/
/
Hooking an instance method with an argument.
-
(void)messageName:(
int
)argument {
%
orig;
}
/
/
Hooking an instance method with no arguments.
-
(
id
)noArguments {
%
orig;
}
%
end
|
正式进行Tweak插件开发前还需要学习一下Logos语法。Logos是Cydia Substrate框架所提供的一组用于实现Hook操作的宏定义,语法简单便于开发者快速针对目标应用进行Hook开发。下面将简单介绍了一些经常用到的语法,如果想要更加深入的学习Logos语法可以看官方文档。
%hook和%end组合,用于Hook目标类,在代码块中可以直接写需要Hook的方法,代码示例如下:
1
2
3
4
5
6
|
%
hook ClassName
/
/
Hooking a
class
method
+
(
id
)sharedInstance {
return
%
orig;
}
%
end
|
%group和%end组合,用于对Logos代码进行分组管理,每个声明的组都需要需要使用%ctor和%init进行初始化操作,代码示例如下:
1
2
3
4
5
6
7
8
9
10
11
|
%
group testGroup
%
hook ClassName
/
/
Hooking a
class
method
+
(
id
)sharedInstance {
return
%
orig;
}
%
end
%
end
%
ctor {
%
init(testGroup);
}
|
%new,用于在Hook的目标的类中添加新的方法,代码示例如下:
1
2
3
4
5
|
%
hook ClassName
%
new
-
(void)addNewMethod {
}
%
end
|
%orig,调用原始方法,可以传入自定义参数和接收原始方法的返回值,示例代码如下:
1
2
3
4
5
6
7
8
9
10
|
%
hook ClassName
-
(
int
)add:(
int
)a to:(
int
)b {
if
(a !
=
0
) {
/
/
Return original result
if
`a`
is
not
0
return
%
orig;
}
/
/
Otherwise, use
1
as `a`
return
%
orig(
1
, b);
}
%
end
|
%log,输出目标方法的将函数的类名、参数等信息输出到,示例代码如下:
1
2
3
4
5
|
%
hook ClassName
-
(void)targetMethod:(
id
)arg1 {
%
log
}
%
end
|
现在开始我们的第一个Tweak插件开发,目标进程以SpringBoard为例进行讲解。对SpringBoard进程中的[SpringBoard applicationDidFinishLaunching]方法尽心Hook,添加弹窗代码。SpringBoard启动时进弹窗,具体代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
#import <SpringBoard/SpringBoard.h>
%
hook SpringBoard
-
(void)applicationDidFinishLaunching:(
id
)application {
%
orig;
UIAlertView
*
alert
=
[[UIAlertView alloc] initWithTitle:@
"Test"
message:@
"Tweak test!!!"
delegate:nil
cancelButtonTitle:@
"确定"
otherButtonTitles:nil];
[alert show];
}
%
end
|
在编译安装之前还需要设置目标手机的IP,否则将安装失败。配置完成代后便可在终端中切换到项目所在目进行编译安装。相关命令如下图所示:
1
2
3
4
|
# 设置Tweak插件安装到目标手机的IP,否则安装将失败
export THEOS_DEVICE_IP
=
[目标手机IP]
# 编译并安装Tweak插件
make do
|
安装成功后SpringBoard将重新启动加载Tweak插件,效果如下图所示。至此你已经初步掌握了Tweak工具的使用。
Drozer是由MWR InfoSecurity 开发的 针对Android应用的安全测试框架。该框架是一款交互式的安全测试工具,支持真实的 Android 设备和模拟器,可以通过测试应用与其它应用程序进行交开展复杂的测试活动,只需很少时间即可评估与 Android 应用安全相关的问题。通过该工具可以帮助安全人员或者开发者 快速发现Android应用中的安全漏洞。
Drozer运行需要依赖python2.x和java环境,在正式安装使用前需要先将其依赖的运行环境配置好。Drozer分为两部分,一部分是客户端,另一部分是手机端代理。手机端代理需要安装在目标设备,用于客户端和目标设备通信时数据代理转发。官网下载地址https://labs.f-secure.com/tools/drozer。
以Mac电脑为例进行安装介绍,在终端中切换到存放drozer-2.4.4-py2-none-any.whl文件的目录下,然后运行一下命令:
1
2
|
# Drozer依赖python 2.x,此处的pip 必须为python 2.x的版本
pip install drozer
-
2.4
.
4
-
py2
-
none
-
any
.whl
-
-
ignore
-
installed pyOpenSSL
|
安装Drozer运行时所必需的依赖
1
2
3
|
pip install protobuf
=
=
3.17
.
3
pyOpenSSL Twisted service_identity
# 安装 Mac Command Line
xcode
-
select
-
-
install
|
备注:安装过程中可能会会遇到网络原因导致下载文件超时报错的情况,重新执行命令直到安装成功即可。
使用数据线将手机和电脑进行连接,安装agent到手机并开启服务。电脑的终端中执行端口转发命令和连接手机命令后,如下图所即可正式开始使用drozer工具。
1
2
3
4
|
# 端口转发
adb forward tcp:
31415
tcp:
31415
# 连接drozer
drozer console connect
|
通过app.package.info模块查看目标应用的基本信息:
1
|
dz> run app.package.info
-
a package_name
|
查看目标应用的攻击面,主要是指Android四大组件中export属性设置为ture的组件:
1
|
dz> run app.package.attacksurface package_name
|
查看目标应用的暴露的activity组件信息:
1
2
|
# 其它组件信息查询命令类似,只需更改命令中的组件类型即可
dz> run app.activity.info
-
a package_name
|
尝试启动导出的activity组件,可通过该功能对组件进行拒绝服务检测:
1
2
3
4
5
|
# 启动时使用空action
dz> run app.activity.start
-
-
component package_name activity_name
# 启动时指定action
dz> run app.activity.start
-
-
component package_name activity_name
-
-
action android.intent.action.XXX
|
目标应用敏感数据泄露检测:
1
2
3
4
|
# 获取目标应用中对外暴露的URI
dz> run scanner.provider.finduris
-
a package_name
# 通过暴露的URI进行信息检索
dz> run app.provider.query content:
/
/
uri
/
passwords
/
-
-
vertical
|
目标应用Content Provider组件的脆弱性检测:
1
|
dz> run scanner.provider.injection
-
a package_name
|
目标应用全局可读\可写文件检测:
1
2
3
4
|
# 全局可写文件检测
dz> run scanner.misc.writablefiles
-
-
privileged
/
data
/
data
/
pacakge_name
# 全局可读文件检测
dz> run scanner.misc.readablefiles
-
-
privileged
/
data
/
data
/
pacakge_name
|
更多【移动应用安全与风控——应用分析常用工具】相关视频教程:www.yxfzedu.com