App信息
包名:com.yaotong.crackme

Java层分析
MainActivity

很容易就能看出来是在securityCheck函数里进行安全校验。securityCheck是一个native函数,到so中进行分析。
SO层分析
定位函数位置
在导出函数里搜索

securityCheck
数据类型修复和重命名后的securityCheck
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| int __fastcall Java_com_yaotong_crackme_MainActivity_securityCheck(JNIEnv *a1, jobject a2, char *str) { const char *inputStr; char *wojiushidaan; int tempResult; int v8; if ( !byte_6359 ) { sub_2494(byte_6304, 8, &unk_446B, &unk_4468, 2, 7); byte_6359 = 1; } if ( !byte_635A ) { sub_24F4(byte_636C, 25, &unk_4530, &unk_4474, 3, 117); byte_635A = 1; } _android_log_print(4, byte_6304, byte_636C); inputStr = (*a1)->GetStringUTFChars(a1, str, 0); wojiushidaan = off_628C; while ( 1 ) { tempResult = *wojiushidaan; if ( tempResult != *inputStr ) break; ++wojiushidaan; ++inputStr; v8 = 1; if ( !tempResult ) return v8; } return 0; }
|
off_628C
进入off_628C偏移查看,它的内容是”wojiushidaan”

数据查看

结合securityCheck函数分析,我觉得这就是正确答案了。
可是输入之后,还是校验失败。

无奈只能动态调试
动态调试
IDA动态调试环境配置这里不再介绍。
附加进程
重新启动程序
在IDA里选择附加到进程

附加进程之后,我们运行一下,会发现,程序崩了,IDA也崩了,说明这个so是有反调试的。
反调试绕过
猜测反调试是通过线程进行循环检测的。
打开线程窗口

发现一个线程yaotong.crackme
,有点可疑,右键这个线程,将状态改为suspend,暂停这个线程。

然后运行,程序没有挂掉,可以进行调试。
断点调试
打开Modules窗口,找到libcrackme.so,双击进去,找到securityCheck函数,双击该函数跳转到函数的位置。

在这个函数起始的位置下一个断点,将光标移动到断点位置,按下快捷键F,然后在输入框输入任意数据,点击输入密码,程序就会运行到断点位置。
F5查看反汇编,找到原来的变量偏移地址处,发现数据变了,变成了aiyou,bucuoo


验证
将aiyou,bucuoo
放进输入框,点击输入密码,跳转到成功界面。

使用frida hook内存
找到存储答案的变量的内存地址

在程序启动之后,使用frida直接对内存进行hook
1 2 3 4 5
| function hook_yaotong(){ var soAddr = Module.findBaseAddress("libcrackme.so"); var hookAddr = soAddr.add(0x4450) console.log(hookAddr.readCString()) }
|

使用unidbg模拟执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package com.yaotong.crackme;
import com.github.unidbg.AndroidEmulator; import com.github.unidbg.Module; import com.github.unidbg.arm.backend.DynarmicFactory; import com.github.unidbg.linux.android.AndroidEmulatorBuilder; import com.github.unidbg.linux.android.AndroidResolver; import com.github.unidbg.linux.android.dvm.*; import com.github.unidbg.memory.Memory; import java.io.File;
public class MainActivity extends AbstractJni { private final AndroidEmulator emulator; private final Memory memory; private final VM vm; private final DalvikModule dalvikModule; private final Module module;
MainActivity() { emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.yaotong.crackme").addBackendFactory(new DynarmicFactory(true)).build(); memory = emulator.getMemory(); memory.setLibraryResolver(new AndroidResolver(23)); vm = emulator.createDalvikVM(new File("unidbg-android/src/test/java/com/yaotong/crackme/alijuanquan.apk")); vm.setJni(this); vm.setVerbose(true); dalvikModule = vm.loadLibrary("crackme",true); module = dalvikModule.getModule(); vm.callJNI_OnLoad(emulator,module); } public static void main(String[] args) { MainActivity test = new MainActivity(); System.out.println(test.Check()); } public Boolean Check() { DvmClass dvmClass = vm.resolveClass("com.yaotong.crackme.MainActivity"); DvmObject dvmObject = dvmClass.newObject(null); String input = "aiyou,bucuoo"; boolean result = dvmObject.callJniMethodBoolean(emulator,"securityCheck(Ljava.lang.sring;)Z",input); System.out.println("result=" + result); return result; } }
|

待完善…
参考文章:https://mp.weixin.qq.com/s/r-XXZQImgRc-Lce5B7x60w