开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 2050|回复: 3
收起左侧

[图文资料] nice app 算法逆向到还原(从 unidbg到算法还原)

[复制链接]
结帖率:100% (38/38)
发表于 2023-7-12 21:04:30 | 显示全部楼层 |阅读模式   江西省赣州市

上一个帖子  https://bbs.125.la/forum.php?mod=viewthread&tid=14788236&extra=  分享了算法 这个帖子分享一下怎么还原的


IDA 反编译so文件导出函数地址

Name Addres
Java_com_nice_main_helpers_utils_NiceSignUtils_getSignRequest 0000000000001D20
Java_com_nice_main_helpers_utils_NiceSignUtils_getSignCode 0000000000001F9C

app主要代码

package com.nice.main.helpers.utils;

import java.nio.charset.StandardCharsets;

/* loaded from: classes4.dex */
public class NiceSignUtils {
    static {
        try {
            System.loadLibrary("salt");
        } catch (Throwable th) {
            th.printStackTrace();
        }
    }

    private static boolean a(byte[] bArr) {
        return bArr != null && bArr.length > 0;
    }

    public static synchronized String b(String str, String str2, String str3, String str4) {
       //  省略部分代码
            if (a(bArr2) && a(bArr) && a(bArr3)) {
                String str52 = "";
                str52 = getSignRequest(str2, bArr2, bArr, bArr3)[2];
                return str52;
            }
            return "";
        }
    }

    public static String c(String str, String str2, String str3) {
              //  省略部分代码
        if (!a(bArr) && a(bArr2) && a(bArr3)) {
            return getSignCode(bArr, bArr2, bArr3);
        }
        return "";
    }

    private static native String getSignCode(byte[] bArr, byte[] bArr2, byte[] bArr3);

    private static native String[] getSignRequest(String str, byte[] bArr, byte[] bArr2, byte[] bArr3);
}

unidbg模拟执行

先搭建好架子

package com.nice.sign;

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 java.io.File;

public class test extends AbstractJni {
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;

    test() {
        emulator = AndroidEmulatorBuilder.for64Bit().setProcessName("com.nice.main").build(); // 创建模拟器实例
        final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
        memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析

        vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/example_binaries/nice.apk")); // 创建Android虚拟机
        vm.setJni(this);
        vm.setVerbose(true); // 设置是否打印Jni调用细节
        DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/arm64-v8a/libsalt.so"), true);
        module = dm.getModule(); //
        dm.callJNI_OnLoad(emulator);

    }

    public static void main(String[] args) {
        test TEST = new test();

    }

}

构造函数

public String getSignRequest(String str, byte[] bArr, byte[] bArr2, byte[] bArr3) {

        List<Object> list = new ArrayList<>();
        list.add(vm.getJNIEnv());
        list.add(0);

        list.add(vm.addLocalObject(new StringObject(vm, str)));
        list.add(vm.addLocalObject(new ByteArray(vm, bArr)));
        list.add(vm.addLocalObject(new ByteArray(vm, bArr2)));
        list.add(vm.addLocalObject(new ByteArray(vm, bArr3)));

        Number number = module.callFunction(emulator, 0x1F9C, list.toArray());
        DvmObject[] result = (DvmObject[]) vm.getObject(number.intValue()).getValue();

        return result[2].getValue().toString();
    }
public static void main(String[] args) throws NoSuchAlgorithmException {
        niceSign SDK = new niceSign();

        byte[] arr = "{\"country\":\"1\",\"mobile\":\"test\",\"password\":\"B7cteuae3Ndw0Ty\\/LNF9deUrY+K3NAu5Fwdekfg0hHctSwyfGx1aRhuNj1SYFUsURcvjtcMc7t4P\\nkT4\\/jMw16KMp8Ib85U2qrJB1jHuiLnrBjTarlFgjeHKUH3r1fh03p7UfEYqjp+CPzAeF41\\/WRxXZ\\n846NrxSswxEybYOC5FU=\\n\",\"platform\":\"mobile\"}".getBytes();

        byte[] arr2 = getDid().getBytes();

        byte[] arr3 = getRandom().getBytes();

        String sign = SDK.getSignRequest(new String(arr), arr, arr2, arr3);

        System.out.println("nice sign算法:" + sign);
    }

