WMCTF2024 RE wp

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求解即可

 

from struct import unpack,pack

enstream = [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)==256
assert len(key) == 4

def Q2b(m):
    return pack("<Q",m)

def D2b(m):
    return pack("<I",m)

enc = Q2b(0x4E4FCE594215BA1F)  + Q2b(0xC745BAE69BFD994) + Q2b(0x87081E9C7F8AFCC0) + Q2b(0x2BB08F87F5646BF5) + D2b(0x29FF53E2)


idx2 = 0
v11 = 0
from z3 import *
s = Solver()

inp = [BitVec(f'inp[{i}]', 8) for i in range(36)]
for idx in range(36):
    idx2+=1
    v13 = (LShR(inp[idx],1) | (inp[idx]<<7)) ^ 0xef
    v14 = enstream[idx2]
    v11 += v14
    v11 &= 0xff
    
    x1 = ((LShR(v13,2) | (v13<<6)) ^ 0xBE)
    v13 = (LShR(x1 ,3)  | (x1 << 5)) ^ 0xAD
    enstream[idx2] = enstream[v11]
    enstream[v11] = v14
    
    x2 = (LShR(v13,4) | (v13 << 4)) ^ 0xDE
    x = key[idx&3] ^ enstream[(enstream[idx2]+v14) & 0xff] ^ (LShR((x2),5) | (x2 << 3)) 
    s.add(x == enc[idx])

print(s.check())
res = s.model()
print("WMCTF{",end = "")
for i in range(0,36):
    print(chr(res[inp[i]].as_long()),end = "")

print("}")

 

Flag即为:

WMCTF{2a04aed7-e736-43c4-80a7-f6ed28de34eb}

 

 

三、ez_learn

题目作者通过控制堆栈修改程序的控制流来达到了代码混淆的作用,IDA静态分析不成功,但实际上只要稍微patch一下,即可还原伪代码:
如图,把阴影部分的汇编全部nop掉,让IDA重新分析一下,即可还原伪代码
 

 

 

接下来是一组加密操作,这组加密操作乍一看有些棘手,不过我们可以把每个函数拆解开来,合并起来一块分析。最后可以化简出加密操作与解密操作的流程:
x = 0x12 ^ inp[i+1] ^ inp[i+2] ^ inp[i+3]
加密操作:
inp[i+4] = Ror(sbox[x],8) ^ Ror(sbox[x],14) ^ Ror(sbox[x],22) ^ Ror(sbox[x],30) ^ sbox[x] ^ 0x34343434 ^ inp[i]
解密操作:
inp[i] = 0x34343434 ^ inp[i+4] ^ Ror(sbox[x],8) ^ Ror(sbox[x],14) ^ Ror(sbox[x],22) ^ Ror(sbox[x],30) ^ sbox[x]

 

 
Exp:
from struct import pack
f_N_a1 = [0xFF055A4E, 0x529CC66A, 0x18E3DA43, 0x0465E0E4, 0xFD58BCB6, 0x2C4E97EC, 0x48A234B8, 0x842EE158, 0x7C55AA74, 0x9BEF3AFE, 0x8779FE09, 0x1685B020, 0x95794366, 0x7AC1501F, 0x7FB0D538, 0x38980B16, 0x33D37C51, 0x5FAACC9B, 0xD47351CC, 0x48CEEAB2, 0x7C296054, 0xF163D1EF, 0x0DDB1E47, 0x9DA4F767, 0xFAF4B1E0, 0xFC5A5FB1, 0xD3FED672, 0x264B1A75, 0xEFA7E6C4, 0x94B344A4, 0xED19375F, 0x58AA0CED]
s_box = [0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, 0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, 0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48]

magic= 0

inp = [0] * 36

inp[35] = 0xc676e86f;
inp[34] = 0xad67e8f8;
inp[33] = 0xca9db9ac;
inp[32] = 0xb1ae068e;
def Ror(val,r):

    return (val >> r) | (val << (32 - r)) & 0xffffffff

for i in range(31,-1,-1):
    idx = 0x12121212 ^ inp[i+3] ^ inp[i+2] ^ inp[i+1] ^ f_N_a1[i]
    sl = s_box[idx&0xff]
    sm0 = s_box[(idx>>8)&0xff]
    sm1 = s_box[(idx>>16)&0xff]
    sh = s_box[(idx>>24)&0xff]
    s = sl + (sm0<<8) + (sm1 << 16) + (sh << 24)
    
    inp[i] = inp[i+4] ^ 0x34343434  ^ Ror(s,8) ^ Ror(s,14) ^ Ror(s,22) ^ Ror(s,30) ^ s

flag = b""
for i in range(4):
    flag +=pack("<I",inp[i])
