查看原文
其他

一道简单的ollvm算法题还原

wyongcan 看雪学苑 2022-07-01
看雪论坛作者ID:wyongcan


本题出自看雪3W班 12月ollvm题。


 题目要求


得益于Unicorn的强大的指令trace能力,可以很容易实现对cpu执行的每一条汇编指令的跟踪,进而对ollvm保护的函数进行剪枝,去掉虚假块,大大提高逆向分析效率。请分别使用Unidbg和Stalker引擎完成对该app中的jnicheck函数的trace跟踪,并简单分析该apk逻辑,找出flag。


 解题思路


题目要求使用unidbg对ollvm加密后的算法进行还原。需要调用的native函数中,又会使用CallStaticBooleanMethodV调用另一个native函数。当时unidbg本身好像不支持这种方式,需要对unidbg代码进行部分修改之后才能正确进行模拟执行。

可以模拟执行之后,简单的思路就是使用unidbg进行trace找出哪些代码分支是可能被执行的,哪些条件分支是可以被优化掉的,之后对so进行patch,再使用ida进行分析。


 知识点


本题主要有两个知识点,第一是对unidbg本身的修改使得能够支持一些原本不支持的场景,第二是对函数进行trace后patch源文件减少ollvm的干扰。


 解题步骤


DvmObject.java中新增initArgs,用于初始化调用参数。
public void initArgs(Emulator<?> emulator, Object...args) { if (objectType == null) { throw new IllegalStateException("objectType is null"); } initArgs(emulator, vm, this, args);}public static Arguments initArgs(Emulator<?> emulator, VM vm, DvmObject<?> thisObj, Object...args) { List<Object> list = new ArrayList<>(10); list.add(vm.getJNIEnv()); list.add(thisObj.hashCode()); if (args != null) { for (Object arg : args) { if (arg instanceof Boolean) { list.add((Boolean) arg ? VM.JNI_TRUE : VM.JNI_FALSE); continue; } else if(arg instanceof Hashable) { list.add(arg.hashCode()); // dvm object if(arg instanceof DvmObject) { vm.addLocalObject((DvmObject<?>) arg); } continue; } else if (arg instanceof String) { StringObject str = new StringObject(vm, (String) arg); list.add(str.hashCode()); vm.addLocalObject(str); continue; } else if(arg instanceof byte[]) { ByteArray array = new ByteArray(vm, (byte[]) arg); list.add(array.hashCode()); vm.addLocalObject(array); continue; } list.add(arg); } } args = list.toArray(); List<Number> numList = new ArrayList<>(args.length); for (Object arg : args) { if (arg instanceof String) { numList.add(new StringNumber((String) arg)); } else if(arg instanceof byte[]) { numList.add(new ByteArrayNumber((byte[]) arg)); } else if(arg instanceof UnidbgPointer) { UnidbgPointer pointer = (UnidbgPointer) arg; numList.add(new PointerNumber(pointer)); } else if(arg instanceof UnidbgStructure) { UnidbgStructure structure = (UnidbgStructure) arg; numList.add(new PointerNumber((UnidbgPointer) structure.getPointer())); } else if (arg instanceof Number) { numList.add((Number) arg); } else if(arg == null) { numList.add(new PointerNumber(null)); // null } else { throw new IllegalStateException("Unsupported arg: " + arg); } } return ARM.initArgs(emulator, true, numList.toArray(new Number[0]));}

DalvikVM64.java中修改CallStaticBooleanMethodV的hook代码,用于支持函数直接初始化调用参数后直接修改pc来call,通过R0来区分判断是否是这种方式调用。
Pointer _CallStaticBooleanMethodV = svcMemory.registerSvc(new Arm64Svc() { @Override public long handle(Emulator<?> emulator) { UnidbgPointer clazz = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X1); UnidbgPointer jmethodID = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X2); UnidbgPointer va_list = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X3); if (log.isDebugEnabled()) { log.debug("CallStaticBooleanMethodV clazz=" + clazz + ", jmethodID=" + jmethodID + ", va_list=" + va_list); } DvmClass dvmClass = classMap.get(clazz.toIntPeer()); DvmMethod dvmMethod = dvmClass == null ? null : dvmClass.getStaticMethod(jmethodID.toIntPeer()); if (dvmMethod == null) { throw new BackendException(); } else { long oriX0 = emulator.getBackend().reg_read(Arm64Const.UC_ARM64_REG_X0).longValue(); VaList vaList = new VaList64(emulator, DalvikVM64.this, va_list, dvmMethod); long ret = dvmMethod.callStaticBooleanMethodV(vaList); long newX0 = emulator.getBackend().reg_read(Arm64Const.UC_ARM64_REG_X0).longValue(); if (oriX0 != newX0) { ret = newX0 - 1; } if (verbose) { System.out.printf("JNIEnv->CallStaticBooleanMethodV(%s, %s(%s) => %s) was called from %s%n", dvmClass, dvmMethod.methodName, vaList.formatArgs(), ret == JNI_TRUE, UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_LR)); } return ret; } }});

