一些简单的Mobile CTF练习

资源链接https://download.csdn.net/download/alickxc/11705813

1.CISCN-2018 Illusion:

首先查看关键点:

可以看出app通过对用户输入数据加密并比较的方式判断flag准确性,再查看so实现,

首先JNI_Onload():

一些简单的Mobile CTF练习_第1张图片

获得加密函数地址:

一些简单的Mobile CTF练习_第2张图片

这里函数翻译有误因为函数调推测并非C语言实现有着工整的开场白和结束语而是内联汇编实现的:

一些简单的Mobile CTF练习_第3张图片

关键点是10AC函数进去看了下有着简单的位移计算并无外部引用,所以我们只要算出0x1-0xff的函数mapping返回数据再根据ASCII码剔除无关分支就能拿到Flag所以我们上手编写模拟程序:

# coding=utf-8
import logging
import ctypes
from unicorn.arm_const import UC_ARM_REG_R0,UC_ARM_REG_R1,UC_ARM_REG_R2,UC_ARM_REG_R3,UC_ARM_REG_PC,UC_ARM_REG_R6,UC_ARM_REG_SP
from unicorn import Uc,UC_ARCH_ARM,UC_MODE_THUMB,UC_PROT_ALL,UC_HOOK_CODE,UcError

UC_MEM_ALIGN = 0x1000

def align(addr, size, growl):
    to = ctypes.c_uint64(UC_MEM_ALIGN).value
    mask = ctypes.c_uint64(0xFFFFFFFFFFFFFFFF).value ^ ctypes.c_uint64(to - 1).value
    right = addr + size
    right = (right + to - 1) & mask
    addr &= mask
    size = right - addr
    if growl:
        size = (size + to - 1) & mask
    return addr, size

def hook_code(uc, address, size, user_data):
    # print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))
    pass

if __name__ == "__main__":
    module_base = 0x1000000

    simulator = Uc(UC_ARCH_ARM, UC_MODE_THUMB)
    with open('/Users/user/ElongDev/testWorkspace/encryptTest/Illusion/libnative-lib.so','rb') as fstream:
        lib_bytes = fstream.read()
        filesize = len(lib_bytes)
        (address,size) = align(module_base,filesize,True);
        simulator.mem_map(address,size,UC_PROT_ALL)
        simulator.mem_write(address,lib_bytes)

        simulator.mem_map(0x800000, 0x1000, UC_PROT_ALL)
        simulator.reg_write(UC_ARM_REG_SP,0x801000)

        

        for i in range(1,256):
            simulator.reg_write(UC_ARM_REG_R0,i)
            simulator.reg_write(UC_ARM_REG_R1,93)
            start_address = module_base+0x10c0+1
            end_address = start_address+0x10-1
            simulator.hook_add(UC_HOOK_CODE, hook_code, start_address, end_address)
            simulator.emu_start(start_address,end_address)
            ret = simulator.reg_read(UC_ARM_REG_R1)+0x20
            print("%d,%d"%(i,ret))
            pass
        pass
    pass
