背景
Android如何Dump内存中的数据,比如so文件
- 有时候so文件是加密或者动态下发,需要从内存中Dump出来后进行使用
- 可以直接使用下面的代码,编译生成bin
Show me the Code
Frida方案
rpc.exports = {
findmodule: function(so_name) {
var libso = Process.findModuleByName(so_name);
return libso;
},
dumpmodule: function(so_name) {
var libso = Process.findModuleByName(so_name);
if (libso == null) {
return -1;
}
Memory.protect(ptr(libso.base), libso.size, 'rwx');
var libso_buffer = ptr(libso.base).readByteArray(libso.size);
libso.buffer = libso_buffer;
return libso_buffer;
},
allmodule: function() {
return Process.enumerateModules()
},
arch: function() {
return Process.arch;
}
}
内存dump
function dump_memory(base,size) {
Java.perform(function () {
var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
var dir = currentApplication.getApplicationContext().getFilesDir().getPath();
var file_path = dir + "/dumpmemory.bin";
var file_handle = new File(file_path, "wb");
if (file_handle && file_handle != null) {
Memory.protect(ptr(base),size, 'rwx');
var libso_buffer = ptr(base).readByteArray(size);
file_handle.write(libso_buffer);
file_handle.flush();
file_handle.close();
console.log("[dump]:", file_path);
}
});
}
dump_memory(0xbb25a208-2048,4096);
编译成C产物方案
#include <dlfcn.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
if (argc < 2) {
printf("usage:./dump ./libxx.so /system/lib/libc.so ...");
return 0;
} else if (argc > 3) {
}
for (int i = 2; i < argc; i++) {
printf("[+] dlopen %s\n", argv[i]);
void* si = dlopen(argv[i], RTLD_LAZY);
if (si == NULL) {
printf("[-] dlopen depend so err!\n");
return 0;
}
}
JavaVM* vm;
JNIEnv* env;
jint res;
JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString = "-Djava.class.path=.";
vm_args.version = 0x00010002;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;
printf("[+] dlopen libdvm.so\n");
void* handle =
dlopen("/system/lib/libdvm.so", RTLD_LAZY); // RTLD_LAZY RTLD_NOW
if (!handle) {
printf("[-] dlopen libdvm.so failed!!\n");
return 0;
}
typedef int (*JNI_CreateJavaVM_Type)(JavaVM**, JNIEnv**, void*);
JNI_CreateJavaVM_Type JNI_CreateJavaVM_Func =
(JNI_CreateJavaVM_Type)dlsym(handle, "JNI_CreateJavaVM");
if (!JNI_CreateJavaVM_Func) {
printf("[-] dlsym failed\n");
return 0;
}
res = JNI_CreateJavaVM_Func(&vm, &env, &vm_args);
void* si = dlopen(argv[1], RTLD_LAZY);
if (si == NULL) {
printf("[-] dlopen err!\n");
return 0;
}
void* addr = (void*)(*(int*)((size_t)si + 0x8c));
uint32_t len = *(uint32_t*)((size_t)si + 0x90);
char path[257] = "";
sprintf(path, "%p_0x%x.so", addr, len);
FILE* fp = fopen(path, "wb");
printf("[+] save %s\n", path);
fwrite(addr, 1, len, fp);
fclose(fp);
return 0;
}
参考
https://bbs.pediy.com/thread-259152.htm