Frida进阶:Objection内存漫游、hookanywhere、抓包

更新时间:2023-07-26 00:58:19 阅读: 评论:0

Frida进阶:Objection内存漫游、hookanywhere、抓包
本章中我们进⼀步介绍,⼤家在学习和⼯作中使⽤Frida的实际场景,⽐如动态查看安卓应⽤程序在当前内存中的状态,⽐如指哪⼉就能hook哪⼉,⽐如脱壳,还有使⽤Frida来⾃动化获取参数、返回值等数据,主动调⽤API获取签名结果sign等⼯作实际⾼频场景,最后介绍⼀些经常遇到的⾼频问题解决思路,希望可以切实地帮助到读者。
1 内存漫游
Frida只是提供了各种API供我们调⽤,在此基础之上可以实现具体的功能,⽐如禁⽤证书绑定之类的脚本,就是使⽤Frida的各种API来组合编写⽽成。于是有⼤佬将各种常见、常⽤的功能整合进⼀个⼯具,供我们直接在命令⾏中使⽤,这个⼯具便是objection。
objection功能强⼤,命令众多,⽽且不⽤写⼀⾏代码,便可实现诸如内存搜索、类和模块搜索、⽅法hook打印参数返回值调⽤栈等常⽤功能,是⼀个⾮常⽅便的,逆向必备、内存漫游神器。objection的界⾯及命令如下图图2-1所⽰。
1.1 获取基本信息
⾸先介绍⼏个基本操作:
键⼊命令之后,回车执⾏;
help:不知道当前命令的效果是什么,在当前命令前加help⽐如,help env,回车之后会出现当前命令的解释信息;
按空格:不知道输⼊什么就按空格,会有提⽰出来,上下选择之后再按空格选中,⼜会有新的提⽰出来;
jobs:作业系统很好⽤,建议⼀定要掌握,可以同时运⾏多项(hook)作业;
我们以安卓内置应⽤“设置”为例,来⽰范⼀下基本的⽤法。
在⼿机上启动frida-rver,并且点击启动“设置”图标,⼿机进⼊设置的界⾯,⾸先查看⼀下“设置”应⽤的包名。
# frida-ps -U|grep -i tting
7107  ings
13370  ings.intelligence
再使⽤objection注⼊“设置”应⽤。
# objection -g ings explore
启动objection之后,会出现提⽰它的logo,这时候不知道输⼊啥命令的话,可以按下空格,有提⽰的命令及其功能出来;再按空格选中,⼜会有新的提⽰命令出来,这时候按回车就可以执⾏该命令,见下图2-2执⾏的应⽤环境信息命令env和frida-rver版本信息命令。
1.2 提取内存信息
查看内存中加载的库
运⾏命令memory list modules,效果如下图2-3所⽰。
查看库的导出函数
运⾏命令memory list exports libssl.so,效果如下图2-4所⽰。
将结果保存到json⽂件中
当结果太多,终端⽆法全部显⽰的时候,可以将结果导出到⽂件中,然后使⽤其他软件查看内容,见
下图2-5。
# memory list exports libart.so --json /root/libart.json
Writing exports as json to /root/
Wrote exports to: /root/libart.json
提取整个(或部分)内存
命令是memory dump all from_ba,这部分内容与下⽂脱壳部分有重叠,我们在脱壳部分介绍⽤法。
搜索整个内存
命令是memory arch --string --offts-only,这部分也与下⽂脱壳部分有重叠,我们在脱壳部分详细介绍⽤法。
1.3 内存堆搜索与执⾏
在堆上搜索实例
我们查看,发现存在着DisplaySettings类,可以在堆上搜索是否存在着该类的实例。⾸先在⼿机上点击进⼊“显⽰”设置,然后运⾏以下命令,并得到相应的实例地址:
# android heap arch instances ings.DisplaySettings
Using exsiting matches for ings.DisplaySettings. U --fresh flag for new instances.
Handle    Class                                toString()
--------  ------------------------------------  -----------------------------------------
0x252a    ings.DisplaySettings  DisplaySettings{69d91ee #0 id=0x7f0a0231}
调⽤实例的⽅法
查看源码得知ings.DisplaySettings类有着getPreferenceScreenResId()⽅法(后⽂也会介绍在objection中直接打印类的所有⽅法的命令),这样就可以直接调⽤该实例
的getPreferenceScreenResId()⽅法,⽤excute命令。
# android heap execute 0x2526 getPreferenceScreenResId
Handle 0x2526 is to class ings.DisplaySettings
电视迷Executing method: getPreferenceScreenResId()
2132082764
可见结果被直接打印了出来。
在实例上执⾏js代码
也可以在找到的实例上直接编写js脚本,输⼊android heap evaluate 0x2526命令后,会进⼊⼀个迷你编辑器环境,输⼊console.log("evaluate result:"+PreferenceScreenResId())这串脚本,按ESC退出编辑器,然后按回车,即会开始执⾏这串脚本,输出结果。
# android heap evaluate 0x2526
(The handle at `0x2526` will be available as the `clazz` variable.)
console.log("evaluate result:"+PreferenceScreenResId())
JavaScript capture complete.
Handle 0x2526 is to class ings.DisplaySettings
evaluate result:2132082764
这个功能其实⾮常厉害,可以即时编写、出结果、即时调试⾃⼰的代码,不⽤再编写→注⼊→操作→看结果→再调整,⽽是直接出结果。
1.4 启动activity或rvice
直接启动activity
直接上代码,想要进⼊显⽰设置,可以在任意界⾯直接运⾏以下代码进⼊显⽰设置:
# android intent launch_activity ings.DisplaySettings
(agent) Starting activity
(agent) Activity successfully asked to start.
查看当前可⽤的activity
可以使⽤android hooking list命令来查看当前可⽤的activities,然后使⽤上述命令进⾏调起。
# android hooking list activities
ings.ActivityPicker
ings.AirplaneModeVoiceActivity
ings.AllowBindAppWidgetActivity
ings.AppWidgetPickActivity
ings.BandMode
ings.ConfirmDeviceCredentialActivity
ings.CredentialStorage
ings.CryptKeeper$FadeToBlack
ings.CryptKeeperConfirm$Blank
ings.DeviceAdminAdd
ings.DeviceAdminSettings
ings.DisplaySettings
ings.EncryptionInterstitial
ings.FallbackHome
ings.HelpTrampoline
ings.LanguageSettings
ings.MonitoringCertInfoActivity
ings.RadioInfo
ings.RegulatoryInfoDisplayActivity
ings.RemoteBugreportActivity
ings.RunningServices
ings.SetFullBackupPassword
ings.SetProfileOwner
ings.Settings
ings.Settings
ings.Settings$AccessibilityDaltonizerSettingsActivity
ings.Settings$AccessibilitySettingsActivity
ings.Settings$AccountDashboardActivity
ings.Settings$AccountSyncSettingsActivity
ings.Settings$AdvancedAppsActivity
直接启动rvice
也可以先使⽤android hooking list rvices查看可供开启的服务,然后使⽤android intent launch_rvice ings.bluetooth.BluetoothPairingService命令来开启服务。
2 Frida hook anywhere
很多新⼿在学习Frida的时候,遇到的第⼀个问题就是,⽆法找到正确的类及⼦类,⽆法定位到实现功能的准确的⽅法,⽆法正确的构造参数、继⽽进⼊正确的重载,这时候可以使⽤Frida进⾏动态调试,来确定以上具体的名称和写法,最后写出正确的hook代码。
2.1 objection(内存漫游)
列出内存中所有的类三农人物
# android hooking list class
sun.util.logging.LoggingSupport
sun.util.logging.LoggingSupport$1
sun.util.logging.LoggingSupport$2
sun.util.logging.PlatformLogger
sun.util.logging.PlatformLogger$1
sun.util.logging.PlatformLogger$JavaLoggerProxy
sun.util.logging.PlatformLogger$Level
sun.util.logging.PlatformLogger$LoggerProxy
void
Found 11885 class
内存中搜索所有的类
在内存中所有已加载的类中搜索包含特定关键词的类。
# android hooking arch class display
[Landroid.hardware.display.WifiDisplay;
[Landroid.icu.impl.ICUCurrencyDisplayInfoProvider$ICUCurrencyDisplayInfo$CurrencySink$EntrypointTable;
[Landroid.icu.impl.LocaleDisplayNamesImpl$CapitalizationContextUsage;
[Landroid.icu.impl.LocaleDisplayNamesImpl$DataTableType;
[Landroid.icu.number.NumberFormatter$DecimalSeparatorDisplay;
[Landroid.icu.number.NumberFormatter$SignDisplay;
[DisplayContext$Type;
[DisplayContext;
[LocaleDisplayNames$DialectHandling;
[Landroid.view.Display$Mode;
[Landroid.view.Display;
android.app.Vr2dDisplayProperties
眼窝凹陷android.hardware.display.AmbientBrightnessDayStats
android.hardware.display.AmbientBrightnessDayStats$1
android.hardware.display.BrightnessChangeEvent
图片卡通
ings.wfd.WifiDisplaySettings$SummaryProvider
ings.wfd.WifiDisplaySettings$SummaryProvider$1
ingslib.display.BrightnessUtils
ingslib.display.DisplayDensityUtils
javax.l.EGLDisplay
Found 144 class
内存中搜索所有的⽅法
在内存中所有已加载的类的⽅法中搜索包含特定关键词的⽅法,上⽂中可以发现,内存中已加载的类就已经⾼达11885个了,那么他们的⽅法⼀定是类的个数的数倍,整个过程会
相当庞⼤和耗时,见下图2-6。
# android hooking arch methods display
列出类的所有⽅法
当搜索到了⽐较关⼼的类之后,就可以直接查看它有哪些⽅法,⽐如我们想要查看ings.DisplaySettings类有哪些⽅法:
# android hooking list class_methods ings.DisplaySettings
private static java.util.List<AbstractPreferenceController> ings.DisplaySettings.t.Context,lifecycle.Lifecycle) protected int PreferenceScreenResId()
protected java.lang.String LogTag()
protected java.util.List<AbstractPreferenceController> t.Context)
public int HelpResource()
public int MetricsCategory()
static java.util.List ings.DisplaySettings.access$t.Context,lifecycle.Lifecycle)
Found 7 method(s)
列出的⽅法与相⽐对之后,发现是⼀模⼀样的。
直接⽣成hook代码
上⽂中在列出类的⽅法时,还直接把参数也提供了,也就是说我们可以直接动⼿写hook了,既然上述写hook的要素已经全部都有了,objection这个“⾃动化”⼯具,当然可以直接⽣成
代码。
# android hooking generate  simple  ings.DisplaySettings
Java.perform(function() {
var clazz = Java.u('ings.DisplaySettings');
//
HelpResource.apply(this, arguments);
}
});
Java.perform(function() {
var clazz = Java.u('ings.DisplaySettings');
//
LogTag.apply(this, arguments);
}
});
Java.perform(function() {
var clazz = Java.u('ings.DisplaySettings');
//
PreferenceScreenResId.apply(this, arguments);
}
想一个人的说说});
⽣成的代码⼤部分要素都有了,只是参数貌似没有填上,还是需要我们后续补充⼀些,看来还是⽆法做到完美。
2.2 objection(hook)
上述操作均是基于在内存中直接枚举搜索,已经可以获取到⼤量有⽤的静态信息,我们再来介绍⼏个⽅法,可以获取到执⾏时动态的信息,当然、同样地,不⽤写⼀⾏代码。
hook类的所有⽅法
我们以⼿机连接蓝⽛⽿机播放⾳乐为例为例,看看⼿机蓝⽛接⼝的动态信息。⾸先我们将⼿机连接上我的蓝⽛⽿机——⼀加蓝⽛⽿机OnePlus Bullets Wireless 2,并可以正常播放⾳
乐;然后我们按照上⽂的⽅法,搜索⼀下与蓝⽛相关的类,搜到⼀个⾼度可疑的类:android.bluetooth.BluetoothDevice。运⾏以下命令,hook这个类:
# android hooking watch class android.bluetooth.BluetoothDevice
使⽤jobs list命令可以看到objection为我们创建的Hooks数为57,也就是将android.bluetooth.BluetoothDevice类下的所有⽅法都hook了。
这时候我们在设置→声⾳→媒体播放到上进⾏操作,在蓝⽛⽿机与“此设备”之间切换时,会命中这些hook之后,此时objection就会将⽅法打印出来,会将类似这样的信息“吐”出来:
ings on (google: 9) [usb] # (agent) [h0u5g7uclo] Called android.Service()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.isConnected()
(agent) [h0u5g7uclo] Called android.Service()
女自拍(agent) [h0u5g7uclo] Called android.AliasName()
(agent) [h0u5g7uclo] Called android.Alias()
(agent) [h0u5g7uclo] Called android.Name()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.Service()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.isConnected()
(agent) [h0u5g7uclo] Called android.Service()
(agent) [h0u5g7uclo] Called android.AliasName()
(agent) [h0u5g7uclo] Called android.Alias()
(agent) [h0u5g7uclo] Called android.Name()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.BatteryLevel()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.BatteryLevel()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.BondState()
(agent) [h0u5g7uclo] Called android.AliasName()
(agent) [h0u5g7uclo] Called android.Alias()
(agent) [h0u5g7uclo] Called android.Name()
(agent) [h0u5g7uclo] Called android.BatteryLevel()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.BatteryLevel()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.BondState()
(agent) [h0u5g7uclo] Called android.AliasName()
(agent) [h0u5g7uclo] Called android.Alias()
(agent) [h0u5g7uclo] Called android.Name()
(agent) [h0u5g7uclo] Called android.Service()
可以看到我们的切换操作,调⽤到了android.bluetooth.BluetoothDevice类中的多个⽅法。
hook⽅法的参数、返回值和调⽤栈
在这些⽅法中,我们对哪些⽅法感兴趣,就可以查看哪些个⽅法的参数、返回值和调⽤栈,⽐如想看getName()⽅法,则运⾏以下命令:
# android hooking watch class_method android.Name --dump-args --dump-return --dump-backtrace
注意最后加上的三个选项--dump-args --dump-return --dump-backtrace,为我们成功打印出来了我们想要看的信息,其实返回值Return Value就是getName()⽅法的返回值,我的蓝⽛⽿机的型号名字OnePlus Bullets Wireless 2;从调⽤栈可以反查如何⼀步⼀步调⽤到getName()这个⽅法的;虽然这个⽅法没有参数,⼤家可以再找个有参数的试⼀下。
hook⽅法的所有重载
objection的help中指出,在hook给出的单个⽅法的时候,会hook它的所有重载。
# help android hooking watch class_method
Command: android hooking watch class_method
Usage: android hooking watch class_method <fully qualified class method> <optional overload>
(optional: --dump-args) (optional: --dump-backtrace)
(optional: --dump-return)
Hooks a specified class method and reports on invocations, together with
the number of arguments that method was called with. This command will
also hook all of the methods available overloads unless a specific
overload is specified.
If the --include-backtrace flag is provided, a full stack trace that
lead to the methods invocation will also be dumped. This would aid in
discovering who called the original method.
Examples:
android hooking watch class_st.login
android hooking watch class_uteQuery
android hooking watch class_uteQuery "java.lang.String,java.lang.String"
android hooking watch class_uteQuery --dump-backtrace
android hooking watch class_st.login --dump-args --dump-return
那我们可以⽤File类的构造器来试⼀下效果。
# android hooking watch class_method java.io.File.$init --dump-args
可以看到objection为我们hook了File构造器的所有重载,⼀共是6个。在设置界⾯随意进出⼏个⼦设置界⾯,可以看到命中很多次该⽅法的不同重载,每次参数的值也都不同,见下图2-9。
2.3 ZenTracer(hook)
前⽂中介绍的objection已经⾜够强⼤,优点是hook准确、粒度细。这⾥再推荐个好友⾃⼰写的批量hook查看调⽤轨迹的⼯具,可以更⼤范围地hook,帮助读者辅助分析。
# pyenv install 3.8.0
# git /hluwa/ZenTracer
# cd ZenTracer
# pyenv local 3.8.0
# python -m pip install --upgrade pip
# pip install PyQt5
# pip install frida-tools
# python ZenTracer.py
上述命令执⾏完毕之后,会出现⼀个PyQt画出来的界⾯,如图2-10所⽰。
点击Action之后,会出现匹配模板(Match RegEx)和过滤模板(Black RegEx)。匹配就是包含的关键词,过滤就是不包含的关键词,见下图2-11。其代码实现就是
通过如下的代码实现,hook出来的结果需要通过匹配模板进⾏匹配,并且筛选剔除掉过滤模板中的内容。
var matchRegEx = {MATCHREGEX};
var blackRegEx = {BLACKREGEX};
onMatch: function (aClass) {
for (var index in matchRegEx) {
// console.log(matchRegEx[index]);
// 通过匹配模板进⾏匹配
if (match(matchRegEx[index], aClass)) {
var is_black = fal;
for (var i in blackRegEx) {
//如果也包含在过滤模板中,则剔除
if (match(blackRegEx[i], aClass)) {
is_black = true;
log(aClass + "' black by '" + blackRegEx[i] + "'");
break;
}
}
if (is_black) {
break;
}
log(aClass + "' match by '" + matchRegEx[index] + "'");
traceClass(aClass);
}
}
},
onComplete: function () {
log("Complete.");
}
});
通过下述代码实现的模糊匹配和精准匹配:
function match(ex, text) {
if (ex[1] == ':') {
var mode = ex[0];
if (mode == 'E') {
ex = ex.substr(2, ex.length - 2);
return ex == text;
} el if (mode == 'M') {
ex = ex.substr(2, ex.length - 2);
} el {
log("Unknown match mode: " + mode + ", current support M(match) and E(equal)")
}
}
return text.match(ex)
}
通过下述代码实现的导⼊导出调⽤栈及观察结果:
def export_onClick(lf):
jobfile = SaveFileName(lf, 'export', '', 'json file(*.json)')
if isinstance(jobfile, tuple):
jobfile = jobfile[0]
if not jobfile:
return
f = open(jobfile, 'w')
export = {}
export['match_regex'] = lf.app.match_regex_list
export['black_regex'] = lf.app.black_regex_list
tree = {}
for tid in lf.app.thread_map:
tree[lf.app.thread_map[tid]['list'][0].text()] = gen_tree(lf.app.thread_map[tid]['list'][0])
export['tree'] = tree
f.write(json.dumps(export))
f.clo()
def import_onClick(lf):
jobfile = OpenFileName(lf, 'import', '', 'json file(*.json)')
if isinstance(jobfile, tuple):
jobfile = jobfile[0]
if not jobfile:
return
f = open(jobfile, 'r')
export = json.ad())
for regex in export['match_regex']: lf.app.match_regex_list.append(
regex), lf.app.match_regex_dialog.tupList()
for regex in export['black_regex']: lf.app.black_regex_list.append(
regex), lf.app.black_regex_dialog.tupList()
for t in export['tree']:
tid = t[0: t.index(' - ')]
tname = t[t.index(' - ') + 3:]
for item in export['tree'][t]:
put_tree(lf.app, tid, tname, item)
我们来完整的演⽰⼀遍,⽐如现在看java.io.File类的所有⽅法,我们可以这样操作,⾸先是精准匹配:
1. 点击打开“设置”应⽤;
2. 选择Action→Match RegEx
3. 输⼊E:java.io.File,点击add,然后关闭窗⼝
4. 点击Action→Start
可以观察到java.io.File类的所有⽅法都被hook了,,并且像java.ateTempFile⽅法的所有重载也被hook了,见下图2-12。
1. 在“设置”应⽤上进⾏操作,打开⼏个⼦选项的界⾯之后,观察⽅法的参数和返回值;
2. 导出json来观察⽅法的调⽤树,选择File→Export json,导出为tmp.json,使⽤vscode来format Document之后,效果如下:{
"match_regex": [
"E:java.io.File"
],
"black_regex": [],
"tree": {
"2 - main": [
{
"clazz": "java.io.File",
"method": "exists()",
"args": [],
"child": [],
"retval": "fal"
},
{
"clazz": "java.io.File",
"method": "toString()",
"args": [],
"child": [
{
"clazz": "java.io.File",
"method": "getPath()",
"args": [],
"child": [],知晓造句
"retval": "/data/ur/0/ings"
}
]
,
"retval": "/data/ur/0/ings"
},
{
"clazz": "java.io.File",
"method": "equals(java.lang.Object)",
"args": [
"/data/ur/0/ings"
],
"child": [
{
"clazz": "java.io.File",
"method": "toString()",
"args": [],
长春拖拉机厂"child": [
{
"clazz": "java.io.File",
"method": "getPath()",
"args": [],
"child": [],
"retval": "/data/ur/0/ings"
}
]
,
"retval": "/data/ur/0/ings"
},
{

本文发布于:2023-07-26 00:58:19,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1117302.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:命令   内存   结果   查看   参数   匹配   搜索
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图