免责声明
本文章中所有内容仅供学习交流使用,严禁用于商业用途和非法用途。若有侵权,请联系我,立即删除!
获取当前程序的包名
adb shell dumpsys window | grep mCurrentFocus
frida 手动jnienv
frida -U -f com.james.easymd5 -l frida_hook_libart/hook_art.js --no-pause
frida 自动追踪 jnitracer
pip install jnitrace
利用objection找so名====>libeasymd5.so
objection -g com.james.easymd5 explore
memory list modules
ps: libeasymd5.so 0x7386f08000 221184 (216.0 KiB) /data/app/com.james.easymd5-3XeGcE9nwvgObFyalCNGsA==/lib/arm64/libeasymd5.s...
emory list exports libeasymd5.so
Save the output by adding `--json exports.json` to this command
Type Name Address
-------- -------------------------------------------- ----------
function Java_com_james_easymd5_MainActivity_mdFile 0xd2b96e39
function _Z7MD5InitP7MD5_CTX 0xd2b96b63
function Java_com_james_easymd5_MainActivity_mdString 0xd2b96a59
function _Z9MD5UpdateP7MD5_CTXPhj 0xd2b96ba5
function _ZN7_JNIEnv12NewStringUTFEPKc 0xd2b96e19
function _Z8MD5FinalP7MD5_CTX 0xd2b96c85
function _ZN7_JNIEnv17GetStringUTFCharsEP8_jstringPh 0xd2b96b3d
c++filt _Z9MD5UpdateP7MD5_CTXPhj
MD5Update(MD5_CTX*, unsigned char*, unsigned int)
命令:jnitrace -l libeasymd5.so com.james.easymd5
Tracing. Press any key to quit...
Traced library "libeasymd5.so" loaded from path "/data/app/com.james.easymd5-3XeGcE9nwvgObFyalCNGsA==/lib/arm64".
/* TID 7350 */
370 ms [+] JNIEnv->NewStringUTF
370 ms |- JNIEnv* : 0x73a98cc1c0
370 ms |- char* : 0x7fd63a6cc1
370 ms |: Hello from C++
370 ms |= jstring : 0x75 { Hello from C++ }
370 ms ----------------------------------------Backtrace----------------------------------------
370 ms |-> 0x7392b97098: _ZN7_JNIEnv12NewStringUTFEPKc+0x2c (libeasymd5.so:0x7392b88000)
370 ms |-> 0x7392b97098: _ZN7_JNIEnv12NewStringUTFEPKc+0x2c (libeasymd5.so:0x7392b88000)
frida Hook so位置
frida -U -f com.james.easymd5 -l dump_dex.js --no-pause
[Google Pixel XL::com.james.easymd5]-> android_dlopen_ext: /data/app/com.james.easymd5-7ZxsaFkVCnATrcrvoqQcSA==/oat/arm/base.odex
android_dlopen_ext: /data/app/com.james.easymd5-7ZxsaFkVCnATrcrvoqQcSA==/lib/arm/libeasymd5.so
android_dlopen_ext: /vendor/lib/hw/gralloc.msm8996.so
dlopen: libadreno_utils.so
dlopen: /vendor/lib/egl/libEGL_adreno.so
android_dlopen_ext: /vendor/lib/hw/android.hardware.graphics.mapper@2.0-impl.so
android_dlopen_ext: /vendor/lib/hw/gralloc.msm8996.so
read elf查看导出表
7z x app-debug.apk
cd lib/armeabi-v7a
readelf -s libeasymd5.so
Symbol table '.dynsym' contains 30 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@LIBC (2)
2: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_f[...]@LIBC (2)
3: 00000000 0 OBJECT GLOBAL DEFAULT UND __sF@LIBC (2)
4: 00000000 0 FUNC GLOBAL DEFAULT UND __stack[...]@LIBC (2)
5: 00000000 0 OBJECT GLOBAL DEFAULT UND __stack[...]@LIBC (2)
6: 00000000 0 FUNC GLOBAL DEFAULT UND __strlen_chk@LIBC (2)
7: 00000000 0 FUNC GLOBAL DEFAULT UND __vspri[...]@LIBC (2)
8: 00000000 0 FUNC GLOBAL DEFAULT UND fclose@LIBC (2)
9: 00000000 0 FUNC GLOBAL DEFAULT UND fopen@LIBC (2)
10: 00000000 0 FUNC GLOBAL DEFAULT UND fprintf@LIBC (2)
11: 00000000 0 FUNC GLOBAL DEFAULT UND fread@LIBC (2)
12: 00000000 0 FUNC GLOBAL DEFAULT UND strlen@LIBC (2)
13: 00000000 0 FUNC GLOBAL DEFAULT UND abort@LIBC (2)
14: 00000000 0 FUNC GLOBAL DEFAULT UND fflush@LIBC (2)
15: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_memclr
16: 00000000 0 FUNC GLOBAL DEFAULT UND __aeabi_memcpy
17: 00000000 0 FUNC GLOBAL DEFAULT UND __gnu_Unwind_Fin[...]
18: 00000000 0 FUNC GLOBAL DEFAULT UND dladdr@LIBC (3)
19: 00000000 0 FUNC GLOBAL DEFAULT UND snprintf@LIBC (2)
20: 00000e39 324 FUNC GLOBAL DEFAULT 13 Java_com_james_e[...]
21: 00000b63 66 FUNC GLOBAL DEFAULT 13 _Z7MD5InitP7MD5_CTX
22: 00005044 0 NOTYPE GLOBAL DEFAULT ABS _edata
23: 00005045 0 NOTYPE GLOBAL DEFAULT ABS _end
24: 00000a59 228 FUNC GLOBAL DEFAULT 13 Java_com_james_e[...]
25: 00000ba5 224 FUNC GLOBAL DEFAULT 13 _Z9MD5UpdateP7MD[...]
26: 00000e19 32 FUNC WEAK DEFAULT 13 _ZN7_JNIEnv12New[...]
27: 00005044 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
28: 00000c85 284 FUNC GLOBAL DEFAULT 13 _Z8MD5FinalP7MD5_CTX
29: 00000b3d 38 FUNC WEAK DEFAULT 13 _ZN7_JNIEnv17Get[...]
objdump -T libeasymd5.so
libeasymd5.so: file format elf32-little
DYNAMIC SYMBOL TABLE:
00000000 DF *UND* 00000000 (LIBC) __cxa_atexit
00000000 DF *UND* 00000000 (LIBC) __cxa_finalize
00000000 DO *UND* 00000000 (LIBC) __sF
00000000 DF *UND* 00000000 (LIBC) __stack_chk_fail
00000000 DO *UND* 00000000 (LIBC) __stack_chk_guard
00000000 DF *UND* 00000000 (LIBC) __strlen_chk
00000000 DF *UND* 00000000 (LIBC) __vsprintf_chk
00000000 DF *UND* 00000000 (LIBC) fclose
00000000 DF *UND* 00000000 (LIBC) fopen
00000000 DF *UND* 00000000 (LIBC) fprintf
00000000 DF *UND* 00000000 (LIBC) fread
00000000 DF *UND* 00000000 (LIBC) strlen
00000000 DF *UND* 00000000 (LIBC) abort
00000000 DF *UND* 00000000 (LIBC) fflush
00000000 DF *UND* 00000000 __aeabi_memclr
00000000 DF *UND* 00000000 __aeabi_memcpy
00000000 DF *UND* 00000000 __gnu_Unwind_Find_exidx
00000000 DF *UND* 00000000 (LIBC) dladdr
00000000 DF *UND* 00000000 (LIBC) snprintf
00000e39 g DF .text 00000144 Base Java_com_james_easymd5_MainActivity_mdFile
00000b63 g DF .text 00000042 Base _Z7MD5InitP7MD5_CTX
00005044 g D *ABS* 00000000 Base _edata
00005045 g D *ABS* 00000000 Base _end
00000a59 g DF .text 000000e4 Base Java_com_james_easymd5_MainActivity_mdString
00000ba5 g DF .text 000000e0 Base _Z9MD5UpdateP7MD5_CTXPhj
00000e19 w DF .text 00000020 Base _ZN7_JNIEnv12NewStringUTFEPKc
00005044 g D *ABS* 00000000 Base __bss_start
00000c85 g DF .text 0000011c Base _Z8MD5FinalP7MD5_CTX
00000b3d w DF .text 00000026 Base _ZN7_JNIEnv17GetStringUTFCharsEP8_jstringPh
Frida hook jni
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
onEnter: function(args) {
var pathptr = args[0];
this.target = false
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
console.log("android_dlopen_ext:", path);
if (path.indexOf("libeasymd5.so") >= 0) {
this.target = true;
console.log("[android_dlopen_ext:]", path);
}
}
},
onLeave: function(retval) {
if (this.target) {
var mdString_addr = Module.findExportByName("libeasymd5.so","Java_com_james_easymd5_MainActivity_mdString");
console.log("mdString address is => ",mdString_addr)
Interceptor.attach(mdString_addr, {
onEnter: function (args) {
console.log("arg2 jstring => ", args[2]);//mdString的方法第三个参数是我们要的值
console.log("arg2 jstring => ", Java.vm.tryGetEnv().getStringUtfChars(args[2], null).readCString());
console.log('CCCryptorCreate called from:\n' +
Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join('\n') + '\n');
}, onLeave: function (retval) {
console.log("retval is => ", retval);
console.log("retval is => ", Java.vm.tryGetEnv().getStringUtfChars(retval, null).readCString());
}
})
}
// if (this.can_hook_libart && !is_hook_libart) {
// dump_dex();
// is_hook_libart = true;
// }
}
});
ps: Invoke JNI===>Java.vm.tryGetEnv()
结果:
[Google Pixel XL::com.james.easymd5]-> android_dlopen_ext: /data/app/com.james.easymd5-7ZxsaFkVCnATrcrvoqQcSA==/oat/arm/base.odex
android_dlopen_ext: /data/app/com.james.easymd5-7ZxsaFkVCnATrcrvoqQcSA==/lib/arm/libeasymd5.so
[android_dlopen_ext:] /data/app/com.james.easymd5-7ZxsaFkVCnATrcrvoqQcSA==/lib/arm/libeasymd5.so
mdString address is => 0xd1873a59
arg2 jstring => 0xffc6e2f0
arg2 jstring => 1234567890
CCCryptorCreate called from:
0xd1a6a143 base.odex!oatexec+0x143
retval is => 0x79
retval is => e807f1fcf82d132f9bb018ca6738a19f
android_dlopen_ext: /vendor/lib/hw/gralloc.msm8996.so
dlopen: libadreno_utils.so
dlopen: /vendor/lib/egl/libEGL_adreno.so
android_dlopen_ext: /vendor/lib/hw/android.hardware.graphics.mapper@2.0-impl.so
android_dlopen_ext: /vendor/lib/hw/gralloc.msm8996.so
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
onEnter: function(args) {
var pathptr = args[0];
this.target = false
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
console.log("android_dlopen_ext:", path);
if (path.indexOf("libeasymd5.so") >= 0) {
this.target = true;
console.log("[android_dlopen_ext:]", path);
}
}
},
onLeave: function(retval) {
if (this.target) {
var mdString_addr = Module.findExportByName("libeasymd5.so","Java_com_james_easymd5_MainActivity_mdString");
console.log("mdString address is => ",mdString_addr)
var md5string = new NativeFunction(mdString_addr,"pointer",["pointer","pointer","pointer"]);
Interceptor.replace(mdString_addr,new NativeCallback(function(env, jclass,jstring){
console.log(Java.vm.tryGetEnv().getStringUtfChars(jstring, null).readCString())
var newJSTRING = Java.vm.tryGetEnv().newStringUtf('james123456');
var retval = md5string(env, jclass,newJSTRING);
console.log("retval is => ", Java.vm.tryGetEnv().getStringUtfChars(retval, null).readCString());
return newJSTRING;
},"pointer",["pointer","pointer","pointer"]))
}
// if (this.can_hook_libart && !is_hook_libart) {
// dump_dex();
// is_hook_libart = true;
// }
}
});
结果:
[Google Pixel XL::com.james.easymd5]-> android_dlopen_ext: /data/app/com.james.easymd5-qBJw9ZijDSWX-eOLgtln-A==/oat/arm/base.odex
android_dlopen_ext: /data/app/com.james.easymd5-qBJw9ZijDSWX-eOLgtln-A==/lib/arm/libeasymd5.so
[android_dlopen_ext:] /data/app/com.james.easymd5-qBJw9ZijDSWX-eOLgtln-A==/lib/arm/libeasymd5.so
mdString address is => 0xd17d2a59
1234567890
retval is => cc6e7cb7cb71073647e833e2fb89482b
jni的动态注册(jni_onload)
1、// Dynamic register
#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
jstring zlj666(
JNIEnv *env, jclass obj, jstring str) {
MD5_CTX mdContext;
int m = 0;
char *inString = const_cast<char *>(env->GetStringUTFChars(str, NULL));
unsigned int len = strlen(inString);
MD5Init(&mdContext);
MD5Update(&mdContext, reinterpret_cast<unsigned char *>(inString), len);
MD5Final(&mdContext);
int i;
char dest[32] = { 0 };
for (i = 0; i < 16; i++) {
sprintf(dest + i * 2, "%02x", mdContext.digest[i]);
}
return env->NewStringUTF(dest);
}
// name (java function name) signature【签名】 jadx打开看mdString的smali的后缀
static JNINativeMethod method_table[] = {
{"mdString", "(Ljava/lang/String;)Ljava/lang/String;", (void *) zlj666},
};
static int registerMethods(JNIEnv *env, const char *className,
JNINativeMethod *gMethods, int numMethods) {
jclass clazz = env->FindClass(className);
if (clazz == nullptr) {
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
}
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = nullptr;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}
// 注册native方法
if (!registerMethods(env,"com/james/easymd5/MainActivity" , method_table, NELEM(method_table))) {
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
2、frida hook jni动态注册
2.1java层调用:
setTimeout(() => {
Java.perform(() => {
var result = Java.use("com.james.easymd5.MainActivity").mdString("1234567890");
console.log("result is => ",result)
})
}, 0);
frida -UF -l invoke.js --runtime=V8 【程序要在运行中】
结果:
result is => e807f1fcf82d132f9bb018ca6738a19f
2.2nativ层调用
Java.perform(() => {
var zlj666_address = Module.findExportByName('libeasymd5.so',"_Z6zlj666P7_JNIEnvP7_jclassP8_jstring")
console.log("found address =>", zlj666_address)
var zlj666 = new NativeFunction(zlj666_address, "pointer", ["pointer", "pointer", "pointer"]);
var newJSTRING = Java.vm.tryGetEnv().newStringUtf("12345james")
var result = zlj666(Java.vm.tryGetEnv(), Java.vm.tryGetEnv(), newJSTRING);
console.log("result is => ", Java.vm.tryGetEnv().getStringUtfChars(result, null).readCString());
})
结果:
found address => 0xd6b9cba5
result is => 048943059b19127c86e2069c6e804f3f
[Google Pixel XL::easymd5]->
2.3脱离app环境运行so环境
adb push libeasymd5.so /data/local/tmp
cp -rf libeasymd5.so /data/app
chmod 777 libeasymd5.so
Java.perform(() => {
var module = Module.load("/data/app/libeasymd5.so")
var zlj666_address = module.findExportByName("_Z6zlj666P7_JNIEnvP7_jclassP8_jstring")
console.log("found address =>", zlj666_address)
var zlj666 = new NativeFunction(zlj666_address, "pointer", ["pointer", "pointer", "pointer"]);
var newJSTRING = Java.vm.tryGetEnv().newStringUtf("12345james")
var result = zlj666(Java.vm.tryGetEnv(), Java.vm.tryGetEnv(), newJSTRING);
console.log("result is => ", Java.vm.tryGetEnv().getStringUtfChars(result, null).readCString());
})
结果:
found address => 0xd6b9cba5
result is => 048943059b19127c86e2069c6e804f3f
[Google Pixel XL::easymd5]->
判断32/64位进程:660就是32位
marlin:/data/app # ps -ef | grep -i zyg
root 659 1 1 16:25:38 ? 00:33:28 zygote64
root 660 1 0 16:25:38 ? 00:00:02 zygote
marlin:/data/app # ps -ef | grep -i 660
root 660 1 0 16:25:38 ? 00:00:02 zygote
u0_a134 5071 660 0 15:17:58 ? 00:00:06 com.james.easymd5
2.4 调用非静态函数(java调用对象或者实例一个对象)
Java.scheduleOnMainThread(() =>{
var result = Java.use("com.roysue.easymd5.MainActivity").$new().mdString("12345james");
console.log("result is => ",result)
})
结果:
found address => 0xd6b9cba5
result is => 048943059b19127c86e2069c6e804f3f
[Google Pixel XL::easymd5]->
unidbg调用jni
public class MainActivity {
public static void main(String[] args) {
long start = System.currentTimeMillis();
com.james.easymd5.MainActivity mainActivity = new com.james.easymd5.MainActivity();
System.out.println("load offset=" + (System.currentTimeMillis() - start) + "ms");
mainActivity.crack();
}
private final AndroidEmulator emulator;
private final VM vm;
private final DvmClass dvmClass;
private MainActivity() {
emulator = AndroidEmulatorBuilder
.for32Bit()
.addBackendFactory(new DynarmicFactory(true))
.build();
Memory memory = emulator.getMemory();
LibraryResolver resolver = new AndroidResolver(23);
memory.setLibraryResolver(resolver);
vm = emulator.createDalvikVM();
vm.setVerbose(true); // 日志开关
DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/armeabi-v7a/libeasymd5.so"), false);
dm.callJNI_OnLoad(emulator);
dvmClass = vm.resolveClass("com/james/easymd5/MainActivity");
}
private void crack() {
//静态函数
DvmObject result = dvmClass.callStaticJniMethodObject(emulator,"mdString(Ljava/lang/String;)Ljava/lang/String;","12345james");
System.out.println("result is => " + result.getValue());
//非静态函数
DvmObject<?> obj = ProxyDvmObject.createObject(vm, this);
DvmObject result2 = obj.callJniMethodObject(emulator,"mdString(Ljava/lang/String;)Ljava/lang/String;","12345james");
System.out.println("result2 is => " + result2.getValue());
}
}
结果:
JNIEnv->FindClass(com/james/easymd5/MainActivity) was called from RX@0x40001ed1[libeasymd5.so]0x1ed1
JNIEnv->RegisterNatives(com/james/easymd5/MainActivity, RW@0x40005000[libeasymd5.so]0x5000, 1) was called from RX@0x40001f01[libeasymd5.so]0x1f01
RegisterNative(com/james/easymd5/MainActivity, mdString(Ljava/lang/String;)Ljava/lang/String;, RX@0x40000ba5[libeasymd5.so]0xba5)
load offset=734ms
Find native function Java_com_james_easymd5_MainActivity_mdString => RX@0x40000ba5[libeasymd5.so]0xba5
JNIEnv->GetStringUtfChars("12345james") was called from RX@0x40000cb7[libeasymd5.so]0xcb7
JNIEnv->NewStringUTF("048943059b19127c86e2069c6e804f3f") was called from RX@0x40000f8d[libeasymd5.so]0xf8d
result is => 048943059b19127c86e2069c6e804f3f
Find native function Java_com_james_easymd5_MainActivity_mdString => RX@0x40000ba5[libeasymd5.so]0xba5
JNIEnv->GetStringUtfChars("12345james") was called from RX@0x40000cb7[libeasymd5.so]0xcb7
JNIEnv->NewStringUTF("048943059b19127c86e2069c6e804f3f") was called from RX@0x40000f8d[libeasymd5.so]0xf8d
result2 is => 048943059b19127c86e2069c6e804f3f
本文暂时没有评论,来添加一个吧(●'◡'●)