一、目标
我们的目标是:没有蛀牙。哦不,是 还原算法。还原算法最佳的伙伴当然是IDA的F5了,不过这个哥们偶尔会闹点小脾气
手撕汇编是不可能,这辈子都不想手撕汇编。男人嘛一个怎么够呢。
二、介绍
RetDec是基于LLVM的开源机器代码反编译器。可以反汇编不限于任何特定的目标体系结构,操作系统或可执行文件格式。这是机翻的,说人话就是支持多种平台的反汇编,重要的还是开源的,有理想的小伙伴可以研究研究他的代码。
源码 https://github.com/avast/retdec
奋飞目前还没有那么远大的理想,就不下载代码编译了,目前Release出来的是V4.0版本,奋飞的开发平台是Mac 10.14.6。所以下载他的 retdec-v4.0-macos-64b.tar.xz
解压完把我惊到了, 5个多G。果然是大块头有大智慧。就拿之前的 libnative-lib.so 来练练手。
python3 retdec-decompiler.py libnative-lib.so
一共生成了4个文件
我们最关心的就是 libnative-lib.so.c 文件了,打开对比下:
// 源代码
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
clazz = env->FindClass(className);
if (clazz == NULL) {
return JNI_FALSE;
}
if ( env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
}
// retdec 反编译出来的
// From module: /Users/fenfei/Desktop/myndk/app/src/main/cpp/native-lib.cpp
// Address range: 0x8f48 - 0x8f94
// Line range: 32 - 45
// Demangled: registerNativeMethods(_JNIEnv*, char const*, JNINativeMethod*, int)
int32_t _ZL21registerNativeMethodsP7_JNIEnvPKcP15JNINativeMethodi(int32_t * a1, char * a2, int32_t * a3, int32_t a4) {
int32_t v1 = (int32_t)a1;
int32_t v2 = function_889c(v1, (int32_t)a2); // 0x8f5a
int32_t result = 0; // 0x8f64
if (v2 != 0) {
// 0x8f6e
result = function_88a8(v1, v2, (int32_t)a3, a4) > -1;
}
// 0x8f8e
return result;
}
// 源代码
extern "C" JNIEXPORT jstring JNICALL
Java_com_fenfei_myndk_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
// retdec 反编译出来的
// From module: /Users/fenfei/Desktop/myndk/app/src/main/cpp/native-lib.cpp
// Address range: 0x8de4 - 0x8e54
// Line range: 5 - 0
int32_t Java_com_fenfei_myndk_MainActivity_stringFromJNI(int32_t env, int32_t a1) {
// 0x8de4
int32_t hello; // bp-24, 0x8de4
function_883c(&hello, 0x15e06);
int32_t v1 = _ZNKSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5c_strEv(&hello); // 0x8e0c
int32_t result = function_8848(env, v1); // 0x8e18
function_8854(&hello);
if (*(int32_t *)g261 == *(int32_t *)g261) {
// 0x8e36
return result;
}
// 0x8e4e
__stack_chk_fail();
return &g335;
}
怎么说呢,可读性也就那么回事吧,还是IDA的F5真香。不过在IDA闹脾气的时候,retdec 也是可以顶一顶的,奋飞感觉用retdec指定反编译某个函数还是有实用价值的,不过目前还没有研究出来用哪个参数,等搞明白了再来更新吧。
retdec也有ida的插件,可以直接支持函数级反汇编,不过目前只支持 IDA 7.5,土豪专用。
三、总结
教员说过,朋友要搞到多多的。东边不亮西边亮。做逆向不要死磕,毕竟我们的目的仅仅是学习下关键算法,而不是把整个工程还原出来。所以多几款工具交叉对比还是有必要的。
关注微信公众号,最新技术干货实时推送