wenwenjiang 发表于 2024-3-23 17:05

2024吾爱红包题逆向初级、中级难度复现

# 前言

过年的时候忘了,没打.......现在来复现复现 应该还是可以学到很多东西的
被and中级题搞到心态了

# Windows

## 【2024春节】初级题1

!(./../image/1710399685939-36.png)

找到输入的函数,flag的长度大概是36位

111111111111111111111111111111111111

直接动调出来了,flag在v7

!(./../image/1710399685930-1.png)

fl@g{H@ppy_N3w_e@r!2o24!Fighting!!!}

# Android

## 【2024春节】初级题1

难度不高,秒的题

!(./../image/1710399685931-2.png)

在吾爱经常玩的小猫游戏,当然可以直接玩通关,但是出于逆向,还是逆一下吧

!(./../image/1710399685931-3.png)

extractDataFromFile()方法就是游戏通关之后拿到的flag函数,是在后一个文件下进行检索 flag{ 字符然后输出到 } 字符,应该是上面的一个mp4的视频,flag应该在哪个文件十六进制的末尾处

!(./../image/1710399685931-4.png)

hook代码

```JavaScript
Java.perform(function () {
    var YSQDActivity = Java.use("com.zj.wuaipojie2024_1.YSQDActivity");
    var mmm = YSQDActivity.extractDataFromFile("/data/user/0/com.zj.wuaipojie2024_1/files/ys.mp4")
    console.log("返回结果是:",mmm)
});
```

getflag:flag{happy_new_year_2024}

## 【2024春节】初级题2

