• Android逆向题解 攻防世界难度4- Android2.0


    Jeb打开apk

    关键代码在Native函数getResult
    在这里插入图片描述

    IDA 打开 so

    发现代码比较简单,可以直接静态分析
    输出字符串也就是flag 长度是15,然后分成三段,第一段是可以整除3,第二段是除3取余=1,第三段是除3取余等于2;

    bool __fastcall Java_com_example_test_ctf03_JNI_getResult(JNIEnv *a1, int a2, int a3)
    {
      int v3; // r4
      const char *v4; // r8
      char *v5; // r6
      char *v6; // r4
      char *v7; // r5
      int i; // r0
      int j; // r0
    
    
      v3 = 0;
      v4 = (*a1)->GetStringUTFChars(a1, a3, 0); //输入字符串
      if ( strlen(v4) == 15 )                   //判断输入字符串长度==15
      {
        v5 = malloc(1u);
        v6 = malloc(1u);
        v7 = malloc(1u);
        Init(v5, v6, v7, v4, 15);       //输入字符串分成三段
        if ( !First(v5) )               //第一部分比较
          return 0;
        for ( i = 0; i != 4; ++i )
          v6[i] ^= v5[i];
        if ( !strcmp(v6, " 5-\x16a") )  //第二部分比较
        {
          for ( j = 0; j != 4; ++j )
            v7[j] ^= v6[j];
          return strcmp(v7, "AFBo}") == 0;  //第三部分比较
        }
        else
        {
          return 0;
        }
      }
      return v3;
    }
    
    Init 字符串分成三段
    int __fastcall Init(int result, char *a2, char *a3, const char *a4, int a5)
    {
      int v5; // r5
      int v6; // r10
      int v7; // r6
      if ( a5 < 1 )
      {
        v6 = 0;
      }
      else
      {
        v5 = 0;
        v6 = 0;
        do
        {
          v7 = v5 % 3;
          if ( v5 % 3 == 2 )   //除3取余 == 2 是第3段
          {
            a3[v5 / 3u] = a4[v5];
          }
          else if ( v7 == 1 ) //除3取余 == 1 是第2段
          {
            a2[v5 / 3u] = a4[v5];
          }
          else if ( !v7 )
          {
            ++v6;
            *(result + v5 / 3u) = a4[v5];  //除3是第1段
          }
          ++v5;
        }
        while ( a5 != v5 );
      }
      *(result + v6) = 0;
      a2[v6] = 0;
      a3[v6] = 0;
      return result;
    }
    

    计算第一段

    就是一个异或运算,注意这里只计算了4位,第5位不用算就是“l”;

    First处理第一段
    bool __fastcall First(char *a1)
    {
      int i; // r1
      for ( i = 0; i != 4; ++i )
        a1[i] = (2 * a1[i]) ^ 0x80;  //经过运算后判断是否== LN^dl ,先乘以2再异或0x80, 反推就是用 LN^dl先异或0x80再除以2
      return strcmp(a1, "LN^dl") == 0;
    }
    

    可以算出第一段的值是 fgorl

            char[] chars = new char[]{'L','N','^','d','l'};
            char[] res = new char[5];
            for (int i = 0; i < 4; i++) {
                res[i] = (char) ((chars[i] ^ 0x80)/2);
            }
            res[4] = 'l';
            System.out.println(res);
    

    计算第二段

    第二段也是一个异或,同样也只算4位,第5位不用异或计算。注意这里的v5 不是上面计算出来的第一段的值,是上面异或之后的也就是“LN^dl” ,

    for ( i = 0; i != 4; ++i )
          v6[i] ^= v5[i];
        if ( !strcmp(v6, a5A) )
    

    可以算出第二段的值 是 l{sra

            char[] c2 = new char[]{0x20,0x35,0x2D,0x16,0x61}; //a5A
            char[] r2 = new char[5];
            for (int i = 0; i < 4; i++) {
                r2[i]  = (char) (chars[i]^c2[i]); //chars 是上面的 LN^dl
            }
            r2[4] = 0x61;
            System.out.println(r2);
    

    计算第三段

    一样的套路,还是异或计算4位,第5位直接照搬是“}”

          for ( j = 0; j != 4; ++j )
            v7[j] ^= v6[j];
          return strcmp(v7, "AFBo}") == 0;
    

    可以计算出第三段 是 asoy}

            char[] c3 = new char[]{0x41, 0x46, 0x42, 0x6F, 0x7D}; // "AFBo}"
            char[] r3 = new char[5];
            for (int i = 0; i < 4; i++) {
                r3[i] = (char) (c2[i] ^  c3[i]);
            }
            r3[4] = 0x7D;
            System.out.println(r3);
    

    组合起来就是flag

    三段数据组合起来就是flag了
    第一段:fgorl -------------整除3,对应的下标就是0,3,6,9,12
    第二段:l{sra -------------除3余1,对应下标就是1,4,7,10,13
    第三段:asoy} -------------除3余2,对应下标就是2,5,8,11,14
    组合结果就是:flag{sosorryla}
    完整计算代码:

        public static void main(String[] args) {
            char[] chars = new char[]{'L','N','^','d','l'};
            char[] res = new char[5];
            for (int i = 0; i < 4; i++) {
                res[i] = (char) ((chars[i] ^ 0x80)/2);
            }
            res[4] = 'l';
            System.out.println(res);
    
            //第二段
            char[] c2 = new char[]{0x20,0x35,0x2D,0x16,0x61};
            char[] r2 = new char[5];
            for (int i = 0; i < 4; i++) {
                r2[i]  = (char) (chars[i]^c2[i]);
            }
            r2[4] = 0x61;
            System.out.println(r2);
    
            //第三段
            char[] c3 = new char[]{0x41, 0x46, 0x42, 0x6F, 0x7D};
            char[] r3 = new char[5];
            for (int i = 0; i < 4; i++) {
                r3[i] = (char) (c2[i] ^  c3[i]);
            }
            r3[4] = 0x7D;
            System.out.println(r3);
    
            //还原
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < 5; i++) {
                stringBuilder.append(res[i]);
                stringBuilder.append(r2[i]);
                stringBuilder.append(r3[i]);
            }
            System.out.println(stringBuilder);
        }
    
  • 相关阅读:
    get与post区别
    《Map-Matching for Low-Sampling-Rate GPS Trajectories》 读书笔记
    深度学习-nlp系列(2)文本分类(Bert)pytorch
    艾美捷C1q天然蛋白的应用和化学性质说明
    联邦学习:多任务思想与聚类联邦学习
    Codeforces Round 899 (Div. 2) E1. Two Permutations (Easy Version) (思维题/交换序列)
    2023年9月11日
    jackson反序列化get空值null抛异常的问题处理方案
    ZZNUOJ_C语言1027:判断水仙花数(完整代码)
    网络编程汇总
  • 原文地址:https://blog.csdn.net/u013170888/article/details/141093776