print(flag)

from struct import pack
f_N_a1 = [0xFF055A4E, 0x529CC66A, 0x18E3DA43, 0x0465E0E4, 0xFD58BCB6, 0x2C4E97EC, 0x48A234B8, 0x842EE158, 0x7C55AA74, 0x9BEF3AFE, 0x8779FE09, 0x1685B020, 0x95794366, 0x7AC1501F, 0x7FB0D538, 0x38980B16, 0x33D37C51, 0x5FAACC9B, 0xD47351CC, 0x48CEEAB2, 0x7C296054, 0xF163D1EF, 0x0DDB1E47, 0x9DA4F767, 0xFAF4B1E0, 0xFC5A5FB1, 0xD3FED672, 0x264B1A75, 0xEFA7E6C4, 0x94B344A4, 0xED19375F, 0x58AA0CED]
s_box = [0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, 0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, 0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48]

magic= 0

inp = [0] * 36

inp[35] = 0xD51B0298;
inp[34] = 0xD827C6D3;
inp[33] = 0x31A5A335;
inp[32] = 0x893A7A66;
def Ror(val,r):

    return (val >> r) | (val << (32 - r)) & 0xffffffff

for i in range(31,-1,-1):
    idx = 0x12121212 ^ inp[i+3] ^ inp[i+2] ^ inp[i+1] ^ f_N_a1[i]
    sl = s_box[idx&0xff]
    sm0 = s_box[(idx>>8)&0xff]
    sm1 = s_box[(idx>>16)&0xff]
    sh = s_box[(idx>>24)&0xff]
    s = sl + (sm0<<8) + (sm1 << 16) + (sh << 24)
    
    inp[i] = inp[i+4] ^ 0x34343434  ^ Ror(s,8) ^ Ror(s,14) ^ Ror(s,22) ^ Ror(s,30) ^ s

for i in range(4):
    flag +=pack("<I",inp[i])

print(flag)

 

flag即为:
WMCTF{CRC32andAnti_IS_SO_EASY!!}

四、re1

又是Android题目,题目作者通过hook系统函数,实现了魔改的xtea加密,此外需要注意的是,真正的检查函数在这里:
作者通过hook printf,scanf,strftime,fgetws这四个系统函数实现了魔改的xtea加密,同时hook strlen系统函数实现了简单的异或运算:
xtea:
简单的异或运算:
Exp:
from ctypes import * 
def encrypt(v, key):   
    v0, v1 = c_uint32(v[0]), c_uint32(v[1])
    delta = 0x5EEFEF3

    total = c_uint32(0)
    for i in range(66):  
        v0.value += (((v1.value << 6) ^ (v1.value >> 6)) + v1.value) ^ (total.value + key[total.value & 3])
        total.value -= delta 
        v1.value += (((v0.value << 6) ^ (v0.value >> 6)) + v0.value) ^ (total.value + key[((total.value&0xff)>>6)])
    return v0.value, v1.value 

def decrypt(v, key):
    v0, v1  = c_uint32(v[0]), c_uint32(v[1])
    delta = 0x5EEFEF3
    
    total = c_uint32(0-(delta * 66))
    for i in range(66):
        v1.value -= (((v0.value << 6) ^ (v0.value >> 6)) + v0.value) ^ (total.value + key[((total.value&0xff) >>6)])
        total.value += delta 
        v0.value -= (((v1.value << 6) ^ (v1.value >> 6)) + v1.value) ^ (total.value + key[total.value & 3])

    return v0.value, v1.value 
  

def xtea(inp:bytes,key:bytes):
    from struct import pack,unpack
    k = unpack("<4I",key)
    inp_len = len(inp) // 4
    value = unpack(f"<{inp_len}I",inp)
    res = b""
    for i in range(0,inp_len,2):
        v = [value[i],value[i+1]]
        # x = encrypt(v,k)
        x = decrypt(v,k)
        res += pack("<2I",*x)
    return res

# cip = b"00112233445566778899aabbccddeeff"
cip = bytes([0xD2, 0x5F, 0xC0, 0xEF, 0x5E, 0x62, 0x78, 0x93, 0xA0, 0x41, 0x1F, 0x84, 0x4A, 0x5F, 0xD0, 0x06, 0x9A, 0x8F, 0x89, 0xDC, 0xFC, 0x7C, 0xAA, 0x21, 0x0B, 0xFB, 0x29, 0x42, 0x8B, 0x2B, 0xE5, 0x31])
key = bytes([0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11])
ret = xtea(cip,key)
ret = bytearray(ret)
for i in range(len(ret)):
    ret[i] ^= i^0x5a
    
print(bytes(ret))

 

flag为: WMCTF{b86d69bbeedeccb9257782534}