-
-
[原创]KCTF2019_q4_第七题_东北奇闻
-
发表于: 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编辑
,原因:
赞赏
他的文章
谁下载
无
看原图
赞赏
雪币:
留言: