一、首先把apk拖到jeb看smali/java代码,发现是需要进so调试的
public class MainActivity extends Activity {
public Button btn_submit;
public EditText inputCode;
static {
System.loadLibrary("crackme");
}
@Override // android.app.Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(0x7F030000); // layout:activity_main
this.getWindow().setBackgroundDrawableResource(0x7F020000); // drawable:bg
this.inputCode = (EditText)this.findViewById(0x7F060000); // id:inputcode
this.btn_submit = (Button)this.findViewById(0x7F060001); // id:submit
this.btn_submit.setOnClickListener(new View.OnClickListener() {
@Override // android.view.View$OnClickListener
public void onClick(View v) {
String v1 = MainActivity.this.inputCode.getText().toString();
if(MainActivity.this.securityCheck(v1)) { <------JNI方法
Intent i = new Intent(MainActivity.this, ResultActivity.class);
MainActivity.this.startActivity(i);
return;
}
Toast.makeText(MainActivity.this.getApplicationContext(), "验证码校验失败", 0).show();
}
});
}
public native boolean securityCheck(String arg1) {
}
}
二、静态调试解压apk,把libcrackme.so拖进ida_pro
signed int __fastcall Java_com_yaotong_crackme_MainActivity_securityCheck(int a1, int a2, int a3)
{
int v3; // r5
int v4; // r4
unsigned __int8 *v5; // r0
char *v6; // r2
int v7; // r3
signed int v8; // r1
v3 = a1;
v4 = a3;
if ( !byte_B4CDA359 )
{
sub_B4CD6494(&unk_B4CDA304, 8, &unk_B4CD846B, &unk_B4CD8468, 2, 7);
byte_B4CDA359 = 1;
}
if ( !byte_B4CDA35A )
{
sub_B4CD64F4(&unk_B4CDA36C, 25, &unk_B4CD8530, &unk_B4CD8474, 3, 117);
byte_B4CDA35A = 1;
}
_android_log_print(4, &unk_B4CDA304, &unk_B4CDA36C);
v5 = (unsigned __int8 *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)v3 + 676))(v3, v4, 0);
v6 = off_B4CDA28C; <-------双击这个看看是什么,结果是wojiushidaan,输入到apk里发现不对,看来要动态调试了
while ( 1 )
{
v7 = (unsigned __int8)*v6;
if ( v7 != *v5 )
break;
++v6;
++v5;
v8 = 1;
if ( !v7 )
return v8;
}
return 0;
}
三、id_pro动态调试securityCheck函数
1、android里推入android_server(看你的机型)
2、启动android_server
3、启动apk,ida_pro attach进程后,找到Java_com_yaotong_crackme_MainActivity_securityCheck函数,在静态分析失败的那个v6处打断点
4、执行debug,发现进不来,估计是jni_onload的时候有反调试
四、id_pro动态调试ni_onload函数
1、android里推入android_server(看你的机型)
2、启动android_server
3、adb shell am start -D -n com.yaotong.crackme/.MainActivity
4、启动jdb调试(可以在程序入口处,停住jvm进程)
adb shell
su
ps | grep com.yaotong.crackme
adb forward tcp:8700 jdwp:上一步的进程号
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700 (注意,android-studio不能开,会冲突)
5、ida_pro attach进程,找到Java_com_yaotong_crackme_MainActivity_securityCheck函数,在静态分析失败的那个v6处打断点
在c语言处打断点,发现不了问题
在汇编处打断点
; Attributes: bp-based frame
EXPORT JNI_OnLoad
JNI_OnLoad
var_20= -0x20
STMFD SP!, {R4-R9,R11,LR} <------在这打断点
ADD R11, SP, #0x18
SUB SP, SP, #8
MOV R4, R0
LDR R0, =(_GLOBAL_OFFSET_TABLE_ - 0xB4CD5BC0)
LDR R9, =(unk_B4CDA290 - 0xB4CD9FBC)
MOV R8, #0
....
BLX R7 <---在这一步退出了。
再次进入调试,看见运行到BLX跳转指令时
在general registers窗口中看到R7 寄存器中是pthread_create函数,是Linux中新建一个线程的方法
所以在静态分析中注释他37 FF 2F E1 改为 00 00 00 00,保存so包
五、反编译,回编译,签名
1、apktool d AliCrackme.apk 生成AliCrackme文件夹
2、替换AliCrackme文件夹中的libcrackme.so
3、apktool b AliCrackme 后取出dist文件夹中AliCrackme.apk
4、签名
java -jar signapk.jar platform.x509.pem platform.pk8 AliCrackme.apk AliCrackme_sign.apk
5、安装AliCrackme_sign.apk包
六、再次id_pro动态调试securityCheck函数
找到Java_com_yaotong_crackme_MainActivity_securityCheck函数,在静态分析失败的那个v6处打断点
发现v6寄存器里是aiyou,bucuoo,密码就是这个。破解结束
参考:
分析一个安卓简单CrackMe
实战分析一个Crackme的过程
IDA动态调试破解AliCrackme与反调试对抗
第一篇文章里没有反反调试
第二篇文章里,地址算法有点问题
第三篇文章比较好,然后第三篇里又推荐了Android逆向之旅—动态方式破解apk进阶篇(IDA调试so源码)也很不错