public static void main(String[] args) throws Exception{

//        String gb = new String(,"GB2312");

        String tmp = "1,33$2,34$3,35$4,36$5,37$6,38$7,39$8,40$9,41$10,42$11,43$12,44$13,45$14,46$15,47$16,48$17,49$18,50$19,51$20,52$21,53$22,54$23,55$24,56$25,57$26,58$27,59$28,60$29,61$30,62$31,63$32,64$33,65$34,66$35,67$36,68$37,69$38,70$39,71$40,72$41,73$42,74$43,75$44,76$45,77$46,78$47,79$48,80$49,81$50,82$51,83$52,84$53,85$54,86$55,87$56,88$57,89$58,90$59,91$60,92$61,93$62,94$63,95$64,96$65,97$66,98$67,99$68,100$69,101$70,102$71,103$72,104$73,105$74,106$75,107$76,108$77,109$78,110$79,111$80,112$81,113$82,114$83,115$84,116$85,117$86,118$87,119$88,120$89,121$90,122$91,123$92,124$93,32$94,33$95,34$96,35$97,36$98,37$99,38$100,39$101,40$102,41$103,42$104,43$105,44$106,45$107,46$108,47$109,48$110,49$111,50$112,51$113,52$114,53$115,54$116,55$117,56$118,57$119,58$120,59$121,60$122,61$123,62$124,63$125,64$126,65$127,66$128,67$129,68$130,69$131,70$132,71$133,72$134,73$135,74$136,75$137,76$138,77$139,78$140,79$141,80$142,81$143,82$144,83$145,84$146,85$147,86$148,87$149,88$150,89$151,90$152,91$153,92$154,93$155,94$156,95$157,96$158,97$159,98$160,99$161,100$162,101$163,102$164,103$165,104$166,105$167,106$168,107$169,108$170,109$171,110$172,111$173,112$174,113$175,114$176,115$177,116$178,117$179,118$180,119$181,120$182,121$183,122$184,123$185,124$186,32$187,33$188,34$189,35$190,36$191,37$192,38$193,39$194,40$195,41$196,42$197,43$198,44$199,45$200,46$201,47$202,48$203,49$204,50$205,51$206,52$207,53$208,54$209,55$210,56$211,57$212,58$213,59$214,60$215,61$216,62$217,63$218,64$219,65$220,66$221,67$222,68$223,69$224,70$225,71$226,72$227,73$228,74$229,75$230,76$231,77$232,78$233,79$234,80$235,81$236,82$237,83$238,84$239,85$240,86$241,87$242,88$243,89$244,90$245,91$246,92$247,93$248,94$249,95$250,96$251,97$252,98$253,99$254,100$255,101";


        Map> map = new HashMap<>();

        for(String str:tmp.split("\\$")){
            String key = str.split(",")[1];
            String value = str.split(",")[0];
            Set set = map.get(key);
            if(set == null)set = new HashSet<>();
            set.add(value);
            map.put(key,set);
        }



        byte[] bytes = "Ku@'G_V9v(yGS".getBytes("GB2312");

        byte[] table = "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;".getBytes();

        for(int i=0;i s = map.get(String.valueOf((int)b));
            for(String str:s){
                int ifo = Integer.parseInt(str)-table[i]+64;
                if(ifo>32&&ifo<128) {
                    char c = (char) ifo;
                    System.out.print(c);
                }
            }
//            System.out.println();
        }
        System.out.println(bytes);
}

最终拿到Flag:CISCN{GJ5728}

2.GCTF05-Mobile:

首先查看关键代码:

一些简单的Mobile CTF练习_第4张图片

流程很简单通过Handler创建一个休息1s的定时任务不过按原App的逻辑我们需要等200000s才能拿到结果...所以需要自己写脚本判断K的值:

public static boolean is2(int n) {
        if (n <= 3) {
            if (n > 1) {
                return true;
            }
            return false;
        } else if (n % 2 == 0 || n % 3 == 0) {
            return false;
        } else {
            int i = 5;
            while (i * i <= n) {
                if (n % i == 0 || n % (i + 2) == 0) {
                    return false;
                }
                i += 6;
            }
            return true;
        }
    }


    public static void aliTime(){
        int beg = 200000;
        int k = 0;
        int now;
        long t1 = 0;
        long t2 = 0;
        while(true){
            t1 += t2;
            now = (int) (t1 / 1000);
            t2 = 1500 - (t1 % 1000);
            if(beg<=now){
                System.out.println(k);
                return;
            }
            if (is2(beg - now)) {
                k += 100;
            } else {
                k--;
            }
        }
    }

计算结束后拿到K的值:1616384

so用unicorn-engine跑一下即可获得flag

3.***CTF-Android2:

首先查看Activity

一些简单的Mobile CTF练习_第5张图片

一些简单的Mobile CTF练习_第6张图片

明显so题目查看so代码:

一些简单的Mobile CTF练习_第7张图片

易知加密分为4步:init(将字符串分组)->First->亦或块1->亦或块2。

既然是亦或操作那逆向逻辑就很简单了:

public static void android2(){
        byte[] bytes = "LN^dl".getBytes();
        byte[] a0 = new byte[5];
        for(int i=0;i<= 4;i++){
            if(i == 4){
                a0[i] = bytes[4];
                continue;
            }
            a0[i] = (byte) ((bytes[i]^0x80)/2&0xff);
        }
        System.out.println(new String(a0));
        byte[] bytes1 = new byte[]{0x20,0x35,0x2d,0x16,0x61};
        byte[] a1 = new byte[5];
        for(int i=0;i

求出此题Flag:flag{sosorryla}

4.CISCN-2018 TryGetFlag:

打开文件发现爱加密壳...我们考虑直接内存dump dex吧 不会让人手工脱爱加密吧....

一些简单的Mobile CTF练习_第8张图片

IDA附加程序可以再module框看到odex文件,直接dump出来:

查看smali代码逻辑,Base64+AES特征明显:

一些简单的Mobile CTF练习_第9张图片

 

 

 

 

 

你可能感兴趣的:(Android,Reserve)