补环境

报错1

java.lang.UnsupportedOperationException: com/nice/main/data/enumerable/User->ach(Ljava/lang/String;)Ljava/lang/String;
    at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethod(AbstractJni.java:432)
    at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethod(AbstractJni.java:421)
    at com.github.unidbg.linux.android.dvm.DvmMethod.callStaticObjectMethod(DvmMethod.java:59)
    at com.github.unidbg.linux.android.dvm.DalvikVM64$111.handle(DalvikVM64.java:1723)
    at com.github.unidbg.linux.ARM64SyscallHandler.hook(ARM64SyscallHandler.java:118)
    at com.github.unidbg.arm.backend.UnicornBackend$11.hook(UnicornBackend.java:345)
    at unicorn.Unicorn$NewHook.onInterrupt(Unicorn.java:128)
    at unicorn.Unicorn.emu_start(Native Method)
    at com.github.unidbg.arm.backend.UnicornBackend.emu_start(UnicornBackend.java:376)
    at com.github.unidbg.AbstractEmulator.emulate(AbstractEmulator.java:380)
    at com.github.unidbg.thread.Function64.run(Function64.java:39)
    at com.github.unidbg.thread.MainTask.dispatch(MainTask.java:19)
    at com.github.unidbg.thread.UniThreadDispatcher.run(UniThreadDispatcher.java:175)
    at com.github.unidbg.thread.UniThreadDispatcher.runMainForResult(UniThreadDispatcher.java:99)
    at com.github.unidbg.AbstractEmulator.runMainForResult(AbstractEmulator.java:340)
    at com.github.unidbg.arm.AbstractARM64Emulator.eFunc(AbstractARM64Emulator.java:262)
    at com.github.unidbg.Module.emulateFunction(Module.java:163)
    at com.github.unidbg.linux.LinuxModule.callFunction(LinuxModule.java:262)
    at com.nice.sign.niceSign.getSignRequest(niceSign.java:78)
    at com.nice.sign.niceSign.main(niceSign.java:158)
通过分析jadx反编译的代码发现这里是一个取随机数的函数
    public static String ach(String str) {
        Random random = new Random();
        StringBuffer stringBuffer = new StringBuffer();
        while (stringBuffer.length() < 16) {
            stringBuffer.append(Integer.toString(random.nextInt() & Integer.MAX_VALUE, 36));
        }
        return stringBuffer.substring(0, 16);
    }
补环境代码
public static String getRandom() {
        Random random = new Random();
        StringBuilder strBuffer = new StringBuilder();
        while (strBuffer.length() < 16) {
            strBuffer.append(Integer.toString(random.nextInt() & Integer.MAX_VALUE, 36));
        }
        return strBuffer.substring(0, 16);
    }
    @Override
    public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass DvmClass, String signature, VarArg varArg) {
        switch (signature) {
            case "com/nice/main/data/enumerable/User->ach(Ljava/lang/String;)Ljava/lang/String;":
                return new StringObject(vm, getRandom());
        }
        return super.callStaticObjectMethod(vm, DvmClass, signature, varArg);
    }

报错2