MainActivity.java主要的模拟调用代码:
package com.kanxue.crackme; import com.github.unidbg.AndroidEmulator;import com.github.unidbg.LibraryResolver;import com.github.unidbg.arm.backend.BlockHook;import com.github.unidbg.linux.android.AndroidARM64Emulator;import com.github.unidbg.linux.android.AndroidResolver;import com.github.unidbg.linux.android.dvm.*;import com.github.unidbg.linux.android.dvm.jni.ProxyClassFactory;import com.github.unidbg.linux.android.dvm.jni.ProxyDvmObject;import com.github.unidbg.memory.Memory;import capstone.Capstone;import keystone.Keystone;import keystone.KeystoneArchitecture;import keystone.KeystoneMode;import org.apache.commons.codec.binary.Hex;import unicorn.Arm64Const; import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.*; public class MainActivity { public static byte[] readFile(File file) throws IOException { long len = file.length(); byte[] bytes = new byte[(int)len]; try (FileInputStream in = new FileInputStream(file)) { in.read(bytes); } return bytes; } public static void main(String[] args) throws IOException { MainActivity mainActivity = new MainActivity(); emulator = new AndroidARM64Emulator(); Memory memory = emulator.getMemory(); LibraryResolver resolver = new AndroidResolver(23); memory.setLibraryResolver(resolver); vm = emulator.createDalvikVM(null); vm.setVerbose(true); vm.setDvmClassFactory(new ProxyClassFactory()); DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/kanxue-dec/03/libnative-lib.so"), true); dm.callJNI_OnLoad(emulator); crypt2Addr = dm.getModule().findSymbolByName("Java_com_kanxue_crackme_MainActivity_crypt2").getAddress(); obj = ProxyDvmObject.createObject(vm,mainActivity);// emulator.traceCode(dm.getModule().base, dm.getModule().base + dm.getModule().size); Map<Long, List<String>> blockAsm = new HashMap<>(); Map<Long, Long> blockEnd = new HashMap<>(); Map<Long, List<Long>> blockCount = new HashMap<>(); Map<Long, Set<Long>> jumpCount = new HashMap<>(); long start = dm.getModule().base; long end = start + dm.getModule().size; System.out.println("base:" + Long.toHexString(dm.getModule().base) + " end:" + Long.toHexString(end)); emulator.getBackend().hook_add_new((BlockHook) (backend, address, size, user) -> { blockEnd.put(address, address + size); if (!blockCount.containsKey(address)) { blockCount.put(address, new ArrayList<>()); } if (!jumpCount.containsKey(lastBlock)) { jumpCount.put(lastBlock, new HashSet<>()); } jumpCount.get(lastBlock).add(address); blockCount.get(address).add(lastBlock); lastBlock = address; if (!blockAsm.containsKey(address)) { Capstone.CsInsn[] csInsns = emulator.disassemble(address, size, 0); ArrayList<String> asms = new ArrayList<>(csInsns.length); for (Capstone.CsInsn csInsn : csInsns) { asms.add(csInsn.mnemonic); } blockAsm.put(address, asms); } }, start, end, null); byte[] content = readFile(new File("unidbg-android/src/test/resources/example_binaries/kanxue-dec/03/libnative-lib.so")); Set<String> blackList = new HashSet<>(); blackList.add("orr,tbnz"); blackList.add("stur,tbnz"); blackList.add("stur,tbz"); blackList.add("str,tbz"); blackList.add("str,tbnz"); boolean result = obj.callJniMethodBoolean(emulator,"jnicheck(Ljava/lang/String;)Z","aaa"); obj.callJniMethodBoolean(emulator,"jnicheck(Ljava/lang/String;)Z","bbbb"); obj.callJniMethodBoolean(emulator,"jnicheck(Ljava/lang/String;)Z","cc"); Keystone ks = new Keystone(KeystoneArchitecture.Arm64, KeystoneMode.LittleEndian); jumpCount.forEach((aLong, aLong2) -> { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append('['); aLong2.forEach(addr -> stringBuilder.append("0x" + Long.toHexString(addr) + ",")); stringBuilder.setLength(stringBuilder.length() - 1); stringBuilder.append(']'); List<String> asms = blockAsm.get(aLong); if (asms != null && asms.size() >= 2) { String lastTwo = asms.get(asms.size() - 2) + "," + asms.get(asms.size() - 1); stringBuilder.append(" <").append(lastTwo).append('>'); if (aLong2.size() == 1) { if (blackList.contains(lastTwo)) { int address = blockEnd.get(aLong).intValue() - 4; byte[] code = ks.assemble("b #0x" + Long.toHexString(aLong2.iterator().next()), address).getMachineCode(); System.out.println("file address: 0x" + Long.toHexString(address - start - 0x10000) + " patch address: 0x" + Long.toHexString(address) + " code:" + Hex.encodeHexString(code)); for (int i = 0; i < code.length; i++) { content[(int) (address - start + i)] = code[i]; } } } } System.out.println("0x" + Long.toHexString(aLong) + " : " + stringBuilder.toString()); }); try (FileOutputStream out = new FileOutputStream(new File("unidbg-android/src/test/resources/example_binaries/kanxue-dec/03/libnative-lib.fix.so"))) { out.write(content); } System.out.println("result:" + result); } public static boolean crypt2(String arg0) { obj.initArgs(emulator, arg0); // 通过R0告诉CallStaticBooleanMethodV忽略函数返回值 long x0 = emulator.getBackend().reg_read(Arm64Const.UC_ARM64_REG_X0).longValue(); emulator.getBackend().reg_write(Arm64Const.UC_ARM64_REG_X0, x0 + 1); emulator.getBackend().reg_write(Arm64Const.UC_ARM64_REG_PC, crypt2Addr); // 该返回值将被忽略 return true; } private static long lastBlock = 0; private static AndroidEmulator emulator; private static VM vm; private static DvmObject obj; private static long crypt2Addr;}

不太懂ollvm怎么剪枝,通过观察发现ollvm生成的很多块都有一些特征,于是直接通过一些简单的条件来把一些块末尾跳转直接改成无条件跳转。


条件是:

1.这个块在执行时的下一个块是唯一的;

2.块的结尾两条汇编指令符合一定特征。

Set<String> blackList = new HashSet<>();blackList.add("orr,tbnz");blackList.add("stur,tbnz");blackList.add("stur,tbz");blackList.add("str,tbz");blackList.add("str,tbnz");

然后随便用几个输入调用一下函数,让尽可能多的块被执行。
obj.callJniMethodBoolean(emulator,"jnicheck(Ljava/lang/String;)Z","aaa");obj.callJniMethodBoolean(emulator,"jnicheck(Ljava/lang/String;)Z","bbbb");obj.callJniMethodBoolean(emulator,"jnicheck(Ljava/lang/String;)Z","cc");

之后把patch后的so保存下来,使用IDA进行分析。
Java_com_kanxue_crackme_MainActivity_jnicheck的反编译结果如下:
__int64 __fastcall Java_com_kanxue_crackme_MainActivity_jnicheck(__int64 a1, __int64 a2, __int64 a3){ __int64 v3; // x0 __int64 v4; // x8 __int64 v5; // x11 int v6; // w0 __int64 v7; // x9 __int64 v8; // x0 __int64 v9; // x8 __int64 v10; // x0 __int64 v11; // x0 __int64 v12; // x8 __int64 v13; // x0 __int64 v14; // x8 char v15; // w0 __int64 v16; // x8 _BOOL4 v17; // w7 unsigned int v18; // w9 __int64 v20; // [xsp-110h] [xbp-480h] BYREF __int64 v21; // [xsp-100h] [xbp-470h] BYREF __int64 v22; // [xsp-F0h] [xbp-460h] BYREF __int64 v23; // [xsp-E0h] [xbp-450h] BYREF _BYTE v24[112]; // [xsp-D0h] [xbp-440h] BYREF __int64 v25; // [xsp-60h] [xbp-3D0h] BYREF __int64 v26; // [xsp-50h] [xbp-3C0h] BYREF _QWORD v27[6]; // [xsp-40h] [xbp-3B0h] BYREF _QWORD v28[72]; // [xsp-10h] [xbp-380h] BYREF int v29; // [xsp+238h] [xbp-138h] int v30; // [xsp+240h] [xbp-130h] int v31; // [xsp+244h] [xbp-12Ch] int v32; // [xsp+248h] [xbp-128h] int v33; // [xsp+24Ch] [xbp-124h] int v34; // [xsp+250h] [xbp-120h] int v35; // [xsp+258h] [xbp-118h] int v36; // [xsp+260h] [xbp-110h] int v37; // [xsp+268h] [xbp-108h] int v38; // [xsp+270h] [xbp-100h] int v39; // [xsp+278h] [xbp-F8h] int v40; // [xsp+280h] [xbp-F0h] int v41; // [xsp+288h] [xbp-E8h] _BOOL4 v42; // [xsp+28Ch] [xbp-E4h] int v43; // [xsp+290h] [xbp-E0h] int v44; // [xsp+294h] [xbp-DCh] __int64 v45; // [xsp+298h] [xbp-D8h] __int64 *v46; // [xsp+2A0h] [xbp-D0h] _BYTE *v47; // [xsp+2A8h] [xbp-C8h] char *v48; // [xsp+2B0h] [xbp-C0h] __int64 *v49; // [xsp+2B8h] [xbp-B8h] __int64 *v50; // [xsp+2C0h] [xbp-B0h] _QWORD *v51; // [xsp+2C8h] [xbp-A8h] _QWORD *v52; // [xsp+2D0h] [xbp-A0h] _BYTE *v53; // [xsp+2D8h] [xbp-98h] __int64 *v54; // [xsp+2E0h] [xbp-90h] __int64 *v55; // [xsp+2E8h] [xbp-88h] __int64 *v56; // [xsp+2F0h] [xbp-80h] int v57; // [xsp+2FCh] [xbp-74h] int v58; // [xsp+304h] [xbp-6Ch] int v59; // [xsp+30Ch] [xbp-64h] int v60; // [xsp+314h] [xbp-5Ch] int v61; // [xsp+31Ch] [xbp-54h] int v62; // [xsp+324h] [xbp-4Ch] int v63; // [xsp+32Ch] [xbp-44h] __int64 v64; // [xsp+330h] [xbp-40h] __int64 v65; // [xsp+338h] [xbp-38h] __int64 v66; // [xsp+340h] [xbp-30h] __int64 v67; // [xsp+348h] [xbp-28h] v67 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40); v66 = a3; v65 = a2; v64 = a1; v63 = y_14; v62 = y_14; v61 = y_14; v60 = y_14; v59 = y_14; v58 = y_14; v57 = y_14; v27[4] = a1; v27[2] = a2; v27[0] = a3; v56 = &v22; v55 = &v21; v54 = &v20; v53 = v28; v52 = v28; v51 = v27; v50 = &v26; v49 = &v25; v48 = v24; v47 = v24; v46 = &v23; v45 = 0LL; v3 = sub_26F30(a1, a3, 0LL); v4 = (__int64)v51; *(v51 - 2) = v3; *(v50 - 2) = v45; v5 = (__int64)v49; *((_DWORD *)v49 - 4) = 0; *(_OWORD *)(v5 - 32) = 0u; *(_OWORD *)(v5 - 48) = 0u; *(_OWORD *)(v5 - 64) = 0u; *(_OWORD *)(v5 - 80) = 0u; *(_OWORD *)(v5 - 96) = 0u; *(_OWORD *)(v5 - 112) = 0u; v6 = sprintf(v48, "%s666", *(const char **)(v4 - 16)); v7 = *(v52 - 2); v44 = v6; v8 = sub_273D0(v7, v48); v9 = (__int64)v47; *((_QWORD *)v47 - 2) = v8; v10 = sub_26F30(*(v52 - 2), *(_QWORD *)(v9 - 16), v45); *(v46 - 2) = v10; v11 = sub_27BD0(*(v52 - 2), "com/kanxue/crackme/MainActivity"); v12 = (__int64)v56; *(v56 - 2) = v11; v13 = sub_28C40(*(v52 - 2), *(_QWORD *)(v12 - 16), "crypt2", "(Ljava/lang/String;)Z"); v14 = (__int64)v55; *(v55 - 2) = v13; v15 = sub_28EB8(*(v52 - 2), *(v56 - 2), *(_QWORD *)(v14 - 16), *((_QWORD *)v47 - 2)); v16 = (__int64)v54; *((_BYTE *)v54 - 16) = v15; v17 = *(_BYTE *)(v16 - 16) != 0; v43 = *(unsigned __int8 *)(v16 - 16); v42 = v17; v41 = y_14; v40 = y_14; v39 = y_14; v38 = y_14; v37 = y_14; v36 = y_14; v35 = y_14; if ( v17 ) { v34 = y_14; if ( ((x_13 * (x_13 - 1)) & 1) != 0 ) { v33 = v34 - 9; if ( v34 > 9 ) goto LABEL_9; } while ( 1 ) { *v53 = 1; v32 = y_14; if ( ((x_13 * (x_13 - 1)) & 1) == 0 ) break; v31 = v32 - 9; if ( v32 <= 9 ) break;LABEL_9: *v53 = 1; } } else { v30 = y_14; *v53 = 0; v29 = y_14; } v18 = (unsigned __int8)*v53; v28[71] = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40) - v67; return v18;}

可以看到返回值主要取决于sub_28EB8。
__int64 sub_28EB8(JNIEnv *a1, __int64 a2, __int64 a3, ...){ jboolean (*v3)(JNIEnv *, jclass, jmethodID, va_list); // x1 jboolean v4; // w0 __int64 v5; // x8 gcc_va_list va1; // [xsp-80h] [xbp-220h] BYREF gcc_va_list va; // [xsp-60h] [xbp-200h] BYREF _QWORD v9[21]; // [xsp-30h] [xbp-1D0h] BYREF unsigned int v10; // [xsp+7Ch] [xbp-124h] _QWORD *v11; // [xsp+80h] [xbp-120h] jboolean (*v12)(JNIEnv *, jclass, jmethodID, va_list); // [xsp+88h] [xbp-118h] int v13; // [xsp+94h] [xbp-10Ch] int v14; // [xsp+9Ch] [xbp-104h] int v15; // [xsp+A4h] [xbp-FCh] int v16; // [xsp+ACh] [xbp-F4h] int v17; // [xsp+B4h] [xbp-ECh] int v18; // [xsp+BCh] [xbp-E4h] int v19; // [xsp+C4h] [xbp-DCh] JNIEnv *v20; // [xsp+C8h] [xbp-D8h] void *v21; // [xsp+D0h] [xbp-D0h] __int64 v22; // [xsp+D8h] [xbp-C8h] __int64 v23; // [xsp+188h] [xbp-18h] va_start(va, a3); v23 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40); v22 = a3; v21 = (void *)a2; v20 = a1; v19 = y_24; v18 = y_24; v17 = y_24; v16 = y_24; v15 = y_24; v14 = y_24; v13 = y_24; v9[4] = a1; v9[2] = a2; v9[0] = a3; v3 = (*a1)->CallStaticBooleanMethodV; va_copy(va1, va); v12 = v3; v11 = v9; v4 = v3(a1, v21, (jmethodID)a3, va1); v5 = (__int64)v11; *((_BYTE *)v11 - 16) = v4; v10 = *(unsigned __int8 *)(v5 - 16); _ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)); return v10;}

sub_28EB8实际上就是去调用Java_com_kanxue_crackme_MainActivity_crypt2。
__int64 __fastcall Java_com_kanxue_crackme_MainActivity_crypt2(__int64 a1, __int64 a2, __int64 a3){ const char *v4; // [xsp+68h] [xbp-A8h] unsigned __int8 v5; // [xsp+8Ch] [xbp-84h] char s[16]; // [xsp+90h] [xbp-80h] BYREF __int128 v7; // [xsp+A0h] [xbp-70h] __int128 v8; // [xsp+B0h] [xbp-60h] __int128 v9; // [xsp+C0h] [xbp-50h] __int128 v10; // [xsp+D0h] [xbp-40h] __int128 v11; // [xsp+E0h] [xbp-30h] int v12; // [xsp+F0h] [xbp-20h] __int64 v13; // [xsp+F8h] [xbp-18h] v13 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40); v4 = (const char *)sub_26F30(a1, a3, 0LL); v12 = 0; v11 = 0u; v10 = 0u; v9 = 0u; v8 = 0u; v7 = 0u; *(_OWORD *)s = 0u; sprintf(s, "%s", v4); if ( (sub_22390(s) & 1) != 0 ) { while ( ((x_25 * (x_25 - 1)) & 1) != 0 && y_26 > 9 ) ; do v5 = 1; while ( ((x_25 * (x_25 - 1)) & 1) != 0 && y_26 > 9 ); while ( ((x_25 * (x_25 - 1)) & 1) != 0 && y_26 > 9 ) ; } else { v5 = 0; } _ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)); return v5;}

Java_com_kanxue_crackme_MainActivity_crypt2的返回值取决于sub_22390,通过调试可以知道它的参数就是我们的输入的字符串后面拼接666。
__int64 __fastcall sub_22390(const char *a1){ __int64 v1; // x0 __int64 v2; // x8 __int64 v4; // [xsp-40h] [xbp-4B0h] BYREF _QWORD v5[4]; // [xsp-30h] [xbp-4A0h] BYREF _DWORD v6[28]; // [xsp-10h] [xbp-480h] BYREF int v7; // [xsp+60h] [xbp-410h] int v8; // [xsp+64h] [xbp-40Ch] int v9; // [xsp+68h] [xbp-408h] int v10; // [xsp+6Ch] [xbp-404h] int v11; // [xsp+70h] [xbp-400h] int v12; // [xsp+74h] [xbp-3FCh] int v13; // [xsp+78h] [xbp-3F8h] int v14; // [xsp+7Ch] [xbp-3F4h] int v15; // [xsp+80h] [xbp-3F0h] int v16; // [xsp+84h] [xbp-3ECh] int v17; // [xsp+88h] [xbp-3E8h] int v18; // [xsp+8Ch] [xbp-3E4h] int v19; // [xsp+90h] [xbp-3E0h] int v20; // [xsp+94h] [xbp-3DCh] int v21; // [xsp+98h] [xbp-3D8h] int v22; // [xsp+9Ch] [xbp-3D4h] int v23; // [xsp+A0h] [xbp-3D0h] int v24; // [xsp+A4h] [xbp-3CCh] int v25; // [xsp+A8h] [xbp-3C8h] int v26; // [xsp+1A0h] [xbp-2D0h] int v27; // [xsp+1A4h] [xbp-2CCh] int v28; // [xsp+1A8h] [xbp-2C8h] int v29; // [xsp+1ACh] [xbp-2C4h] int v30; // [xsp+1B0h] [xbp-2C0h] int v31; // [xsp+1B4h] [xbp-2BCh] int v32; // [xsp+1B8h] [xbp-2B8h] int v33; // [xsp+1BCh] [xbp-2B4h] int v34; // [xsp+1C0h] [xbp-2B0h] int v35; // [xsp+1C4h] [xbp-2ACh] int v36; // [xsp+1C8h] [xbp-2A8h] int v37; // [xsp+1CCh] [xbp-2A4h] int v38; // [xsp+1D0h] [xbp-2A0h] int v39; // [xsp+1D4h] [xbp-29Ch] int v40; // [xsp+1D8h] [xbp-298h] int v41; // [xsp+1DCh] [xbp-294h] __int64 v42; // [xsp+1E0h] [xbp-290h] int v43; // [xsp+1F0h] [xbp-280h] int v44; // [xsp+1F4h] [xbp-27Ch] int v45; // [xsp+1FCh] [xbp-274h] int v46; // [xsp+204h] [xbp-26Ch] int v47; // [xsp+20Ch] [xbp-264h] int v48; // [xsp+214h] [xbp-25Ch] int v49; // [xsp+21Ch] [xbp-254h] int v50; // [xsp+224h] [xbp-24Ch] int v51; // [xsp+22Ch] [xbp-244h] int v52; // [xsp+234h] [xbp-23Ch] int v53; // [xsp+23Ch] [xbp-234h] int v54; // [xsp+244h] [xbp-22Ch] int v55; // [xsp+24Ch] [xbp-224h] int v56; // [xsp+254h] [xbp-21Ch] int v57; // [xsp+25Ch] [xbp-214h] int v58; // [xsp+264h] [xbp-20Ch] int v59; // [xsp+26Ch] [xbp-204h] int v60; // [xsp+274h] [xbp-1FCh] int v61; // [xsp+27Ch] [xbp-1F4h] int v62; // [xsp+284h] [xbp-1ECh] int v63; // [xsp+28Ch] [xbp-1E4h] int v64; // [xsp+294h] [xbp-1DCh] int v65; // [xsp+29Ch] [xbp-1D4h] int v66; // [xsp+2A4h] [xbp-1CCh] int v67; // [xsp+2ACh] [xbp-1C4h] int v68; // [xsp+2B0h] [xbp-1C0h] int v69; // [xsp+2B4h] [xbp-1BCh] int v70; // [xsp+2B8h] [xbp-1B8h] int v71; // [xsp+2BCh] [xbp-1B4h] int v72; // [xsp+2C0h] [xbp-1B0h] int v73; // [xsp+2C4h] [xbp-1ACh] int v74; // [xsp+2C8h] [xbp-1A8h] int v75; // [xsp+2CCh] [xbp-1A4h] int v76; // [xsp+2D0h] [xbp-1A0h] int v77; // [xsp+2D4h] [xbp-19Ch] int v78; // [xsp+2D8h] [xbp-198h] int v79; // [xsp+2DCh] [xbp-194h] int v80; // [xsp+2E0h] [xbp-190h] int v81; // [xsp+2E4h] [xbp-18Ch] int v82; // [xsp+2E8h] [xbp-188h] int v83; // [xsp+2ECh] [xbp-184h] int v84; // [xsp+2F0h] [xbp-180h] int v85; // [xsp+2F4h] [xbp-17Ch] int v86; // [xsp+2F8h] [xbp-178h] int v87; // [xsp+2FCh] [xbp-174h] int v88; // [xsp+300h] [xbp-170h] int v89; // [xsp+304h] [xbp-16Ch] int v90; // [xsp+308h] [xbp-168h] int v91; // [xsp+30Ch] [xbp-164h] int v92; // [xsp+310h] [xbp-160h] int v93; // [xsp+314h] [xbp-15Ch] int v94; // [xsp+318h] [xbp-158h] int v95; // [xsp+31Ch] [xbp-154h] int v96; // [xsp+320h] [xbp-150h] int v97; // [xsp+324h] [xbp-14Ch] int v98; // [xsp+328h] [xbp-148h] int v99; // [xsp+32Ch] [xbp-144h] int v100; // [xsp+330h] [xbp-140h] int v101; // [xsp+334h] [xbp-13Ch] int v102; // [xsp+338h] [xbp-138h] int v103; // [xsp+33Ch] [xbp-134h] int v104; // [xsp+340h] [xbp-130h] int v105; // [xsp+344h] [xbp-12Ch] int v106; // [xsp+348h] [xbp-128h] int v107; // [xsp+34Ch] [xbp-124h] int v108; // [xsp+350h] [xbp-120h] int v109; // [xsp+354h] [xbp-11Ch] int v110; // [xsp+358h] [xbp-118h] int v111; // [xsp+35Ch] [xbp-114h] int v112; // [xsp+360h] [xbp-110h] int v113; // [xsp+364h] [xbp-10Ch] int v114; // [xsp+368h] [xbp-108h] int v115; // [xsp+36Ch] [xbp-104h] int v116; // [xsp+370h] [xbp-100h] int v117; // [xsp+374h] [xbp-FCh] int v118; // [xsp+378h] [xbp-F8h] int v119; // [xsp+37Ch] [xbp-F4h] int v120; // [xsp+380h] [xbp-F0h] int v121; // [xsp+384h] [xbp-ECh] int v122; // [xsp+388h] [xbp-E8h] int v123; // [xsp+38Ch] [xbp-E4h] int v124; // [xsp+390h] [xbp-E0h] int v125; // [xsp+394h] [xbp-DCh] int v126; // [xsp+398h] [xbp-D8h] int v127; // [xsp+39Ch] [xbp-D4h] int v128; // [xsp+3A0h] [xbp-D0h] int v129; // [xsp+3A4h] [xbp-CCh] int v130; // [xsp+3A8h] [xbp-C8h] int v131; // [xsp+3ACh] [xbp-C4h] int v132; // [xsp+3B0h] [xbp-C0h] int v133; // [xsp+3B4h] [xbp-BCh] int v134; // [xsp+3B8h] [xbp-B8h] int v135; // [xsp+3BCh] [xbp-B4h] int v136; // [xsp+3C0h] [xbp-B0h] int v137; // [xsp+3C4h] [xbp-ACh] int v138; // [xsp+3C8h] [xbp-A8h] int v139; // [xsp+3CCh] [xbp-A4h] int v140; // [xsp+3D0h] [xbp-A0h] int v141; // [xsp+3D4h] [xbp-9Ch] int v142; // [xsp+3D8h] [xbp-98h] int v143; // [xsp+3DCh] [xbp-94h] int v144; // [xsp+3E0h] [xbp-90h] int v145; // [xsp+3E4h] [xbp-8Ch] int v146; // [xsp+3E8h] [xbp-88h] int v147; // [xsp+3ECh] [xbp-84h] int v148; // [xsp+3F4h] [xbp-7Ch] int v149; // [xsp+3FCh] [xbp-74h] int v150; // [xsp+404h] [xbp-6Ch] int v151; // [xsp+40Ch] [xbp-64h] int v152; // [xsp+414h] [xbp-5Ch] _BOOL4 v153; // [xsp+418h] [xbp-58h] int v154; // [xsp+41Ch] [xbp-54h] __int64 v155; // [xsp+420h] [xbp-50h] const char *v156; // [xsp+428h] [xbp-48h] _QWORD *v157; // [xsp+430h] [xbp-40h] __int64 *v158; // [xsp+438h] [xbp-38h] _BYTE *v159; // [xsp+440h] [xbp-30h] int v160; // [xsp+44Ch] [xbp-24h] const char *v161; // [xsp+450h] [xbp-20h] __int64 v162; // [xsp+458h] [xbp-18h] v162 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40); v161 = a1; v160 = y_12; v5[2] = a1; v4 = 0LL; v159 = v6; v158 = &v4; v157 = v5; v156 = a1; v155 = strlen(a1); v1 = sub_19A60(v156, v155, v158); v2 = (__int64)v157; *(v157 - 2) = v1; v154 = strcmp((const char *)qword_2C0C8, *(const char **)(v2 - 16)); v153 = v154 == 0; v152 = y_12; v151 = y_12; v150 = y_12; v149 = y_12; v148 = y_12; if ( !v154 ) { v147 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v146 = v147 - 9; do { v145 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v144 = v145 - 9; } while ( v145 > 9 ); v143 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v142 = v143 - 9; if ( v143 > 9 ) goto LABEL_105; } while ( 1 ) { v141 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v140 = v141 - 9; if ( v141 <= 9 ) break;LABEL_105: v25 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v24 = v25 - 9; do { v23 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v22 = v23 - 9; } while ( v23 > 9 ); } v139 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v138 = v139 - 9; do { v137 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v136 = v137 - 9; do { v135 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v134 = v135 - 9; } while ( v135 > 9 ); v133 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v132 = v133 - 9; } while ( v133 > 9 ); v131 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v130 = v131 - 9; do { v129 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v128 = v129 - 9; do { v127 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v126 = v127 - 9; } while ( v127 > 9 ); v125 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v124 = v125 - 9; do { v123 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v122 = v123 - 9; do { v121 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v120 = v121 - 9; } while ( v121 > 9 ); v119 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v118 = v119 - 9; } while ( v119 > 9 ); v117 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v116 = v117 - 9; } while ( v117 > 9 ); v115 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v114 = v115 - 9; if ( v115 > 9 ) goto LABEL_111; } while ( 1 ) { v113 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v112 = v113 - 9; do { v111 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v110 = v111 - 9; } while ( v111 > 9 ); v109 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v108 = v109 - 9; if ( v109 <= 9 ) break;LABEL_111: v21 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v20 = v21 - 9; do { v19 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v18 = v19 - 9; } while ( v19 > 9 ); } v107 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v106 = v107 - 9; while ( 1 ) { v105 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v104 = v105 - 9; if ( v105 > 9 ) goto LABEL_116; } while ( 1 ) { v103 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v102 = v103 - 9; do { v101 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v100 = v101 - 9; } while ( v101 > 9 ); v99 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v98 = v99 - 9; if ( v99 <= 9 ) break;LABEL_116: v17 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v16 = v17 - 9; do { v15 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v14 = v15 - 9; } while ( v15 > 9 ); } v97 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v96 = v97 - 9; if ( v97 > 9 ) continue; } v95 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) goto LABEL_56; v94 = v95 - 9; if ( v95 <= 9 ) goto LABEL_56; while ( 1 ) { v41 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v40 = v41 - 9; do { v39 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v38 = v39 - 9; } while ( v39 > 9 ); v37 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v36 = v37 - 9; if ( v37 > 9 ) {LABEL_126: v9 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v8 = v9 - 9; if ( v9 > 9 )LABEL_136: *v159 = 1; } *v159 = 1; v7 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v6[27] = v7 - 9; if ( v7 > 9 ) goto LABEL_136; } } } v35 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v34 = v35 - 9; if ( v35 > 9 )LABEL_135: *v159 = 1; } *v159 = 1; v33 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v32 = v33 - 9; if ( v33 > 9 ) goto LABEL_135; } v31 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v30 = v31 - 9; if ( v31 > 9 ) goto LABEL_126; } v29 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v28 = v29 - 9; do { v27 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v26 = v27 - 9; } while ( v27 > 9 );LABEL_56: v93 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v92 = v93 - 9; do { v91 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v90 = v91 - 9; } while ( v91 > 9 ); v89 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v88 = v89 - 9; do { v87 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v86 = v87 - 9; if ( v87 > 9 ) goto LABEL_121; } while ( 1 ) { v85 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v84 = v85 - 9; do { v83 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v82 = v83 - 9; } while ( v83 > 9 ); v81 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v80 = v81 - 9; if ( v81 <= 9 ) break;LABEL_121: v13 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v12 = v13 - 9; do { v11 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v10 = v11 - 9; } while ( v11 > 9 ); } v79 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v78 = v79 - 9; } while ( v79 > 9 ); v77 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v76 = v77 - 9; if ( v77 > 9 ) {LABEL_103: *v159 = 1; goto LABEL_74; } }LABEL_74: *v159 = 1; v75 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v74 = v75 - 9; if ( v75 > 9 ) goto LABEL_103; } v73 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) v72 = v73 - 9; do { v71 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) == 0 ) break; v70 = v71 - 9; } while ( v71 > 9 ); v69 = y_12; if ( ((x_11 * (x_11 - 1)) & 1) != 0 ) { v68 = v69 - 9; if ( v69 > 9 ) continue; } goto LABEL_84; } } } v67 = y_12; v66 = y_12; v65 = y_12; v64 = y_12; v63 = y_12; v62 = y_12; v61 = y_12; v60 = y_12; v59 = y_12; v58 = y_12; v57 = y_12; v56 = y_12; v55 = y_12; v54 = y_12; v53 = y_12; *v159 = 0; v52 = y_12; v51 = y_12; v50 = y_12;LABEL_84: v49 = y_12; v48 = y_12; v47 = y_12; v46 = y_12; v45 = y_12; v44 = (unsigned __int8)*v159; v43 = y_12; v42 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40) - v162; return v44 & 1;}

sub_22390中还是有大量的ollvm混淆后的分支,说明我们之前的几个错误输入都没有进入到里面执行,因此我们需要想办法构造一个输入来进入到里面进行执行,我们的输入首先被传入了sub_19A60中。
_BYTE *__fastcall sub_19A60(__int64 a1, __int64 a2, __int64 *a3){ int v4; // [xsp+78h] [xbp-38h] int v5; // [xsp+7Ch] [xbp-34h] _BYTE *v6; // [xsp+80h] [xbp-30h] __int64 v7; // [xsp+88h] [xbp-28h] _BYTE *v11; // [xsp+A8h] [xbp-8h] if ( a2 % 3 ) v7 = 4 * (a2 / 3 + 1); else v7 = 4 * (a2 / 3); v6 = malloc((int)v7 + 1); if ( v6 ) { v6[v7] = 0; *a3 = v7; v5 = 0; v4 = 0; while ( v5 < v7 - 2 ) { while ( 1 ) { v6[v5] = aAbcdefghijklmn[(int)*(unsigned __int8 *)(a1 + v4) >> 2]; v6[v5 + 1] = aAbcdefghijklmn[(16 * (*(_BYTE *)(a1 + v4) & 3)) | ((int)*(unsigned __int8 *)(a1 + v4 + 1) >> 4)]; v6[v5 + 2] = aAbcdefghijklmn[(4 * (*(_BYTE *)(a1 + v4 + 1) & 0xF)) | ((int)*(unsigned __int8 *)(a1 + v4 + 2) >> 6)]; v6[v5 + 3] = aAbcdefghijklmn[*(_BYTE *)(a1 + v4 + 2) & 0x3F]; if ( x * (x - 1) % 2u == 0 || y < 10 ) break; v6[v5] = aAbcdefghijklmn[(int)*(unsigned __int8 *)(a1 + v4) >> 2]; v6[v5 + 1] = aAbcdefghijklmn[(16 * (*(_BYTE *)(a1 + v4) & 3)) | ((int)*(unsigned __int8 *)(a1 + v4 + 1) >> 4)]; v6[v5 + 2] = aAbcdefghijklmn[(4 * (*(_BYTE *)(a1 + v4 + 1) & 0xF)) | ((int)*(unsigned __int8 *)(a1 + v4 + 2) >> 6)]; v6[v5 + 3] = aAbcdefghijklmn[*(_BYTE *)(a1 + v4 + 2) & 0x3F]; } v4 += 3; v5 += 4; } if ( a2 % 3 == 1 ) { v6[v5 - 2] = 61; v6[v5 - 1] = 61; } else if ( a2 % 3 == 2 ) { v6[v5 - 1] = 61; } v11 = v6; } else { while ( x * (x - 1) % 2u != 0 && y >= 10 ) ; while ( x * (x - 1) % 2u != 0 && y >= 10 ) ; while ( x * (x - 1) % 2u != 0 && y >= 10 ) ; do v11 = 0LL; while ( x * (x - 1) % 2u != 0 && y >= 10 ); while ( x * (x - 1) % 2u != 0 && y >= 10 ) ; while ( x * (x - 1) % 2u != 0 && y >= 10 ) ; while ( x * (x - 1) % 2u != 0 && y >= 10 ) ; } return v11;}

很显然是一个base64的函数,通过调试可以知道之后的结果通过strcmp与WFVlNjY2进行比较来判断是否进入下面的分支中运行。WFVlNjY2解码得到XUe666,因此我们在模拟调用时以XUe作为参数再次运行后对so进行patch,可以发现XUe就是正确的答案,同时之前一些分支的混淆也被去除了。
 
sub_22390
__int64 __fastcall sub_22390(const char *a1){ __int64 v1; // x0 __int64 v2; // x8 __int64 v4; // [xsp-40h] [xbp-4B0h] BYREF _QWORD v5[4]; // [xsp-30h] [xbp-4A0h] BYREF __int64 v6; // [xsp-10h] [xbp-480h] BYREF char v7; // [xsp+1F4h] [xbp-27Ch] int v8; // [xsp+1FCh] [xbp-274h] int v9; // [xsp+204h] [xbp-26Ch] int v10; // [xsp+20Ch] [xbp-264h] int v11; // [xsp+214h] [xbp-25Ch] int v12; // [xsp+21Ch] [xbp-254h] int v13; // [xsp+224h] [xbp-24Ch] int v14; // [xsp+22Ch] [xbp-244h] int v15; // [xsp+234h] [xbp-23Ch] int v16; // [xsp+23Ch] [xbp-234h] int v17; // [xsp+244h] [xbp-22Ch] int v18; // [xsp+24Ch] [xbp-224h] int v19; // [xsp+254h] [xbp-21Ch] int v20; // [xsp+25Ch] [xbp-214h] int v21; // [xsp+264h] [xbp-20Ch] int v22; // [xsp+26Ch] [xbp-204h] int v23; // [xsp+274h] [xbp-1FCh] int v24; // [xsp+27Ch] [xbp-1F4h] int v25; // [xsp+284h] [xbp-1ECh] int v26; // [xsp+28Ch] [xbp-1E4h] int v27; // [xsp+294h] [xbp-1DCh] int v28; // [xsp+29Ch] [xbp-1D4h] int v29; // [xsp+2A4h] [xbp-1CCh] int v30; // [xsp+2ACh] [xbp-1C4h] int v31; // [xsp+2B4h] [xbp-1BCh] int v32; // [xsp+2BCh] [xbp-1B4h] int v33; // [xsp+2C4h] [xbp-1ACh] int v34; // [xsp+2CCh] [xbp-1A4h] int v35; // [xsp+2D4h] [xbp-19Ch] int v36; // [xsp+2DCh] [xbp-194h] int v37; // [xsp+2E4h] [xbp-18Ch] int v38; // [xsp+2ECh] [xbp-184h] int v39; // [xsp+2F4h] [xbp-17Ch] int v40; // [xsp+2FCh] [xbp-174h] int v41; // [xsp+304h] [xbp-16Ch] int v42; // [xsp+30Ch] [xbp-164h] int v43; // [xsp+314h] [xbp-15Ch] int v44; // [xsp+31Ch] [xbp-154h] int v45; // [xsp+324h] [xbp-14Ch] int v46; // [xsp+32Ch] [xbp-144h] int v47; // [xsp+334h] [xbp-13Ch] int v48; // [xsp+33Ch] [xbp-134h] int v49; // [xsp+344h] [xbp-12Ch] int v50; // [xsp+34Ch] [xbp-124h] int v51; // [xsp+354h] [xbp-11Ch] int v52; // [xsp+35Ch] [xbp-114h] int v53; // [xsp+364h] [xbp-10Ch] int v54; // [xsp+36Ch] [xbp-104h] int v55; // [xsp+374h] [xbp-FCh] int v56; // [xsp+37Ch] [xbp-F4h] int v57; // [xsp+384h] [xbp-ECh] int v58; // [xsp+38Ch] [xbp-E4h] int v59; // [xsp+394h] [xbp-DCh] int v60; // [xsp+39Ch] [xbp-D4h] int v61; // [xsp+3A4h] [xbp-CCh] int v62; // [xsp+3ACh] [xbp-C4h] int v63; // [xsp+3B4h] [xbp-BCh] int v64; // [xsp+3BCh] [xbp-B4h] int v65; // [xsp+3C4h] [xbp-ACh] int v66; // [xsp+3CCh] [xbp-A4h] int v67; // [xsp+3D4h] [xbp-9Ch] int v68; // [xsp+3DCh] [xbp-94h] int v69; // [xsp+3E4h] [xbp-8Ch] int v70; // [xsp+3ECh] [xbp-84h] int v71; // [xsp+3F4h] [xbp-7Ch] int v72; // [xsp+3FCh] [xbp-74h] int v73; // [xsp+404h] [xbp-6Ch] int v74; // [xsp+40Ch] [xbp-64h] int v75; // [xsp+414h] [xbp-5Ch] _BOOL4 v76; // [xsp+418h] [xbp-58h] int v77; // [xsp+41Ch] [xbp-54h] __int64 v78; // [xsp+420h] [xbp-50h] const char *v79; // [xsp+428h] [xbp-48h] _QWORD *v80; // [xsp+430h] [xbp-40h] __int64 *v81; // [xsp+438h] [xbp-38h] char *v82; // [xsp+440h] [xbp-30h] int v83; // [xsp+44Ch] [xbp-24h] const char *v84; // [xsp+450h] [xbp-20h] __int64 v85; // [xsp+458h] [xbp-18h] v85 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40); v84 = a1; v83 = y_12; v5[2] = a1; v4 = 0LL; v82 = (char *)&v6; v81 = &v4; v80 = v5; v79 = a1; v78 = strlen(a1); v1 = sub_19A60(v79, v78, v81); v2 = (__int64)v80; *(v80 - 2) = v1; v77 = strcmp((const char *)qword_2C0C8, *(const char **)(v2 - 16)); v76 = v77 == 0; v75 = y_12; v74 = y_12; v73 = y_12; v72 = y_12; v71 = y_12; if ( v77 ) { v30 = y_12; v29 = y_12; v28 = y_12; v27 = y_12; v26 = y_12; v25 = y_12; v24 = y_12; v23 = y_12; v22 = y_12; v21 = y_12; v20 = y_12; v19 = y_12; v18 = y_12; v17 = y_12; v16 = y_12; *v82 = 0; v15 = y_12; v14 = y_12; v13 = y_12; } else { v70 = y_12; v69 = y_12; v68 = y_12; v67 = y_12; v66 = y_12; v65 = y_12; v64 = y_12; v63 = y_12; v62 = y_12; v61 = y_12; v60 = y_12; v59 = y_12; v58 = y_12; v57 = y_12; v56 = y_12; v55 = y_12; v54 = y_12; v53 = y_12; v52 = y_12; v51 = y_12; v50 = y_12; v49 = y_12; v48 = y_12; v47 = y_12; v46 = y_12; v45 = y_12; v44 = y_12; v43 = y_12; v42 = y_12; v41 = y_12; v40 = y_12; v39 = y_12; v38 = y_12; v37 = y_12; v36 = y_12; v35 = y_12; *v82 = 1; v34 = y_12; v33 = y_12; v32 = y_12; v31 = y_12; } v12 = y_12; v11 = y_12; v10 = y_12; v9 = y_12; v8 = y_12; v7 = *v82; _ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)); return v7 & 1;}

去除混淆后,可以发现sub_22390的逻辑很简单,就是返回输入的值经过base64与一个常量比较的结果。至此整个逻辑分析完毕,正确答案是XUe。
 
由于本题的ollvm混淆比较有特征性,所以才能够简单的去除掉。


 


看雪ID:wyongcan

https://bbs.pediy.com/user-home-209173.htm

  *本文由看雪论坛 wyongcan 原创,转载请注明来自看雪社区


# 往期推荐





公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



球分享

球点赞

球在看



点击“阅读原文”,了解更多!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存