KCTF2020秋季赛 第四题 突破重围 writeup

KCTF2020秋季赛 第四题 突破重围 wp

一道Android题

图片描述

Java层分析

1、com.kanxue.crackme.MainActivity

1
2
3
4
5
System.loadLibrary( "crack" );
 
init();  - > DexClassLoader / assets / b.txt
 
check() 反射执行 com.kanxue.crackme.Crack.check()

2、com.kanxue.crackme.MyCrack

1
2
3
4
5
public class MyCrack {
     public static String crypt = "otVvmpP4ZI58pqB26OTaYw==" ;
 
     public static native byte[] crackjni(byte[] bArr);
}

3、/assets/b.txt -> /assets/b.dex

com.kanxue.crackme.Crack.check

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public static boolean check(String content) {
         if (content = = null || content.length() ! = 16 ) {
             return false;
         }
         Class MyCrackClass = null;
         Field cryptfield = null;
         byte[] result = crypt(content.getBytes());
         Method crackjni = null;
         try {
             MyCrackClass = Crack. class .getClassLoader().loadClass( "com.kanxue.crackme.MyCrack" );
             cryptfield = MyCrackClass.getDeclaredField( "crypt" );
             Method[] methods = MyCrackClass.getDeclaredMethods();
             for ( int i = 0 ; i < methods.length; i + + ) {
                 if (methods[i].getName().equals( "crackjni" )) {
                     crackjni = methods[i];
                 }
             }
         } catch (ClassNotFoundException e) {
             e.printStackTrace();
         } catch (NoSuchFieldException e2) {
             e2.printStackTrace();
         }
         if (crackjni ! = null) {
             try {
                 result = (byte[]) crackjni.invoke(null, new Object []{result});
             } catch (IllegalAccessException e3) {
                 e3.printStackTrace();
             } catch (InvocationTargetException e4) {
                 e4.printStackTrace();
             }
         }
         String finalresult = Base64.encodeToString(crypt(result), 0 );
         String cryptcontent = "test" ;
         if (!(cryptfield = = null || MyCrackClass = = null)) {
             try {
                 cryptcontent = (String) cryptfield.get(null);
             } catch (IllegalAccessException e5) {
                 e5.printStackTrace();
             }
         }
         if (finalresult.equals(cryptcontent)) {
             return true;
         }
         return false;
     }

com.kanxue.crackme.Crack.crypt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public static byte[] crypt(byte[] b_data) {
         String mKkey = "kaokaonio" ;
         if (b_data = = null) {
             return null;
         }
         int x = 0 ;
         int y = 0 ;
         byte[] b_key = mKkey.getBytes();
         byte[] key = new byte[ 256 ];
         for ( int i = 0 ; i < 256 ; i + + ) {
             key[i] = (byte) i;
         }
         int index1 = 0 ;
         int index2 = 0 ;
         if (b_key = = null || b_key.length = = 0 ) {
             return null;
         }
         for ( int i2 = 0 ; i2 < 256 ; i2 + + ) {
             index2 = ((b_key[index1] & 255 ) + (key[i2] & 255 ) + index2) & 255 ;
             byte tmp = key[i2];
             key[i2] = key[index2];
             key[index2] = tmp;
             index1 = (index1 + 1 ) % b_key.length;
         }
         byte[] result = new byte[b_data.length];
         for ( int i3 = 0 ; i3 < b_data.length; i3 + + ) {
             x = (x + 1 ) & 255 ;
             y = ((key[x] & 255 ) + y) & 255 ;
             byte tmp2 = key[x];
             key[x] = key[y];
             key[y] = tmp2;
             result[i3] = (byte) (b_data[i3] ^ key[((key[x] & 255 ) + (key[y] & 255 )) & 255 ]);
         }
         return result;
     }

对/assets/b.dex进行动态调试:

图片描述
找到cryptcontent的值为 "l+x7fKd2FBaaEY4NV4309A==\n"

 

图片描述
crypt中的mkey有改变 "kaokaonio" -> "keepGoing"

执行流程如下:

1
2
3
4
5
6
7
8
9
1. input 长度 16
 
2. byte[] result = crypt( input ) crypt方法中的 mkey = kaokaonio
 
3. crackjni_reslut = libcarack.so - >crackjni(reslut) 对 reslut 进行加密
 
4. reslut = crypt(crackjni_reslut) crypt方法中的 mkey = keepGoing
 
5. base64(reslut) 与 cryptcontent = "l+x7fKd2FBaaEY4NV4309A==\n" 进行比较

Native层分析

1、libcrack.so 使用了 aes 加密

图片描述
S盒
图片描述