也是一个类似的游戏题,达成某种条件后就可以getflag 这种题有一个通解就跟windows端的keypatch一样修改代码逻辑、数值从而达到想要的效果。下面是题目原图.....原神含量好足(虽然没玩过

!(./../image/1710399685931-5.png)

简单分析一下函数的逻辑,反正就是真·保底......

!(./../image/1710399685931-6.png)

再看一下flag生成的部分:

!(./../image/1710399685931-7.png)

所以大体函数分析完成,之后就是如何getflag

1、可以直接去修改爆率或者判断的smile代码直接get flag 注意不要改签名信息就好

2、找到签名信息然后自己去异或 getflag

我就偏向于第一种吧,但是也先简单说说第二组。签名信息存储在main-inf的文件夹下的一个.rsa文件中,用ida查看16进制信息即可

!(./../image/1710399685931-8.png)

mt做法:

0x50对应的是80,也就是上面的概率(假概率)本来是从80开始减,直接改成0,相当于直接百分百得到flag

!(./../image/1710399685931-9.png)

在修改保存的时候一定不要自动签名,不然会改变签名信息导致flag错误

!(./../image/1710399685932-10.png)

可以关掉签名校验安装,当然直接安也没什么问题

!(./../image/1710399685932-11.png)

然后一次直接拿到flag,还是可以的

!(./../image/1710399685932-12.png)

另外看佬的wp,发现了可以直接运行指定的activity

```JavaScript
adb shell su -c am start-activity -n com.kbtx.redpack_simple/.FlagActivity
```

!(./../image/1710399685932-13.png)

直接弹flag的activity了,两个初级题同理直接秒了

## 【2024春节】中级题

打开apk运行一下,是一个类似于锁屏的一个控件

!(./../image/1710399685932-14.png)

!(./../image/1710399685932-15.png)

下面是正己师傅对于这段代码的详细解读,非常的详细

```Java
public boolean checkPassword(String str) {
    try {
      // 打开assets目录下的"classes.dex"文件作为InputStream
      InputStream open = getAssets().open("classes.dex");
      // 创建一个字节数组,大小为可读取的字节数,即整个文件的大小
      byte[] bArr = new byte;
      // 从InputStream中读取数据到字节数组中
      open.read(bArr);
      // 创建一个指向应用的内部目录("data"目录)中的"1.dex"文件的File对象
      File file = new File(getDir("data", 0), "1.dex");
      // 创建一个向该文件写入数据的FileOutputStream
      FileOutputStream fileOutputStream = new FileOutputStream(file);
      // 将字节数组bArr的内容写入到"1.dex"文件中
      fileOutputStream.write(bArr);
      // 关闭文件输出流
      fileOutputStream.close();
      // 关闭文件输入流
      open.close();
      // 使用DexClassLoader加载"1.dex"文件,并调用其中一个类的静态方法
      // "com.zj.wuaipojie2024_2.C"是类的全路径名
      // "isValidate"是方法名,它接收一个Context对象,一个String对象和一个int数组作为参数
      // 调用方法并传入当前Context(this),密码字符串str,以及一个从资源数组R.array.A_offset中获取的int数组
      String str2 = (String) new DexClassLoader(file.getAbsolutePath(),
                                                getDir("dex", 0).getAbsolutePath(),
                                                null,
                                                getClass().getClassLoader())
                                    .loadClass("com.zj.wuaipojie2024_2.C")
                                    .getDeclaredMethod("isValidate", Context.class, String.class, int[].class)
                                    .invoke(null, this, str, getResources().getIntArray(R.array.A_offset));
      // 检查返回的字符串是否为null或者不以"唉!"开头
      if (str2 == null || !str2.startsWith("唉!")) {
            // 如果是,则认为密码检查失败
            return false;
      }
      // 如果密码检查成功,则更新UI组件tvText的文本为返回的字符串,并将myunlock组件设为不可见
      this.tvText.setText(str2);
      this.myunlock.setVisibility(8);
      // 返回true表示密码检查成功
      return true;
    } catch (Exception e) {
      // 捕获到异常,打印异常堆栈信息,并返回false表示密码检查失败
      e.printStackTrace();
      return false;
    }
}

public static String isValidate(Context context, String str, int[] iArr) throws Exception {
    try {
      // 尝试从动态加载的DEX中获取并调用静态方法
      // getStaticMethod是一个自定义方法,用于根据给定参数动态获取特定的静态方法
      // 参数包括上下文(context),一个整型数组(iArr),类的全名("com.zj.wuaipojie2024_2.A"),方法名("d"),以及该方法的参数类型(Context.class, String.class)
      // 该方法预期返回一个Method对象,该对象代表了一个静态方法,可以被调用
      // invoke方法用于执行这个静态方法,传入的参数为null(因为是静态方法,所以不需要实例),上下文(context)和字符串(str)
      // 方法执行的结果被强制转换为String类型,并作为isValidate方法的返回值
      return (String) getStaticMethod(context, iArr, "com.zj.wuaipojie2024_2.A", "d", Context.class, String.class).invoke(null, context, str);
    } catch (Exception e) {
      // 如果在尝试获取或调用方法时发生异常,记录错误信息到日志,并打印堆栈跟踪
      Log.e(TAG, "咦,似乎是坏掉的dex呢!");
      e.printStackTrace();
      // 出现异常时,方法返回一个空字符串
      return "";
    }
}
private static Method getStaticMethod(Context context, int[] iArr, String str, String str2, Class<?>... clsArr) throws Exception {
    try {
      // read方法用于读取原始DEX文件,然后fix方法根据提供的iArr参数和上下文来处理数据。
      File fix = fix(read(context), iArr, iArr, iArr, context);

      // 获取应用的当前类加载器
      ClassLoader classLoader = context.getClass().getClassLoader();

      // 获取或创建一个名为"fixed"的目录,用于存放处理过的DEX文件
      File dir = context.getDir("fixed", 0);

      // 使用DexClassLoader动态加载修复后的DEX文件。
      // fix.getAbsolutePath()是DEX文件的路径,dir.getAbsolutePath()是优化后的DEX文件存放路径。
      // null是父类加载器,classLoader是应用的当前类加载器,作为新的类加载器的父加载器。
      Method declaredMethod = new DexClassLoader(fix.getAbsolutePath(), dir.getAbsolutePath(), null, classLoader)
                              .loadClass(str) // 加载指定的类
                              .getDeclaredMethod(str2, clsArr); // 获取指定的方法

      // 删除处理过的DEX文件和其在"fixed"目录下的优化版本,以清理临时文件
      fix.delete();
      new File(dir, fix.getName()).delete();

      // 返回找到的Method对象
      return declaredMethod;
    } catch (Exception e) {
      // 如果过程中发生任何异常,打印堆栈跟踪并返回null
      e.printStackTrace();
      return null;
    }
}
private static File fix(ByteBuffer byteBuffer, int i, int i2, int i3, Context context) throws Exception {
    try {
      // 获取或创建应用内"data"目录
      File dir = context.getDir("data", 0);
      // 使用自定义的D.getClassDefData方法获取类定义数据,然后从返回的HashMap中获取"class_data_off"的值
      int intValue = D.getClassDefData(byteBuffer, i).get("class_data_off").intValue();
      // 获取类数据,并根据给定的索引修改指定的直接方法的访问标志
      //已知i2是3,也就意味着访问的是直接方法列表中的第四个方法(因为数组索引是从0开始的)
      //i3则是方法的偏移,注意要转换成ULEB128格式
      HashMap<String, int[][]> classData = D.getClassData(byteBuffer, intValue);
      classData.get("direct_methods") = i3;
      // 使用自定义的D.encodeClassData方法将修改后的类数据编码回字节数组
      byte[] encodeClassData = D.encodeClassData(classData);
      // 将ByteBuffer的位置设置到类数据偏移处,并将修改后的类数据写回ByteBuffer
      byteBuffer.position(intValue);
      byteBuffer.put(encodeClassData);
      // 设置ByteBuffer的位置到32,从这个位置开始读取数据,用于SHA-1哈希计算
      byteBuffer.position(32);
      byte[] bArr = new byte;
      byteBuffer.get(bArr);
      // 使用自定义的Utils.getSha1方法计算数据的SHA-1哈希
      byte[] sha1 = Utils.getSha1(bArr);
      // 将ByteBuffer的位置设置到12,并将计算出的SHA-1哈希写入ByteBuffer
      byteBuffer.position(12);
      byteBuffer.put(sha1);
      // 使用自定义的Utils.checksum方法计算校验和
      int checksum = Utils.checksum(byteBuffer);
      // 将ByteBuffer的位置设置到8,并将校验和写入ByteBuffer(注意校验和的字节顺序被反转以符合DEX文件格式)
      byteBuffer.position(8);
      byteBuffer.putInt(Integer.reverseBytes(checksum));
      // 获取ByteBuffer中的字节数组
      byte[] array = byteBuffer.array();
      // 创建一个新的DEX文件,并将修改后的数据写入该文件
      File file = new File(dir, "2.dex");
      FileOutputStream fileOutputStream = new FileOutputStream(file);
      fileOutputStream.write(array);
      fileOutputStream.close();
      // 返回新创建的DEX文件
      return file;
    } catch (Exception e) {
      // 在发生异常时打印堆栈跟踪并返回null
      e.printStackTrace();
      return null;
    }
}
修复后的代码:
public static String d(Context context, String str) {
    MainActivity.sSS(str);//frida检测
    String signInfo = Utils.getSignInfo(context);//签名校验
    if (signInfo == null || !signInfo.equals("fe4f4cec5de8e8cf2fca60a4e61f67bcd3036117")) {
      return "";
    }
      //输入的字符串与运算后的048531267进行对比
    StringBuffer stringBuffer = new StringBuffer();
    int i = 0;
    while (stringBuffer.length() < 9 && i < 40) {
      int i2 = i + 1;
      String substring = "0485312670fb07047ebd2f19b91e1c5f".substring(i, i2);
      if (!stringBuffer.toString().contains(substring)) {
            stringBuffer.append(substring);
      }
      i = i2;
    }

    return !str.equals(stringBuffer.toString().toUpperCase()) ? "" : "唉!哪有什么亿载沉睡的玄天帝,不过是一位被诅咒束缚的旧日之尊,在灯枯之际挣扎的南柯一梦罢了。有缘人,这份机缘就赠予你了。坐标在B.d";
}
public static String d(String str) {
    return "机缘是{" + Utils.md5(Utils.getSha1("password+你的uid".getBytes())) + "}";
}
```

函数大致逻辑如下: 首先加载组件,然后根据组件的密码正确与否,进行一个判断

如果正确的话那就只输出,没啥用 如果错误的话,那就会运行checkPassword()方法

checkPassword方法首先会使用classes.dex生成一个1.dex

使用DexClassLoader方法去调取1.dex里面的方法

显示dex损坏或读取不到dex 自主修复1.dex,然后命名为2.dex

根据修复后的代码,修复B.d

Getflag

大致的函数过程如此,要想解决这个问题第一步还是修复dex

!(./../image/1710399685932-16.png)

拖进010直接爆红,说明是文件头错误的dex,可以使用np修复,mt会修复全部的dex信息所以不太行

或者直接使用(https://github.com/luoyesiqiu/DexRepair)

java -jar DexRepair.jar /path/to/dex

!(./../image/1710399685932-17.png)

修复好了之后再压入到软件里面,最好是不要改变签名信息

!(./../image/1710399685932-18.png)

修复了之后就可以正常走程序流程了,但是我怎么hook都报错

!(./../image/1710399685933-19.png)

看报错貌似在so层有点问题

!(./../image/1710399685933-20.png)

一直hook不到

!(./../image/1710399685933-21.png)

!(./../image/1710399685933-22.png)

好好好,原来是在so层加了frida检测

!(./../image/1710399685933-23.png)

怪不得会有这个,自己找了找so,除此之外没找到什么so的作用,所以直接干脆不让他导入这个so得了 把这个so层的导入函数改成本地的空函数就行

!(./../image/1710399685933-24.png)

!(./../image/1710399685933-25.png)

变成了本地的空函数了,就不会再进行frida检测了

能hook上的(虽然但是...........捣鼓半天后用一个全新的附件来hook怎么也能hook上...........难道根本没调用吗?????逆天

算了无所谓,不去管了

!(./../image/1710399685933-26.png)

现在的问题重点在于他在生成了1.dex后又删除了,所以我也想通过mt来删掉这个函数,mt删掉这两个参数

!(./../image/1710399685933-27.png)

!(./../image/1710399685933-28.png)

原来是读取文件.....就离谱 刚刚记得生成的是1.dex,但是这里是decode.dex,很明显读取不到 因为我没有装as(在虚拟机里,but虚拟机寄了)如果装了as那么就可以直接查看日志信息了 再去mt里面改改导入的dex名字

!(./../image/1710399685933-29.png)

顺便把删除生成1.dex的方法给删掉

!(./../image/1710399685933-30.png)

然后运行一下apk程序,果然他俩没有被删,先看看1在了什么

!(./../image/1710399685934-31.png)

不用看了,搞不出来,好像题目一直有异常,都给我搞得怀疑人生了。。。。。

bmk佬说是题目附件的问题(真不知道是怎么一直触发异常的 于是借鉴了and_1师傅的思路-复现加密

以上可以忽略不看,是我个人的一些试错记录,我真不是水(bushi

### 复现加密

在idea单独起一个项目,用来复现加密流程,idea路径大致如下:

!(./../image/1710399685934-32.png)

!(./../image/1710399685934-33.png)

以下是代码:

```Java
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.util.HashMap;

public class Main {

    private static File fix(ByteBuffer byteBuffer, int v, int v1, int v2) throws Exception {
      File file = new File("./data");
      int classDataOffset = (int) (((Integer) D.getClassDefData(byteBuffer, v).get("class_data_off")));
      HashMap<String, int[][]> classData = D.getClassData(byteBuffer, classDataOffset);
      classData.get("direct_methods") = v2;
      byte[] encodedClassData = D.encodeClassData(classData);
      byteBuffer.position(classDataOffset);
      byteBuffer.put(encodedClassData);
      byteBuffer.position(0x20);
      byte[] data = new byte;
      byteBuffer.get(data);
      byte[] sha1 = Utils.getSha1(data);
      byteBuffer.position(12);
      byteBuffer.put(sha1);
      int checksum = Utils.checksum(byteBuffer);
      byteBuffer.position(8);
      byteBuffer.putInt(Integer.reverseBytes(checksum));
      byte[] bufferData = byteBuffer.array();
      File outputFile = new File(file, "2.dex");
      FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
      fileOutputStream.write(bufferData);
      fileOutputStream.close();
      return outputFile;
    }

    private static ByteBuffer readDex() {
      try {
            File inputFile = new File("./data/1.dex");
            if (!inputFile.exists()) {
                System.out.printf("File does not exist.");
                return null;
            }

            FileInputStream fileInputStream = new FileInputStream(inputFile);
            byte[] data = new byte;
            fileInputStream.read(data);
            ByteBuffer byteBuffer = ByteBuffer.wrap(data);
            fileInputStream.close();
            System.out.printf("\n File read successfully.");
            return byteBuffer;
      } catch (Exception ex) {
            return null;
      }
    }

    public static void main(String[] args) throws Exception {
      ByteBuffer buf = readDex();
      byte byteValue = buf.get(); // 读取一个字节
      char charValue = (char) byteValue;
      System.out.printf("%c", charValue);
      byteValue = buf.get(); //
      charValue = (char) byteValue;
      System.out.printf("%c", charValue);
      byteValue = buf.get(); //
      charValue = (char) byteValue;
      System.out.printf("%c", charValue);
      //key =
      //key =

      File fixed = fix(buf, 0, 3, 7908);
    }
}
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;

/* loaded from: assets/classes.dex */
public class Utils {
    public static final String SHA1 = "SHA1";

    public static byte[] toULEB128(int i) {
      int i2 = i >> 28;
      if (i2 > 0) {
            return new byte[]{(byte) ((i & 127) | 128), (byte) (((i >> 7) & 127) | 128), (byte) (((i >> 14) & 127) | 128), (byte) (((i >> 21) & 127) | 128), (byte) (i2 & 15)};
      }
      int i3 = i >> 21;
      if (i3 > 0) {
            return new byte[]{(byte) ((i & 127) | 128), (byte) (((i >> 7) & 127) | 128), (byte) (((i >> 14) & 127) | 128), (byte) (i3 & 127)};
      }
      int i4 = i >> 14;
      if (i4 > 0) {
            return new byte[]{(byte) ((i & 127) | 128), (byte) (((i >> 7) & 127) | 128), (byte) (i4 & 127)};
      }
      int i5 = i >> 7;
      return i5 > 0 ? new byte[]{(byte) ((i & 127) | 128), (byte) (i5 & 127)} : new byte[]{(byte) (i & 127)};
    }

    public static byte[] getSha1(byte[] bArr) {
      try {
            return MessageDigest.getInstance("SHA").digest(bArr);
      } catch (Exception unused) {
            return null;
      }
    }

    public static String md5(byte[] bArr) {
      try {
            String bigInteger = new BigInteger(1, MessageDigest.getInstance("md5").digest(bArr)).toString(16);
            for (int i = 0; i < 32 - bigInteger.length(); i++) {
                bigInteger = "0" + bigInteger;
            }
            return bigInteger;
      } catch (NoSuchAlgorithmException unused) {
            throw new RuntimeException("ops!!");
      }
    }

    public static int checksum(ByteBuffer byteBuffer) {
      byteBuffer.position(12);
      int capacity = byteBuffer.capacity();
      int i = 1;
      int i2 = 0;
      boolean z = false;
      while (byteBuffer.position() < capacity) {
            ArrayList arrayList = new ArrayList();
            int i3 = 0;
            while (true) {
                if (i3 < 1024) {
                  arrayList.add(Integer.valueOf(byteBuffer.get() & 255));
                  if (byteBuffer.position() == byteBuffer.limit()) {
                        z = true;
                        break;
                  }
                  i3++;
                } else {
                  break;
                }
            }
            int[] calculateVar = calculateVar(arrayList, i, i2);
            int i4 = calculateVar;
            int i5 = calculateVar;
            if (z) {
                return (i5 << 16) + i4;
            }
            i2 = i5;
            i = i4;
      }
      return 0;
    }

    private static int[] calculateVar(ArrayList<Integer> arrayList, int i, int i2) {
      int i3 = 0;
      while (i3 < arrayList.size()) {
            int intValue = (arrayList.get(i3).intValue() + i) % 65521;
            i2 = (i2 + intValue) % 65521;
            i3++;
            i = intValue;
      }
      return new int[]{i, i2};
    }


    public static int[] fromULEB128(ByteBuffer byteBuffer) {
      int i;
      int i2 = byteBuffer.get() & 255;
      if (i2 > 127) {
            int i3 = byteBuffer.get() & 255;
            i2 = (i2 & 127) | ((i3 & 127) << 7);
            if (i3 > 127) {
                int i4 = byteBuffer.get() & 255;
                i2 |= (i4 & 127) << 14;
                if (i4 > 127) {
                  int i5 = byteBuffer.get() & 255;
                  i2 |= (i5 & 127) << 21;
                  if (i5 > 127) {
                        i2 |= (byteBuffer.get() & 255) << 28;
                        i = 5;
                  } else {
                        i = 4;
                  }
                } else {
                  i = 3;
                }
            } else {
                i = 2;
            }
      } else {
            i = 1;
      }
      return new int[]{i2, i};
    }
}
import java.nio.ByteBuffer;
import java.util.HashMap;

public class D {
    private static byte[] decode_field(int[] arr_v, int v) {
      int v1 = arr_v - v;
      int v2 = arr_v;
      return D.merge(new byte[][]{Utils.toULEB128(v1), Utils.toULEB128(v2)});
    }

    private static byte[] decode_method(int[] arr_v, int v) {
      int v1 = arr_v - v;
      int v2 = arr_v;
      int v3 = arr_v;
      return D.merge(new byte[][]{Utils.toULEB128(v1), Utils.toULEB128(v2), Utils.toULEB128(v3)});
    }

    public static byte[] encodeClassData(HashMap hashMap0) {
      int[][] arr2_v = (int[][])hashMap0.get("static_fields");
      int[][] arr2_v1 = (int[][])hashMap0.get("instance_fields");
      int[][] arr2_v2 = (int[][])hashMap0.get("direct_methods");
      int[][] arr2_v3 = (int[][])hashMap0.get("virtual_methods");
      byte[] arr_b = D.merge(new byte[][]{Utils.toULEB128(arr2_v.length), Utils.toULEB128(arr2_v1.length), Utils.toULEB128(arr2_v2.length), Utils.toULEB128(arr2_v3.length)});
      if(arr2_v.length > 0) {
            int v = 0;
            int v1 = 0;
            while(v < arr2_v.length) {
                int[] arr_v = arr2_v;
                arr_b = D.merge(new byte[][]{arr_b, D.decode_field(arr_v, v1)});
                v1 = arr_v;
                ++v;
            }
      }

      if(arr2_v1.length > 0) {
            int v2 = 0;
            int v3 = 0;
            while(v2 < arr2_v1.length) {
                int[] arr_v1 = arr2_v1;
                arr_b = D.merge(new byte[][]{arr_b, D.decode_field(arr_v1, v3)});
                v3 = arr_v1;
                ++v2;
            }
      }

      if(arr2_v2.length > 0) {
            int v4 = 0;
            int v5 = 0;
            while(v4 < arr2_v2.length) {
                int[] arr_v2 = arr2_v2;
                arr_b = D.merge(new byte[][]{arr_b, D.decode_method(arr_v2, v5)});
                v5 = arr_v2;
                ++v4;
            }
      }

      if(arr2_v3.length > 0) {
            int v6 = 0;
            int v7 = 0;
            while(v6 < arr2_v3.length) {
                int[] arr_v3 = arr2_v3;
                arr_b = D.merge(new byte[][]{arr_b, D.decode_method(arr_v3, v7)});
                v7 = arr_v3;
                ++v6;
            }
      }

      return arr_b;
    }

    private static int[] encode_field(ByteBuffer byteBuffer0) {
      return new int[]{Utils.fromULEB128(byteBuffer0), Utils.fromULEB128(byteBuffer0)};
    }

    private static int[] encode_method(ByteBuffer byteBuffer0) {
      return new int[]{Utils.fromULEB128(byteBuffer0), Utils.fromULEB128(byteBuffer0), Utils.fromULEB128(byteBuffer0)};
    }

    public static HashMap getClassData(ByteBuffer byteBuffer0, int v) {
      byteBuffer0.position(v);
      int v1 = Utils.fromULEB128(byteBuffer0);
      int v2 = Utils.fromULEB128(byteBuffer0);
      int v3 = Utils.fromULEB128(byteBuffer0);
      int v4 = Utils.fromULEB128(byteBuffer0);
      int[][] arr2_v = new int;
      if(v1 > 0) {
            int v5 = 0;
            int v6 = 0;
            while(v5 < v1) {
                int[] arr_v = D.encode_field(byteBuffer0);
                v6 = v5 == 0 ? arr_v : v6 + arr_v;
                arr2_v = new int[]{v6, arr_v};
                ++v5;
            }
      }

      int[][] arr2_v1 = new int;
      if(v2 > 0) {
            int v7 = 0;
            int v8 = 0;
            while(v7 < v2) {
                int[] arr_v1 = D.encode_field(byteBuffer0);
                v8 = v7 == 0 ? arr_v1 : v8 + arr_v1;
                arr2_v1 = new int[]{v8, arr_v1};
                ++v7;
            }
      }

      int[][] arr2_v2 = new int;
      if(v3 > 0) {
            int v9 = 0;
            int v10 = 0;
            while(v9 < v3) {
                int[] arr_v2 = D.encode_method(byteBuffer0);
                v10 = v9 == 0 ? arr_v2 : v10 + arr_v2;
                arr2_v2 = new int[]{v10, arr_v2, arr_v2};
                ++v9;
            }
      }

      int[][] arr2_v3 = new int;
      if(v4 > 0) {
            int v11 = 0;
            int v12 = 0;
            while(v11 < v2) {
                int[] arr_v3 = D.encode_method(byteBuffer0);
                v12 = v11 == 0 ? arr_v3 : v12 + arr_v3;
                arr2_v3 = new int[]{v12, arr_v3, arr_v3};
                ++v11;
            }
      }

      HashMap hashMap0 = new HashMap();
      hashMap0.put("static_fields", arr2_v);
      hashMap0.put("instance_fields", arr2_v1);
      hashMap0.put("direct_methods", arr2_v2);
      hashMap0.put("virtual_methods", arr2_v3);
      return hashMap0;
    }

    public static HashMap getClassDefData(ByteBuffer byteBuffer0, int v) {
      if(byteBuffer0 != null) {
            byteBuffer0.position(100);
            byteBuffer0.position(v * 0x20 + Integer.reverseBytes(byteBuffer0.getInt()));
            HashMap hashMap0 = new HashMap();
            int v1 = Integer.reverseBytes(byteBuffer0.getInt());
            int v2 = Integer.reverseBytes(byteBuffer0.getInt());
            int v3 = Integer.reverseBytes(byteBuffer0.getInt());
            int v4 = Integer.reverseBytes(byteBuffer0.getInt());
            int v5 = Integer.reverseBytes(byteBuffer0.getInt());
            int v6 = Integer.reverseBytes(byteBuffer0.getInt());
            int v7 = Integer.reverseBytes(byteBuffer0.getInt());
            int v8 = Integer.reverseBytes(byteBuffer0.getInt());
            hashMap0.put("class_idx", Integer.valueOf(v1));
            hashMap0.put("access_flag", Integer.valueOf(v2));
            hashMap0.put("superclass_idx", Integer.valueOf(v3));
            hashMap0.put("interfaces_off", Integer.valueOf(v4));
            hashMap0.put("source_file_idx", Integer.valueOf(v5));
            hashMap0.put("annotation_off", Integer.valueOf(v6));
            hashMap0.put("class_data_off", Integer.valueOf(v7));
            hashMap0.put("static_values_off", Integer.valueOf(v8));
            return hashMap0;
      }

      throw new IllegalArgumentException("Buffer cannot be null");
    }

    private static byte[] merge(byte[][] arr2_b) {
      int v = 0;
      int v1 = 0;
      while(v < arr2_b.length) {
            v1 += arr2_b.length;
            ++v;
      }

      ByteBuffer byteBuffer0 = ByteBuffer.allocate(v1);
      int v2;
      for(v2 = 0; v2 < arr2_b.length; ++v2) {
            byteBuffer0.put(arr2_b);
      }

      byte[] arr_b = new byte;
      byteBuffer0.position(0);
      byteBuffer0.get(arr_b);
      return arr_b;
    }
}
```

(其实都是从安卓复制过来的然后修修报错能运行就问题不大了

!(./../image/1710399685934-34.png)

最后也是终于获得了机缘

!(./../image/1710399685934-35.png)

Hmily 发表于 2024-3-25 17:53

@wenwenjiang 把图片上传到论坛本地吧,版主已经加优秀鼓励了,不然我们也没法制作精华集,大家也无法阅读,尽快修改一下。

正己 发表于 2024-3-24 21:09

不知道是不是我的原因,我这图片都加载不出来

duso 发表于 2024-3-24 22:22

学习一下,感谢分享!!

erichyx 发表于 2024-3-24 22:50

图片都挂了

jujiaomubiao 发表于 2024-3-24 23:49

像大神学习,谢谢分享!

zjh889 发表于 2024-3-25 00:06

这东西很不错,谢谢大师!

cfantv 发表于 2024-3-25 00:16

牛逼呀,看来我需要学习的还很多

爱飞的猫 发表于 2024-3-25 07:56

正己 发表于 2024-3-24 21:09
不知道是不是我的原因,我这图片都加载不出来

图片地址都是本地文件的相对路径,没有作为附件上传到论坛/图床。

StackNoOverflow 发表于 2024-3-25 09:37

麻烦重新上传一下图片吧,访问不到了

cs_sunsky 发表于 2024-3-25 17:20

我这图片都加载不出来
页: [1] 2 3
查看完整版本: 2024吾爱红包题逆向初级、中级难度复现