注入安卓进程,并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(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) {

// 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 boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action 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;

u4 hints;

/* 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){

//??oaders

jclass clazzApplicationLoaders = jenv->FindClass("android/app/ApplicationLoaders");

jthrowable exception = jenv->ExceptionOccurred();

if (ClearException(jenv)) {

ALOG("Exception","No class : %s", "android/app/ApplicationLoaders");

return NULL;

}

jfieldID fieldApplicationLoaders = jenv->GetStaticFieldID(clazzApplicationLoaders,"gApplicationLoaders","Landroid/app/ApplicationLoaders;");

if (ClearException(jenv)) {

ALOG("Exception","No Static Field :%s","gApplicationLoaders");

return NULL;

}

jobject objApplicationLoaders = jenv->GetStaticObjectField(clazzApplicationLoaders,fieldApplicationLoaders);

if (ClearException(jenv)) {

ALOG("Exception","GetStaticObjectField is failed [%s","gApplicationLoaders");

return NULL;

}

jfieldID fieldLoaders = jenv->GetFieldID(clazzApplicationLoaders,"mLoaders","Ljava/util/Map;");

if (ClearException(jenv)) {

ALOG("Exception","No Field :%s","mLoaders");

return NULL;

}

jobject objLoaders = jenv->GetObjectField(objApplicationLoaders,fieldLoaders);

if (ClearException(jenv)) {

ALOG("Exception","No object :%s","mLoaders");

return NULL;

}

//??map??alues

jclass clazzHashMap = jenv->GetObjectClass(objLoaders);

jmethodID methodValues = jenv->GetMethodID(clazzHashMap,"values","()Ljava/util/Collection;");

jobject values = jenv->CallObjectMethod(objLoaders,methodValues);

jclass clazzValues = jenv->GetObjectClass(values);

jmethodID methodToArray = jenv->GetMethodID(clazzValues,"toArray","()[Ljava/lang/Object;");

if (ClearException(jenv)) {

ALOG("Exception","No Method:%s","toArray");

return NULL;

}

jobjectArray classLoaders = (jobjectArray)jenv->CallObjectMethod(values,methodToArray);

if (ClearException(jenv)) {

ALOG("Exception","CallObjectMethod failed :%s","toArray");

return NULL;

}

int size = jenv->GetArrayLength(classLoaders);

for(int i = 0 ; i < size ; i ++){

jobject classLoader = jenv->GetObjectArrayElement(classLoaders,i);

jclass clazzCL = jenv->GetObjectClass(classLoader);

jmethodID loadClass = jenv->GetMethodID(clazzCL,"loadClass","(Ljava/lang/String;)Ljava/lang/Class;");

jstring param = jenv->NewStringUTF(apn);

jclass tClazz = (jclass)jenv->CallObjectMethod(classLoader,loadClass,param);

if (ClearException(jenv)) {

ALOG("Exception","No");

continue;

}

return tClazz;

}

ALOG("Exception","No");

return NULL;

}

bool HookDalvikMethod(jmethodID jmethod){

Method *method = (Method*)jmethod;

//?!!??О?native

SET_METHOD_FLAG(method, ACC_NATIVE);

int argsSize = dvmComputeMethodArgsSize(method);

if (!dvmIsStaticMethod(method))

argsSize++;

method->registersSize = method->insSize = argsSize;

if (dvmIsNativeMethod(method)) {

method->nativeFunc = dvmResolveNativeMethod;

method->jniArgInfo = computeJniArgInfo(&method->prototype);

}

}

bool ClassMethodHook(HookInfo info){

JNIEnv *jenv = GetEnv();

jclass clazzTarget = jenv->FindClass(info.tClazz);

if (ClearException(jenv)) {

ALOG("Exception","ClassMethodHook[Can‘t find class:%s in bootclassloader",info.tClazz);

clazzTarget = findAppClass(jenv,info.tClazz);

if(clazzTarget == NULL){

ALOG("Exception","%s","Error in findAppClass");

return false;

}

}

jmethodID method = jenv->GetMethodID(clazzTarget,info.tMethod,info.tMeihodSig);

if(method==NULL){

ALOG("Exception","ClassMethodHook[Can‘t find method:%s",info.tMethod);

return false;

}

if(isArt()){

HookArtMethod(jenv,method);

}else{

HookDalvikMethod(method);

}

JNINativeMethod gMethod[] = {

{info.tMethod, info.tMeihodSig, info.handleFunc},

};

//func?NULL??А??????

if(info.handleFunc != NULL){

//?!!??????ative

if (jenv->RegisterNatives(clazzTarget, gMethod, 1) < 0) {

ALOG("RegisterNatives","err");

return false;

}

}

DetachCurrent();

return true;

}

int Hook(){

init();

void* handle = dlopen("/data/local/libTest.so",RTLD_NOW);

const char *dlopen_error = dlerror();

if(!handle){

ALOG("Error","cannt load plugin :%s",dlopen_error);

return -1;

}

SetupFunc setup = (SetupFunc)dlsym(handle,"getpHookInfo");

const char *dlsym_error = dlerror();

if (dlsym_error) {

ALOG("Error","Cannot load symbol ‘getpHookInfo‘ :%s" , dlsym_error);

dlclose(handle);

return 1;

}

HookInfo *hookInfo;

setup(&hookInfo);

ALOG("LOG","Target Class:%s",hookInfo[0].tClazz);

ALOG("LOG","Target Method:%s",hookInfo[0].tMethod);

ClassMethodHook(hookInfo[0]);

}

以下是我们想要的目标进程java世界执行的我们自定义的代码

libTest.so

#include "native.h"

#include <android/log.h>

#include "stdio.h"

#include "stdlib.h"

#include "MethodHooker.h"

#define log(a,b) __android_log_print(ANDROID_LOG_VERBOSE,a,b); // LOG ?:info

#define log_(b) __android_log_print(ANDROID_LOG_VERBOSE,"JNI_LOG_INFO",b); // LOG ?:info

int getpHookInfo(HookInfo** pInfo);

JNIEXPORT void JNICALL Java_com_example_testar_InjectClassloader_hookMethodNative

(JNIEnv * jenv, jobject jboj, jobject jobj, jclass jclazz, jint slot)

{

//log("TestAE","start Inject other process");

}

JNIEXPORT jstring JNICALL test(JNIEnv *env, jclass clazz)

{

//__android_log_print(ANDROID_LOG_VERBOSE, "tag", "call <native_printf> in java");

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

}

HookInfo hookInfos[] = {

{"android/net/wifi/WifiInfo","getMacAddress","()Ljava/lang/String;",(void*)test},

//{"com/example/testar/MainActivity","test","()Ljava/lang/String;",(void*)test},

//{"android/app/ApplicationLoaders","getText","()Ljava/lang/CharSequence;",(void*)test},

};

int getpHookInfo(HookInfo** pInfo){

*pInfo = hookInfos;

return sizeof(hookInfos) / sizeof(hookInfos[0]);

}

程序大致的流程是这样的,首先将so.so注入到目标进程,执行里面的Hook()函数,然后Hook()加载libTest.so,获取里面定义的Hook信息.接着用ClassMethodHook挂钩java世界的方法.

关键一,从native世界进入java世界.熟悉jni编程的都知道,java到native的桥梁是JNIEnv,我们只要获得一个JNIEnv就能进入到java世界了.突破点就在AndroidRuntime,android::AndroidRuntime::getJavaVM();这个静态方法能够获取一个JavaVM, JavaVM->GetEnv方法能够获得一个JNIEnv了.JNIEnv是和线程相关的,使用前一定记得将其附加到当前进程,也要在适当的时候将其销毁.

关键二,怎么影响内存里的java代码,这个情况替换内存是不现实的,但是可以取巧.我们知道java代码里将一个方法声明为native方法时,对此函数的调用就会到native世界里找.我们何不在运行时将一个不是native的方法修改成native方法呢?这是可以做到的,看着段代码

bool HookDalvikMethod(jmethodID jmethod){

Method *method = (Method*)jmethod;

//?!!??О?native

SET_METHOD_FLAG(method, ACC_NATIVE);

int argsSize = dvmComputeMethodArgsSize(method);

if (!dvmIsStaticMethod(method))

argsSize++;

method->registersSize = method->insSize = argsSize;

if (dvmIsNativeMethod(method)) {

method->nativeFunc = dvmResolveNativeMethod;

method->jniArgInfo = computeJniArgInfo(&method->prototype);

}

}

Jni反射调用java方法时要用到一个jmethodID指针,这个指针在Dalvik里其实就是Method类,通过修改这个类的一些属性就可以实现在运行时将一个方法修改成native方法.

SET_METHOD_FLAG(method, ACC_NATIVE); 就是这么做的,其后面的代码就是设定native函数的参数占用内存大小统计.

也许你发现了,虽然将其修改成一个native方法了,但是这个方法对应的native代码在那里呢?这样做

//?!!??????ative

if (jenv->RegisterNatives(clazzTarget, gMethod, 1) < 0) {

ALOG("RegisterNatives","err");

return false;

}

可以将一个native函数绑定到一个java的native方法

这样就能够实现开始的目标了!

我这里讲得是有点粗略了,但是这个技术牵涉到的知识太多了,主要是给老鸟参考的,小菜们拿来用用就好,要是要讲得小菜们都能明白,就不知要讲到何年何月了.还有就是上面的art环境的代码是跑不起来的,等我后面有空完善了再发一次吧!

本教程仅供学习交流用途,请勿用于非法用途!

希望老鸟勿笑,小鸟勿喷!谢谢观赏!

测试代码猛击这里:http://pan.baidu.com/s/1nt9GBsX

Hook Java的的一个改进版本
《注入安卓进程,并Hook java世界的方法》这篇好文相信大家都看这,里面所提到的方法估
计大家也都试过。不过里面的所用的方法,我发现有两个可以改进的地方。
改进点一:更简单地修改java方法为本地方法
...
// hook method
int argsSize = calcMethodArgsSize(method->shorty);
if (!dvmIsStaticMethod(method))
argsSize++;
SET_METHOD_FLAG(method, ACC_NATIVE);
method->registersSize = method->insSize = argsSize;
method->outsSize = 0;
method->jniArgInfo = dvmComputeJniArgInfo(method->shorty);
// save info to insns
method->insns = (u2*)info;
// bind the bridge func,only one line
method->nativeFunc = method_handler;
LOGI("[+] %s->%s was hooked\n", classDesc, methodName);
...
直接把method->nativeFunc即可,无需重新调用JNIEnv的RegisterNatives方法,其中
method_handler可以是下面两种形式之一:
typedef void (*DalvikBridgeFunc)(const u4* args, JValue* pResult, const
Method* method, struct Thread* self);
typedef void (*DalvikNativeFunc)(const u4* args, JValue* pResult);
这样有一个好处,就是所有java方法都可以统一指向同一个native func,而不需要像为每一个
java method方法指定一个native func。
改进点二:方法回调避免线程安全问题
原来的方法,是这样的
//hook之前先拷?
uint mlen = sizeof(Method);
Method *oldMeth = (Method*)malloc(mlen);
memcpy(oldMeth,method,mlen);
info->odlMethod = oldMeth;
info->curMethod = method;
//回调后再拷?回来,再通过jni->callXXXXMethod调?,之后再重新hook
memcpy(hi->curMethod,hi->odlMethod,mlen);
jmethodID om = (jmethodID)hi->curMethod;
jenv->CallVoidMethod(me,om,gDevice_Sensors);
ClassMethodHook(jenv,&baiduhookInfos[0]);
这个方法,其实是有线程安全问题的,其中在dalvik中,有很多方法可以直接调用Method对
象,比如dvmCallMethod, dvmCallMethodA, dvmCallMethodV,dvmInvokeMethod等等。针对
DalvikBridgeFunc和DalvikNativeFunc的参数,我最后选择使用dvmInvokeMethod,这个函数
的原型是这样的:
Object* dvmInvokeMethod(Object* obj, const Method* method, ArrayObject*
argList, ArrayObject* params, ClassObject* returnType, bool noAccessCheck)
其中,obj是this或者null(如果是static方法),method可以直接使用hook之前copy的对象,
比较麻烦是argList,params和returnType的获取。获取argList的方法,我在Proxy.cpp中到了
现成的boxMethodArgs方法,而returnType通过Reflect.h中dvmGetBoxedReturnType的方法
也可以获取,而剩下的params只能自己写代码了,下面是我的代码:
STATIC ArrayObject* dvmGetMethodParamTypes(const Method* method, const char*
methodsig){
/* count args */
size_t argCount = dexProtoGetParameterCount(&method->prototype);
STATIC ClassObject* java_lang_object_array = dvmFindSystemClass("
[Ljava/lang/Object;");
/* allocate storage */
ArrayObject* argTypes = dvmAllocArrayByClass(java_lang_object_array,
argCount, ALLOC_DEFAULT);
if(argTypes == NULL){
return NULL;
}
Object** argObjects = (Object**) argTypes->contents;
const char *desc = (const char *)(strchr(methodsig, ‘(‘) + 1);
/*
* Fill in the array.
*/
size_t desc_index = 0;
size_t arg_index = 0;
bool isArray = false;
char descChar = desc[desc_index];
while (descChar != ‘)‘) {
switch (descChar) {
case ‘Z‘:
case ‘C‘:
case ‘F‘:
case ‘B‘:
case ‘S‘:
case ‘I‘:
case ‘D‘:
case ‘J‘:
if(!isArray){
argObjects[arg_index++] = dvmFindPrimitiveClass(descChar);
isArray = false;
}else{
char buf[3] = {0};
memcpy(buf, desc + desc_index - 1, 2);
argObjects[arg_index++] = dvmFindSystemClass(buf);
}
desc_index++;
break;
case ‘[‘:
isArray = true;
desc_index++;
break;
case ‘L‘:
int s_pos = desc_index, e_pos = desc_index;
while(desc[++e_pos] != ‘;‘);
s_pos = isArray ? s_pos - 1 : s_pos;
isArray = false;
size_t len = e_pos - s_pos + 1;
char buf[128] = { 0 };
memcpy((void *)buf, (const void *)(desc + s_pos), len);
argObjects[arg_index++] = dvmFindClass(buf);
desc_index = e_pos + 1;
break;
}
descChar = desc[desc_index];
}
return argTypes;
}
通过上面几个类型的获取之后,最后再看一下整个method hook的实现,过程其实大同小异,
不过直接把上述提及的向种类型信息预先获取并保存到method->insns里头了:
extern int __attribute__ ((visibility ("hidden")))
dalvik_java_method_hook(JNIEnv* env, HookInfo *info) {
const char* classDesc = info->classDesc;
const char* methodName = info->methodName;
const char* methodSig = info->methodSig;
const bool isStaticMethod = info->isStaticMethod;
jclass classObj = dvmFindJNIClass(env, classDesc);
if (classObj == NULL) {
LOGE("[-] %s class not found", classDesc);
return -1;
}
jmethodID methodId =
isStaticMethod ?
env->GetStaticMethodID(classObj, methodName, methodSig)
:
env->GetMethodID(classObj, methodName, methodSig);
if (methodId == NULL) {
LOGE("[-] %s->%s method not found", classDesc, methodName);
return -1;
}
// backup method
Method* method = (Method*) methodId;
if(method->nativeFunc == method_handler){
LOGW("[*] %s->%s method had been hooked", classDesc, methodName);
return -1;
}
Method* bakMethod = (Method*) malloc(sizeof(Method));
memcpy(bakMethod, method, sizeof(Method));
// init info
info->originalMethod = (void *)bakMethod;
info->returnType = (void *)dvmGetBoxedReturnType(bakMethod);
info->paramTypes = dvmGetMethodParamTypes(bakMethod, info->methodSig);
// hook method
int argsSize = calcMethodArgsSize(method->shorty);
if (!dvmIsStaticMethod(method))
argsSize++;
SET_METHOD_FLAG(method, ACC_NATIVE);
method->registersSize = method->insSize = argsSize;
method->outsSize = 0;
method->jniArgInfo = dvmComputeJniArgInfo(method->shorty);
// save info to insns
method->insns = (u2*)info;
// bind the bridge func,only one line
method->nativeFunc = method_handler;
LOGI("[+] %s->%s was hooked\n", classDesc, methodName);
return 0;
}
然后是method_handler的实现,这个方法是所有java方法的跳转函数,所以在这里可以注册
callback,不过这部分逻辑我没有做上,有兴趣的朋友可以加上。
STATIC void method_handler(const u4* args, JValue* pResult, const Method*
method, struct Thread* self){
HookInfo* info = (HookInfo*)method->insns; //get hookinfo pointer from
method-insns
LOGI("entry %s->%s", info->classDesc, info->methodName);
Method* originalMethod = reinterpret_cast<Method*>(info->originalMethod);
Object* thisObject = (Object*)args[0];
ArrayObject* argTypes = dvmBoxMethodArgs(originalMethod, args + 1);
pResult->l = (void *)dvmInvokeMethod(thisObject, originalMethod,
argTypes, (ArrayObject *)info->paramTypes, (ClassObject *)info->returnType,
true);
dvmReleaseTrackedAlloc((Object *)argTypes, self);
}
最后通过dvmInvokeMethod就可以直接调回原来的函数了。
最后
写这个代码,主要是因为我在工作中要注入到某个系统进程,然后要hook java中的某些方法,
但用cydia和xposed感觉太笨重了,特别是xposed,里面的很多参数的boxed/unboxed都是通
过jni模块自动转换的,整个框架已经离不开dex文件了。
所以才想自己实现一套纯本地的java hook代码,而《注入安卓进程,并Hook java世界的方
法》所介绍的方法,我感觉用起来不太方便,跟cydia和xposed两个框架的主要区别就是缺少
了一个“中转函数”,所以而有了本码。

时间: 2024-11-05 13:42:22

注入安卓进程,并hook java世界的方法及改进的相关文章

使用Cydia Substrate 从Native Hook Android Java世界

这里介绍了如何使用Cydia Substrate Hook安卓Java世界.这篇文章介绍如何从Native中Hook 安卓Java世界. 手机端配置见之前文章. 一.建立工程 建立一个Android工程.不需要创建默认的Activity.修改AndroidManifest.xml如下: <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.cyd

将dll文件注入到其他进程中的一种新方法

http://www.45it.com/windowszh/201212/33946.htm http://www.hx95.cn/Article/OS/201212/65095.html 我们知道将动态连接库注入到其他进程中有很多种方法.最常见的方法是使用钩子函数(Hook),但是这种方法主要有两个缺点:第一如果某个进程没有加载User32.dll,那么Hook DLL将永远也不会被加载.第二Hook DLL加载的时机问题,只有在进程发出User32调用的时候, Hook DLL才有可能被加载

Android 开创java世界(JNI Invocation API)

在Android的世界中,由名称为app_process的C++本地应用程序(路径为:framework/base/cmds/app_process/app_main.cpp)调用JNI Invocation API 在自身进程中加载dalvikvm虚拟机,这样就开创了java世界. 现在就简单的Demo一下这个原理,在Ubuntu11.10的终端中操作,已安装了jdk的条件. 1.首先创建一个工作目录: mkdir javaVMTest 2.创建一个java文件,Called.java,内容:

Java 世界的盘古和女娲 —— Zygote

本文基于 Android 9.0 , 代码仓库地址 : android_9.0.0_r45 文中源码链接: Zygote.java ZygoteInit.java ZygoteServer.java ZygoteConnection.java RuntimeInit.java 仔细看看下面这张 Android 体系图,找一下 Zygote 在什么地方. 上图来自 Gityuan 博客 . 纵观整个 Android 体系结构,底层内核空间以 Linux Kernel 为核心,上层用户空间以 C++

Atitit,通过pid获取进程文件路径&#160;java&#160;php&#160;&#160;c#.net版本大总结

Atitit,通过pid获取进程文件路径 java php  c#.net版本大总结 1. 通过PID获取进程路径的几种方法2 1.1. GetModuleFileNameEx 想获得进程可执行文件的路径最常用的方法是通过GetModuleFileNameEx函数获得可执行文件的模块路径这个函数从Windows NT 4.0开始到现在的Vista系统都能使用,向后兼容性比较好.2 1.2. 第二种方法是GetProcessImageFileName函数,这个函数在Windows XP及其以后的系

Delphi XE7的安卓程序如何调用JAVA的JAR,使用JAVA的类?

本文使用工具和全部源码下载: http://download.csdn.net/detail/sunylat/8190765 为什么我们要在Delphi XE7的安卓程序调用Java的JAR,使用JAVA的类?如果能够这样做,那么就意味着我们把Delphi开发的安卓程序扩展到了一个更大的开发范围了,理论上可以调用任意JAVA编写的代码,对于同时精通Delphi和JAVA的程序员来说,简直如虎添翼!! 我差不多用了一天时间吧,最终在老猫的帮助下,成功实现了在Delphi XE7的安卓程序中调用JA

世界上最恶心的调用方法:Delphi调用Java的class方法法

世界上最恶心的调用方法是,:用Delphi调用Java的class方法: 如果写了一个java方法: package com.api; public class DelphiCallJava { public static String dTest(String args,int args2,String args3){ if(args==null){ return "您沒有輸入參數."; }else { return "您輸入的參數是:"+args; } } }

JAVA世界

这算是我的的第一篇文章了.以前还真不怎么喜欢写些东西.可能最近有时间了吧!进入JAVA世界已有二年多时间了.记得刚进北大青鸟时那种热情是无法用言语去表达.在java 的世界是这样的.它把一切东西看作对象凡是这一类对象都抽象成一个class 每一个对象中都各自的属性和动作(也就是方法) 例如衣服以及衣服上扭扣都可以看作一个对象.只是它们只有各自属性没有方法罢了!其实我们在写软件时返回到前台页面列表中的一行行数据就是一个个对象而已! 我还记得第一次进入北大青鸟第一课时老师所说的话:"程序设计并不是那

原来Java世界里也有这么多精彩的故事,学Java真有趣!

大千世界,无所不有.这世上不光有人类世界,还有咱们的java世界.今天就由我这个实习导游带领你们了解了解咱们的java世界奇妙之处. 有一种暖男叫catch,有一种真爱叫try---catch,世上最真情的爱恋就是你在try我在catch,无论你发什么脾气,我都静静的接受,默默地处理,不管你有什么错,我都会原谅你,爱着你. 有一种懒汉员工叫throws,甭管有啥事都往外抛,做错事了就交给上级擦屁股,上级不会再给上级,给到老板为止,老板也不会那就gg了,倒闭吧. 有一种听话员工叫循环,你让他做几遍