2、Java_com_kanxue_crackme_MyCrack_crackjni

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
int __fastcall Java_com_kanxue_crackme_MyCrack_crackjni(_JNIEnv * a1, int a2, int a3)
{
   v25 = sub_CF79ECBC((void * ) 0xFFFFFF9C , "/proc/self/maps" , 0 , 0 ); / / frida anti
   if ( v25 > = 1 )
   {
     while ( sub_CF7A2168(v25, &s, 0x200 ) > = 1 )
     {
       if ( strstr(&s, "frida" ) )
         MEMORY[ 0 ] = 0x63 ;
       if ( sscanf(&s, "%x-%lx %4s %lx %*s %*s %s" , &v31, &v30, &v33, &v32, &v39) = = 5
         && v33 = = 0x72
         && v34 = = 0x70
         && !v32
         && strlen(&v39)
         && v39 ! = 0x5B
         && (unsigned int )(v30 - v31) > 0xF4240
         && !sub_CF7A22C0(&v39, ".oat" )
         && sub_CF7A2228(v31) = = 1
         && sub_CF7A20D2(v31, 0 , v30, v30 >> 0x1F ) = = 1 )
       {
         MEMORY[ 0 ] = 0x63 ;
         break ;
       }
     }
   }
     ......
 
   sub_CF79ED60(v5, "kaokaonikaokaoni" , v6); / / AES加密
 
     ......
 
   if ( dword_CF7D73E4 )
   {
     if ( dword_CF7D73D8 )
     {
       v12 = dword_CF7D73D8 + 0x16D3A6 ;
       v13 = * (_BYTE * )(dword_CF7D73D8 + 0x16D3A6 );
       v14 = dword_CF7D73E4 + + ;
       * (_BYTE * )(dword_CF7D73D8 + 0x16D3A6 ) = v13 + v14;
       * (_BYTE * )(v12 + 1 ) = 0x3D ;
       v15 = sub_CF7A38C2(v29, "com/kanxue/crackme/MyCrack" );
       v16 = sub_CF7A38EC(v29, v15, "crypt" , "Ljava/lang/String;" );
       v17 = sub_CF7A3934(v29, "ZmxhZ3RyeWFnYWluP30=" );
       sub_CF7A3960(v29, v15, v16, v17);
     }
     + + dword_CF7D73E4;
   }
   else
   {
     if ( dword_CF7D73D8 )
     {
       v8 = dword_CF7D73D8 + 0x16D3A6 ;
       * (_BYTE * )(dword_CF7D73D8 + 0x16D3A6 ) = 0xD3u ;              / / "kaokaonio" - > "keepGoing"
       * (_BYTE * )(v8 + 1 ) = 0x3D ;
       v9 = sub_CF7A38C2(v29, "com/kanxue/crackme/MyCrack" );
       v10 = sub_CF7A38EC(v29, v9, "crypt" , "Ljava/lang/String;" );                                    
       v11 = sub_CF7A3934(v29, "l+x7fKd2FBaaEY4NV4309A==\n" ); / / "otVvmpP4ZI58pqB26OTaYw==" - > "l+x7fKd2FBaaEY4NV4309A=="   
       sub_CF7A3960(v29, v9, v10, v11);
     }
     + + dword_CF7D73E4;
   }
 
}

AES扩展密钥算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
int sub_CF79EDE8()
{
   unsigned __int8 v0; / / ST04_1
   unsigned int j; / / [sp + 8h ] [bp - 18h ]
   unsigned int i; / / [sp + Ch] [bp - 14h ]
   unsigned __int8 v4; / / [sp + 10h ] [bp - 10h ]
   unsigned __int8 v5; / / [sp + 11h ] [bp - Fh]
   unsigned __int8 v6; / / [sp + 12h ] [bp - Eh]
   unsigned __int8 v7; / / [sp + 13h ] [bp - Dh]
 
   for ( i = 0 ; i < = 3 ; + + i )
   {
     byte_CF7B6318[ 4 * i] = * (_BYTE * )(dword_CF7B6314 + 4 * i);
     byte_CF7B6318[ 4 * i + 1 ] = * (_BYTE * )(dword_CF7B6314 + 4 * i + 1 );
     byte_CF7B6318[ 4 * i + 2 ] = * (_BYTE * )(dword_CF7B6314 + 4 * i + 2 );
     byte_CF7B6318[ 4 * i + 3 ] = * (_BYTE * )(dword_CF7B6314 + 4 * i + 3 );
   }
   while ( i < = 0x2B )
   {
     for ( j = 0 ; j < = 3 ; + + j )
       * (&v4 + j) = byte_CF7B6318[ 4 * i - 4 + j];
     if ( !((unsigned __int8)i << 0x1E ) )
     {
       v0 = v4;
       v4 = v5;
       v5 = v6;
       v6 = v7;
       v7 = v0;
       v4 = sub_CF79F084(v4);
       v5 = sub_CF79F084(v5);
       v6 = sub_CF79F084(v6);
       v7 = sub_CF79F084(v7);
       v4 ^ = byte_CF7AFE5C[i >> 2 ];
     }
     byte_CF7B6318[ 4 * i] = byte_CF7B6318[ 4 * i - 0x10 ] ^ v4;
     byte_CF7B6318[ 4 * i + 1 ] = byte_CF7B6318[ 4 * i - 0xF ] ^ v5;
     byte_CF7B6318[ 4 * i + 2 ] = byte_CF7B6318[ 4 * i - 0xE ] ^ v6;
     byte_CF7B6318[ 4 * i + 3 ] = byte_CF7B6318[ 4 * i - 0xD ] ^ v7;
     + + i;
   }
   return _stack_chk_guard;
}

图片描述

获取flag

1、"l+x7fKd2FBaaEY4NV4309A==" -> bytes -> base64 -> crypto (mKey=keepGoing)

1
40 , - 128 , - 114 , - 30 , 10 , - 79 , 122 , 37 , - 62 , 22 , 120 , 86 , 58 , 74 , 127 , - 85

2、AES解密
图片描述
3、解密字符串
crypto (mKey=kaokaonio)
图片描述

 

图片描述



更多【KCTF2020秋季赛 第四题 突破重围 writeup】相关视频教程:www.yxfzedu.com


评论