Android逆向之hook框架frida篇

前言

Frida是一款基于python + javascript 的hook框架,通杀android\ios\linux\win\osx等各平台,由于是基于脚本的交互,因此相比xposed和substrace cydia更加便捷,本文重点介绍Frida在android下面的使用。Frida的官网为:http://www.frida.re/

安装和搭建Frida环境

首先要保证你的android手机已经root。通过pip安装frida:

pip install frida

下载frida-server:

frida_server的下载地址:https://github.com/frida/frida/releases

到android手机上并且运行

adb push frida-server /data/local/tmp/
adb shell
su
cd /data/local/tmp/
chmod 777 frida-server
./frida-server

转发android TCP端口到本地:

adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043

测试frida环境,如果出现android手机的进程列表说明搭建成功:

frida-ps -R
PID Name


2700 acceleratord
2713 adbd
2798 agnsscontrol
2799 agnsslog
2195 akmd09911
8078 android.process.acore
31283 android.process.media
2185 atcmdserver
4939 chargelogcat
2796 chr_logd
22856 com.android.browser
7912 com.android.contacts
22417 com.android.gallery3d
....

得到android手机当前最前端Activity所在的进程

get_front_app.py

其中get_front_app.py的内容如下:

import frida
rdev = frida.get_remote_device()
front_app = rdev.get_frontmost_application()
print front_app

枚举android手机所有的进程

enum_process.py

enum_process.py内容如下:

import frida
rdev = frida.get_remote_device()
processes = rdev.enumerate_processes()
for process in processes:
    print process

枚举某个进程加载的所有模块以及模块中的导出函数

import frida
rdev = frida.get_remote_device()
session = rdev.attach("com.tencent.mm")  #如果存在两个一样的进程名可以采用rdev.attach(pid)的方式
modules = session.enumerate_modules()
for module in modules:
    print module
    export_funcs = module.enumerate_exports()
    print "\tfunc_name\tRVA"
    for export_func in export_funcs:
        print "\t%s\t%s"%(export_func.name,hex(export_func.relative_address))

hook android的native函数

import frida
import sys
rdev = frida.get_remote_device()
session = rdev.attach("com.tencent.mm")
scr = """
Interceptor.attach(Module.findExportByName("libc.so" , "open"), {
    onEnter: function(args) {
        send("open("+Memory.readCString(args[0])+","+args[1]+")");
    },
    onLeave:function(retval){
    
    }
});
"""
script = session.create_script(scr)
def on_message(message ,data):
    print message
script.on("message" , on_message)
script.load()
sys.stdin.read()

hook android的java层函数

如下代码为hook微信(测试版本为6.3.13,不同版本由于混淆名字的随机生成的原因或者代码改动导致类名不一样)
com.tencent.mm.sdk.platformtools.ay类的随机数生成函数,让微信猜拳随机(type=2),而摇色子总是为6点(type=5)

import frida
import sys
rdev = frida.get_remote_device()
session = rdev.attach("com.tencent.mm")

scr = """
Java.perform(function () {
var ay = Java.use("com.tencent.mm.sdk.platformtools.ay");
ay.pu.implementation = function(){
    var type = arguments[0];
    send("type="+type);
    if (type == 2)
    {
    return this.pu(type);
    }
    else
    {
    return 5;
    }
};

});
"""

script = session.create_script(scr)
def on_message(message ,data):
    print message
script.on("message" , on_message)
script.load()
sys.stdin.read()

通过frida向android进程注入dex

import frida, sys, optparse, re
def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)

jscode = """
Java.perform(function () {
    var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
    var context = currentApplication.getApplicationContext();
    var pkgName = context.getPackageName();
    var dexPath = "%s";
    var entryClass = "%s";
    Java.openClassFile(dexPath).load();
    console.log("inject " + dexPath +" to " + pkgName + " successfully!")
    Java.use(entryClass).%s("%s");
    console.log("call entry successfully!")
});
"""

def checkRequiredArguments(opts, parser):
    missing_options = []
    for option in parser.option_list:
        if re.match(r'^\[REQUIRED\]', option.help) and eval('opts.' + option.dest) == None:
            missing_options.extend(option._long_opts)
    if len(missing_options) > 0:
        parser.error('Missing REQUIRED parameters: ' + str(missing_options))

if __name__ == "__main__":
    usage = "usage: python %prog [options] arg\n\n" \
            "example: python %prog -p com.android.launcher " \
            "-f /data/local/tmp/test.apk " \
            "-e com.parker.test.DexMain/main " \
            "\"hello fridex!\""
    parser = optparse.OptionParser(usage)
    parser.add_option("-p", "--package", dest="pkg", type="string",
                      help="[REQUIRED]package name of the app to be injected.")
    parser.add_option("-f", "--file", dest="dexPath", type="string",
                      help="[REQUIRED]path of the dex")
    parser.add_option("-e", "--entry", dest="entry", type="string",
                      help="[REQUIRED]the entry function Name.")

    (options, args) = parser.parse_args()
    checkRequiredArguments(options, parser)
    if len(args) == 0:
        arg = ""
    else:
        arg = args[0]

    pkgName = options.pkg
    dexPath = options.dexPath
    entry = options.entry.split("/")
    if len(entry) > 1:
        entryClass = entry[0]
        entryFunction = entry[1]
    else:
        entryClass = entry[0]
        entryFunction = "main"

    process = frida.get_usb_device(1).attach(pkgName)
    jscode = jscode%(dexPath, entryClass, entryFunction, arg)
    script = process.create_script(jscode)
    script.on('message', on_message)
    print('[*] Running fridex')
    script.load()
    sys.stdin.read()

通过注入抛出异常代码实现跟踪程序调用栈

在<<Android 软件安全与逆向分析>>这本书中第八章有介绍通过重打包写入异常代码进行栈跟踪,但是这样比较麻烦,使用frida注入更方便。

frida的相关资源

https://github.com/dweinstein/awesome-frida
http://jaq.alibaba.com/community/art/show?articleid=816
https://koz.io/using-frida-on-android-without-root/
http://www.ninoishere.com/frida-learn-by-example/
https://github.com/TheCjw/Frida-Android-Scripts

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容