首页
社区
课程
招聘
[原创]KCTF2019_q4_第七题_东北奇闻
发表于: 2019-12-16 11:04 3228

[原创]KCTF2019_q4_第七题_东北奇闻

ccfer 活跃值
16
2019-12-16 11:04
3228
先看看dex:
public class AppC0mpatActivity extends AppCompatActivity {
    static {
        System.loadLibrary("native-lib");
    }

    public AppC0mpatActivity() {
        super();
    }

    public native boolean showAssist(Bundle arg1) {
    }
}

public class MainActivity extends AppC0mpatActivity {
    public MainActivity() {
        super();
    }

    protected void onCreate(Bundle arg4) {
        super.onCreate(arg4);
        this.setContentView(0x7F0A001C);
        this.findViewById(0x7F070042).setOnClickListener(new View$OnClickListener(this.findViewById(0x7F070054), arg4) {
            public void onClick(View arg3) {
                if(this.val$ed.getText() == null || (TextUtils.isEmpty(this.val$ed.getText().toString())) || (MainActivity.this.showAssist(this.val$savedInstanceState))) {
                    Toast.makeText(MainActivity.this, "null", 1).show();
                }
            }
        });
    }
}
得知验证函数是libnative-lib.so中的showAssist
.data.rel.ro:0002B668 off_2B668       DCD aShowassist         ; "showAssist"
.data.rel.ro:0002B66C                        DCD aLandroidOsBund     ; "(Landroid/os/Bundle;)Z"
.data.rel.ro:0002B670                        DCD sub_19F80+1
下个断点断下来后一路往下调试,来到这里:
.text:00019B32                 LDR             R2, [R5,R0]
.text:00019B34                 ADD             R0, R5
.text:00019B36                 LDR             R0, [R0,#4]
.text:00019B38                 STR             R0, [R1,#4]
.text:00019B3A                 MOV             R0, R10          ; 输入的8个字节
.text:00019B3C                 STR             R2, [R1]         ; 密钥
.text:00019B3E                 BL              sub_9CB0		; 解密函数
.text:00019B42                 ADD.W           R8, R8, #1
.text:00019B46                 MOVS            R0, #0
.text:00019B48                 CMP.W           R8, #0x19	; 循环计数
...
.text:00019B8E                 LDR             R1, =(byte_30031 - 0x19B9C)
.text:00019B90                 LDRB.W          R2, [R9,R0]
.text:00019B94                 ADD.W           R0, R11, R0,LSL#1 ; s
.text:00019B98                 ADD             R1, PC           ; "%.2x" 
.text:00019B9A                 BLX             sprintf          ; 格式化成HexString
...
.text:00019BC0                 LDR             R1, =(byte_30040 - 0x19BC8)
.text:00019BC2                 MOV             R0, R11		; 
.text:00019BC4                 ADD             R1, PC 	        ; 目标字符串:"68dd8a0f7065609e3106fb2bb1059423e80fb1347318ffeb83b8a074a7e6c9cf"
.text:00019BC6                 BLX             strcmp           ; 结果比较,我们只需关心前64个字符,后面其实都是0的加密结果解密
解密函数:
int __fastcall sub_9CB0(unsigned int *a1, unsigned __int8 *a2)
{
  unsigned int *v2; // r10
  unsigned __int8 *v3; // ST00_4
  unsigned int v4; // r5
  unsigned int v5; // r11
  unsigned int v6; // r8
  unsigned int v7; // r2
  int v8; // r11
  unsigned int v9; // r4
  int v10; // r8
  unsigned int v11; // r5
  int v12; // lr
  unsigned int v13; // r6
  int v14; // r12
  unsigned int v15; // r5
  int v16; // lr
  unsigned int v17; // r6
  int v18; // r12
  unsigned int v19; // r6
  int v20; // lr
  unsigned int v21; // r5
  int v22; // r12
  unsigned int v23; // r6
  int v24; // lr
  unsigned int v25; // r6
  int v26; // r12
  unsigned int v27; // r5
  unsigned int v28; // r4
  unsigned int v29; // r5
  unsigned int v30; // r6
  int result; // r0

  v2 = a1;
  //省略一大段xor解密常数表过程,我们直接从内存dump出来使用
  v3 = a2;
  v4 = *((_DWORD *)a2 + 1);
  v5 = bswap32(*(_DWORD *)a2);
  printf(&byte_2D004, v5);
  v6 = bswap32(v4);
  printf(&byte_2D004, v6);
  v7 = __ROR4__(*v2 + v6, 32 - v2[16]);
  v8 = v5 ^ ((dword_2D410[(v7 >> 16) & 0xFF] ^ dword_2D010[v7 >> 24])
           - dword_2D810[(unsigned __int16)v7 >> 8]
           + dword_2DC10[(unsigned __int8)v7]);
  v9 = __ROR4__(v8 ^ v2[1], 32 - v2[17]);
  v10 = (dword_2D010[v9 >> 24] - dword_2D410[(v9 >> 16) & 0xFF] + dword_2D810[(unsigned __int16)v9 >> 8]) ^ v6 ^ dword_2DC10[(unsigned __int8)v9];
  v11 = __ROR4__(v2[2] - v10, 32 - v2[18]);
  v12 = (((dword_2D410[(v11 >> 16) & 0xFF] + dword_2D010[v11 >> 24]) ^ dword_2D810[(unsigned __int16)v11 >> 8])
       - dword_2DC10[(unsigned __int8)v11]) ^ v8;
  v13 = __ROR4__(v12 + v2[3], 32 - v2[19]);
  v14 = (dword_2DC10[(unsigned __int8)v13]
       + (dword_2D410[(v13 >> 16) & 0xFF] ^ dword_2D010[v13 >> 24])
       - dword_2D810[(unsigned __int16)v13 >> 8]) ^ v10;
  v15 = __ROR4__(v2[4] ^ v14, 32 - v2[20]);
  v16 = dword_2DC10[(unsigned __int8)v15] ^ v12 ^ (dword_2D010[v15 >> 24]
                                                 - dword_2D410[(v15 >> 16) & 0xFF]
                                                 + dword_2D810[(unsigned __int16)v15 >> 8]);
  v17 = __ROR4__(v2[5] - v16, 32 - v2[21]);
  v18 = v14 ^ (((dword_2D010[v17 >> 24] + dword_2D410[(v17 >> 16) & 0xFF]) ^ dword_2D810[(unsigned __int16)v17 >> 8])
             - dword_2DC10[(unsigned __int8)v17]);
  v19 = __ROR4__(v2[6] + v18, 32 - v2[22]);
  v20 = v16 ^ ((dword_2D410[(v19 >> 16) & 0xFF] ^ dword_2D010[v19 >> 24])
             - dword_2D810[(unsigned __int16)v19 >> 8]
             + dword_2DC10[(unsigned __int8)v19]);
  v21 = __ROR4__(v2[7] ^ v20, 32 - v2[23]);
  v22 = dword_2DC10[(unsigned __int8)v21] ^ v18 ^ (dword_2D010[v21 >> 24]
                                                 - dword_2D410[(v21 >> 16) & 0xFF]
                                                 + dword_2D810[(unsigned __int16)v21 >> 8]);
  v23 = __ROR4__(v2[8] - v22, 32 - v2[24]);
  v24 = v20 ^ (((dword_2D410[(v23 >> 16) & 0xFF] + dword_2D010[v23 >> 24]) ^ dword_2D810[(unsigned __int16)v23 >> 8])
             - dword_2DC10[(unsigned __int8)v23]);
  v25 = __ROR4__(v2[9] + v24, 32 - v2[25]);
  v26 = v22 ^ ((dword_2D010[v25 >> 24] ^ dword_2D410[(v25 >> 16) & 0xFF])
             - dword_2D810[(unsigned __int16)v25 >> 8]
             + dword_2DC10[(unsigned __int8)v25]);
  v27 = __ROR4__(v2[10] ^ v26, 32 - v2[26]);
  v28 = (dword_2D010[v27 >> 24] - dword_2D410[(v27 >> 16) & 0xFF] + dword_2D810[(unsigned __int16)v27 >> 8]) ^ dword_2DC10[(unsigned __int8)v27] ^ v24;
  v29 = __ROR4__(v2[11] - v28, 32 - *((_BYTE *)v2 + 108));
  v30 = ((dword_2D810[(unsigned __int16)v29 >> 8] ^ (dword_2D010[v29 >> 24] + dword_2D410[(v29 >> 16) & 0xFF]))
       - dword_2DC10[(unsigned __int8)v29]) ^ v26;
  v3[0] = sub_DF18(v30 >> 24);
  v3[1] = sub_DF18((v30 >> 16) & 0xFF);
  v3[2] = sub_DF18((unsigned __int16)v30 >> 8);
  v3[3] = sub_DF18((unsigned __int8)v30);
  v3[4] = sub_DF18(v28 >> 24);
  v3[5] = sub_DF18((v28 >> 16) & 0xFF);
  v3[6] = sub_DF18((unsigned __int16)v28 >> 8);
  result = sub_DF18((unsigned __int8)v28);
  v3[7] = result;
  return result;
}
其中sub_DF18这个函数不太好反出来直接使用,观察得知是个单字节固定变换函数,相当于查表,
所以直接查thumb指令手册,在原地16进制构造一个循环如下:
.text:0000DEA8 00 00                       MOVS            R0, R0
.text:0000DEAA A8 47                       BLX             R5      ; sub_DF18
.text:0000DEAC 89 F8 00 00                 STRB.W          R0, [R9]
.text:0000DEB0 09 F1 01 09                 ADD.W           R9, R9, #1
.text:0000DEB4 06 F1 01 00                 ADD.W           R0, R6, #1
.text:0000DEB8 F6 E7                       B               loc_DEA8
循环256次后,把R9中内容dump出来得到转换表
然后把sub_9CB0流程倒推一下得到加密函数,把68dd8a0f7065609e3106fb2bb1059423e80fb1347318ffeb83b8a074a7e6c9c加密后得到结果:
flag{9eca5de49470144c1694f6}
详细代码见附件


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-12-16 11:07 被ccfer编辑 ,原因:
上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//