2021-3-8 攻防世界 easyJNI

首先拿到apk,直接反编译,看看逻辑(别问我为什么不跑一下,跑了能有思路?)在这里插入图片描述
两个函数,一个是主函数,另一个估计是加密函数,看看其逻辑,大致意思输入一个数,然后一系类操作后返回一个true就是对了。那么看看他的加密逻辑。
好的不愧是easyJNI,有一部分加密在SO文件里面,这里先不急先看看java代码在这里插入图片描述
大致意思是,输入的代码,进入a函数去跑。恕我直言这个加密代码我不会,但是一看这个码表是人都觉得是base64 ,既然如此,手撸(网上抄的)base64解密,然后改一下码表就好了。
出于好心,这里贴出来代码

package zhiyuanhui.util;

import java.util.List;
import java.util.ArrayList;
public class Base64 {

   // private static String base64Code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    private static String base64Code = String.valueOf(new char[]{'i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c', 'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k', 'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V', 'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a', 'J', 'R', 'Z', 'N'});

    public static void main(String[] args) {
        System.out.println(encode("Base64"));
        System.out.println(decode("QmFzZTY0"));
    }

    public static String encode(String srcData) {
        if(srcData == null && srcData.length() == 0) {
            return srcData;
        }
        char[] chArr = srcData.toCharArray();
        String asciiBin = null;
        StringBuilder asciiBin_all = new StringBuilder();
        for(int i= 0; i< chArr.length; i++) {
            //将字符转换成ASCII编码再转换成对应二进位
            asciiBin = Integer.toBinaryString((int)chArr[i]);
            //给不足8位的在高位补0直到补足8位
            while(asciiBin.length()< 8) {
                asciiBin= "0"+ asciiBin;
            }
            //最后把所有二进位拼接成一个字串
            asciiBin_all.append(asciiBin);
        }
        //若长度不能被6整除,则在低位补0到能被6整除为止
        while(asciiBin_all.length()% 6!= 0) {
            asciiBin_all.append("0");
        }
        String asciiBinStr = asciiBin_all.toString();
        //按6个一组拆分成字串数组
        List<String> bin6List = new ArrayList<String>();
        String temp = null;
        while(asciiBinStr.length()/ 6> 0) {
            temp = asciiBinStr.substring(0, 6);
            asciiBinStr = asciiBinStr.substring(6);
            bin6List.add(temp);
        }
        String[] bin6Str = bin6List.toArray(new String[bin6List.size()]);
        int[] index = new int[bin6Str.length];
        //确定最终补位长度
        int overLen = 0;
        if(srcData.length()% 3 != 0) {
            overLen = 3- srcData.length()% 3;
        }
        //设定存放最终编码的容器
        char[] code = new char[index.length+ overLen];
        for(int i= 0; i< index.length; i++) {
            //将二进位转换成十进制数字
            index[i] = Integer.parseInt(bin6Str[i], 2);
            //Base64 : Value -> Encoding
            code[i] = base64Code.charAt(index[i]);
        }
        switch(overLen) {
            case 2:code[code.length- 2] = '=';//不需要break
            case 1:code[code.length- 1] = '=';
            default:
        }
        return String.valueOf(code);
    }

    public static String decode(String srcData) {
        //检测元数据中“=”的个数,并将之去除
        int counter = 0;
        if(srcData.contains("=")) {
            counter = 1;
            if(srcData.substring(srcData.length()- 2, srcData.length()- 1).equals("=")) {
                counter = 2;
            }
        }
        srcData = srcData.replaceAll("=", "");
        //将密文根据Base64编码表转换成对应Value,再转换成二进位 ,然后将所有二进位补足6位,最后将所有二进位存进一个字串
        char[] srcCh = srcData.toCharArray();
        StringBuffer bin6SB = new StringBuffer();
        int index;
        String bin6Str;
        for(int i= 0; i< srcCh.length; i++) {
            //获得Base64编码表的Value
            index = base64Code.indexOf(srcCh[i]);
            //将Value转为二进位
            bin6Str = Integer.toBinaryString(index);
            //在长度不足6位的二进位的高位上补0直到补足6位,再保存进字串
            while(bin6Str.length()< 6) {
                bin6Str = "0"+ bin6Str;
            }
            bin6SB.append(bin6Str);
        }
        String bin6Str_all = bin6SB.toString();
        //如果二进位字串后有多补的0,将之去除
        if(counter == 1) {
            bin6Str_all = bin6Str_all.substring(0, bin6Str_all.length()- 2);
        } else if(counter == 2) {
            bin6Str_all = bin6Str_all.substring(0, bin6Str_all.length()- 4);
        }
        //按8个一组拆分成字串数组
        List<String> bin8List = new ArrayList<String>();
        String temp;
        while(bin6Str_all.length()/ 6> 0) {
            temp = bin6Str_all.substring(0, 8);
            bin6Str_all = bin6Str_all.substring(8);
            bin8List.add(temp);
        }
        String[] bin8Str = bin8List.toArray(new String[bin8List.size()]);
        //将该字串数组的每个元素(即一组二进位)转成十进制数,再强制转换成char类型
        char[] ascii = new char[bin8Str.length];
        for(int i= 0; i< ascii.length; i++) {
            ascii[i] = (char)Integer.parseInt(bin8Str[i], 2);
        }
        return String.valueOf(ascii);
    }

已经有了解码了,接下来看看ncheck函数里面是啥,打开ida 反编译下so文件
在这里插入图片描述
得到如下代码

signed int __fastcall Java_com_a_easyjni_MainActivity_ncheck(int a1, int a2, int a3)
{
  int v3; // r8
  int v4; // r5
  int v5; // r8
  const char *v6; // r6
  int v7; // r0
  char *v8; // r2
  char v9; // r1
  int v10; // 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;
  v4 = a1;
  v5 = a3;
  v6 = (const char *)(*(int (__fastcall **)(int, int, _DWORD))(*(_DWORD *)a1 + 676))(a1, a3, 0);
  if ( strlen(v6) == 32 )
  {
    v7 = 0;
    do
    {
      v8 = &s1[v7];
      s1[v7] = v6[v7 + 16];
      v9 = v6[v7++];
      v8[16] = v9;
    }
    while ( v7 != 16 );
    (*(void (__fastcall **)(int, int, const char *))(*(_DWORD *)v4 + 680))(v4, v5, v6);
    v10 = 0;
    do
    {
      v12 = __OFSUB__(v10, 30);
      v11 = v10 - 30 < 0;
      v16 = s1[v10];
      s1[v10] = s1[v10 + 1];
      s1[v10 + 1] = v16;
      v10 += 2;
    }
    while ( v11 ^ v12 );
    v13 = memcmp(s1, "MbT3sQgX039i3g==AQOoMQFPskB1Bsc7", 0x20u);
    result = 0;
    if ( !v13 )
      result = 1;
  }
  else
  {
    (*(void (__fastcall **)(int, int, const char *))(*(_DWORD *)v4 + 680))(v4, v5, v6);
    result = 0;
  }
  return result;
}

可以的这C语言我看不懂,能看到的画面是说他32位中前16和后16换位置,接下来就蒙了,去看看人家的wp把,大致意思就是换位,然后更改他们的奇偶数的顺序。(OK 白嫖了人家的二段加密)
对MbT3sQgX039i3gAQOoMQFPskB1Bsc7进行解密(懂了逻辑还要看别人代码,我手撸解密),然后得到QAoOQMPFks1BsB7cbM3TQsXg30i9g3
进行解密
在这里插入图片描述

flag{just_ANot#er_@p3}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值