首页
社区
课程
招聘
[原创]第二题 变形金刚
2019-3-25 15:02 4194

[原创]第二题 变形金刚

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编辑 ,原因:
收藏
点赞2
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回