题目来源于海淀区网络与信息安全管理员大赛,题目中将加密验证算法打包进.so,在程序中动态调用check。
本题目通过System.loadLibrary("native-lib")加载了libnative-lib.so文件,该文件通过jeb可以实现提取

图1 题目关键代码
调试环境选择与配置mumu模拟器 x64位版本,测试后发现sprintf会导致程序崩溃
夜神模拟器x64,x32的版本经过测试后,sprintf均导致程序崩溃
雷电5模拟器测试后,sprintf导致程序崩溃,动态调试libnative-lib.so时,且无法下载libart.so
最终选用 mumu x32位版本可以进行调试
动态调试选用IDA+MUMU x86模拟器对动态库libnative-lib.so调试
调试环境adb的基础配置adb connect 127.0.0.1:7555

图2 adb 服务端连接
adb install test.apk

图3 adb shell连接
应用程序的配置./adb shell am start -D -n com.example.dynamic/.MainActivity

图4 adb 启动程序分析

图5 adb 动态调试程序
IDA 的配置./adb push android_x86_server /data/local/tmp

图6 查看tmp文件夹权限
chmod +x android_x86_server
./adb.exe forward tcp:23946 tcp:23946

图7 启动IDA 调试server端

图8 配置IDA动态调试

图9 IDA远程attach
‘图10 附加到指定进程

图11 dynamic程序界面
./adb forward tcp:8700 jdwp:1535
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700

图12 IDA提示检测到本地.so

图13 附加到调试进程后,dynamic界面

图14 IDA中显示断点
.so的调试反调试绕过
图15 IDA调试选项配置

图16 查看IDA中的代码段

图17 adb shell中查看内存中的数据地址分布

图18 重置eax的值
可以直接右键或者在eax寄存器上使用快捷键0重置

图19 重置eax的值
注册native的方法static JNINativeMethod jniMethods[] = {
{"check", "(Ljava/lang/String;)Z", (void *)hello},
};
boolean xxxx( char* s) {
// do something
return JNI_TRUE;
}
#在JNI_OnLoad中调用RegisterNatives方法注册Natives方法到JVM,建立映射关系。
int JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv *env;
if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK) {
return JNI_ERR;
}
​
jclass cls = (*env)->FindClass(env, "LHelloJNI");
if (cls == NULL)
return JNI_ERR;
​
int len = sizeof(jniMethods) / sizeof(jnimethods[0]);
(*env)->RegisterNatives(env, cls, jniMethods, len);
​
return JNI_VERSION_1_4;
}
check 函数的定位
图20 查找check函数
const char \*name: Java中声明的native方法。
const char \*signature:方法的签名。
void \*fnPtr: 函数指针

图21 定位check函数
MD5的简单调试*(_OWORD *)v63 = xmmword_B2E6FA40;
.rodata:B2E6FA40 xmmword_B2E6FA40 xmmword 1032547698BADCFEEFCDAB8967452301h
.text:B2E51040 8D 84 24 B4 00 00 00 lea eax, [esp+0B4h]
.text:B2E51047 89 44 24 04 mov [esp+4], eax
.text:B2E5104B 8D 44 24 58 lea eax, [esp+58h]
.text:B2E5104F 89 04 24 mov [esp], eax
.text:B2E51052 E8 A9 E7 FF FF call __Z4ffffP7MD5_CTXPh ; ffff(MD5_CTX *,uchar *)
Python>esp=get_reg_value('esp')
Python>data=get_bytes(esp+0xb4,16)
Python>data.hex()
'a82e0cb168bfe134f22dbde167cf046c'
>>> import hashlib
>>> result=hashlib.md5("wojiushidaan0!!!".encode())
>>> result
<md5 _hashlib.HASH object @ 0x00000167FF8BDEF0>
>>> result.hexdigest()
'a82e0cb168bfe134f22dbde167cf046c'
.text:B2F11398 89 54 24 08 mov [esp+8], edx
.text:B2F1139C 8B 44 24 14 mov eax, [esp+14h]
.text:B2F113A0 89 44 24 04 mov [esp+4], eax ; s2
.text:B2F113A4 89 0C 24 mov [esp], ecx ; s1
.text:B2F113A7 E8 84 E4 FF FF call _memcmp
b'c640fc761edbd22f431efb861bc0e28a'
b'12345678123456781234567812345678'

图22 调试flag结果
flag{c640fc761edbd22f431efb861bc0e28a}

图23 验证flag结果
def get_new_color(current_color):
colors = [0xffe699, 0xffcc33, 0xe6ac00, 0xb38600]
if current_color == 0xFFFFFF:
return colors[0]
if current_color in colors:
pos = colors.index(current_color)
if pos == len(colors)-1:
return colors[pos]
else:
return colors[pos+1]
return 0xFFFFFF
​
addr = ida_dbg.get_ip_val()
while addr < 0xB2ED241F:
event = wait_for_next_event(WFNE_ANY, -1)
t = step_over()
addr = ida_dbg.get_ip_val()
current_color = get_color(addr, CIC_ITEM)
new_color = get_new_color(current_color)
set_color(addr, CIC_ITEM, new_color)
#https://www.cnblogs.com/blacksunny/p/7300271.html参考trace 修改的step over
有待改进的地方本文涉及的命令adb connect 127.0.0.1:7555
adb install test.apk
./adb shell am start -D -n com.example.dynamic/.MainActivity
./adb push android_x86_server /data/local/tmp
./adb.exe forward tcp:23946 tcp:23946
./adb forward tcp:8700 jdwp:1535
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700来自freebuff.com