-
-
[原创]一道简单的ollvm算法题还原
-
2021-6-28 00:08 13385
-
本题出自看雪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,用于初始化调用参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | 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来区分判断是否是这种方式调用.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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 主要的模拟调用代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | 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.块的结尾两条汇编指令符合一定特征
1 2 3 4 5 6 | 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" ); |
然后随便用几个输入调用一下函数,让尽可能多的块被执行
1 2 3 | 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的反编译结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | __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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | __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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | __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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 | __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中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | _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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | __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混淆比较有特征性,所以才能够简单的去除掉。