Frida Hook Android framework system_server插桩调试方法

Frida Hook Android framework system_server插桩调试方法

已有环境:

Ubuntu20.04.1

使用工具:

VS code Python3

概述:由于本人的工作调整,所以最近要转战到framework层开发,因此调试framework就成了重中之重,但是在源码中修改代码和添加log,再编译烧录到机器上,这一套流程下去,费时费力,尤其开发人员又受限于后台服务器的安全设定,那就更难受,并且效率十分低下,如果在源码开放的情况下,使用AS断点,也是不错的方法,但是很不幸运,我们的代码不开源,因此只能另外寻求方法。

参考文档:Android Hook工具之Frida安装配置教程

Android Hook工具之Frida 安装配置教程 - 简书

Frida官网地址:Frida • A world-class dynamic instrumentation toolkit | Observe and reprogram running programs on Windows, macOS, GNU/Linux, iOS, watchOS, tvOS, Android, FreeBSD, and QNX

Frida简介:

Frida是一款基于Python + JavaScript的Hook调试框架,可以将自己编写的JavaScript代码注入到Windows,MACOS,Linux, iOS,Android和QNX 的应用中从而进行Hook,其实Frida功能不仅仅是Hook,还包括以下这些功能:

  • 访问进程的内存
  • 在应用程序运行时覆盖一些功能
  • 从导入的类中调用函数
  • 在堆上查找对象实例并使用这些对象实例
  • Hook,跟踪和拦截函数等等

步骤:(Ubuntu环境,已安装Python3.8 直接使用命令行即可)

  • 下载安装Frida
  • 下载安装frida-tools

出现ERROR

ERROR: Could not find a version that satisfies the requirement frida (from versions: none)
ERROR: No matching distribution found for frida

 

解决:pip3 install frida -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

直接选用pip源并且信任它的来源就可以解决这种问题。

安装完成后,直接在终端中输入frida-ps命令查看,如果能显示当前系统进程则证明安装成功

      Frida Hook Android framework system_server插桩调试方法_第1张图片

下载frida server

Frida-server:

直接去官网下载:https://github.com/frida/frida/releases

对应的版本即可,注意:Frida-server的版本必须跟你宿主机的Frida版本一致。

查看Frida版本

    

比如我宿主机Frida的版本是14.2.17,Android手机是arm64的,那么应该下载:frida-server-14.2.17-android-arm64.xz 文件。
下载后解压文件

    

使用adb push命令推送到手机中

    

推送完成后将frida-sever赋予执行的权限,并运行Frida-server,使用以下命令:

    Frida Hook Android framework system_server插桩调试方法_第2张图片

注1: 如果frida-server没有启动,查看一下你是否使用的是Root用户来启动,如果使用Root用户则应该是#
注2: 如果要启动frida-server作为后台进程、可以使用这个命令./frida-server
正常启动后,另开一个终端,使用frida-ps -U命令检查Frida是否正常运行,如果正常运行则会列出Android设备上当前正在运行的进程.

    Frida Hook Android framework system_server插桩调试方法_第3张图片

参数-U 代表USB,意思让Frida检查USB设备。

(上述准备工作完成后,开始进行调试步骤)

脚本调试(前期编写比较耗时,之后调试只需微改,比较实用)

以Hook WMS ActivityStarter startActivityUnchecked为例

进程:system_server

Java.use : /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

key point: startActivityUnchecked

编写Python脚本(详细见附件)

创建main.py(注:Python注意空格和换行)

'''

/**

 * VS code Ctrl+Alt +- :Go Forward Go Back

 * VS code 自动排版: Ctrl+K 紧接着Ctrl+F

 *

 */

'''

import frida

import sys

import time



#Hook 进程名称 Frida-ps -U查看 "com.example.testfrida" "system_server"

url_example = "com.example.testfrida"

url_system = "system_server"



#Frida 具体实现JS "./common_function.js" "./recents.js"

JS_common = "./common_function.js"

JS_recents = "./recents.js"





def read_js(file):

    with open(file, encoding='UTF-8') as fp:

        return fp.read()



def on_message(message, data):

    if message["type"] == "send":

        print("[+] {}".format(message["payload"]))

    else:

        print("[-] {}".format(message))



#选择hook方式: 运行时hook False,spawn hook True

def get_session(isSpawn, url):

    #开始 hook

    remote_device = frida.get_usb_device()

    print(remote_device)

    #session = remote_device.attach("system_server")

    #session = remote_device.attach("com.example.testfrida")



    # spawn hook

    '''

    device = frida.get_usb_device()

    print(device)

    pid = device.spawn(["com.example.testfrida"])

    device.resume(pid)

    time.sleep(1) #Without it Java.perform silently fails

    session = device.attach(pid)

    '''

    # spawn hook 调试APP时使用

    if isSpawn == True:

            pid = remote_device.spawn([url])

            remote_device.resume(pid)

            time.sleep(1) #Without it Java.perform silently fails

            session = remote_device.attach(pid)

    else:#运行时hook

        session = remote_device.attach(url)

    return session

'''

js - Hook 解释文件js,打桩进入目标类&目标方法

isSpawn - Hook选择,是否启动该进程

url - 宿主机器的进程名称

'''

def run(js, isSpawn, url):

    src = read_js(js)

    script = get_session(isSpawn,url).create_script(src)

    script.on("message", on_message)

    script.load()



#此处添加需要hook的进程和解释器(js文件),可添加多个

#run("./common_function.js",True,url_example)

run(JS_recents,False,url_system)

sys.stdin.read()

编写JS(主要的Hook工作,全部在JS中完成,详细代码参考附件)

主函数:

/**
 * 主函数
 */
Java.perform(function () {
    try {
        main();
    } catch (err) {
        console.log(err);
    }
});

全局变量赋值:

 /**
     * 全局变量赋值
     */
    var WindowManagerDebigConfig
        = Java.use('com.android.server.wm.WindowManagerDebugConfig');
    WindowManagerDebigConfig.DEBUG_LAYOUT.value = true;
    logi("WindowManagerDebigConfig.DEBUG_LAYOUT: " + WindowManagerDebigConfig.DEBUG_LAYOUT.value);

重写已有函数(注:传参要对应)

 /**
     * 重写方法
     */
    var ActivityStarter = Java.use('com.android.server.wm.ActivityStarter');
    var startActivityUnchecked = ActivityStarter.startActivityUnchecked
    logi("Hook startActivityUnchecked: " + startActivityUnchecked);
    startActivityUnchecked.implementation = function (r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, outActivity, restrictedBgActivity) {
        logi("startActivityUnchecked: options: " + options + ", r: " + r);
        //调用原方法,注:传参多个this变量
        var result = startActivityUnchecked.call(this, r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
        logi("startActivityUnchecked: result: " + result);
        return result;
    }

内部类

 /**
     * 内部类使用$
     */
    var Engine = Java.use("android.service.wallpaper.WallpaperService$Engine");
    var updateSurface = Engine.updateSurface
    logi("Hook updateSurface: " + updateSurface);
    updateSurface.implementation = function (forceRelayout, forceReport, redrawNeeded) {
        logi("updateSurface: forceRelayout: " + forceRelayout + "; forceReport: " + forceReport + "; redrawNeeded: " + redrawNeeded);
        updateSurface.call(this, forceRelayout, forceReport, redrawNeeded);
        logi("updateSurface: result: " + result);
    }

例子详细见附件:FridaHookAndroidframework-main.zip_fridahook系统system_server-Ubuntu文档类资源-CSDN下载

你可能感兴趣的:(android,java)