Happy Android Security
  • 前言
  • CTF
    • 2014 NAGA&PIOWIND APP应用攻防竞赛 Crackme01
    • 2014 NAGA&PIOWIND APP应用攻防竞赛 Crackme02
    • 2014 NAGA&PIOWIND APP应用攻防竞赛 Crackme03
    • 2014 NAGA&PIOWIND APP应用攻防竞赛 Crackme04
    • 2015 0CTF Vezel 100
    • 2015 0CTF Simple 150
    • 2015 XCTF&RCTF Flag System 100
    • 2015 XCTF&RCTF Where 300
    • 2015 海峡两岸CTF 一个APK逆向试试吧
    • 2016 LCTF EASY 100
    • 2016 AliCTF Timer 50
    • 2016 AliCTF Loop And Loop 100
    • 2016 ZCTF Android1 200
    • 2016 LCTF EASY EASY 200
    • 2017 ISCC 全国大学生信息安全与对抗技术竞赛 简单到不行
    • 2017 SSCTF 加密勒索软件 100
    • 2017 SSCTF Login 200
    • 2017 XCTF&NJCTF Easy Crack 100
    • 2017 XCTF&NJCTF Safe Box 100
    • 2017 XCTF&NJCTF Little Rotator Game 200
    • 2017 陕西省网络安全大赛 拯救鲁班七号 100
    • 2017 陕西省网络安全大赛 The Marauders Map 150
    • 2017 陕西省网络安全大赛 人民的名义 抓捕赵德汉1 200
    • 2017 陕西省网络安全大赛 人民的名义 抓捕赵德汉2 200
    • 2017 陕西省网络安全大赛 取证密码 200
  • 应用侧安全
    • 任意私有组件启动漏洞的利用
    • [ByteDance] [TikTok] NotificationBroadcastReceiver导出存在任意私有组件启动结合FileProvider机制与FbSoLoader框架导致本地代码执行漏洞
    • [ByteDance] [TikTok] DetailActivity导出存在任意私有组件启动结合FileProvider机制与FbSoLoader框架导致本地代码执行漏洞
    • [ByteDance] [TikTok] WallPaperDataProvider导出存在任意私有文件读取漏洞
    • [Adobe] [Acrobat Reader] AdobeReader处理DeepLink时未正确进行合法性校验导致下载PDF文件过程出现路径穿越可造成远程代码执行
    • [CVE-2019-16253] [Samsung] [SMT] SamsungTTSService导出存在任意私有组件调用提权漏洞
    • [CVE-2021-25390] [Samsung] [Photo Table] PermissionsRequestActivity存在任意私有组件启动漏洞可获取ContentProvider数据
    • [CVE-2021-25391] [Samsung] [Secure Folder] KnoxSettingCheckLockTypeActivity泄露Intent可获取ContentProvider数据
    • [CVE-2021-25397] [Samsung] [TelephonyUI] PhotoringReceiver导出存在任意文件写漏洞结合动态库加载行为可实现本地任意代码执行
    • [CVE-2021-25410] [Samsung] [CallBGProvider] CallBGProvider的调用权限定义为Normal可实现任意私有文件读取
    • [CVE-2021-25413] [Samsung] [Contacts] SetProfilePhotoActivity导出存在任意私有组件启动漏洞可获取ContentProvider数据
    • [CVE-2021-25414] [Samsung] [Contacts] SetProfilePhotoActivity导出存在任意私有文件读写漏洞
    • [CVE-2021-25440] [Samsung] [FactoryCameraFB] CameraTestActivity导出存在文件读写权限泄露漏洞
    • [CVE-2022-22292] [Samsung] [Telecom] 动态注册BroadcastReceiver默认导出存在任意私有组件启动漏洞
  • 系统侧安全
    • REDMI 5 Plus Second Space Password Bypass
    • 【蓝牙】CVE-2017-13258 CVE-2017-13260 CVE-2017-13261 CVE-2017-13262信息泄露
    • 【蓝牙】CVE-2018-9357 BNEP_Write越界写导致RCE
    • 【蓝牙】CVE-2018-9358 信息泄露
    • 【蓝牙】CVE-2018-9359 process_l2cap_cmd_L2CAP_CMD_INFO_REQ未判断缓冲区边界造成信息泄露
    • 【蓝牙】CVE-2018-9360 process_l2cap_cmd_L2CAP_CMD_CONN_REQ未判断缓冲区边界造成信息泄露
    • 【蓝牙】CVE-2018-9361 process_l2cap_cmd_L2CAP_CMD_DISC_REQ未判断缓冲区边界造成信息泄露
    • 【蓝牙】CVE-2018-9365 smp_sm_event数组越界访问导致RCE
    • 【蓝牙】CVE-2018-9381 gatts_process_read_by_type_req未初始化栈变量导致信息泄露
    • 【NFC】CVE-2018-9584 nfc_ncif_set_config_status未检测长度越界读写
    • 【NFC】CVE-2018-9585_nfc_ncif_proc_get_routing未检测长度越界读写
    • 【蓝牙】CVE-2019-2209 未检测PIN码长度导致越界读造成信息泄露
    • 【NFC】CVE-2019-9358 ce_t3t_data_cback越界读写
  • 内核驱动侧安全
Powered by GitBook
On this page
  1. CTF

2016 LCTF EASY EASY 200

Previous2016 ZCTF Android1 200Next2017 ISCC 全国大学生信息安全与对抗技术竞赛 简单到不行

Last updated 2 years ago

2016年LCTF的第二道Mobile题,分值200,有言在先,本百分之九十九靠着自己多年酱油选手的灵感