java.lang.UnsupportedOperationException: com/nice/main/data/enumerable/Sticker->ach(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethod(AbstractJni.java:432)
    at com.nice.sign.niceSign.callStaticObjectMethod(niceSign.java:145)
    at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethod(AbstractJni.java:421)
    at com.github.unidbg.linux.android.dvm.DvmMethod.callStaticObjectMethod(DvmMethod.java:59)
    at com.github.unidbg.linux.android.dvm.DalvikVM64$111.handle(DalvikVM64.java:1723)
    at com.github.unidbg.linux.ARM64SyscallHandler.hook(ARM64SyscallHandler.java:118)
    at com.github.unidbg.arm.backend.UnicornBackend$11.hook(UnicornBackend.java:345)
    at unicorn.Unicorn$NewHook.onInterrupt(Unicorn.java:128)
    at unicorn.Unicorn.emu_start(Native Method)
    at com.github.unidbg.arm.backend.UnicornBackend.emu_start(UnicornBackend.java:376)
    at com.github.unidbg.AbstractEmulator.emulate(AbstractEmulator.java:380)
    at com.github.unidbg.thread.Function64.run(Function64.java:39)
    at com.github.unidbg.thread.MainTask.dispatch(MainTask.java:19)
    at com.github.unidbg.thread.UniThreadDispatcher.run(UniThreadDispatcher.java:175)
    at com.github.unidbg.thread.UniThreadDispatcher.runMainForResult(UniThreadDispatcher.java:99)
    at com.github.unidbg.AbstractEmulator.runMainForResult(AbstractEmulator.java:340)
    at com.github.unidbg.arm.AbstractARM64Emulator.eFunc(AbstractARM64Emulator.java:262)
    at com.github.unidbg.Module.emulateFunction(Module.java:163)
    at com.github.unidbg.linux.LinuxModule.callFunction(LinuxModule.java:262)
    at com.nice.sign.niceSign.getSignRequest(niceSign.java:78)
    at com.nice.sign.niceSign.main(niceSign.java:167)
这里是拼接字符串操作
public static String ach(String str, String str2, String str3, String str4) {
        return NetworkUtils.getNiceURL(str, str2, str3, str4);
    }

public static String getNiceURL(String firstpart, String secondpart, String thirdpart, String forthpart) {
        return firstpart + secondpart + ":" + thirdpart + "/" + forthpart;
    }
补环境代码
    public static String getNiceURL(String firstpart, String secondpart, String thirdpart, String forthpart) {
        return firstpart + secondpart + ":" + thirdpart + "/" + forthpart;
    }

@Override
    public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass DvmClass, String signature, VarArg varArg) {
        switch (signature) {
            case "com/nice/main/data/enumerable/Sticker->ach(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;":
                try {
                    String value = getNiceURL(varArg.getObjectArg(0).getValue().toString(), varArg.getObjectArg(1).getValue().toString(), varArg.getObjectArg(2).getValue().toString(), varArg.getObjectArg(3).getValue().toString());
                    return new StringObject(vm, value);
                } catch (ArithmeticException e) {
                    return new StringObject(vm, "10086");
                }
        }
        return super.callStaticObjectMethod(vm, DvmClass, signature, varArg);
    }

最终补完环境的代码如下(直接Copy的自己的代码 没有按照教程上面的写 基本上都一样的):

package com.nice.sign;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;

import com.github.unidbg.arm.HookStatus;
import com.github.unidbg.debugger.Debugger;
import com.github.unidbg.hook.HookContext;
import com.github.unidbg.hook.ReplaceCallback;
import com.github.unidbg.hook.hookzz.HookEntryInfo;
import com.github.unidbg.hook.hookzz.HookZz;
import com.github.unidbg.hook.hookzz.HookZzArm64RegisterContext;
import com.github.unidbg.hook.hookzz.WrapCallback;
import com.github.unidbg.hook.xhook.IxHook;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.XHookImpl;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.linux.android.dvm.array.ByteArray;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.utils.Inspector;
import com.sun.jna.Pointer;

