ida中 识别md5 ,先右键转为hex 或者按h
_DWORD *__fastcall MD5Init(_DWORD *result)
{
*result = 0;
result[1] = 0;
result[2] = 1732584193;
result[3] = -271733879;
result[4] = -1732584194;
result[5] = 271733878;
return result;
}
在ida中当然也可以使用搜索
search imdate-value 搜索立即数 0x67452301; 这是上面的init中的state一个数···
v2 = __ROR4__((v66 & ~v99 | v83 & v99) + v133 + v116 - 0x28955B88, 25);
__ROR4__ 是循环右移
鼠标右键 invert sign可以改正一些纠正一下负号 3 + 0x242070DB
数值类型转换
int __fastcall MD5Final(unsigned int *a1, unsigned __int8 *a2)
{
unsigned int v3; // [sp+8h] [bp-28h]
unsigned int v4; // [sp+10h] [bp-20h]
unsigned __int8 v7[8]; // [sp+1Ch] [bp-14h] BYREF
v4 = (*a1 >> 3) & 0x3F;
if ( v4 > 0x37 )
v3 = 120 - v4;
else
v3 = 56 - v4;
MD5Encode(v7, a1, 8u);
MD5Update(a1, PADDING, v3);
MD5Update(a1, v7, 8);
MD5Encode(a2, a1 + 2, 0x10u);
return _stack_chk_guard;
//这是识别的final ,计算长度,压入padding放入长度 拼接
====》padding
.data:00006000 AREA .data, DATA
.data:00006000 ; ORG 0x6000
.data:00006000 EXPORT PADDING
.data:00006000 PADDING DCD dword_80 ; DATA XREF: LOAD:00000520↑o
.data:00006000 ; MD5Final(MD5_CTX *,uchar *)+5A↑o ...
.data:00006004 ALIGN 0x40
.data:00006040 DCD unk_6044
dcd 指定是低位的
按D 会转 dcb ====>
6000 EXPORT PADDING
.data:00006000 PADDING DCB 0x80 ; DATA XREF: LOAD:00000520↑o
.data:00006000 ; MD5Final(MD5_CTX *,uchar *)+5A↑o ...
.data:00006001 DCB 0
.data:00006002 DCB 0
.data:00006003 DCB 0
.data:00006004 ALIGN 0x40
.data:00006040 DCD unk_6044
dcq代表八个字节
ida的算法识别 md5
某个libwtf.so的算法
这个final 中的update 中的update padding
thumb 有两个字节 有四个字节 ,arm 是四个字节
find hash 的使用
把 findhash.xmlfindhash.py 放到ida plugins 文件夹下
用之前写的revdemo来试一下
点击 plugins/findhash
Python 3.11.6 (tags/v3.11.6:8b6ee5b, Oct 2 2023, 14:57:12) [MSC v.1935 64 bit (AMD64)]
IDAPython 64-bit v7.4.0 final (serial 0) (c) The IDAPython Team <idapython@googlegroups.com>
---------------------------------------------------------------------------------------------
Propagating type information...
Function argument information has been propagated
lumina: Invalid remote certificate
The initial autoanalysis has been finished.
findHash (v0.1) plugin has been loaded.
这个脚本只考虑了32位SO的反编译代码,64位未适配。
***************************在二进制文件中检索hash算法常量************************************
0x4b100:padding used in hashing algorithms (0x80 0 ... 0)
0x1e978:函数MD5Init(MD5_CTX *)疑似哈希函数,包含初始化魔数的代码。
0x1eb98:函数MD5Transform(uint *,uchar *)疑似哈希函数运算部分。
0x20634:函数MD5InitMagic(MD5_CTX *)疑似哈希函数,包含初始化魔数的代码。
0x2c114:函数sub_2C114疑似哈希函数,包含初始化魔数的代码。
0x317dc:函数sub_317DC疑似哈希函数,包含初始化魔数的代码。
0x31f18:函数sub_31F18疑似哈希函数,包含初始化魔数的代码。
0x330dc:函数sub_330DC疑似哈希函数,包含初始化魔数的代码。
0x33dcc:函数sub_33DCC疑似哈希函数,包含初始化魔数的代码。
0x33fdc:函数sub_33FDC疑似哈希函数,包含初始化魔数的代码。
0x3436c:函数sub_3436C疑似哈希函数,包含初始化魔数的代码。
0x3b248:函数sub_3B248疑似哈希函数,包含初始化魔数的代码。
0x3bb84:函数sub_3BB84疑似哈希函数,包含初始化魔数的代码。
***************************存在以下可疑的字符串************************************
0x4f3b:Java_com_koohai_revdemo_utils_EncryptCUtils_md5
0x4fe4:md5(std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>> const&)
0x5189:Java_com_koohai_revdemo_utils_EncryptCUtils_md5_1magic
0x51c0:md5magic(std::__ndk1::basic_string<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>> const&)
生成对应的hook脚本如下:
frida -UF -l E:\Coding\XposedDemo\app-debug\lib\arm64-v8a\librevdemo_findhash_1719082084.js
***********************************************************************************
花费 40.45436191558838 秒,因为会对全部函数反编译,所以比较耗时间哈
只能说插件强大,把之前的md5 和md5_magic都识别了
插件自动生成的hook代码如下:
function hook_suspected_function(targetSo) {
const funcs = [['MD5Init(MD5_CTX *)', '函数MD5Init(MD5_CTX *)疑似哈希函数,包含初始化魔数的代码。', '0x1e978'], ['MD5Transform(uint *,uchar *)', '函数MD5Transform(uint *,uchar *)疑似哈希函数运算部分。', '0x1eb98'], ['MD5InitMagic(MD5_CTX *)', '函数MD5InitMagic(MD5_CTX *)疑似哈希函数,包含初始化魔数的代码。', '0x20634'], ['sub_2C114', '函数sub_2C114疑似哈希函数,包含初始化魔数的代码。', '0x2c114'], ['sub_317DC', '函数sub_317DC疑似哈希函数,包含初始化魔数的代码。', '0x317dc'], ['sub_31F18', '函数sub_31F18疑似哈希函数,包含初始化魔数的代码。', '0x31f18'], ['sub_330DC', '函数sub_330DC疑似哈希函数,包含初始化魔数的代码。', '0x330dc'], ['sub_33DCC', '函数sub_33DCC疑似哈希函数,包含初始化魔数的代码。', '0x33dcc'], ['sub_33FDC', '函数sub_33FDC疑似哈希函数,包含初始化魔数的代码。', '0x33fdc'], ['sub_3436C', '函数sub_3436C疑似哈希函数,包含初始化魔数的代码。', '0x3436c'], ['sub_3B248', '函数sub_3B248疑似哈希函数,包含初始化魔数的代码。', '0x3b248'], ['sub_3BB84', '函数sub_3BB84疑似哈希函数,包含初始化魔数的代码。', '0x3bb84']];
for (var i in funcs) {
let relativePtr = funcs[i][2];
let funcPtr = targetSo.add(relativePtr);
let describe = funcs[i][1];
let handler = (function() {
return function(args) {
console.log("\n");
console.log(describe);
console.log(Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n"));
};
})();
//Interceptor.attach(funcPtr, {onEnter: handler});
hook_native_addr(funcPtr)
//替换为下面的函数 ,可以打印参数。
}
}
//他会自己给出疑似的地址,就直接在so进行hook MD5InitMagic 这个自己魔改了初始址 也被发现了
对于这个算法,可以稍微改进一下,让他生成的js 加上打印参数 ,MD5的话 transfrom 第二个参数 的64个字节 就是明文,拼起来就是完整的铭文。
//ptr(addr)主要用于呈现地址本身的易读形式,
//而hexdump(addr)则用于展示该地址指向的内存区域的详细十六进制内容
function print_arg(addr){
var module = Process.findRangeByAddress(addr);
if(module != null){
return hexdump(addr) + "\n";
}else{
return ptr(addr) + "\n";
}
}
function hook_native_addr(funcPtr){
var module = Process.findModuleByAddress(funcPtr);
Interceptor.attach(funcPtr, {
onEnter: function(args){
console.log(Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n"));
this.args0 = args[0];
this.args1 = args[1];
this.args2 = args[2];
this.args3 = args[3];
this.logs = [];
this.logs.push("call " + module.name + "!" + ptr(funcPtr).sub(module.base) + "\n");
this.logs.push("this.args0 onEnter: " + print_arg(this.args0));
this.logs.push("this.args1 onEnter: " + print_arg(this.args1));
this.logs.push("this.args2 onEnter: " + print_arg(this.args2));
this.logs.push("this.args3 onEnter: " + print_arg(this.args3));
}, onLeave: function(retval){
this.logs.push("this.args0 onLeave: " + print_arg(this.args0));
this.logs.push("this.args1 onLeave: " + print_arg(this.args1));
this.logs.push("this.args2 onLeave: " + print_arg(this.args2));
this.logs.push("this.args3 onLeave: " + print_arg(this.args3));
this.logs.push("retval onLeave: " + retval + "\n");
console.log(this.logs);
}
});
}
//这里可以打印参数。 在离开的时候一起打印
// 参数可能是地址 或者数值 明文指针/长度 需要判断。 地址的话就打印整个内容 。数值就打印数值。
//ptr(addr)主要用于呈现地址本身的易读形式,
//而hexdump(addr)则用于展示该地址指向的内存区域的详细十六进制内容
===》
frida-trace 能获取到所有地址
把地址放到上面的so hook中,就可以hook所有函数 加参数
//更多代码,更多内容请移步公众号一起
学习,同篇笔记会有更新喔