吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2315|回复: 5
收起左侧

[Android CTF] 《攻防世界》MOBILE--easyjni

[复制链接]
HNHuangJingYU 发表于 2021-9-29 20:16
本帖最后由 HNHuangJingYU 于 2021-9-30 10:47 编辑

1.将easyjni.apk拖进jeb分析代码,和常一样进入启动页分析(职业病了都)

1

1

2.这里介绍输入字符进行判断,往往,一看便知又是逆向算法的题目

2

2

3.核心函数,将输入的字符串传入a类中的a函数进行加密,点进来看就知道就是一个Base64加密,只不过换了码表,之后再将java加密后的字符串穿入so层加密并且进行判断,打开IDA

3

3


4.从这里知道memcmp函数就是将内存中的前0x20个字节数据进行对比相等则返回0,后面对v13进行了判断如果v13==0则这个函数返回true,分析下来很简单,就是我们输入的函数经过两层加密后要等于”MbT3sQgX039i3g==AQOoMQFPskB1Bsc7”,首先我们来正向分析下:
[C++] 纯文本查看 复制代码
signed int __fastcall Java_com_a_easyjni_MainActivity_ncheck(_JNIEnv *env, int jclass, int string)
{
  int v3; // r8
  _JNIEnv *env_1; // r5
  void *string_1; // r8
  const char *data; // r6
  int index; // r0
  char *v8; // r2
  char v9; // r1
  int index2; // r0
  bool v11; // nf
  unsigned __int8 v12; // vf
  int v13; // r1
  signed int result; // r0
  char s1[32]; // [sp+3h] [bp-35h]
  char v16; // [sp+23h] [bp-15h]
  int v17; // [sp+28h] [bp-10h]

  v17 = v3;
  env_1 = env;
  string_1 = string;
  data = env->functions->GetStringUTFChars(&env->functions, string, 0);//分配内存存储字符串
  if ( strlen(data) == 32 ) //java层加密后的数据必须为32长度的字符串
  {
    index = 0;    //flag{just_ANot#er_@p3}
    do
    {
      v8 = &s1[index];
      s1[index] = data[index + 16];   //把data[16-32]位 给 s1[0-15]位
      v9 = data[index++];       //把data[0-15]位 给 s1[16-32]位     
      v8[16] = v9;
    } 
    while ( index != 16 );      //第一层循环是将data前16位和后16位换位置给s1
    env_1->functions->ReleaseStringUTFChars(&env_1->functions, string_1, data); //清空jVM内存  配合GetStringUTFChars使用
    index2 = 0;
    do
    {
      v12 = __OFSUB__(index2, 30);
      v11 = index2 - 30 < 0;
      v16 = s1[index2];        
      s1[index2] = s1[index2 + 1];
      s1[index2 + 1] = v16;
      index2 += 2;
    }
    while ( v11 ^ v12 );    //将s1索引处1,2换位置 3,4换位置  依次类推
    v13 = memcmp(s1, "MbT3sQgX039i3g==AQOoMQFPskB1Bsc7", 0x20u);
    result = 0;
    if ( !v13 )
      result = 1;
  }
  else
  {
    env_1->functions->ReleaseStringUTFChars(&env_1->functions, string_1, data);
    result = 0;
  }
  return result;
}

