注入安卓进程,并hook java世界的方法

注入安卓进程,并hook java世界的方法

         说明:

安卓系统的可执行对象有两个世界,一个是Linux Native世界,一个是Java世界.两个世界能够通过jvm产生交互,具体来说就是通过jni技术进行互相干涉.但是在正常情况下,只能在Java世界通过jni调用native方法,二native不能在没有任何java上的支持下干涉java世界.

在一些应用中,我们需要对一个app的java世界进行干涉.再说到linux上的进程注入技术,已不用我多讲,但是传统的linux进程注入技术在安卓上只能进入目标进程的native世界.

于是本教程是要注入别的进程,并hook java世界的java 方法!

条件:

1)      手机已root

2)      布置好了的ndk环境

3)      网友贡献的inject代码

由于安卓上的进程注入网上已经有很多方案了,这里就不列举了,这里就假设读者已经能够将so注入到别的进程并顺利运行了.

首先贴一下这次的目标

package com.example.testar;

 

import java.lang.reflect.Field;

import java.util.HashMap;

import java.util.Map;

 

import dalvik.system.DexClassLoader;

import android.net.wifi.WifiInfo;

import android.net.wifi.WifiManager;

import android.os.Bundle;

import android.app.Activity;

import android.content.Context;

import android.text.GetChars;

import android.util.Log;

import android.view.Menu;

import android.view.View;

import android.widget.Button;

 

public class MainActivity extends Activity {

    private final Map<String, ClassLoader> mLoaders = new HashMap<String, ClassLoader>();

 

   @Override

    protected void onCreate(BundlesavedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.activity_main);

 

       Button btn = (Button) findViewById(R.id.button1);

       btn.setOnClickListener(new View.OnClickListener() {

 

           @Override

           public void onClick(View v) {

                // TODO Auto-generated method stub

                WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);

                WifiInfo info = wifi.getConnectionInfo();

                System.out.println("Wifi mac:" + info.getMacAddress());

               System.out.println("return " + test());

           }

       });

    }

 

   @Override

    public booleanonCreateOptionsMenu(Menu menu) {

       // Inflate the menu; this adds items to theaction bar if it is present.

       getMenuInflater().inflate(R.menu.main, menu);

       return true;

    }

 

    private String test() {

       return "real";

    }

}

我们的目标是上面的test()方法,我们要改变其返回值.

接下来看看我们要注入到目标进程的so.cpp, MethodHooker.cpp

so.cpp:

#include "jni.h"

#include"android_runtime/AndroidRuntime.h"

#include "android/log.h"

#include "stdio.h"

#include "stdlib.h"

#include "MethodHooker.h"

#include <utils/CallStack.h>

#include "art.h"

#define log(a,b)__android_log_write(ANDROID_LOG_INFO,a,b); // LOG Ѝ:info

#define log_(b)__android_log_write(ANDROID_LOG_INFO,"JNI_LOG_INFO",b); // LOG Ѝ:info

 

 

extern "C" void InjectInterface(char*arg){

   log_("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");

   log_("*-*-*-*-*-*Injected so *-*-*-*-*-*-*-*");

   log_("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");

   Hook();

   log_("*-*-*-*-*-*-*-End -*-*-*-*-*-*-*-*-*-*");

}

 

extern "C" JNIEXPORT jstring JNICALL Java_com_example_testar_InjectApplication_test(JNIEnv *env, jclass clazz)

{

   Abort_();

    return env->NewStringUTF("haha ");;

}

MethodHooker.cpp:

#include "MethodHooker.h"

#include "jni.h"

#include"android_runtime/AndroidRuntime.h"

#include "android/log.h"

#include "stdio.h"

#include "stdlib.h"

#include "native.h"

#include <dlfcn.h>

#define ANDROID_SMP 0

#include "Dalvik.h"

#include "alloc/Alloc.h"

 

#include "art.h"

 

#define ALOG(...)__android_log_print(ANDROID_LOG_VERBOSE, __VA_ARGS__)

 

static bool g_bAttatedT;

static JavaVM *g_JavaVM;

 

void init()

{

   g_bAttatedT = false;

   g_JavaVM = android::AndroidRuntime::getJavaVM();

}

 

static JNIEnv *GetEnv()

{

    int status;

   JNIEnv *envnow = NULL;

   status = g_JavaVM->GetEnv((void **)&envnow, JNI_VERSION_1_4);

    if(status < 0)

    {

       status = g_JavaVM->AttachCurrentThread(&envnow, NULL);

       if(status < 0)

       {

           return NULL;

       }

       g_bAttatedT = true;

    }

    return envnow;

}

 

static void DetachCurrent()

{

    if(g_bAttatedT)

    {

       g_JavaVM->DetachCurrentThread();

    }

}

 

static int computeJniArgInfo(const DexProto* proto)

{

    const char* sig = dexProtoGetShorty(proto);

    int returnType, jniArgInfo;

    u4hints;

 

    /* The first shorty character is the return type. */

    switch (*(sig++)) {

    case 'V':

       returnType = DALVIK_JNI_RETURN_VOID;

       break;

    case 'F':

       returnType = DALVIK_JNI_RETURN_FLOAT;

       break;

    case 'D':

       returnType = DALVIK_JNI_RETURN_DOUBLE;

       break;

    case 'J':

       returnType = DALVIK_JNI_RETURN_S8;

       break;

    case 'Z':

    case 'B':

       returnType = DALVIK_JNI_RETURN_S1;

       break;

    case 'C':

       returnType = DALVIK_JNI_RETURN_U2;

       break;

    case 'S':

       returnType = DALVIK_JNI_RETURN_S2;

       break;

    default:

       returnType = DALVIK_JNI_RETURN_S4;

       break;

    }

 

   jniArgInfo = returnType << DALVIK_JNI_RETURN_SHIFT;

 

   hints = dvmPlatformInvokeHints(proto);

 

    if (hints &DALVIK_JNI_NO_ARG_INFO) {

       jniArgInfo |= DALVIK_JNI_NO_ARG_INFO;

    } else {

       assert((hints & DALVIK_JNI_RETURN_MASK) == 0);

       jniArgInfo |= hints;

    }

 

    return jniArgInfo;

}

 

int ClearException(JNIEnv *jenv){

   jthrowable exception = jenv->ExceptionOccurred();

    if (exception != NULL) {

       jenv->ExceptionDescribe();

       jenv->ExceptionClear();

       return true;

    }

    return false;

}

 

bool isArt(){

    return true;

}

 

static jclass findAppClass(JNIEnv *jenv,const char *apn){

    //

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值