Android中通过进程注入技术修改系统返回的Mac地址

本文介绍了如何通过进程注入技术在Android中修改系统返回的Mac地址,涉及知识点包括非native方法转native方法、类加载器、NDK项目编译等。作者详细解析了注入流程,包括获取进程ID、注入SO文件、执行Hook函数等步骤,以及利用反射和Dalvik机制实现方法的Hook。
摘要由CSDN通过智能技术生成
               

致谢

感谢看雪论坛中的这位大神,分享了这个技术:http://bbs.pediy.com/showthread.php?t=186054,从这篇文章中学习到了很多内容,如果没有这篇好文章,我在研究的过程中会遇到很多困难,说不定我就放弃了~~在此感谢他。


前言

之前的几篇文章都是在介绍了OC的相关知识,之前的半个月也都是在搞IOS的相关东西,白天上班做Android工作,晚上回家还有弄IOS,感觉真的很伤了。不过OC的知识也学习了差不多了。不过在这段时间遗留了很多Android方面的问题都没有进行解决和总结。所以从这段时间开始,需要将解决的问题都总结一下吧。


问题

Android中通过注入技术修改系统返回的Mac地址


技术准备

下面来看一下这个技术需要哪些知识点

1、如何将非native方法变成native方法

2、如何将native方法直接注册(不需要jni这样的头文件了)

3、Android中的类加载器相关知识

4、如何编译Android系统引用系统头文件的NDK项目

虽然这里有这四个知识点,但是其中有两个我在之前的blog中已经介绍了:

Android中的类加载器:http://blog.csdn.net/jiangwei0910410003/article/details/41384667

如何编译Android系统引用系统头文件的NDK项目:http://blog.csdn.net/jiangwei0910410003/article/details/40949475

不过在这篇文章中,我们在介绍一种新的编译方式


项目测试

第一、Android项目

package com.example.testar;import android.net.wifi.WifiInfo;import android.net.wifi.WifiManager;import android.os.Bundle;import android.app.Activity;import android.content.Context;import android.util.Log;import android.view.Menu;import android.view.View;import android.widget.Button;public class MainActivity extends Activity {  @Override protected void onCreate(Bundle savedInstanceState) {  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) {    WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);    WifiInfo info = wifi.getConnectionInfo();    System.out.println("Wifi mac :" + info.getMacAddress());    Log.d("DEMO", "Wifi mac:"+info.getMacAddress());   }  }); }}
我们看到,这里的代码很简单,就是打印一下设备的Mac地址,现在我们要做的就是:注入这个Demo进程,然后修改Mac的值。


第二、底层的实现

首先来看一下inject.c

这个是注入进程的核心文件,由于代码比较多,这里只看核心的部分:

int main(int argc, char** argv) char *pn = "com.example.testar"char *is = "/data/local/libso.so"printf("%s\n",pn); printf("%s\n",is);  pid_t target_pid; target_pid = find_pid_of(pn); printf("pid: %d\n",target_pid); int ret = inject_remote_process(target_pid, is, "InjectInterface", (void*)"I'm parameter!", strlen("I'm parameter!") ); printf("result: %d\n",ret);}
就是他的主函数代码

我们看到有一个重要的函数:

inject_remote_process

第一个参数:注入进程的id

第二个参数:需要注入到目标进程的so文件

第三个参数:so文件中需要执行的函数名

第四个参数:执行函数的参数

第五个参数:执行函数的参数的长度


主要还是前面三个参数。

这里我们通过find_pid_of(pn)函数来获取进程id

传递进去的是进程名

Android中应用的进程名就是包名

char *pn = "com.example.testar";
看到上面注入到目标进程的so文件

char *is = "/data/local/libso.so";
下面再来看一下这个so文件的源代码

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>#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ÀàÐÍ:infoextern "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){    return env->NewStringUTF("haha ");}
在这个文件中,我们看到了函数 InjectInterface了,因为so是C++程序,但是inject是C程序,为了兼容,就有这种方式了

extern "C"  函数{

//do something

}

这个代码没什么难度和复杂性

这个函数中调用了Hook函数,下面在来看一下Hook函数的定义


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"#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 = tr
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值