5.再进行逆向算法:
[Java] 纯文本查看 复制代码
@Test
public void demo6() {
    //如果输入1234567890123456789012
    //则加密后应该为:...9fH3T1Dd4coiKf==4f9GL1Cq91pKLfwW...........
    //但是ida调试的时候显示这个字符串害我搞了半天:...9fH3T1Dd4coiKf==4f9GL1Cq91pKLfwWWb...........(求大佬解答)

    
    System.out.println("----------------正向加密---------------");
    String inputString = "1234567890123456789012";
    System.out.println("输入的字符串:" + inputString);
    inputString = new AClass().a(inputString.getBytes());        //这个就是apk中加密函数的a类只不过我换了个名字看的清楚点
    System.out.println("java加密:" + inputString + "长度为:" + inputString.length());

    char[] data = inputString.toCharArray();
    char[] s1 = new char[32]; // [sp+3h] [bp-35h]
    char v9;
    if (data.length == 32) {
        int index = 0;
        do {
            s1[index] = data[index + 16];
            v9 = data[index];
            s1[index + 16] = v9;
            index++;
        }
        while (index != 16);
        //第二次循环
        int index2 = 0;
        char v16;
        do {
            v16 = s1[index2];
            s1[index2] = s1[index2 + 1];
            s1[index2 + 1] = v16;
            index2 += 2;
        }
        while (index2 < 32);
        System.out.println("so加密后:");
        System.out.println(s1);
    }


    System.out.println("----------------逆向还原flag---------------");
    String flag = "MbT3sQgX039i3g==AQOoMQFPskB1Bsc7";
    StringBuilder sb = new StringBuilder();
    char[] chars = flag.toCharArray();
    for (int i = 0; i < chars.length; i += 2) {
        char aChar = chars[i];
        chars[i] = chars[i + 1];
        chars[i + 1] = aChar;
    }

    List<Character> list = new ArrayList<>();
    for (int i = 0; i < chars.length; i++) {
        if (i < 16) {
            list.add(chars[i]);
            chars[i] = chars[i + 16];
        } else
            chars[i] = list.get(i - 16);
        sb.append(chars[i]);
    }
    System.out.println("so还原:");
    System.out.println(sb);
    System.out.println("java还原:");
    new AClass().Base64Decode(sb.toString());        //java层逆向解码
}

6.再使用还原还原,这里就是easy_apk那题的向算法:
[Java] 纯文本查看 复制代码
public void Base64Decode(String enflag) {
    StringBuilder flag = new StringBuilder();
    String flag_temp = "";
    for(int i = 0;i < enflag.length();i+=4)
    {
        String enf = enflag.substring(i,i+4);
        byte flag1 = (byte)(((getIndex(enf.charAt(0)) & 255) << 2 | ((getIndex(enf.charAt(1)) & 255) >>> 4)));
        byte flag2 = (byte)(((getIndex(enf.charAt(1)) & 255) << 4 | ((getIndex(enf.charAt(2)) & 255) >>> 2)));
        byte flag3 = (byte)(((getIndex(enf.charAt(2)) & 255) << 6 | ((getIndex(enf.charAt(3)) & 255))));

        flag_temp = "" + (char)flag1 + (char)flag2 + (char)flag3;
        flag.append(flag_temp);
    }
    System.out.println(flag);
}

public byte getIndex(char x)
{
    byte index = -1;
    String talbe = new String(AClass.a);
    if(x != '=') {
        index = (byte) talbe.indexOf(x);
    }
    else {
        index = 0;
    }
    return index;
}


最后打印结果:flag{just_ANot#er_@p3}

免费评分

参与人数 1威望 +1 吾爱币 +20 热心值 +1 收起 理由
qtfreet00 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

头像被屏蔽
xiaohuihui3 发表于 2021-9-30 10:26
提示: 作者被禁止或删除 内容自动屏蔽
Design 发表于 2021-9-30 10:31
 楼主| HNHuangJingYU 发表于 2021-9-30 10:38
Design 发表于 2021-9-30 10:31
大佬,你是咋修复jni 结构的

正常情况来说,如果是静态函数那么参数一是JNIEnv,参数二是jclass,参数三、四就是java传入的参数了,动态函数(JNIOnload)参数一就是JavaVm,参数二是jobject,参数三、四上同,明白了对应的参数类型用jni.h头文件进行转化就可以了
Design 发表于 2021-9-30 11:50
HNHuangJingYU 发表于 2021-9-30 10:38
正常情况来说,如果是静态函数那么参数一是JNIEnv,参数二是jclass,参数三、四就是java传入的参数了,动 ...

可以顺便上传样本吗
wantwill 发表于 2021-10-19 17:14
技术就是生产力呀
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 16:57

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表