#include <jni.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <android/log.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <elf.h>
#include <sys/mman.h>
#include <assert.h>
/***************************************************************************************
*
* 宏定义
*
****************************************************************************************/
//输出调试信息到logcat
#define DEBUG
#define LOG_TAG "LOG_ANDROID_SHELL"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
//求一维数组元素个数
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
//Application类,壳入口
#define JNIREG_CLASS "com/lzy/androidshell/MainApplication"
/***************************************************************************************
*
* 范例代码
*
****************************************************************************************/
//解密dex
JNIEXPORT
void
JNICALL
sub_1111(JNIEnv* env, jobject thiz, jobject context)
{
jclass native_clazz = env->GetObjectClass(context);
jmethodID methodID_func = env->GetMethodID(native_clazz, "getPackageName",
"()Ljava/lang/String;");
jstring packagename = (jstring) (env->CallObjectMethod(context,
methodID_func));
const char *str = env->GetStringUTFChars(packagename, 0);
char destination[128];
const char *blank = "/data/data/", *c = "/.cache/";
strcpy(destination, blank);
strcat(destination, str);
strcat(destination, c);
LOGI("stringcccccccccccccccc %s", destination);
env->ReleaseStringUTFChars(packagename, str);
jint a = mkdir(destination, 777);
LOGI("Created a file in android! %d", a);
const char *pre = "chmod 755 ";
char cmd[128];
strcpy(cmd, pre);
strcat(cmd, destination);
LOGI("cmd %s", cmd);
jstring jcmd = CharTojstring(env, cmd);
//exec
jclass Runtime = env->FindClass("java/lang/Runtime");
jmethodID Runtime_func = env->GetStaticMethodID(Runtime, "getRuntime",
"()Ljava/lang/Runtime;");
jobject class_obj = env->CallStaticObjectMethod(Runtime, Runtime_func);
jclass class_java = env->GetObjectClass(class_obj);
jmethodID exec_func = env->GetMethodID(class_java, "exec",
"(Ljava/lang/String;)Ljava/lang/Process;");
jobject method_obj = env->CallObjectMethod(class_obj, exec_func, jcmd);
jclass class_method_obj = env->GetObjectClass(method_obj);
jmethodID waitfor_func = env->GetMethodID(class_method_obj, "waitFor",
"()I");
jint result = env->CallIntMethod(method_obj, waitfor_func);
LOGI("CallIntMethod %d", result);
jclass native_clazz2 = env->GetObjectClass(context);
jmethodID methodID_func2 = env->GetMethodID(native_clazz2, "getPackageName",
"()Ljava/lang/String;");
jstring packagename2 = (jstring) (env->CallObjectMethod(context,
methodID_func2));
const char *str2 = env->GetStringUTFChars(packagename2, 0);
char destination2[128];
const char *blank2 = "/data/data/", *c2 = "/.cache/classdex.jar";
strcpy(destination2, blank2);
strcat(destination2, str2);
strcat(destination2, c2);
LOGI("string %s", destination2);
LOGI("log test ok ");
env->ReleaseStringUTFChars(packagename2, str2);
jstring jdestination = CharTojstring(env, destination2);
jmethodID methodID_getApplicationInfo = env->GetMethodID(native_clazz2,
"getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
jobject ApplicationInfo = env->CallObjectMethod(context,
methodID_getApplicationInfo);
jclass cls_ApplicationInfo = env->GetObjectClass(ApplicationInfo);
jfieldID JarFieldId = env->GetFieldID(cls_ApplicationInfo,
"publicSourceDir", "Ljava/lang/String;");
jstring SourceDir = (jstring) (env->GetObjectField(ApplicationInfo,
JarFieldId));
const char *strs = env->GetStringUTFChars(SourceDir, 0);
char destinations[128];
strcpy(destinations, strs);
jbyteArray bytes = env->NewByteArray(65536);
LOGI("HAHAHAHHAHAHAHA %s", destinations);
env->ReleaseStringUTFChars(SourceDir, strs);
LOGI("HAHAHAHHAHAHAHA222222222222222");
char *classdex_jar2 = "assets/ErickyProtect.so";
jstring jclassdex_jar = CharTojstring(env, classdex_jar2);
jclass cls_JarFile = env->FindClass("java/util/jar/JarFile");
jmethodID methodID_JarFile = env->GetMethodID(cls_JarFile, "<init>",
"(Ljava/lang/String;)V");
jobject localJarFile = env->NewObject(cls_JarFile, methodID_JarFile,
SourceDir);
//localjarFile getEntry method
jmethodID methodID_getentry = env->GetMethodID(cls_JarFile, "getEntry",
"(Ljava/lang/String;)Ljava/util/zip/ZipEntry;");
jobject LocalZipEntry = env->CallObjectMethod(localJarFile,
methodID_getentry, jclassdex_jar);
//localjarFile getInputStream method
jmethodID methodID_getInputStream = env->GetMethodID(cls_JarFile,
"getInputStream",
"(Ljava/util/zip/ZipEntry;)Ljava/io/InputStream;");
jobject BufferinputstreamParam = env->CallObjectMethod(localJarFile,
methodID_getInputStream, LocalZipEntry);
//new a File class
jclass cls_File = env->FindClass("java/io/File");
jmethodID methodID_File = env->GetMethodID(cls_File, "<init>",
"(Ljava/lang/String;)V");
jobject localFile = env->NewObject(cls_File, methodID_File, jdestination);
//new BufferedInputStream
jclass cls_BufferedInputStream = env->FindClass(
"java/io/BufferedInputStream");
jmethodID methodID_BufferedInputStream = env->GetMethodID(
cls_BufferedInputStream, "<init>", "(Ljava/io/InputStream;)V");
jobject localBufferedInputStream = env->NewObject(cls_BufferedInputStream,
methodID_BufferedInputStream, BufferinputstreamParam);
//new FileoutputStream
jclass cls_FileOutputStream = env->FindClass("java/io/FileOutputStream");
jmethodID methodID_FileOutputStream = env->GetMethodID(cls_FileOutputStream,
"<init>", "(Ljava/io/File;)V");
jobject BufferoutputstreamParam = env->NewObject(cls_FileOutputStream,
methodID_FileOutputStream, localFile);
//new BufferedOutputStream
jclass cls_BufferedOutputStream = env->FindClass(
"java/io/BufferedOutputStream");
jmethodID methodID_BufferedOutputStream = env->GetMethodID(
cls_BufferedOutputStream, "<init>", "(Ljava/io/OutputStream;)V");
jobject localBufferedOutputStream = env->NewObject(cls_BufferedOutputStream,
methodID_BufferedOutputStream, BufferoutputstreamParam);
//some preparations
jmethodID methodID_write = env->GetMethodID(cls_BufferedOutputStream, "write", "([BII)V");
jmethodID methodID_read = env->GetMethodID(cls_BufferedInputStream, "read", "([B)I");
jmethodID output_flush = env->GetMethodID(cls_BufferedOutputStream, "flush", "()V");
jmethodID output_close = env->GetMethodID(cls_BufferedOutputStream, "close", "()V");
jmethodID input_close = env->GetMethodID(cls_BufferedInputStream, "close", "()V");
while (true) {
jint i = env->CallIntMethod(localBufferedInputStream, methodID_read, bytes);
LOGI("IIIIIIIIII %d", i);
if (i <= 0) {
env->CallVoidMethod(localBufferedOutputStream, output_flush);
env->CallVoidMethod(localBufferedOutputStream, output_close);
env->CallVoidMethod(localBufferedInputStream, input_close);
return;
}
env->CallVoidMethod(localBufferedOutputStream, methodID_write, bytes, 0, i);
LOGI("afterwrite %d", i);
}
}
//动态加载DEX
JNIEXPORT
jobject
JNICALL
sub_2222(JNIEnv* env, jobject thiz, jobject context)
{
jclass native_clazz = env->GetObjectClass(context);
jmethodID methodID_func = env->GetMethodID(native_clazz, "getPackageName", "()Ljava/lang/String;");
jstring packagename = (jstring) (env->CallObjectMethod(context, methodID_func));
char *aa = "android.app.ActivityThread", *bb = "currentActivityThread";
jstring jaa = CharTojstring(env, aa);
jstring jbb = CharTojstring(env, bb);
jobjectArray pareTyple;
jobjectArray pareVaules;
jobject currentActivityThread = invokeStaticMethodss(env, jaa, jbb, pareTyple, pareVaules);
char *cc = "android.app.ActivityThread", *dd = "mPackages";
jstring jcc = CharTojstring(env, cc);
jstring jdd = CharTojstring(env, dd);
jclass class_hashmap = env->FindClass("java/util/HashMap");
jmethodID hashmap_construct_method = env->GetMethodID(class_hashmap, "<init>", "()V");
jobject obj_hashmap = env->NewObject(class_hashmap, hashmap_construct_method, "");
obj_hashmap = getFieldOjbect(env, jcc, currentActivityThread, jdd);
jclass class_WeakReference = env->FindClass("java/lang/ref/WeakReference");
if (class_WeakReference == NULL) {
LOGI("class_WeakReference Not Found ");
}
jmethodID WeakReference_get_method = env->GetMethodID(class_WeakReference, "get", "()Ljava/lang/Object;");
if (WeakReference_get_method == NULL) {
LOGI("WeakReference_get_method Not Found ");
}
jmethodID get_func = env->GetMethodID(class_hashmap, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
if (get_func == NULL) {
LOGI("get_func Not Found ");
}
jobject get_obj = env->CallObjectMethod(obj_hashmap, get_func, packagename);
if (get_obj == NULL) {
LOGI("get_obj Not Found ");
}
jobject get_get_obj = env->CallObjectMethod(get_obj, WeakReference_get_method);
if (get_get_obj == NULL) {
LOGI("get_get_obj Not Found ");
}
//Strings prepared
const char *str = env->GetStringUTFChars(packagename, 0);
char parameter1[128];
char parameter2[128];
char parameter3[128];
const char *qz = "/data/data/", *hz1 = "/.cache/classdex.jar", *hz2 = "/.cache", *hz3 = "/.cache/";
strcpy(parameter1, qz);
strcat(parameter1, str);
strcat(parameter1, hz1);
strcpy(parameter2, qz);
strcat(parameter2, str);
strcat(parameter2, hz2);
strcpy(parameter3, qz);
strcat(parameter3, str);
strcat(parameter3, hz3);
LOGI("protect parameter1 %s", parameter1);
LOGI("protect parameter2 %s", parameter2);
LOGI("protect parameter3 %s", parameter3);
env->ReleaseStringUTFChars(packagename, str);
jstring jparameter1 = CharTojstring(env, parameter1);
jstring jparameter2 = CharTojstring(env, parameter2);
jstring jparameter3 = CharTojstring(env, parameter3);
char *loadapk = "android.app.LoadedApk", *mClassLoader = "mClassLoader";
jstring jloadapk = CharTojstring(env, loadapk);
jstring jmClassLoader = CharTojstring(env, mClassLoader);
jclass class_DexClassloader = env->FindClass("dalvik/system/DexClassLoader");
if (class_DexClassloader == NULL) {
LOGI("class_DexClassloader Not Found ");
}
jmethodID DexClassloader_construct_method = env->GetMethodID(class_DexClassloader, "<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
if (DexClassloader_construct_method == NULL) {
LOGI("DexClassloader_construct_method Not Found ");
}
jobject obj_DexClassloader = env->NewObject(class_DexClassloader,
DexClassloader_construct_method, jparameter1, jparameter2,
jparameter3,
getFieldOjbect(env, jloadapk, get_get_obj, jmClassLoader));
if (obj_DexClassloader == NULL) {
LOGI("obj_DexClassloader Not Found ");
}
setFieldOjbect(env, jloadapk, jmClassLoader, get_get_obj, obj_DexClassloader);
return get_get_obj;
}
//char* 到 jstring 转换
jstring
CharTojstring(JNIEnv* env, char* str)
{
jsize len = strlen(str);
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("GB2312");
jmethodID mid = env->GetMethodID(clsstring, "<init>",
"([BLjava/lang/String;)V");
jbyteArray barr = env->NewByteArray(len);
env->SetByteArrayRegion(barr, 0, len, (jbyte*) str);
return (jstring) env->NewObject(clsstring, mid, barr, strencode);
}
//调用指令类的静态函数
jobject
invokeStaticMethodss(JNIEnv *env, jstring class_name, jstring method_name, jobjectArray pareTyple, jobjectArray pareVaules)
{
jclass context = env->FindClass("java/lang/Class");
jmethodID forName_func = env->GetStaticMethodID(context, "forName",
"(Ljava/lang/String;)Ljava/lang/Class;");
jobject class_obj = env->CallStaticObjectMethod(context, forName_func,
class_name);
jclass class_java = env->GetObjectClass(class_obj);
jmethodID getMethod_func = env->GetMethodID(class_java, "getMethod",
"(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
jobject method_obj = env->CallObjectMethod(class_obj, getMethod_func,
method_name, pareTyple);
jclass class_method_obj = env->GetObjectClass(method_obj);
jmethodID invoke_func = env->GetMethodID(class_method_obj, "invoke",
"(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
jobject invoke_obj = env->CallObjectMethod(method_obj, invoke_func, NULL,
pareVaules);
env->DeleteLocalRef(class_java);
env->DeleteLocalRef(method_obj);
return invoke_obj;
}
//获取类的成员变量的值
jobject
getFieldOjbect(JNIEnv *env, jstring class_name, jobject obj, jstring fieldName)
{
jclass context = env->FindClass("java/lang/Class");
jmethodID forName_func = env->GetStaticMethodID(context, "forName",
"(Ljava/lang/String;)Ljava/lang/Class;");
jobject class_obj = env->CallStaticObjectMethod(context, forName_func,
class_name);
jclass class_java = env->GetObjectClass(class_obj);
jmethodID getField_func = env->GetMethodID(class_java, "getDeclaredField",
"(Ljava/lang/String;)Ljava/lang/reflect/Field;");
jobject method_obj = env->CallObjectMethod(class_obj, getField_func,
fieldName);
jclass class_method_obj = env->GetObjectClass(method_obj);
jmethodID setaccess_func = env->GetMethodID(class_method_obj,
"setAccessible", "(Z)V");
env->CallVoidMethod(method_obj, setaccess_func, true);
jmethodID get_func = env->GetMethodID(class_method_obj, "get",
"(Ljava/lang/Object;)Ljava/lang/Object;");
jobject get_obj = env->CallObjectMethod(method_obj, get_func, obj);
env->DeleteLocalRef(class_java);
env->DeleteLocalRef(method_obj);
return get_obj;
}
//修改类的成员变量的值
void
setFieldOjbect(JNIEnv *env, jstring class_name, jstring fieldName, jobject obj, jobject filedVaule)
{
jclass context = env->FindClass("java/lang/Class");
jmethodID forName_func = env->GetStaticMethodID(context, "forName",
"(Ljava/lang/String;)Ljava/lang/Class;");
jobject class_obj = env->CallStaticObjectMethod(context, forName_func,
class_name);
jclass class_java = env->GetObjectClass(class_obj);
jmethodID getField_func = env->GetMethodID(class_java, "getDeclaredField",
"(Ljava/lang/String;)Ljava/lang/reflect/Field;");
jobject method_obj = env->CallObjectMethod(class_obj, getField_func,
fieldName);
jclass class_method_obj = env->GetObjectClass(method_obj);
jmethodID setaccess_func = env->GetMethodID(class_method_obj,
"setAccessible", "(Z)V");
env->CallVoidMethod(method_obj, setaccess_func, true);
jmethodID set_func = env->GetMethodID(class_method_obj, "set",
"(Ljava/lang/Object;Ljava/lang/Object;)V");
env->CallVoidMethod(method_obj, set_func, obj, filedVaule);
env->DeleteLocalRef(class_java);
env->DeleteLocalRef(method_obj);
}