Jadx载入样本,先判断了输入字符串的长度,然后对字符串进行处理,最后调用函数进行校验

调用Format类的函数进行处理,这里写了这么多个,肯定在后面会用到,不然出题人吃饱撑着写这么多

check()函数里显示检测了模拟器,所以直接运行在真机上,然后调用native函数进行校验

IDA载入so,先看checkEmulator()函数,这个函数并没有做其它操作,只是根据传入的值返回

同时,我们看到还有一个checkPasswd()函数

我们进行简单的分析,可以看出来中间用到了某种加密操作

在对整个校验函数有了简单的认识后,进行深入分析

sub_91C0(&v23, &unk_19D7F, &v22);
sub_7118(&v23, input_chars_new, num_33);
sub_8740(*v21 - 12);
sub_8740(v23 - 12);

在翻了几下之后,发现这几个函数并没有太大关系,我们需要关注的是

j_j_j__Z7encryptPKcj(v20, v22, *(v22 - 12));

找到v22 - 12的定义就是vInput_,v20在后面会有操作,所以应该是输出

-00000028 vInput_         DCD ?
-00000024 var_24          DCB 4 dup(?)
-00000020 var_20          DCB ?
-0000001F                 DCB ? ; undefined
-0000001E                 DCB ? ; undefined
-0000001D                 DCB ? ; undefined
-0000001C var_1C 

跟进去

这明显的Base64算法,那么分析到这里就可以回去了

最后的对比

v14 = *v20;
v15 = sub_7B10(&secret, v14);

这里调用sub_7B10,可以跟进去

int __fastcall sub_7B10(const void **a1, const char *a2)
{
    const void *v2; // r7@1
    const char *v3; // r6@1
    size_t v4; // r5@1
    size_t v5; // r4@1
    size_t v6; // r2@1
    int result; // r0@3

    v2 = *a1;
    v3 = a2;
    v4 = *(*a1 - 3);
    v5 = j_j_strlen(a2);
    v6 = v5;
    if ( v5 > v4 )
        v6 = v4;
    result = j_j_memcmp(v2, v3, v6);
    if ( !result )
        result = v4 - v5;
    return result;
}

调用memcpy()函数进行对比,那么现在关键的就是secret

使用交叉引用,找到一处对secret的调用

int sub_4C54()
{
    int result; // r0@1
    int v1; // [sp+0h] [bp-18h]@1
    char v2; // [sp+4h] [bp-14h]@1
    int v3; // [sp+8h] [bp-10h]@1

    v3 = _stack_chk_guard;
    My_create(&secret, "dHR0dGlldmFodG5vZGllc3VhY2VibGxlaHNhdG5hd2k.", &v1);
    j_j___cxa_atexit(sub_6BE4, &secret, &unk_1E000);
    My_create(&dword_1E09C, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", &v2);
    j_j___cxa_atexit(sub_6BE4, &dword_1E09C, &unk_1E000);
    result = _stack_chk_guard - v3;
    if ( _stack_chk_guard != v3 )
      j_j___stack_chk_fail();
    return result;
}

从第二个字符串来看,这是Base64算法无误了

那么分析到这,我们可以逆推一下,首先将dHR0dGlldmFodG5vZGllc3VhY2VibGxlaHNhdG5hd2k.用Base64还原,然后倒序

>>> temp = "ttttievahtnodiesuacebllehsatnawi!"
>>> temp[::-1]
'!iwantashellbecauseidonthaveitttt'

鉴于没有参赛我也不知道flag到底是什么

网上流传的flag:iwantashellbecauseidonthaveitttt

可是我记得前面是有调用一个Format类的一个函数做substring()操作,应该是补上固定长度的任意字符串

不过还有一点点其它的东西可以跟大家聊一聊

我们注意到

>>> temp = "iwantashellbecauseidonthaveitttt"
>>> print len(temp)
32

而我们Java层传进来的字符串应该是33位,再来翻so文件,蓦然发现有一个JNI_OnLoad()函数

粗略一看,这里面的东西还是很多的,先是做初始化,猜测这里是要获取dex文件

通过/proc/self/maps找dex文件

寻找dex的Magic Number

接下来看到了比较关键的代码,这通常用于Dex文件自篡改,一大堆乱七八糟的东西没看懂是啥

if(v91)
{
    if(!j_j_mprotect(v75, v71, 7))
    {
        *v86 = *filenamed;
        v92 = *(filenamed + 3);
        if (v92)
        {
            v93 = filenamed + 16;
            v94 = v86 + 8;
            do
            {
                *v94 = *v93;
                ++v93;
                ++v94;
                --v92;
            }while(v92);
        }
        j_j_mprotect(v75, v71, 5);
    }
}

这时候开始瞎猜,一定有篡改,而且截取的长度由33变成32,获取的是Lcom/example/ring/wantashell/Format;类

再回头看该类的四个函数,主办方还是很仁慈的,并没有换三个长度都是32的函数

public class Format {
    protected String form(String input) {
        return input.substring(5, 38);
    }

    protected String fo1m(String input) {
        return input.substring(5, 36);
    }

    protected String forn(String input) {
        return input.substring(5, 39);
    }

    protected String f0rm(String input) {
        return input.substring(5, 37);
    }
}

大胆的猜测这里是将form()自篡改成f0rm()

那么现在flag是iwantashellbecauseidonthaveitttt就没什么问题了

至于反调试,可以直接patch so的调用反调试函数指令,也可以动态调试的时候下断点,patch一下内存

如果有同学感觉好的,在看secret赋值那里,就应该猜到这是Base64算法,感觉再好一点的,直接就解出了flag