zoukankan      html  css  js  c++  java
  • 进击的Android注入术《二》

    继续

    在《一》里,我把基本思路描写叙述了一遍,接下为我们先从注入開始入手。

    注入


    分类

    我们平时所说的代码注入,主要静态和动态两种方式
    • 静态注入,针对是可运行文件,比方平时我们改动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被载入后,函数被自己主动运行;
    __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++全局对象初始化,其构造函数会被自己主动运行;
    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
    /*
     * inso.h
     *
     *  Created on: 2014年6月24日
     *      Author: boyliang
     */
    
    
    __attribute__ ((visibility ("default"))) void setA(int i);
    
    __attribute__ ((visibility ("default"))) int getA();
    /*
     * 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;
    }
    /*
     * 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代码

    /*
     * 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>。以下是演示样例的输出显示:
    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上特有的注入技术,敬请期待。

  • 相关阅读:
    作业3
    数组求和
    2.自己的Github试用过程
    2.自己的Github注册流程
    图片左右滑动整理为插件
    artDialog中的time参数,ajax请求中的异步与同步
    简单的图片放大镜效果插件
    3月份学习安排
    前端好的网站
    web app开发中遇到的问题
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4487344.html
Copyright © 2011-2022 走看看