import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class SignUtil extends AbstractJni {
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;

    SignUtil() {
        emulator = AndroidEmulatorBuilder.for64Bit().setProcessName("com.nice.main").build(); // 创建模拟器实例
        final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
        memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析

        vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/example_binaries/nice.apk")); // 创建Android虚拟机
        vm.setJni(this);
        vm.setVerbose(false); // 设置是否打印Jni调用细节
        DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/arm64-v8a/libsalt.so"), true);
        module = dm.getModule(); //
        dm.callJNI_OnLoad(emulator);
    }
    public static String getRandom() {
        Random random = new Random();
        StringBuilder strBuffer = new StringBuilder();
        while (strBuffer.length() < 16) {
            strBuffer.append(Integer.toString(random.nextInt() & Integer.MAX_VALUE, 36));
        }
        return strBuffer.substring(0, 16);
    }

    public static String getNiceURL(String firstpart, String secondpart, String thirdpart, String forthpart) {
        return firstpart + secondpart + ":" + thirdpart + "/" + forthpart;
    }

    @Override
    public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass DvmClass, String signature, VarArg varArg) {
        switch (signature) {
            case "com/nice/main/data/enumerable/User->ach(Ljava/lang/String;)Ljava/lang/String;":
                return new StringObject(vm, getRandom());
            case "com/nice/main/data/enumerable/Sticker->ach(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;":
                try {
                    String value = getNiceURL(varArg.getObjectArg(0).getValue().toString(), varArg.getObjectArg(1).getValue().toString(), varArg.getObjectArg(2).getValue().toString(), varArg.getObjectArg(3).getValue().toString());
                    return new StringObject(vm, value);
                } catch (ArithmeticException e) {
                    return new StringObject(vm, "10086");
                }
        }
        return super.callStaticObjectMethod(vm, DvmClass, signature, varArg);
    }

    public static String getDid() throws NoSuchAlgorithmException {
        MessageDigest Hash = MessageDigest.getInstance("MD5");
        byte[] digest = Hash.digest(getRandom().getBytes());
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b & 0xff));
        }
        return sb.toString();
    }

    public String getSignRequest(String str, byte[] bArr, byte[] bArr2, byte[] bArr3) {

        List<Object> list = new ArrayList<>();
        list.add(vm.getJNIEnv()); // 第一个参数是env
        list.add(0); // 第二个参数,实例方法是jobject,静态方法是jclazz,直接填0,一般用不到。

        list.add(vm.addLocalObject(new StringObject(vm, str)));
        list.add(vm.addLocalObject(new ByteArray(vm, bArr)));
        list.add(vm.addLocalObject(new ByteArray(vm, bArr2)));
        list.add(vm.addLocalObject(new ByteArray(vm, bArr3)));

        Number number = module.callFunction(emulator, 0x1F9C, list.toArray());
        DvmObject[] result = (DvmObject[]) vm.getObject(number.intValue()).getValue();

        return result[2].getValue().toString();
    }

    public static void main(String[] args) throws NoSuchAlgorithmException {
        SignUtil SDK = new SignUtil();

        byte[] arr = "{\"country\":\"1\",\"mobile\":\"test\",\"password\":\"B7cteuae3Ndw0Ty\\/LNF9deUrY+K3NAu5Fwdekfg0hHctSwyfGx1aRhuNj1SYFUsURcvjtcMc7t4P\\nkT4\\/jMw16KMp8Ib85U2qrJB1jHuiLnrBjTarlFgjeHKUH3r1fh03p7UfEYqjp+CPzAeF41\\/WRxXZ\\n846NrxSswxEybYOC5FU=\\n\",\"platform\":\"mobile\"}".getBytes();

        byte[] arr2 = getDid().getBytes();

        byte[] arr3 = getRandom().getBytes();

        String sign = SDK.getSignRequest(new String(arr), arr, arr2, arr3);

        System.out.println("nice sign算法:" + sign);
    }
}

算法还原

ida静态分析

主要代码其实是在 nice_sign_v3函数中

