zoukankan      html  css  js  c++  java
  • CTF题GoNative破解过程记录

      我对native部分真的当前了解的非常少,必须从现在起抓紧时间给它一顿暴学。

      本次破解的是一到CTF题,找到正确的Flag即可。

      Apk下载地址:链接:https://pan.baidu.com/s/1K6wauXK73pzO4wpueCWV9A
              提取码:qola

      jni.h下载地址:链接:https://pan.baidu.com/s/1DSlUORCsZVcxbvfzaJTUYg
             提取码:psxs

      1.老规矩吧,先拖到jeb里,给它一顿反编译。由于只有一个界面,直接查看MainActivity即可。

      2.最终填入的String应该是放到FlagChecker.checkFlag方法中进入校验。查看checkFlag方法。

       3.这段很容易懂,正确的字符串大体上应该长成这个屌样:“MOBISEC{X1-X2}"  。 其中X2部分是由数字组成,长度为6。最终将X1字符串和转成int值的X2传入到native方法中。

      首先找到so,armeabiv-v7a: 第7代及以上的 ARM 处理器。2011年15月以后的生产的大部分Android设备都使用它.
            arm64-v8a: 第8代、64位ARM处理器,很少设备,三星 Galaxy S6是其中之一。
            armeabi: 第5代、第6代的ARM处理器,早期的手机用的比较多。
            x86: 平板、模拟器用得比较多。
            x86_64: 64位的平板。

      到apk中对应的位置找到native-lib.so然后拖到IDA中一路确定,找到helloFromTheOtherSide方法,按F5查看伪代码。

    bool __fastcall Java_com_mobisec_gonative_FlagChecker_helloFromTheOtherSide(int a1, int a2, int a3, int a4)
    {
      int v4; // r6
      int v5; // r4
      int v6; // r8
      const char *v7; // r0
      char *v8; // r5
      size_t v9; // r0
      bool v10; // zf
      _BOOL4 result; // r0
      int v12; // r0
      bool v13; // zf
      int v14; // r0
      bool v15; // zf
      int v16; // r0
      bool v17; // zf
      int v18; // r4
      char dest; // [sp+6h] [bp-22h]
      char v20; // [sp+Bh] [bp-1Dh]
      int v21; // [sp+Ch] [bp-1Ch]
    
      v4 = a1;
      v5 = a4;
      v6 = a3;
      v7 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
      v8 = (char *)v7;
      v9 = strlen(v7);
      v10 = v9 == 12;
      if ( v9 == 12 )
        v10 = v5 == 31337;
      if ( v10 )
        goto LABEL_6;
    LABEL_4:
      (*(void (__fastcall **)(int, int, char *))(*(_DWORD *)v4 + 680))(v4, v6, v8);
      result = 0;
      while ( _stack_chk_guard != v21 )
      {
    LABEL_6:
        v12 = (unsigned __int8)*v8;
        v13 = v12 == 110;
        if ( v12 == 110 )
          v13 = v8[11] == 111;
        if ( !v13 )
          goto LABEL_4;
        strncpy(&dest, v8 + 1, 5u);
        v20 = 0;
        if ( strncmp("ative", &dest, 5u) )
          goto LABEL_4;
        v14 = (unsigned __int8)v8[9];
        v15 = v14 == 95;
        if ( v14 == 95 )
          v15 = v8[6] == 95;
        if ( !v15 )
          goto LABEL_4;
        v16 = (unsigned __int8)v8[7];
        v17 = v16 == 105;
        if ( v16 == 105 )
          v17 = v8[8] == 115;
        if ( !v17 )
          goto LABEL_4;
        v18 = strcmp("so", v8 + 10);
        (*(void (__fastcall **)(int, int, char *))(*(_DWORD *)v4 + 680))(v4, v6, v8);
        result = v18 == 0;
      }
      return result;
    }

       4.这是什么鸟玩意呀,C语言里的指针这个星那个星的,看的我到是满眼的星。传进来两个参数怎么给我整成4个int了?

       首先要知道,在JNI中本地方法第一个参数是JNIEnv接口指针,指向一个个函数表,函数表中的每一个入口指向一个JNI函数。

       第二个参数根据本地方法是一个静态方法还是实例方法而有所不同。本地方法是一个静态方法时,第二个参数代表本地方法所在的类;本地方法是一个实例方法时,第二个参数代表本地方法所在的对象。

       其次,要导入jni.h的函数库,点File->Load file->Parse C header file 找到jni.h所在位置点打开,此时显示Compilation successful 导入成功。

       点击函数第一个参数int 右键Convert to struct* 在弹出的框中选择_JNIEnv点ok。

       将已经显示出来一些函数,选中右键Force call type。

       然后点住第一个参数a1按住n键重命名为env。         

     1 bool __fastcall Java_com_mobisec_gonative_FlagChecker_helloFromTheOtherSide(_JNIEnv *env, int a2, int a3, int a4)
     2 {
     3   _JNIEnv *v4; // r6
     4   int v5; // r4
     5   void *v6; // r8
     6   const char *v7; // r0
     7   const char *v8; // r5
     8   size_t v9; // r0
     9   bool v10; // zf
    10   _BOOL4 result; // r0
    11   int v12; // r0
    12   bool v13; // zf
    13   int v14; // r0
    14   bool v15; // zf
    15   int v16; // r0
    16   bool v17; // zf
    17   int v18; // r4
    18   char dest; // [sp+6h] [bp-22h]
    19   char v20; // [sp+Bh] [bp-1Dh]
    20   int v21; // [sp+Ch] [bp-1Ch]
    21 
    22   v4 = env;
    23   v5 = a4;
    24   v6 = (void *)a3;
    25   v7 = env->functions->GetStringUTFChars(&env->functions, (jstring)a3, 0);     //把一个jstring指针(指向JVM内部的Unicode字符序列)
                                                      转化成一个UTF-8格式的C字符串
    26 v8 = v7; 27 v9 = strlen(v7); //获取字符串长度 28 v10 = v9 == 12; 29 if ( v9 == 12 ) 30 v10 = v5 == 31337; 31 if ( v10 ) 32 goto LABEL_6; 33 LABEL_4: 34 v4->functions->ReleaseStringUTFChars(&v4->functions, v6, v8); //从GetStringUTFChars中获取的UTF-8字符串在本地代码中使用完毕后,
                                                 要使用ReleaseStringUTFChars告诉JVM这个UTF-8字符串不会被使用了,
                                                 因为这个UTF-8字符串占用的内存会被回收。
    35 result = 0; 36 while ( _stack_chk_guard != v21 ) 37 { 38 LABEL_6: 39 v12 = *(unsigned __int8 *)v8; 40 v13 = v12 == 110; //”n“ 41 if ( v12 == 110 ) 42 v13 = v8[11] == 111; //”o“ 43 if ( !v13 ) 44 goto LABEL_4; 45 strncpy(&dest, v8 + 1, 5u); 46 v20 = 0; 47 if ( strncmp("ative", &dest, 5u) ) 48 goto LABEL_4; 49 v14 = *((unsigned __int8 *)v8 + 9); 50 v15 = v14 == 95; //”_" 51 if ( v14 == 95 ) 52 v15 = v8[6] == 95; 53 if ( !v15 ) 54 goto LABEL_4; 55 v16 = *((unsigned __int8 *)v8 + 7); 56 v17 = v16 == 105; //“i” 57 if ( v16 == 105 ) 58 v17 = v8[8] == 115; //“s” 59 if ( !v17 ) 60 goto LABEL_4; 61 v18 = strcmp("so", v8 + 10); 62 v4->functions->ReleaseStringUTFChars(&v4->functions, v6, v8); 63 result = v18 == 0; 64 } 65 return result; 66 }

       5.是不是读起来好接受多了,从这段代码中就能分析出来,先判断传进来的X1长度是不是12,再看X2是不是等于31337,由此可得后半段字符串应为”031337}“。

       c语言中对字符比较只能比较其ascii码,所以下面的步骤是先比较第一位和最后一位是不是“n”和“o”。是的话看第2到第6位是不是“ative”。

       再看第10位和第7位是不是“_",再看第8第9位是不是”i“和”s“,最后比较最后两位是不是”so“。所以前半段应该为”MOBISEC{native_is_so”。最终结果为“MOBISEC{native_is_so-031337}”。

       6.破解完后如下图所示,有一说一,这个so里的逻辑很简单,非常适合我这种刚刚起步的小老弟。今后还是要把这个逆向给它一顿臭学。 

        参考资料: https://www.52pojie.cn/thread-742703-1-1.html (推荐)

             https://blog.csdn.net/a345017062/article/details/8068917

             https://www.cnblogs.com/H-BolinBlog/p/6095961.html  

  • 相关阅读:
    druid spring监控配置
    深入理解Java:SimpleDateFormat安全的时间格式化
    Thread.join()方法
    static 作用
    Java链接SqlServer,学生数据管理面板
    java巅峰作业
    2019.6.12Java/IO data
    Java常用类
    2019.6.5
    java求和运算窗口5.29
  • 原文地址:https://www.cnblogs.com/CYCLearning/p/11817013.html
Copyright © 2011-2022 走看看