-
-
[原创]第二题 变形金刚
-
2019-3-25 15:02 4194
-
这道题目是一个安卓的题,主要是一个登陆界面,拖入jeb首先看前端。找到MainActivity如下:
public class MainActivity extends AppCompiatActivity { class MyHandler extends Handler { WeakReference mWeakReference; public MyHandler(MainActivity arg2) { super(); this.mWeakReference = new WeakReference(arg2); }
这有一个fake,MainActivity继承的是自定义的AppCompiatActivity,并不是AppCompatActivity,打开该类看一看。
public class AppCompiatActivity extends AppCompatActivity { public static final int MSG_LOGIN; private Handler handler; private Button login; private String mName; private String mPassword; private EditText name; private EditText password; static { System.loadLibrary("oo000oo"); }
可以发现这其实是真实的破解代码索要研究的内容。继续观察如下代码:
protected native boolean eq(String arg1) { } protected void onStart() { super.onStart(); this.login = this.findViewById(2131165260); this.login.setOnClickListener(new View$OnClickListener() { public void onClick(View arg5) { AppCompiatActivity.this.mName = AppCompiatActivity.this.name.getText().toString(); AppCompiatActivity.this.mPassword = AppCompiatActivity.this.password.getText().toString(); if(!TextUtils.isEmpty(AppCompiatActivity.this.mName)) { if(TextUtils.isEmpty(AppCompiatActivity.this.mPassword)) { } else { int v1 = 0; AppCompiatActivity.this.login.setEnabled(false); if(AppCompiatActivity.this.eq(AppCompiatActivity.this.mPassword)) { byte[] v5 = AppCompiatActivity.this.mPassword.getBytes(); int v3 = 24; if(v5.length != v3) { byte[] v2 = new byte[v3]; while(v1 < v2.length) { byte v3_1 = v1 < v5.length ? v5[v1] : ((byte)v1); v2[v1] = v3_1; ++v1; } v5 = v2; }
发现登陆时候使用了eq这个函数进行判断,eq改函数是前面的System.loadLibrary("oo000oo")中的,所以打开ida,对该so文件进行分析。
发现so文件中并没有eq该函数,所以判断在JNI_LOAD或者在init_array里面做了手脚。
JNI_LOAD函数如下:
signed int __fastcall JNI_OnLoad(JNIEnv *a1) { int v1; // r8 signed int result; // r0 JNIEnv *v3; // r5 int v4; // r6 JNIEnv *v5; // [sp+0h] [bp-18h] int v6; // [sp+4h] [bp-14h] int v7; // [sp+8h] [bp-10h] v7 = v1; v5 = 0; if ( !((int (*)(void))(*a1)->FindClass)() ) goto LABEL_4; LABEL_2: result = -1; while ( _stack_chk_guard != v6 ) { LABEL_4: v3 = v5; v4 = ((int (__fastcall *)(JNIEnv *, void *))(*v5)->FindClass)(v5, off_CADFB010); dword_CADFB110 = ((int (__fastcall *)(JNIEnv *, int))(*v3)->NewGlobalRef)(v3, v4); if ( !v4 || ((int (__fastcall *)(JNIEnv *, int, char **, signed int))(*v3)->RegisterNatives)(v3, v4, off_CADFB014, 1) <= -1 ) { goto LABEL_2; } result = 0x10006; } return result; }
init_array函数执行了datadiv_decode5009363700628197108字符串解密函数,两个函数以整合,可以知道eq函数就是sub_784函数。
该函数是一个判断函数,主要判断逻辑为:
do { v28 = (v28 + 1) % 256; v35 = (unsigned __int8)v46[v28]; v30 = (v30 + v35) % 256; v46[v28] = v46[v30]; v46[v30] = v35; v17 = (char *)(unsigned __int8)v46[v28]; middle_value = v46[(unsigned __int8)(v35 + (_BYTE)v17)] ^ password[v29]; if ( v29 && (v27 = 0xAAAAAAAB * (unsigned __int64)v29 >> 32, v37 = 3 * (v29 / 3), v37 != v29) ) { v31 = v29 == 1; if ( v29 != 1 ) v31 = v37 + 1 == v29; if ( v31 ) { v32 = array; v26[v44 + v29] = array[(unsigned __int8)v26[v44 + v29] | ((unsigned int)middle_value >> 4)]; v17 = &v26[v44 + v29]; v27 = 4 * middle_value & 0x3C; v17[1] = v27; if ( v29 + 1 >= v24 ) goto LABEL_53; } else { v33 = v29 == 2; if ( v29 != 2 ) v33 = v37 + 2 == v29; if ( v33 ) { v17 = (char *)(middle_value & 0xC0); v34 = v44++ + v29; v26[v34] = array[(unsigned __int8)v26[v34] | ((unsigned int)v17 >> 6)] ^ 0xF; v27 = (int)&v26[v34]; *(_BYTE *)(v27 + 1) = array[middle_value & 0x3F]; } } } else { v26[v44 + v29] = array[(unsigned int)middle_value >> 2] ^ 7; v17 = &v26[v44 + v29]; v27 = 16 * middle_value & 0x30; v17[1] = v27; if ( v29 + 1 >= v24 ) { v38 = array[v27]; *((_WORD *)v17 + 1) = 0x3B3B; goto LABEL_43; } } ++v29; } while ( v29 < v24 ); }
该逻辑还是很好看懂的,可以写出如下的solve代码:
#print hex(0x20 ^ 0x7) #print hex(0x9b ^ 0x67) #print hex(63<<2) #print hex(0xfc^0x9b) #print chr(0x67) array1 =[0x20,0x7B,0x39,0x2A,0x38,0x67,0x61,0x2A, 0x6C,0x21,0x54,0x6E,0x3F,0x40,0x23,0x66, 0x6A,0x27,0x6A,0x24,0x5C,0x67,0x3B,0x3B] #0x20 0x7B 0x39 0x2A 0x38 0x67 0x61 0x2A #0x6C 0x21 0x54 0x6E 0x3F 0x40 0x23 0x66 #0x6A 0x27 0x6A 0x24 0x5C 0x67 0x3B 0x3B array =[0x21,0x3A,0x23,0x24,0x25,0x26,0x28,0x29,0x2B,0x2D,0x2A,0x2F,0x60,0x7E,0x5F,0x5B, 0x5D,0x7B,0x7D,0x3F,0x3C,0x3E,0x2C,0x2E,0x40,0x5E,0x61,0x62,0x63,0x64,0x65,0x66, 0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76, 0x77,0x78,0x79,0x7A,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x5C,0x27, 0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] mm = [0x9b,0x6b,0xba,0x25,0x73,0x82,0xe0,0x31,0x86,0x80,0xf1,0xc5,0xda,0x82,0xda,0x08,0x38,0x90] #mm = [0x25,0x73,0x82] mm2 = [] result = [] x1 = 0 x2 = 0 x3 = 0 for i in range(0,5): for x1 in range(0,128): mv = mm[0+3*i] ^ x1 if (array[mv>>2] ^ 7) == array1[0+4*i]: x11 = 16 * mv & 0x30 for x2 in range(0,128): mv = mm[1+3*i] ^ x2 if(array[x11 | mv >>4] == array1[1+4*i]): x22 = 4 * mv & 0x3C for x3 in range(0,128): mv = mm[2+3*i] ^ x3 if((array[x22 | (mv & 0xc0)>>6]) ^ 0xf) == array1[2+4*i]: if array[mv & 0x3F] == array1[3+4*i]: print chr(x1),chr(x2),chr(x3) for x1 in range(0,128): mv = 0x08 ^ x1 if (array[mv>>2] ^ 7) == 0x5c: print chr(x1) x11 = 16 * mv & 0x30 if x11 == 0x67: print chr(x1)
得出最后的flag为fu0kzHp2aqtZAuY6
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2019-3-25 15:03
被foyjog编辑
,原因:
赞赏
他的文章
看原图