日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

进击的Android Hook 注入术《二》

發布時間:2025/3/15 Android 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进击的Android Hook 注入术《二》 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄(?)[-]

  • 繼續
  • 注入
  • 分類
  • 本質
  • 目的
  • 過程
  • 示例一
  • Host代碼
  • libmysoso代碼
  • 調用
  • 示例代碼
  • 繼續

    在《一》里,我把基本思路描述了一遍,接下為我們先從注入開始入手。

    注入


    分類

    我們平時所說的代碼注入,主要靜態和動態兩種方式
    • 靜態注入,針對是可執行文件,比如平時我們修改ELF,DEX文件等等,相關的輔助工具也很多,比如IDA、JEB、ApkTool等等;
    • 動態注入,針對是進程,比如修改進程的寄存器、內存值等等;
    動態跟靜態最大的區別是,動態不需要改動源文件,但需要高權限(通常是root權限),而且所需的技術含量更高。

    本質

    動態注入技術,本質上就是一種調度技術。想想平時我們調試一個進程時,可以做哪些功能? 一般有下列幾項:
    • 查看變量值
    • 修改變量值
    • 跟蹤進程跳轉
    • 查看進程調用堆棧
    • 等等
    動態注入相比于普通的調試,最大的區別就是動態注入是一個”自動化調試并達到加載自定義動態鏈接庫“的過程。所謂自動化,其實就是通過代碼實現,在Linux上通過Ptrace就可以完成上面所有功能,當然Ptrace功能是比較原始的,平時調試中的功能還需要很多高層邏輯封裝才可以實現。 在閱讀下面章節之前,強烈建議閱讀一下man文檔,見這里。

    目的

    一般而言,我們要對一個進程進行注入,主要有以下幾方面目的:
    • 增強目標進程的功能;
    • 修復目標進程缺陷;
    • 劫持目標進程函數;
    • 竊取目標進程數據;
    • 篡改目標進程數據;


    過程

    如上圖所示,進程A注入到進程B后,通過修改寄存器和內存,讓進程B加載自定義的動態庫a,當a被加載后,a會嘗試加載其他模塊,比如加載dex文件等等,具體的注入過程如下:
    • ATTATCH,指定目標進程,開始調試;
    • GETREGS,獲取目標進程的寄存器,保存現場;
    • SETREGS,修改PC等相關寄存器,使其指向mmap;
    • POPETEXT,把so path寫入mmap申請的地址空間;
    • SETRESG,修改PC等相關寄存器,使其指向dlopen;
    • SETREGS,恢復現場;
    • DETACH,解除調試,使其恢復;
    上述是一個簡化的過程,整個注入的代碼,我已經上傳到github,地址https://github.com/boyliang/Poison 當so被dlopen加載到目標進程后,我們需要讓so中的邏輯被執行,比較復雜的做法是同樣使用ptrace修改寄存器的辦法,讓目標進程調用dlsym找到我們函數的地址。而比較簡單的做法有兩種,如下
    • 使用gcc的預編譯指令__attribute__ ((__constructor__)),作用是讓so被加載后,函數被自動執行;
    [cpp] view plain copy
  • __attribute__?((__constructor__))??
  • void?Main()?{??
  • ?LOGI(">>>>>>>>>>>>>I?am?in,?I?am?a?bad?boy?1!!!!<<<<<<<<<<<<<<");??
  • ??
  • ?void*?handle?=?dlopen("libinso.so",?RTLD_NOW);??
  • ?void?(*setA_func)(int)?=?(void?(*)(int))dlsym(handle,?"setA");??
  • ??
  • ?if?(setA_func)?{??
  • ???setA_func(999);??
  • ?}??
  • }??
    • 使用c++全局對象初始化,其構造函數會被自動執行;
    [cpp] view plain copy
  • void?Main();??
  • ??
  • static?void*?_main(void*){??
  • ????Main();??
  • ????return?NULL;??
  • }??
  • ??
  • class?EntryClass?{??
  • public:??
  • ??
  • ????EntryClass()?{??
  • ????????pthread_t?tid;??
  • ????????pthread_create(&tid,?NULL,?_main,?NULL);??
  • ????????pthread_detach(tid);??
  • ????}??
  • ??
  • }?boy;??

  • 示例一

    下面示例一個通過ptrace注入的示例,涉及到兩部分代碼,一部分是目標進程代碼記作host,另一部分是被我們注入的so代碼記作libmyso.so

    Host代碼

    包含三個源文件,分別是demo1.c,inso.h, inso.c [cpp] view plain copy
  • /*?
  • ?*?inso.h?
  • ?*?
  • ?*??Created?on:?2014年6月24日?
  • ?*??????Author:?boyliang?
  • ?*/??
  • ??
  • ??
  • __attribute__?((visibility?("default")))?void?setA(int?i);??
  • ??
  • __attribute__?((visibility?("default")))?int?getA();??
  • [cpp] view plain copy
  • /*?
  • ?*?inso.c?
  • ?*?
  • ?*??Created?on:?2014年6月24日?
  • ?*??????Author:?boyliang?
  • ?*/??
  • ??
  • #include?<stdio.h>??
  • #include?"inso.h"??
  • ??
  • static?int?gA?=?1;??
  • ??
  • void?setA(int?i){??
  • ????gA?=?i;??
  • }??
  • ??
  • int?getA(){??
  • ????return?gA;??
  • }??
  • [cpp] view plain copy
  • /*?
  • ?*?demo1.c?
  • ?*?
  • ?*??Created?on:?2014年6月24日?
  • ?*??????Author:?boyliang?
  • ?*/??
  • ??
  • #include?<stdio.h>??
  • #include?<unistd.h>??
  • ??
  • #include?"inso.h"??
  • #include?"log.h"??
  • ??
  • int?main(){??
  • ??
  • ????LOGI("DEMO1?start.");??
  • ??
  • ????while(1){??
  • ????????LOGI("%d",?getA());??
  • ????????setA(getA()?+?1);??
  • ????????sleep(2);??
  • ????}??
  • ??
  • ????return?0;??
  • }??
  • libmyso.so代碼

    [cpp] view plain copy
  • /*?
  • ?*?myso.c?
  • ?*?
  • ?*??Created?on:?2014年6月24日?
  • ?*??????Author:?boyliang?
  • ?*/??
  • ??
  • #include?<stdio.h>??
  • #include?<stddef.h>??
  • #include?<dlfcn.h>??
  • #include?<pthread.h>??
  • #include?<stddef.h>??
  • ??
  • #include??"log.h"??
  • ??
  • __attribute__?((__constructor__))??
  • void?Main()?{??
  • ????LOGI(">>>>>>>>>>>>>I?am?in,?I?am?a?bad?boy?1!!!!<<<<<<<<<<<<<<");??
  • ??
  • ????void*?handle?=?dlopen("libinso.so",?RTLD_NOW);??
  • ????void?(*setA_func)(int)?=?(void?(*)(int))dlsym(handle,?"setA");??
  • ??
  • ????if?(setA_func)?{??
  • ????????setA_func(999);??
  • ????}??
  • }??
  • 調用

    注入程序,我將其命名為poison,使用方法是poison <so_path> <target_pit>。下面是示例的輸出顯示: [plain] view plain copy
  • I/TTT?????(??594):?DEMO1?start.??
  • I/TTT?????(??594):?1??
  • I/TTT?????(??594):?2??
  • I/TTT?????(??594):?3??
  • I/TTT?????(??594):?4??
  • I/TTT?????(??594):?5??
  • I/TTT?????(??594):?6??
  • I/TTT?????(??594):?7??
  • I/TTT?????(??594):?>>>>>>>>>>>>>I?am?in,?I?am?a?bad?boy?1!!!!<<<<<<<<<<<<<<??
  • I/TTT?????(??594):?999??
  • I/TTT?????(??594):?1000??
  • I/TTT?????(??594):?1001??
  • 當執行./poison /data/local/tmp/libmyso.so 594后,輸出中馬上出現了特定字符串,并且打印的數據一下子變成了999,證明我們注入成功了。

    示例代碼

    上述示例所涉及到代碼,我都放發布到github上了,大家如果想研究代碼,可以到https://github.com/boyliang/injection_by_ptrace

    在《三》,我會再介紹一種Android上特有的注入技術,敬請期待。



    原文地址:?http://blog.csdn.net/l173864930/article/details/38456313

    總結

    以上是生活随笔為你收集整理的进击的Android Hook 注入术《二》的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。