jobjectArray __fastcall Java_com_nice_main_helpers_utils_NiceSignUtils_getSignRequest(_JNIEnv *a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5)
{

//省略N行
  v27 = nice_sign_v3(v16, v20, v11);
  v28 = a1->functions->SetObjectArrayElement;
  v29 = a1->functions->NewStringUTF(a1, v11);
  v28(&a1->functions, v24, 1LL, v29);
  free(v16);
  free(v20);
  v30 = a1->functions->NewStringUTF(a1, v27);
  v31 = a1->functions->CallStaticObjectMethod(a1, GenerateSignClass, createSign, v12, v30, v10, a3);
  a1->functions->ReleaseStringUTFChars(a1, v10, v11);
  a1->functions->DeleteLocalRef(a1, v10);
  a1->functions->DeleteLocalRef(a1, v12);
  a1->functions->DeleteLocalRef(a1, v30);
  a1->functions->SetObjectArrayElement(a1, v24, 2LL, v31);
  return v24;
}

nice_sign_v3

char *__fastcall nice_sign_v3(const char *a1, const char *a2, const char *a3)
{
 // 省略N行
  v70 = *(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  v69 = 0;
  *v67 = 0u;
  v68 = 0u;
  v66 = 0;
  v65 = 0u;
  *v64 = 0u;
  strcpy(v64, a2);
  v5 = strlen(v64) >> 1;
  if ( v5 >= 1 )
  {
    v6 = (v5 - 1) + 1LL;
    v7 = v5;
    if ( v6 < 0x20 )
    {
      LODWORD(v8) = 0;
      v9 = v64;
      goto LABEL_11;
    }
    v8 = v6 & 0x1FFFFFFE0LL;
    v9 = v64;
    if ( (v6 & 0x1FFFFFFE0LL) == 0 )
    {
LABEL_11:
      v17 = v5 - v8;
      do
      {
        v18 = *v9;
        --v17;
        *v9 = v9[v7];
        (v9++)[v7] = v18;
      }
      while ( v17 );
      goto LABEL_13;
    }
    v10 = (v5 - 1);
    if ( v64 < &v64[v5 + 1 + v10] && &v64[v5] < &v64[v10 + 1] )
    {
      LODWORD(v8) = 0;
      goto LABEL_11;
    }
    v9 = &v64[v8];
    v11 = v64;
    v12 = v6 & 0x1FFFFFFE0LL;
    do
    {
      v13 = &v11[v5];
      v14 = *(v13 + 1);
      v15 = *v11;
      v16 = *(v11 + 1);
      v12 -= 32LL;
      *v11 = *v13;
      *(v11 + 1) = v14;
      v11 += 32;
      *v13 = v15;
      *(v13 + 1) = v16;
    }
    while ( v12 );
    if ( v6 != v8 )
      goto LABEL_11;
  }
LABEL_13:
  v19 = strlen(a1);
  v20 = malloc(v19 + 101);
  v21 = v20;
  if ( !v20 )
    return 0LL;
  strcpy(v20, a3);
  v22 = nice_md5(v64);
  strcat(v21, v22);
  strcpy(&v21[strlen(v21)], "8a5f746c1c9c99c0b458e1ed510845e5");
  v23 = nice_md5(v21);
  strcpy(v67, v23);
  v24 = strlen(v67) >> 1;
  if ( v24 >= 1 )
  {
    v25 = (v24 - 1) + 1LL;
    v26 = v24;
    if ( v25 < 0x20 )
    {
      LODWORD(v27) = 0;
      v28 = v67;
      goto LABEL_24;
    }
    v27 = v25 & 0x1FFFFFFE0LL;
    v28 = v67;
    if ( (v25 & 0x1FFFFFFE0LL) == 0 )
    {
LABEL_24:
      v36 = v24 - v27;
      do
      {
        v37 = *v28;
        --v36;
        *v28 = v28[v26];
        (v28++)[v26] = v37;
      }
      while ( v36 );
      goto LABEL_26;
    }
    v29 = (v24 - 1);
    if ( v67 < &v67[v24 + 1 + v29] && &v67[v24] < &v67[v29 + 1] )
    {
      LODWORD(v27) = 0;
      goto LABEL_24;
    }
    v28 = &v67[v27];
    v30 = v67;
    v31 = v25 & 0x1FFFFFFE0LL;
    do
    {
      v32 = &v30[v24];
      v33 = *(v32 + 1);
      v34 = *v30;
      v35 = *(v30 + 1);
      v31 -= 32LL;
      *v30 = *v32;
      *(v30 + 1) = v33;
      v30 += 32;
      *v32 = v34;
      *(v32 + 1) = v35;
    }
    while ( v31 );
    if ( v25 != v27 )
      goto LABEL_24;
  }
LABEL_26:
  v38 = cJSON_Parse(a1);
  v39 = v38;
  if ( !v38 )
    return 0LL;
  v40 = sub_25B0(v38);
  cJSON_Delete(v39);
  if ( strlen(v40) < 2uLL )
  {
    v41 = 0LL;
    v46 = 32LL;
  }
  else
  {
    v41 = 0LL;
    v42 = v40 + 1;
    v43 = 0x2000000000LL;
    do
    {
      v44 = *(v42 - 1);
      v45 = *v42;
      v42 += 2;
      v21[v41++] = v44 & 0xF0 | v45 & 0xF;
      v43 += 0x100000000LL;
    }
    while ( strlen(v40) >> 1 > v41 );
    v46 = v43 >> 32;
  }
  free(v40);
  strncpy(&v21[v41], v67, 0x20u);
  v21[v46] = 0;
  v48 = nice_sha1(v21);
  v47 = byte_1A041;
  strncpy(byte_1A041, (v48 + 8), 0x20u);
  free(v21);
  v49 = strlen(byte_1A041) >> 1;
  if ( v49 >= 1 )
  {
    v50 = (v49 - 1) + 1LL;
    v51 = v49;
    if ( v50 >= 0x20 )
    {
      v52 = v50 & 0x1FFFFFFE0LL;
      v53 = byte_1A041;
      if ( (v50 & 0x1FFFFFFE0LL) != 0 )
      {
        v54 = (v49 - 1);
        if ( &byte_1A041[v49 + 1 + v54] <= byte_1A041 || &byte_1A041[v49] >= &byte_1A041[v54 + 1] )
        {
          v53 = &byte_1A041[v52];
          v55 = byte_1A041;
          v56 = v50 & 0x1FFFFFFE0LL;
          do
          {
            v57 = &v55[v49];
            v58 = *(v57 + 1);
            v59 = *v55;
            v60 = *(v55 + 1);
            v56 -= 32LL;
            *v55 = *v57;
            *(v55 + 1) = v58;
            v55 += 32;
            *v57 = v59;
            *(v57 + 1) = v60;
          }
          while ( v56 );
          if ( v50 == v52 )
            return byte_1A041;
        }
        else
        {
          LODWORD(v52) = 0;
        }
      }
    }
    else
    {
      LODWORD(v52) = 0;
      v53 = byte_1A041;
    }
    v61 = v49 - v52;
    v47 = byte_1A041;
    do
    {
      v62 = *v53;
      --v61;
      *v53 = v53[v51];
      (v53++)[v51] = v62;
    }
    while ( v61 );
  }
  return v47;
}

执行流程请执行GhatGPT 这里讲一下主要的位置

LABEL_26:
  v38 = cJSON_Parse(a1);  // JSON解析文本
  v39 = v38;
  if ( !v38 )
    return 0LL;
  v40 = sub_25B0(v38);   // 将 CJson对象转换成 键值对形式
  cJSON_Delete(v39); // 释放Cjson对象
  if ( strlen(v40) < 2uLL )
  {
    v41 = 0LL;
    v46 = 32LL;
  }
  else
  {
    v41 = 0LL;
    v42 = v40 + 1;  // 初始化指针v42指向字符串v40的第一个字符
    v43 = 0x2000000000LL;
    do
    {
      v44 = *(v42 - 1);   //从v42指向的字符串中读取一个字符
      v45 = *v42;  //从v42指向的字符串中读取下一个字符
      v42 += 2;   // 指针v42向后移动2个字节
      v21[v41++] = v44 & 0xF0 | v45 & 0xF;  // 将读取的两个字符转换为一个字节,并存储在数组v21中
      v43 += 0x100000000LL;  // 增加变量变量的值
    }
    while ( strlen(v40) >> 1 > v41 );   // 当已经转换的字节数小于字符串长度除以2时继续循环
    v46 = v43 >> 32;
  }
  free(v40); 
  strncpy(&v21[v41], v67, 0x20u);  //字符串拼接
  v21[v46] = 0;
  v48 = nice_sha1(v21);  // 标准的sha1加密
  v47 = byte_1A041;
  strncpy(byte_1A041, (v48 + 8), 0x20u);
  free(v21);
  v49 = strlen(byte_1A041) >> 1;

以下是使用JavaScript还原的代码(请自行导入Crypto库)


function Hash_sha1(word) {
    return CryptoJS.SHA1(word).toString(CryptoJS.enc.Hex);
}
function Hash_md5(word) {
    return CryptoJS.MD5(word).toString(CryptoJS.enc.Hex);
}

function get_random(len) {
    let r = Math.random().toString(36).substring(2);
    if (r.length < len) {
        r += get_random(len - r.length)
    }
    return r;

}

function get_did() {
    return Hash_md5(get_random(16));
}

function Build_NiceSignText(input) {
    let output = []
    let ptr = input;
    let output_index = 4;

    while (input.length >> 1 > output_index - 4) {
        const c1 = ptr.charCodeAt(0);
        const c2 = ptr.charCodeAt(1);

        const byte = ((c1 & 0xF0) | (c2 & 0xF));
        output[output_index++] = byte;

        ptr = ptr.slice(2);
    }
    return output.map(value => {
        return String.fromCharCode(value)
    }).join('')
}

function nice_sign_v3(JsonData, did, random) {

    let result = {
        data: "",
        random: random || get_random(),
        did: did || get_did()
    }

    let md5 = [];

    md5.push(Hash_md5(result.did.substring(16, 32) + result.did.substring(0, 16)));
    md5.push(Hash_md5(result.random + md5[0] + "8a5f746c1c9c99c0b458e1ed510845e5"));
    md5[1] = md5[1].substring(16, 32) + md5[1].substring(0, 16)

    let obj = JsonData === "" ? {} : typeof JsonData === "string" ? JSON.parse(JsonData) : JsonData

    let SignText = Build_NiceSignText(Object.keys(obj).sort().map(value => {
        return value + "=" + obj[value];
    }).join('&'))

    console.log(SignText + md5[1])

    let Sign = Hash_sha1(SignText + md5[1])

    console.log(Sign.substring(24, 41) ,Sign.substring(8, 24))

    result.data = `nice-sign-v1://${Sign.substring(24, 41) + Sign.substring(8, 24)}:${result.random}/${JSON.stringify(obj)}`

    return JSON.stringify(result)
}

console.log(nice_sign_v3('{"country":"1","mobile":"888888888","send":"yes","check":"no"}', "",''))

结帖率:100% (5/5)

签到天数: 30 天

发表于 2023-7-12 23:29:46 | 显示全部楼层   印度
不是有js的编辑器吗
回复 支持 反对

使用道具 举报

发表于 2023-7-12 21:57:09 | 显示全部楼层   黑龙江省哈尔滨市
膜拜大佬
回复 支持 反对

使用道具 举报

结帖率:100% (83/83)
发表于 2023-7-12 21:40:04 | 显示全部楼层   湖北省咸宁市
已经顶贴,感谢您对论坛的支持!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

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