Python调用加密算法的方式

Java层加密

  1. 将加密的java代码复制粘贴出来到自己写的java文件中,这里假设java文件为Sign.java
  2. 新建一个manifest.txt文件,文件内容Main-Class: Sign
  3. 使用以下代码将java文件打包成jar包
    1. javac Sign.java
    2. jar cvf Sign.jar Sign.class
  4. python使用subprocess.run(['java', '-cp', '.;', '包名', '参数'], capture_output=True, text=True)调用

So层加密

使用unidbg工具。在unidbg-android/src/main/java/com下新建文件。

以下为示例代码

package com.yuanrenxue.match2022.fragment.challenge;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.memory.MemoryBlock;
import com.github.unidbg.pointer.UnidbgPointer;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ChallengeEightFragment {
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;
    private final DvmClass ChallengeEightFragment;
    private final boolean logging;

    public ChallengeEightFragment(boolean logging) {
        this.logging = logging;
        emulator = AndroidEmulatorBuilder.for64Bit().setProcessName("com.yuanrenxue.match2022").build();
        final Memory memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23));
        /*
            创建DalvikVM,可以载入apk,也可以为null
            vm = emulator.createDalvikVM(new File("yuanrenxuem1010.apk"));
            vm = emulator.createDalvikVM((File) null);
        */
        vm = emulator.createDalvikVM((File) null);
        vm.setVerbose(logging);

        /*
            载入要执行的 so,可以是本地so文件,也能是apk中的so文件
            DalvikModule dm = vm.loadLibrary(new File("libmatch08.so"), false);
            DalvikModule dm = vm.loadLibrary("match08", true);
        */
        DalvikModule dm = vm.loadLibrary(new File("libmatch08.so"), false);
        dm.callJNI_OnLoad(emulator);
        module = dm.getModule();
        ChallengeEightFragment = vm.resolveClass("com/yuanrenxue/match2022/fragment/challenge/ChallengeEightFragment");
    }

    public void destroy() throws IOException {
        emulator.close();
    }

    public static void main(String[] args) throws Exception {
        ChallengeEightFragment challengeEightFragment = new ChallengeEightFragment(true);
        System.out.println(challengeEightFragment.getData(2));
        challengeEightFragment.destroy();
    }

    /*
       使用方法名称调用so文件内的方法
    */
    public String getData(int page) {
        StringObject data = ChallengeEightFragment.newObject(null).callJniMethodObject(
                emulator,
                "data(I)Ljava/lang/String;",
                page
        );
        return data.getValue();
    }

    /*
       使用地址调用,并传参数
    */
    public String getDeviceId() {
        /*
            第一个参数是随机值
            第二个参数是时间戳加mac地址
            第三个参数是第二个参数的长度
        */
        String arg1 = "C5A6D4F9B38E0721";
        String arg2 = System.currentTimeMillis() + "$E6:CA:E3:4D:6A:08";
        int arg3 = arg2.getBytes().length;
        /*
            emulator.getMemory().malloc(size, isZeroInitialized);
            在模拟器(‌emulator)‌的内存中分配一个新的内存块,并设置其大小和初始化是否为0.

            emulator.getMemory() 获取模拟器的内存操作接口
            .malloc(size, isZeroInitialized):‌是一个内存分配方法,‌其中size指定了要分配的内存块的大小,‌isZeroInitialized指定了是否将分配的内存初始化为零。‌

            UnidbgPointer input_ptr1 = memoryBlock1.getPointer(); 从memoryBlock1内存块中获取一个指针input_ptr1
            input_ptr1.write(arg1.getBytes());将arg1字符串的字节数据写入到input_ptr1指针所指向的内存地址中。‌
        */
        MemoryBlock memoryBlock1 = emulator.getMemory().malloc(arg1.getBytes().length, false);
        UnidbgPointer input_ptr1 = memoryBlock1.getPointer();
        input_ptr1.write(arg1.getBytes());

        MemoryBlock memoryBlock2 = emulator.getMemory().malloc(arg3, false);
        UnidbgPointer input_ptr2 = memoryBlock2.getPointer();
        input_ptr2.write(arg2.getBytes());

        MemoryBlock memoryBlock3 = emulator.getMemory().malloc(32, false);
        UnidbgPointer output_buffer = memoryBlock3.getPointer();

        /*
            在so文件中0x49E68方法需要传入4个参数,
            以下代码将4个参数都添加到数组中,并实现传递
        */
        List<Object> list1 = new ArrayList<>();
        list1.add(input_ptr1);
        list1.add(input_ptr2);
        list1.add(arg3);
        list1.add(output_buffer);
        module.callFunction(emulator, 0x49E68, list1.toArray());
//        System.out.println("结果存放地址:" + output_buffer);
//        Inspector.inspect(output_buffer.getByteArray(0, 32), "output");
        return byte2HexString(output_buffer.getByteArray(0, 32)) + arg1;
    }

    public static String byte2HexString(byte[] b) {
        String r = "";
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            r += hex.toUpperCase();
        }
        return r;
    }


}

调试好代码后使用IDEA将代码打包成jar包给python调用

  1. 点击 File–Project Structure–Artifacts
  2. 点击 添加–JAR–From Modules
  3. Module选择unidbg-android
  4. Main Class选择你写的java文件
  5. 选择 extract to the target JAR
  6. 点击OK
  7. 记住Output directory地址,这是文件输出目录
  8. 再次点击OK
  9. 点击 Bulid–Bulid Artifacts–Bulid

python代码调用 pip install JPype1

import jpype
# path后面是导出的jar包
jpype.startJVM(jpype.getDefaultJVMPath(), "-ea", "-Djava.class.path=./unidbg-android.jar")
# JPackage的参数为java文件顶部的package。后面解类名
jclass = jpype.JPackage("com.yuanrenxue.match2022.fragment.challenge").ChallengeEightFragment
encrypt = jclass(False)
# 使用.方法名(参数)的方式进行调用
print(encrypt.getData(1))

上一篇
下一篇