Android逆向之hook框架frida篇

前言

Frida是一款基于python + javascript 的hook框架,通殺android\ios\linux\win\osx等各平臺陶衅,由于是基于腳本的交互匀伏,因此相比xposed和substrace cydia更加便捷昂拂,本文重點介紹Frida在android下面的使用碟绑。Frida的官網(wǎng)為:http://www.frida.re/

安裝和搭建Frida環(huán)境

首先要保證你的android手機已經(jīng)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

轉發(fā)android TCP端口到本地:

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

測試frida環(huán)境碘举,如果出現(xiàn)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

枚舉某個進程加載的所有模塊以及模塊中的導出函數(shù)

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函數(shù)

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層函數(shù)

如下代碼為hook微信(測試版本為6.3.13忘瓦,不同版本由于混淆名字的隨機生成的原因或者代碼改動導致類名不一樣)
com.tencent.mm.sdk.platformtools.ay類的隨機數(shù)生成函數(shù),讓微信猜拳隨機(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()

通過注入拋出異常代碼實現(xiàn)跟蹤程序調用棧

在<<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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末明场,一起剝皮案震驚了整個濱河市汽摹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌苦锨,老刑警劉巖逼泣,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異舟舒,居然都是意外死亡拉庶,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門秃励,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氏仗,“玉大人,你說我怎么就攤上這事夺鲜〗远” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵币励,是天一觀的道長慷蠕。 經(jīng)常有香客問我,道長食呻,這世上最難降的妖魔是什么流炕? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮仅胞,結果婚禮上每辟,老公的妹妹穿的比我還像新娘。我一直安慰自己干旧,他們只是感情好影兽,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著莱革,像睡著了一般。 火紅的嫁衣襯著肌膚如雪讹开。 梳的紋絲不亂的頭發(fā)上盅视,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音旦万,去河邊找鬼闹击。 笑死,一個胖子當著我的面吹牛成艘,可吹牛的內容都是我干的赏半。 我是一名探鬼主播贺归,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼断箫!你這毒婦竟也來了拂酣?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤仲义,失蹤者是張志新(化名)和其女友劉穎婶熬,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體埃撵,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡赵颅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了暂刘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饺谬。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谣拣,靈堂內的尸體忽然破棺而出募寨,到底是詐尸還是另有隱情,我是刑警寧澤芝发,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布绪商,位于F島的核電站,受9級特大地震影響辅鲸,放射性物質發(fā)生泄漏格郁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一独悴、第九天 我趴在偏房一處隱蔽的房頂上張望例书。 院中可真熱鬧,春花似錦刻炒、人聲如沸决采。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽树瞭。三九已至,卻和暖如春爱谁,著一層夾襖步出監(jiān)牢的瞬間晒喷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工访敌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留凉敲,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像爷抓,于是被迫代替她去往敵國和親势决。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內容