在安卓逆向过程,常常遇见一些加密字段没有写在java层,写在native层通过加密算法动态生成,但是只要是一个正常算法的生成,就一定会调用系统的库函数,故写了一段hook系统库函数的代码用于分析加密字符串的生成😀
var target = "com";function hook_memcpy() {var libc = Module.findBaseAddress('libc.so');var memcpAddress = Module.findExportByName('libc.so', 'memcpy');if (!memcpAddress) {console.log('memcpy not found');return;}Interceptor.attach(memcpAddress, {onEnter: function(args) {// 需要确保 args[1] 是有效的指针if (args[1] && args[1].isNull() === false) {var srcCString = args[1].readCString();if (srcCString && srcCString.includes(target)) {console.log('memcpy called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')); // 打印调用栈console.log('src: ' + srcCString); // 源地址console.log('dest: ' + args[0]); // 目标地址console.log('size: ' + args[2].toInt32() + '\n'); // 拷贝大小}}},onLeave: function(retval) {// console.log('memcpy returned: ' + retval);}});}function hook_strcmp() {var libc = Module.findBaseAddress('libc.so');var memcmpAddress = Module.findExportByName('libc.so', 'memcmp');if (!memcmpAddress) {console.log('memcmp not found');return;}Interceptor.attach(memcmpAddress, {onEnter: function(args) {// args[0] 和 args[1] 是待比较的内存块,args[2] 是要比较的字节数var ptr1 = args[0]; // 第一个内存块的指针var ptr2 = args[1]; // 第二个内存块的指针var numBytes = args[2].toInt32(); // 比较的字节数// 确保指针有效if (ptr1 && !ptr1.isNull() && ptr2 && !ptr2.isNull()) {var str1 =Memory.readCString(ptr1)var str2 =Memory.readCString(ptr2)// 输出比较的内容//console.log('Memory 1: ' + hexdump(ptr1, { length: numBytes, ansi: true }));//console.log('Memory 2: ' + hexdump(ptr2, { length: numBytes, ansi: true }));//console.log('Number of bytes: ' + numBytes + '\n'); // 比较的字节数if (str1 && str1.includes(target)) {console.log('memcmp called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')); // 打印调用栈console.log('Memory 1: ' + str1); // 第一个内存块的内容}if (str2 && str2.includes(target)) {console.log('memcmp called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')); // 打印调用栈console.log('Memory 2: ' + str2); // 第二个内存块的内容}}},onLeave: function(retval) {//console.log('memcmp returned: ' + retval);}});}function hook_strlen(){var libc = Module.findBaseAddress('libc.so');var strlenAddress = Module.findExportByName('libc.so', 'strlen');if (!strlenAddress) {console.log('strlen not found');return;}Interceptor.attach(strlenAddress, {onEnter: function(args) {var strPtr = args[0]; // 获取指向字符串的指针// 确保指针有效if (strPtr && !strPtr.isNull()) {var str = Memory.readCString(strPtr); // 读取 C 字符串// 检查是否包含目标字符串if (str.includes(target)) {console.log('memcpy called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')); // 打印调用栈console.log('Target string found in input========>>>>' + str);}}},onLeave: function(retval) {//console.log('strlen returned: ' + retval.toInt32()); // 打印返回的字符串长度}});
}function hook_memmove(){var libc = Module.findBaseAddress('libc.so');var memmoveAddress = Module.findExportByName('libc.so', 'memmove');if (!memmoveAddress) {console.log('memmove not found');return;}Interceptor.attach(memmoveAddress, {onEnter: function(args) {var destPtr = args[0]; // 目标地址var srcPtr = args[1]; // 源地址var numBytes = args[2].toInt32(); // 拷贝的字节数// 确保指针有效if (srcPtr && !srcPtr.isNull() && destPtr && !destPtr.isNull()) {var srcString = Memory.readCString(srcPtr);// 检查是否包含目标字符串if (srcString.includes(target)) {console.log('memmove called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')); // 打印调用栈console.log('Target string found in src======>>>>>' + srcString);}}},onLeave: function(retval) {//console.log('memmove returned: ' + retval); // 打印返回值}});}function hook_strstr() {var libc = Module.findBaseAddress('libc.so');var strstrAddress = Module.findExportByName('libc.so', 'strstr');if (!strstrAddress) {console.log('strstr not found');return;}Interceptor.attach(strstrAddress, {onEnter: function(args) {var haystackPtr = args[0]; // 搜索的目标字符串var needlePtr = args[1]; // 要查找的子字符串// 确保指针有效if (haystackPtr && !haystackPtr.isNull() && needlePtr && !needlePtr.isNull()) {var haystackString = Memory.readCString(haystackPtr); // 读取目标字符串var needleString = Memory.readCString(needlePtr); // 读取要查找的子字符串// 检查是否包含目标字符串if (haystackString.includes(target) || needleString.includes(target)) {console.log('strstr called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')); // 打印调用栈console.log('Target string found in haystack=======>>>>>' + haystackString);console.log('Target string found in needle======>>>>>' + needleString);}}},onLeave: function(retval) {}});
}function hook_strncpy() {var libc = Module.findBaseAddress('libc.so'); // 获取 libc.so 的基本地址var strncpyAddress = Module.findExportByName('libc.so', 'strncpy'); // 找到 strncpy 函数的地址if (!strncpyAddress) {console.log('strncpy not found');return;}Interceptor.attach(strncpyAddress, {onEnter: function(args) {var destPtr = args[0]; // 目标地址var srcPtr = args[1]; // 源地址var numBytes = args[2].toInt32(); // 要拷贝的字节数// 确保指针有效if (srcPtr && !srcPtr.isNull() && destPtr && !destPtr.isNull()) {var srcString = Memory.readCString(srcPtr); // 读取源字符串// 检查是否包含目标字符串if (srcString.includes(target)) {// 输出调用信息console.log('strncpy called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')); // 打印调用栈console.log('Target string found in src======>>>>' + srcString);}}},onLeave: function(retval) {//console.log('strncpy returned: ' + retval); // 打印返回值}});
}function hook_strncmp() {var libc = Module.findBaseAddress('libc.so'); // 获取 libc.so 的基本地址var strncmpAddress = Module.findExportByName('libc.so', 'strncmp'); // 找到 strncmp 函数的地址if (!strncmpAddress) {console.log('strncmp not found');return;}Interceptor.attach(strncmpAddress, {onEnter: function(args) {var str1Ptr = args[0]; // 第一个字符串的指针var str2Ptr = args[1]; // 第二个字符串的指针var numChars = args[2].toInt32(); // 要比较的字符数// 确保指针有效if (str1Ptr && !str1Ptr.isNull() && str2Ptr && !str2Ptr.isNull()) {var str1 = Memory.readCString(str1Ptr); // 读取第一个字符串var str2 = Memory.readCString(str2Ptr); // 读取第二个字符串// 检查是否包含目标字符串if (str1.includes(target)|| str2.includes(target)) {console.log('strncmp called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')); // 打印调用栈console.log('Target string found in str1======>>>>' + str1);console.log('Target string found in str2======>>>>' + str2);}}},onLeave: function(retval) {//console.log('strncmp returned: ' + retval.toInt32()); // 打印返回值}});
}function hook_strncat() {var libc = Module.findBaseAddress('libc.so'); // 获取 libc.so 的基本地址var strncatAddress = Module.findExportByName('libc.so', 'strncat'); // 找到 strncat 函数的地址if (!strncatAddress) {console.log('strncat not found');return;}Interceptor.attach(strncatAddress, {onEnter: function(args) {var destPtr = args[0]; // 目标字符串的指针var srcPtr = args[1]; // 源字符串的指针var numBytes = args[2].toInt32(); // 要追加的字节数// 确保指针有效if (destPtr && !destPtr.isNull() && srcPtr && !srcPtr.isNull()) {var destString = Memory.readCString(destPtr); // 读取目标字符串var srcString = Memory.readCString(srcPtr); // 读取源字符串// 检查源字符串中是否包含目标字符串if (srcString.includes(target) || destString.includes(target)) {console.log('strncat called from:\n' +Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')); // 打印调用栈console.log('Target string found in src======>>>>' + srcString);console.log('Target string found in dest======>>>>>' + destString);}}},onLeave: function(retval) {//console.log('strncat returned: ' + retval); // 打印返回值}});
}hook_strncat()