AK了逆向
一、easyAndroid
二血
思绪:.so层的代码逻辑极其杂乱,简直无从下手,不过经过分析后发现标题采用了单字节加密,可以直接爆破出flag解题流程如下:实验trace跟踪一下字符串这里使用unidbg对输入字符串地址下内存访问断点,跟踪log如下:- [12:41:03 810] Memory READ at 0x400e1000, data size = 8, data value = 0x3333323231313030, PC=RX@0x4021cbf4[libc.so]0x1cbf4, LR=RX@0x40038338[libeasyandroid.so]0x38338
- [12:41:03 811] Memory READ at 0x400e1008, data size = 8, data value = 0x3737363635353434, PC=RX@0x4021cbf4[libc.so]0x1cbf4, LR=RX@0x40038338[libeasyandroid.so]0x38338
- [12:41:03 811] Memory READ at 0x400e1010, data size = 8, data value = 0x6262616139393838, PC=RX@0x4021cbf4[libc.so]0x1cbf4, LR=RX@0x40038338[libeasyandroid.so]0x38338
- [12:41:03 811] Memory READ at 0x400e1018, data size = 8, data value = 0x6666656564646363, PC=RX@0x4021cbf4[libc.so]0x1cbf4, LR=RX@0x40038338[libeasyandroid.so]0x38338
- [12:41:03 811] Memory READ at 0x400e1020, data size = 8, data value = 0x6e736c74, PC=RX@0x4021cbf4[libc.so]0x1cbf4, LR=RX@0x40038338[libeasyandroid.so]0x38338
- [12:41:03 811] Memory READ at 0x400e1010, data size = 4, data value = 0x39393838, PC=RX@0x40021c00[libeasyandroid.so]0x21c00, LR=RX@0x40038348[libeasyandroid.so]0x38348
- [12:41:03 811] Memory READ at 0x400e1020, data size = 4, data value = 0x6e736c74, PC=RX@0x40021c00[libeasyandroid.so]0x21c00, LR=RX@0x40038348[libeasyandroid.so]0x38348
- [12:41:03 811] Memory READ at 0x400e1008, data size = 4, data value = 0x35353434, PC=RX@0x40021c00[libeasyandroid.so]0x21c00, LR=RX@0x40038348[libeasyandroid.so]0x38348
- [12:41:03 811] Memory READ at 0x400e1000, data size = 4, data value = 0x31313030, PC=RX@0x40021c00[libeasyandroid.so]0x21c00, LR=RX@0x40038348[libeasyandroid.so]0x38348
- [12:41:03 812] Memory READ at 0x400e1000, data size = 8, data value = 0x3333323231313030, PC=RX@0x4021c180[libc.so]0x1c180, LR=RX@0x40021d88[libeasyandroid.so]0x21d88
- [12:41:03 812] Memory READ at 0x400e1008, data size = 8, data value = 0x3737363635353434, PC=RX@0x4021c180[libc.so]0x1c180, LR=RX@0x40021d88[libeasyandroid.so]0x21d88
- [12:41:03 812] Memory READ at 0x400e1010, data size = 8, data value = 0x6262616139393838, PC=RX@0x4021c180[libc.so]0x1c180, LR=RX@0x40021d88[libeasyandroid.so]0x21d88
- [12:41:03 812] Memory READ at 0x400e1018, data size = 8, data value = 0x6666656564646363, PC=RX@0x4021c180[libc.so]0x1c180, LR=RX@0x40021d88[libeasyandroid.so]0x21d88
- [12:41:03 812] Memory READ at 0x400e1014, data size = 8, data value = 0x6464636362626161, PC=RX@0x4021c198[libc.so]0x1c198, LR=RX@0x40021d88[libeasyandroid.so]0x21d88
- [12:41:03 812] Memory READ at 0x400e101c, data size = 8, data value = 0x6e736c7466666565, PC=RX@0x4021c198[libc.so]0x1c198, LR=RX@0x40021d88[libeasyandroid.so]0x21d88
复制代码
定位到地址 偏移为 0x21D88的函数(0x21BB8),在函数首部下断点,使用unidbg调试一下,经过调试,我们可以发现一些端倪,我们可以发现,每次进入0x21BB8的时候 x1寄存器的变化如下(输入字符串为 "abcdefghijklmnopqrstuvwxyz0123456789")- abcdefghijklmnopqrstuvwxyz0123456789
- e2
- be
- e3
- ed
- e3
- e3
- e2
- bf
- e3
- b9
- bf
- e2
- bf
- bb
- bf
- e2
- bf
- bf
- e2bee3ede3e3e2bfe3b9bfe2bfbbbfe2bfbf
- abcdefghijklmnopqrstuvwxyz0123456789
- 99bee3ede3e3e2bfe3b9bfe2bfbbbfe2bfbf
- \x99
- \x999bee3ede3e3e2bfe3b9bfe2bfbbbfe2bfbf
- bcdefghijklmnopqrstuvwxyz0123456789
- 02bee3ede3e3e2bfe3b9bfe2bfbbbfe2bfbf
- 9902e3ede3e3e2bfe3b9bfe2bfbbbfe2bfbf
- \x02
- \x99\0202e3ede3e3e2bfe3b9bfe2bfbbbfe2bfbf
- cdefghijklmnopqrstuvwxyz0123456789
- 4602e3ede3e3e2bfe3b9bfe2bfbbbfe2bfbf
- 990246ede3e3e2bfe3b9bfe2bfbbbfe2bfbf
- \x46
- \x99\x02\x46246ede3e3e2bfe3b9bfe2bfbbbfe2bfbf
- defghijklmnopqrstuvwxyz0123456789
- bdF246ede3e3e2bfe3b9bfe2bfbbbfe2bfbf
- 990246bde3e3e2bfe3b9bfe2bfbbbfe2bfbf
- \xbd
- \x99\x02\x46\xBD46bde3e3e2bfe3b9bfe2bfbbbfe2bfbf
- efghijklmnopqrstuvwxyz0123456789
- 9eF.46bde3e3e2bfe3b9bfe2bfbbbfe2bfbf
- 990246bd9ee3e2bfe3b9bfe2bfbbbfe2bfbf
- \x9e
- \x99\x02\x46\xbd\x9e6bd9ee3e2bfe3b9bfe2bfbbbfe2bfbf
- fghijklmnopqrstuvwxyz0123456789
- 3cF\xBD\x9E6bd9ee3e2bfe3b9bfe2bfbbbfe2bfbf
- 990246bd9e3ce2bfe3b9bfe2bfbbbfe2bfbf
- \x3c
- \x99\x02\x46\xBD\x9E\x3Cbd9e3ce2bfe3b9bfe2bfbbbfe2bfbf
- ghijklmnopqrstuvwxyz0123456789
- 42F\xBD\x9E\x3Cbd9e3ce2bfe3b9bfe2bfbbbfe2bfbf
- ...
- ...
- ...
- 9e5112e8ca6d1700271280763df544927f776aeed3f0e8abd16f510c79dd62bed1fe11bc
复制代码
通过不断的调试,更换输入字符串,我们可以猜测出,这是一个有关字符串处理惩罚的函数,加密过程中存在一个特定的key: e2bee3ede3e3e2bfe3b9bfe2bfbbbfe2bfbf,同时程序采用了单字节加密的方法且加密的效果与字符所在的序列有关系,明白了这些点之后,我们可以实验爆破flag。这里我先得到了全部字符("0123456789wertyuiopasdfghjklzxcvbnm@!_{}-")的加密后的效果,由于加密效果与字符所在字符串序列有关,因此我得到了全部字符在全部序列的加密效果,之后直接暴力循环映射即可Exp:用unidbg获取全部字符在全部序列的解密效果:- package com.WMCTF;
- import com.github.unidbg.Emulator;
- import com.github.unidbg.arm.HookStatus;
- import com.github.unidbg.AndroidEmulator;
- import com.github.unidbg.Module;
- import com.github.unidbg.Symbol;
- import com.github.unidbg.debugger.BreakPointCallback;
- import com.github.unidbg.hook.hookzz.*;
- import com.github.unidbg.debugger.DebuggerType;
- import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
- import com.github.unidbg.linux.android.AndroidResolver;
- import com.github.unidbg.linux.android.dvm.DalvikModule;
- import com.github.unidbg.linux.android.dvm.DvmClass;
- import com.github.unidbg.linux.android.dvm.DvmObject;
- import com.github.unidbg.linux.android.dvm.VM;
- import com.github.unidbg.memory.Memory;
- import com.github.unidbg.virtualmodule.android.AndroidModule;
- import java.io.File;
- import com.github.unidbg.arm.context.Arm64RegisterContext;
- public class soeasy {
- public final AndroidEmulator emulator;
- public final VM vm;
- public final Memory memory;
- public final Module module;
- DvmClass cNative;
- public int hitCount = 0;
- public soeasy(){
- emulator = AndroidEmulatorBuilder.for64Bit().build();
- memory = emulator.getMemory();
- memory.setLibraryResolver(new AndroidResolver(23));
- emulator.getSyscallHandler().setEnableThreadDispatcher(true);
- vm = emulator.createDalvikVM();
- // vm.setVerbose(true);
- new AndroidModule(emulator,vm).register(memory);
- DalvikModule dalvikModule = vm.loadLibrary(new File("D:\\BTools\\APK_EASY_TOOL\\APK Easy Tool v1.60 Portable\\1-Decompiled APKs\\easyAndroid\\lib\\arm64-v8a\\libeasyandroid.so"), true);
- module = dalvikModule.getModule();
- vm.callJNI_OnLoad(emulator,module);
- }
- public void bc(){
- hitCount = 0;
- }
- public static void main(String[] args){
- soeasy mainActivity = new soeasy();
- String mp = "0123456789wertyuiopasdfghjklzxcvbnm@!_{}-";
- for (int i=0;i<mp.length();i++){
- char ch = mp.charAt(i);
- String x = String.valueOf(ch).repeat(36);
- System.out.printf(",");
- mainActivity.debugger(x);
- mainActivity.bc();
- }
- }
- private void debugger(String x) {
- // emulator.traceCode(module.base + 0x0000000000187D0,module.base + 0x0000000000B3F00);
- // emulator.traceRead(0x400e1000,0x400e1020);
- emulator.attach(DebuggerType.CONSOLE).addBreakPoint(module.base + 0x21bb8, new BreakPointCallback() {
- @Override
- public boolean onHit(Emulator<?> emulator, long address) {
- hitCount+=1;
- if(hitCount !=17+36*5+2){
- return true;
- }else{
- Arm64RegisterContext context = emulator.getContext();
- long x1Value = context.getXLong(1);
- Memory memory = emulator.getMemory();
- String read_data = memory.pointer(x1Value).getString(0).substring(0,72);
- // System.out.printf("->%x\n",x1Value);
- System.out.println(read_data);
- return true;
- }
- }
- });
- cNative = vm.resolveClass("com.s0rry.easyandroid.MainActivity");
- // String ang0 = "abcdefghijklmnopqrstuvwxyz0123456789";
- DvmObject<?> strRc = cNative.callStaticJniMethodObject(emulator,"aaa(Ljava/lang/String;)Z",x);
- }
- }
-
复制代码
python暴力映射:- mp1 = "0123456789wertyuiopasdfghjklzxcvbnm@!_{}-"
- mp2 = [
- bytes.fromhex("c85015e9cb6a15003a11d6753ce84097762577bcd7f1ebb6d96754047add67ecd8ab14bd")
- ,bytes.fromhex("c95114e8ca6b14013b10d7743de94196772476bdd6f0eab7d86655057bdc66edd9aa15bc")
- ,bytes.fromhex("ca5217ebc96817023813d4773eea4295742775bed5f3e9b4db65560678df65eedaa916bf")
- ,bytes.fromhex("cb5316eac86916033912d5763feb4394752674bfd4f2e8b5da64570779de64efdba817be")
- ,bytes.fromhex("cc5411edcf6e11043e15d27138ec4493722173b8d3f5efb2dd6350007ed963e8dcaf10b9")
- ,bytes.fromhex("cd5510ecce6f10053f14d37039ed4592732072b9d2f4eeb3dc6251017fd862e9ddae11b8")
- ,bytes.fromhex("ce5613efcd6c13063c17d0733aee4691702371bad1f7edb0df6152027cdb61eadead12bb")
- ,bytes.fromhex("cf5712eecc6d12073d16d1723bef4790712270bbd0f6ecb1de6053037dda60ebdfac13ba")
- ,bytes.fromhex("c0581de1c3621d083219de7d34e0489f7e2d7fb4dff9e3bed16f5c0c72d56fe4d0a31cb5")
- ,bytes.fromhex("c1591ce0c2631c093318df7c35e1499e7f2c7eb5def8e2bfd06e5d0d73d46ee5d1a21db4")
- ,bytes.fromhex("8f1752ae8c2d52477d5691327baf07d0316230fb90b6acf19e2013433d9a20ab9fec53fa")
- ,bytes.fromhex("9d0540bc9e3f40556f44832069bd15c2237022e982a4bee38c3201512f8832b98dfe41e8")
- ,bytes.fromhex("8a1257ab89285742785394377eaa02d5346735fe95b3a9f49b251646389f25ae9ae956ff")
- ,bytes.fromhex("8c1451ad8f2e51447e55923178ac04d3326133f893b5aff29d2310403e9923a89cef50f9")
- ,bytes.fromhex("81195ca082235c4973589f3c75a109de3f6c3ef59eb8a2ff902e1d4d33942ea591e25df4")
- ,bytes.fromhex("8d1550ac8e2f50457f54933079ad05d2336032f992b4aef39c2211413f9822a99dee51f8")
- ,bytes.fromhex("91094cb092334c5963488f2c65b119ce2f7c2ee58ea8b2ef803e0d5d23843eb581f24de4")
- ,bytes.fromhex("970f4ab694354a5f654e892a63b71fc8297a28e388aeb4e986380b5b258238b387f44be2")
- ,bytes.fromhex("881055a98b2a55407a5196357ca800d7366537fc97b1abf6992714443a9d27ac98eb54fd")
- ,bytes.fromhex("990144b89a3b44516b4087246db911c6277426ed86a0bae7883605552b8c36bd89fa45ec")
- ,bytes.fromhex("8b1356aa88295643795295367fab03d4356634ff94b2a8f59a241747399e24af9be857fe")
- ,bytes.fromhex("9c0441bd9f3e41546e45822168bc14c3227123e883a5bfe28d3300502e8933b88cff40e9")
- ,bytes.fromhex("9e0643bf9d3c43566c4780236abe16c1207321ea81a7bde08f3102522c8b31ba8efd42eb")
- ,bytes.fromhex("9f0742be9c3d42576d4681226bbf17c0217220eb80a6bce18e3003532d8a30bb8ffc43ea")
- ,bytes.fromhex("90084db193324d5862498e2d64b018cf2e7d2fe48fa9b3ee813f0c5c22853fb480f34ce5")
- ,bytes.fromhex("920a4fb391304f5a604b8c2f66b21acd2c7f2de68dabb1ec833d0e5e20873db682f14ee7")
- ,bytes.fromhex("930b4eb290314e5b614a8d2e67b31bcc2d7e2ce78caab0ed823c0f5f21863cb783f04fe6")
- ,bytes.fromhex("940c49b59736495c664d8a2960b41ccb2a792be08badb7ea853b085826813bb084f748e1")
- ,bytes.fromhex("821a5fa381205f4a705b9c3f76a20add3c6f3df69dbba1fc932d1e4e30972da692e15ef7")
- ,bytes.fromhex("80185da183225d4872599e3d74a008df3e6d3ff49fb9a3fe912f1c4c32952fa490e35cf5")
- ,bytes.fromhex("9b0346ba98394653694285266fbb13c4257624ef84a2b8e58a340757298e34bf8bf847ee")
- ,bytes.fromhex("8e1653af8d2c53467c5790337aae06d1306331fa91b7adf09f2112423c9b21aa9eed52fb")
- ,bytes.fromhex("9a0247bb99384752684384276eba12c5247725ee85a3b9e48b350656288f35be8af946ef")
- ,bytes.fromhex("960e4bb795344b5e644f882b62b61ec9287b29e289afb5e887390a5a248339b286f54ae3")
- ,bytes.fromhex("950d48b49637485d674c8b2861b51dca2b782ae18aacb6eb843a095927803ab185f649e0")
- ,bytes.fromhex("b8206599bb1a65704a61a6054c9830e7065507cca7819bc6a91724740aad179ca8db64cd")
- ,bytes.fromhex("d94104f8da7b04112b00c7642df95186673466adc6e0faa7c87645156bcc76fdc9ba05ac")
- ,bytes.fromhex("a73f7a86a4057a6f557eb91a53872ff8194a18d3b89e84d9b6083b6b15b20883b7c47bd2")
- ,bytes.fromhex("831b5ea280215e4b715a9d3e77a30bdc3d6e3cf79cbaa0fd922c1f4f31962ca793e05ff6")
- ,bytes.fromhex("851d58a48627584d775c9b3871a50dda3b683af19abca6fb942a194937902aa195e659f0")
- ,bytes.fromhex("d54d08f4d677081d270ccb6821f55d8a6b386aa1caecf6abc47a491967c07af1c5b609a0")]
- enc = bytes.fromhex("9e 51 12 e8 ca 6d 17 00 27 12 80 76 3d f5 44 92 7f 77 6a ee d3 f0 e8 ab d1 6f 51 0c 79 dd 62 be d1 fe 11 bc")
- flag = ""
- for i in range(len(enc)):
- x = enc[i]
- for j in range(len(mp2)):
-
- if mp2[j][i] == x:
- flag += mp1[j]
- print(flag)
复制代码
得到flag:WMCTF{f1711720-3f31-459b-b413-8858305b9e51}Ps: 其实这里直接用unidbg 的hook功能直接爆破就完事了,但我不是很熟悉unidbg上的hook,于是才采用了这种方法,借助python脚本完成爆破二、rustdroid
Rust语言编写的.so文件,没有去符号,加密逻辑也比较简单,直接z3求解即可
[code]from struct import unpack,packenstream = [0x66, 0xD1, 0xBB, 0x64, 0x21, 0x57, 0x10, 0x3F, 0xB6, 0xFE, 0x6D, 0xD2, 0x7F, 0xC6, 0x9D, 0xB4, 0xC3, 0x71, 0xE9, 0x5F, 0xF3, 0xA1, 0x2E, 0x34, 0xB2, 0xB3, 0xCA, 0x13, 0xB8, 0xA2, 0xC2, 0x82, 0xB7, 0x95, 0x68, 0x23, 0xA7, 0x41, 0xD5, 0x3C, 0x72, 0x63, 0x3E, 0x19, 0x06, 0x2F, 0x2C, 0xB9, 0xF1, 0xDB, 0x94, 0x1C, 0x56, 0xA3, 0x5E, 0x3B, 0xCE, 0x93, 0xE6, 0x32, 0xB5, 0x49, 0x6A, 0x8A, 0x7C, 0xAA, 0x9F, 0xD6, 0x50, 0xFA, 0x80, 0x15, 0x8E, 0x5A, 0xF8, 0x03, 0x84, 0xE4, 0x98, 0x59, 0x43, 0x67, 0x0E, 0xCB, 0x5D, 0x5C, 0xD4, 0x40, 0xFD, 0xC0, 0x20, 0x70, 0x75, 0x1F, 0x2B, 0xEF, 0x08, 0x8B, 0x2D, 0x09, 0xC7, 0x86, 0x92, 0x28, 0xF7, 0x6F, 0x00, 0x8F, 0x45, 0x85, 0x35, 0xD9, 0xAE, 0x90, 0x14, 0xC5, 0x60, 0x58, 0xD8, 0x27, 0x3A, 0x17, 0x12, 0x76, 0xE1, 0xDF, 0x8D, 0x6C, 0xE0, 0xF4, 0x31, 0x1A, 0xBA, 0xAC, 0xE8, 0xAF, 0x9C, 0x25, 0xAD, 0x54, 0x91, 0xCD, 0x11, 0xEC, 0xE2, 0x01, 0x38, 0x47, 0x7B, 0x22, 0x1B, 0x02, 0xE5, 0xBE, 0xBD, 0x18, 0xA0, 0xC4, 0x99, 0x83, 0xC8, 0xCF, 0x96, 0x46, 0x3D, 0xBF, 0x87, 0xA9, 0xD3, 0xF6, 0x55, 0x24, 0x48, 0x78, 0xE3, 0xD7, 0xF5, 0x07, 0x65, 0xB0, 0xA6, 0x4D, 0x77, 0xFF, 0xA4, 0x1E, 0x9A, 0x4C, 0x30, 0x9E, 0x36, 0xDA, 0x89, 0xEE, 0x52, 0xAB, 0x9B, 0x0A, 0xDD, 0x53, 0x05, 0xEB, 0x51, 0xFB, 0xF9, 0x4B, 0x0F, 0x61, 0x69, 0xDC, 0xA5, 0x79, 0x7E, 0xED, 0x8C, 0xD0, 0xF2, 0x4F, 0x04, 0x33, 0x7A, 0x4E, 0x97, 0x74, 0x62, 0x0B, 0x1D, 0x2A, 0x16, 0xB1, 0x7D, 0x44, 0x42, 0xBC, 0x88, 0xF0, 0x4A, 0x81, 0x29, 0x39, 0xEA, 0x6E, 0xC9, 0x37, 0xE7, 0x5B, 0xFC, 0x0D, 0x73, 0xA8, 0x26, 0x6B, 0xCC, 0x0C, 0xDE, 0xC1]key = [0x77, 0x88, 0x99, 0x66]assert len(enstream)==256assert len(key) == 4def Q2b(m): return pack(" |