2018年10月28日星期日

LLVM(一)安装&编译

学习笔记

0x0 概述

LLVM ​项目​的起源于 Chris Lattner 个人对编译器的兴趣,在硕士毕业论文中,其提出了一套完整的在编译时、链接时、运行时甚至是在闲置时优化程序的编译思想,奠定了LLVM的基础。
相对于用c的gcc,用c++的llvm更高效、模块化、协议更放松,也更清爽、干净、现代化。
另外LLVM使用GCC作为前端来对用户程序进行语义分析产生 IF(Intermidiate Format),然后使用分析结果完成代码优化和生成。

0x1 安装

LLVM是Apple官方支持的编译器,而该编译器的前端是Clang,这两个工 具都被集成到了Xcode里面。而 Ubuntu 这样的主流Linux发行版,则可以使用 apt 包管理器进行安装。
所以macOS系统在苹果开发者中心下载好 Xcode 和对应版本的 Command Line Tools ,安装即可。
安装成功后clang -v指令可以获取版本信息:
$ clang -v
Apple LLVM version 10.0.0 (clang-1000.11.45.2)
Target: x86_64-apple-darwin18.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

0x2 llvm && clang 混合编译

想要深入学习 llvm,从源码编译生成 llvm 套件是必不可少的
LLVM Download Page
下载LLVM和Clang,并将Clang放入LLVM的tools目录下
$ wget http://releases.llvm.org/7.0.0/llvm-7.0.0.src.tar.xz
$ tar -xvf llvm-7.0.0.src.tar.xz
$ wget http://releases.llvm.org/7.0.0/cfe-7.0.0.src.tar.xz
$ tar -xvf cfe-7.0.0.src.tar.xz
$ mv ./cfe-7.0.0.src ./llvm-7.0.0.src/tools/clang/
在解压后的文件夹内部编译会失败,需要在外部新建一个文件夹
$ mkdir build
$ cd build
$ cmake -G "Unix Makefiles" ../llvm-7.0.0.src
$ make
cmake用于检查编译环境,没有报错即可执行make编译
如果没有cmake工具,可以用brew install cmake安装

2018年10月26日星期五

Android(七)macOS平台编译Android源码


学习笔记,参考:通过 libFuzzer 进行模糊测试
Android默认支持libFuzzer,但需要编译插桩版本才能使用,而插桩版本需要以完整userdebug编译版本为起点继续编译,故需要编译两次。

0x1 编译环境搭建

系统:macOS 10.14
  1. 创建区分大小写的磁盘映像
    $ hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 40g ~/android.dmg
    
    以下命令可以用来调整映像大小
    $ hdiutil resize -size 80g ~/android.dmg.sparseimage
    
    ~/.bash_profile 中添加辅助函数
    如果系统创建的是 .dmg.sparseimage 文件,将 ~/android.dmg 替换为 ~/android.dmg.sparseimage
    # mount the android file image
    mountAndroid() { hdiutil attach ~/android.dmg -mountpoint /Volumes/android; }
    # unmount the android file image
    umountAndroid() { hdiutil detach /Volumes/android; }
    
  2. 安装xcode工具
    $ xcode-select --install
    
  3. 下载安装对应版本MacPort
    并添加环境变量
    export PATH=/opt/local/bin:$PATH
    
  4. 通过 MacPorts 获取 Make、Git 和 GPG 程序包
    $ POSIXLY_CORRECT=1 sudo port install gmake libsdl git gnupg
    
    macOS 10.4还需安装 bison
    POSIXLY_CORRECT=1 sudo port install bison
    
  5. 安装 JDK
    Java SE 8 Archive Downloads
    • Android 7.0 (Nougat) - Android 8.0 (O):Ubuntu - OpenJDK 8;Mac OS - jdk 8u45 或更高版本
    • Android 5.x (Lollipop) - Android 6.0 (Marshmallow):Ubuntu - OpenJDK 7;Mac OS - jdk-7u71-macosx-x64.dmg
    • Android 2.3.x (Gingerbread) - Android 4.4.x (KitKat):Ubuntu - Java JDK 6;Mac OS - Java JDK 6
    • Android 1.5 (Cupcake) - Android 2.2.x (Froyo):Ubuntu - Java JDK 5
      .bash_profile添加环境变量
      $echo JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home >> ~/.bash_profile
      $ export JAVA_HOME >> ~/.bash_profile
      $ export PATH=$JAVA_HOME/bin:$PATH >> ~/.bash_profile
      $ source ~/.bash_profile
      
  6. 安装Android SDK
    推荐使用homebrew安装
    $ brew cask install android-sdk
    
  7. 安装Android NDK
    $ brew cask install android-ndk
    
  8. 安装Android Studio(可选)
    $ brew cask install android-studio
    
  9. 设置文件描述符数量上限
    将下列行添加到 ~/.bash_profile or ~/.zshrc中:
    # set the number of open files to be 1024
    ulimit -S -n 1024
    

0x2 编译AddressSanitizer版Android

目标设备:pixel(sailfish)
使用调试模式 (aosp_sailfish-userdebug)

0x21 下载Android源码

  1. 安装repo工具
    $ mkdir ~/bin
    $ export PATH=~/bin:$PATH
    $ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
    $ chmod a+x ~/bin/repo
    
  2. 进入项目目录
    $ cd /Volumes/android
    
  3. 初始化仓库
    $ repo init -u https://android.googlesource.com/platform/manifest -b master
    
    墙内可以使用清华源:
    $ export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'
    $ repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b master
    
  4. 下载源码树
    源码有50g,下载时间较长
    $ repo sync -c -j8
    
  5. 下载获取对应设备的驱动文件:
    https://source.android.com/setup/build/requirements#binaries

master分支选择预览Blob版本,其他分支从硬件支持二进制文件选择对应版本
$ wget https://dl.google.com/dl/android/aosp/google_devices-sailfish-5057318-f64030a5.tgz
$ tar xvf google_devices-sailfish-5057318-f64030a5.tgz
$ ./extract-google_devices-sailfish.sh
$ wget https://dl.google.com/dl/android/aosp/qcom-sailfish-5057318-00f1c263.tgz
$ tar xvf qcom-sailfish-5057318-00f1c263.tgz
$ ./extract-qcom-sailfish.sh
$ . build/envsetup.sh
选择debug模式
$ lunch aosp_sailfish-userdebug
lunch不带任何参数会弹出选项,参考如下:
Buildtype 用途
user 有限的权限;适合一般用户
userdebug 类似user模式,但有root权限和debug能力,适合debug
eng 带有额外的debug工具的开发配置。
网络问题
添加代理
$ export HTTP_PROXY=http://<proxy_user_id>:<proxy_password>@<proxy_server>:<proxy_port>
$ export HTTPS_PROXY=http://<proxy_user_id>:<proxy_password>@<proxy_server>:<proxy_port>
如果用的是ss代理
$ export ALL_PROXY=socks5://127.0.0.1:1080
取消代理
$ unset http_proxy
$ unset https_proxy
or
$ export HTTP_PROXY=""
$ export HTTPS_PROXY=""

0x22 编译userdebug版Android

  1. 设置 ccache优化编译环境(可选)
    ccache 是适用于 C 和 C++ 的编译器缓存,有助于提高编译速度
    在源代码树的根目录下执行以下命令
    $ export USE_CCACHE=1
    $ mkdir ccache
    $ export CCACHE_DIR=ccache
    $ prebuilts/misc/darwin-x86/ccache/ccache -M 50G
    
    将以下内容添加到 .bashrc(或等同文件)中
    export USE_CCACHE=1
    
    没有ccache可以brew安装
  2. 执行完整的 Android 编译过程
    通过执行以下命令来执行初始编译,编译时间较长:
    $ make -j$(nproc)
    
    nproc是操作系统级别对每个用户创建的进程数的限制,要实现最快的编译速度,可以使用介于 make -j16 到 make -j32 之间的命令
  3. 将编译得到的版本刷入设备
    解锁引导加载程序,刷入新编译的映像(-w用于擦除用户数据)
    刷机时,除必需刷入的*.img文件,还需要android-info.txt,刷完后备份这几个文件即可
    $ export ANDROID_PRODUCT_OUT=/Volumes/android/out/target/product/salifish
    $ fastboot oem unlock
    $ fastboot flashall -w
    

0x23 编译AddressSanitizer版Android

  1. 在userdebug版本基础之上执行插桩编译,并将修改后的二进制文件刷入设备
    $ make -j$(nproc) SANITIZE_TARGET='address coverage'
    $ fastboot flash userdata
    $ fastboot flashall
    
  2. 检查插桩目录
    官方文档称插桩编译会有以下目录,但编译的Android P和Android Q均无此目录
    $ adb root
    $ adb shell ls -ld /data/asan/lib*
    drwxrwx--x 6 system system 8192 2016-10-05 14:52 /data/asan/lib
    drwxrwx--x 6 system system 8192 2016-10-05 14:52 /data/asan/lib64
    
编译时候遇到的坑
  • 1、fatal error: linux/netfilter/xt_DSCP.h: No such file or directory
    在对应目录下新建xt_DSCP.h文件:
 /* based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <[email protected]>
 * This software is distributed under GNU GPL v2, 1991
 *
 * See RFC2474 for a description of the DSCP field within the IP Header.
 *
 * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp
*/
#ifndef _XT_DSCP_TARGET_H
#define _XT_DSCP_TARGET_H
#include <linux/netfilter/xt_dscp.h>
#include <linux/types.h>

/* target info */
struct xt_DSCP_info {
        __u8 dscp;
};

struct xt_tos_target_info {
        __u8 tos_value;
        __u8 tos_mask;
};

#endif /* _XT_DSCP_TARGET_H */
  • 2、sed: 1: “…”: invalid command code o
    sed是linux命令,用于处理文件内容(修改,替换等),在mac下,sed -i需要带一个字符串作为备份源文件的文件名称,如果这个字符串长度为0,则不备份。
    如原指令,linux下可以执行成功,mac下会执行失败:
    $ sed -i "s/a/b/g" "example.txt"
    
    指令修改如下:
    $ sed -i "_bak" "s/a/b/g" "example.txt"
    
    or
    $ sed -i "" "s/a/b/g" "example.txt"
    
    推荐使用brew工具重新安装gnu-sed,并使用--with-default-name来覆盖原来的sed, 命令如下:
    $ brew install gnu-sed --with-default-names
    
  • 3、dump process tree failed with: exit status 1
    原因不明,重新执行make -j$(nproc)即可
  • 4、unknown type name ‘off64_t’; did you mean ‘off_t’?
    off64_t修改为off_t
    类似错误同理,macOS10.14默认只有64位,所以部分定义没有64标记
  • 5、no member named ‘onClients’ in ‘android::hidl::manager::v1_2::IClentCallback’
    打开./system/libhidl/+/master/transport/manager/1.2/IClientCallback.hal文件,发现代码定义如下:
    oneway onNoClients(interface registered);
    
    对比参考Google最新源码后,修改为:
    oneway onClients(interface registered, bool hasClients);
    
  • 6、undefined reference to ‘android::base::MappedFile::FromFd(int,long long,unsigned int,int)’
    提示的参数类型与源码不同,但本地与Google最新源码完全一致
    应该是配置文件的问题,但检索不到文件,只好将本地代码参数修改为错误提示的类型,make通过
  • 7、build/make/core/Makefile:28: error: overriding commands for target ‘out/target/product/sailfish/system/lib/libclcore_neon.bc’, previously defined at build/make/core/base_rules.mk:414
    源码分支版本与驱动版本错误,换成对应版本
  • 8、repo强制同步
    强制与远程服务器同步,会删除对服务器文件的修改,但是不会删除添加到目录的新文件
    $ repo forall -c 'git reset --hard'
    
    删除新添加的文件
    $ repo forall -c 'git clean -f -d'
    
  • 9、ninja: ‘vender/qcom/marlin/······, missing and no know rule to make it
    实际路径是vender/qcom/sailfish/,未检索到相关配置文件,只好添加软链接:
    ln -s vender/qcom/sailfish/  vender/qcom/marlin/
    
  • 10、unused parameter ‘time’ [-Werror,-Wunsed-parameter]
    检索报错模块下的android.bp和Android.mk文件,删除编译标志-Werror
    或者在Android.mk中添加标志禁用指定的Werror类型:
    LOCAL_CFLAGS += -Wno-error=format-security
    
  • 11、当前shell关闭or重挂载android.dmg后,编译模式等参数会被修改,需重新配置
  • 12、Could not find a supported mac sdk: [“10.10” “10.11” “10.12” “10.13”]
    当前mac sdk版本不匹配引起的
    • 1、去https://github.com/phracker/MacOSX-SDKs下载对应sdk版本,如10.13
    • 2、将下载的sdk解压后放在目录/Applications/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
    • 3、执行
      $ sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
      
  • 13、build/core/base_rules.mk: error: * already define by *
    删除提示中前者的Android.pbAndroid.mkMakefile,重构后再重新执行make
    $ rm -rf *
    $ rm out/soon/.bootstrap/bin/soong_build out/soong/build.ninja
    $ make -j8
    

2018年10月12日星期五

iOS/Malware(九)Roaming Mantis

概述

Roaming Mantis系列是卡巴斯基发现的一套涉及Android、Windows、iOS、路由器等平台,使用DNS劫持传播的恶意代码,相关信息如下:
Roaming Mantis uses DNS hijacking to infect Android smartphones
Roaming Mantis dabbles in mining and phishing multilingually
Roaming Mantis part III: iOS crypto-mining and spreading via malicious content delivery system
之前对其中Android相关恶意代码(卡巴最初只公布了少数部分,其实还有更多迭代版本)进行过深度分析及拓线溯源,但因某些原因不便放出,故这里只好梳理一下iOS相关信息。

攻击方式

网络钓鱼

根据卡巴报告,Roaming Mantis iOS攻击并未出现相应平台的恶意代码,而是感染路由器后,路由器进行的DNS劫持攻击。
当用户通过iOS设备连接到目标网页时,用户将被重定向到“http://security.apple.com/”:
该地址实际并不存在,所以正常情况是无法访问的。而感染了恶意代码的路由器DNS服务则将此域解析为IP地址172.247.116.155,从而展示一个模仿Apple网站的网络钓鱼页面,浏览器的地址栏中则会显示非常令人放心的域名“security.apple.com”,然后可以轻易的诱导受害者填写Apple ID和信用卡等信息,另外这个钓鱼页面的HTML源代码支持25种语言:

JS挖矿

攻击者在后续的版本中修改了iOS相关的攻击代码,如图注销了展示钓鱼页面,出现了执行挖矿的JavaScript代码,该JS脚本之前用于攻击PC平台(参考Mining is the new black):
如果受害者从iOS设备访问此页面,Web浏览器中只会显示空白页。然而在后台CPU使用率立即增加到90%:

小结

此次事件虽然并未出现iOS相关恶意代码,但依然出现了利用路由器DNS劫持来攻击iOS平台的攻击模式,无论是展示钓鱼网站还是利用iOS设备挖矿,无一不说明了即便系统本身再安全,攻击者依然能从其他方向对你进行攻击,尤其黑产。

企业产业链安全风控脑图

脑洞之作,有人提了个企业在产业链中的安全,然后就随手画了这个脑图



2018年10月8日星期一

macOS(三)远程内核调试

参考资料

调试环境

被调试设备:Mac mini late 2014
系统版本:10.13.6(17G65)
详细版本信息获取方式如下:

Kernel Debug Kit

Apple开发者中心,下载对应版本的内核调试套件Kernel Debug Kit
KDK包打开后是一个pkg安装文件,里面包含了大量的调试符号和一些内核驱动模块,提供了Release、Debug、Development三种版本的内核程序,后两种提供了完整的调试和开发功能,Development内核可以用于日常使用,并且具有最小的性能开销,而DEBUG内核具有更多的错误检查。而安装pkg包其实也只是将其中的文件释放到对应的目录
另外只有被调试的机器需要安装KDK包,调试机中只需要Xcode自带的lldb调试器即可。

替换内核

在macOS中,内核的可执行文件位于/Systems/Library/Kernels下,所以我们只需要在KDK安装目录的可执行文件下找到kernel.development或kernel.debug可执行文件,复制到/Systems/Library/Kernels 即可
需要关闭SIP保护才能进行复制
1、重启 Mac,按住 Command+R 键直到 Apple logo 出现,进入 Recovery Mode
2、顶部导航栏,点击 Utilities > Terminal
3、在 Terminal 中输入 csrutil disable,之后回车
4、重启 Mac

Android(六)ELF-OAT & MultiDex & vdex

ELF-OAT

分析某个app,大量核心代码不在dex中,而是动态加载的dex文件,dex文件运行后解包释放到以下目录
/data/data/[包名]/app_plugins_opt/
通过file指令显示为elf格式,jeb等工具无法直接解析
通过ida可以发现为ELF-OAT格式,而ida只能解析出smali代码:
OAT文件是一种Android私有ELF文件格式,是Android运行时ART的核心,不仅包含有从DEX文件翻译而来的本地机器指令,还包含有原来的DEX文件内容。(OAT文件格式参考Android运行时ART加载OAT文件的过程分析
OAT文件在最外层具有一般ELF文件的结构,但包含有两个特殊的段oatdata和oatexec,oatdata包含有用来生成本地机器指令的dex文件内容,oatexec包含有生成的本地机器指令。
OAT文件原生支持内嵌多个Dalvik的dex文件,一般情况下boot.oat包含了多个dex文件,普通的app的OAT文件通常只有一个dex文件。不过在OAT的header中dex_file_count_字段记录了该oat文件中包含的dex文件个数。
oat文件的加载时,首先加载elf文件,然后以oatdata和oatlastword找到真正的oat文件。接着解析oat header,根据其中的信息解析oat文件余下的部分例,如装载Dalvik的dex文件等。另外ART中利用OatDexFile类来标示Dalvik的dex,但实际上该类还是会调用DexFile类。
既然OAT文件内嵌了原始dex,那么分析OAT文件时候可以手动提取出来,如在16进制编辑器里面检索ascii码的“dex”字符串找到“dex.035”,删掉“dex.035”之前即可使用jeb等加载:
或者直接检索“dex.035”的hex byte“64 65 78 0a 30 33 35”,若有多dex也可直接发现:
当然还有更方便的方法,如jeb的oat插件:ANDROID DALVIK, INSIDE OAT, INSIDE ELF

MultiDex

早期的 Android 系统中,DexOpt方法数有65K的限制问题,尽管在新版本系统修复了这个问题,但app仍然需要对低版本的 Android 系统做兼容。针对这个问题通常采用分包的方案解决,主流的方案有Google官方MultiDex和DEX动态加载方式。
分析MultiDex时,好在jeb2后期版本已经支持MultiDex,可以无障碍的在multidex中使用交叉引用功能。不过对于从OAT提取的dex或者其他动态加载的dex仍不太方便,所以可以考虑将这些所有的文件集中处理。
  • 思路:将所有dex解压到同一目录,然后smali2dex合并成dex,最后用aapt add替换apk包中原始dex
  • 工具:dex2jar工具集、aapt、unzip
    1. 提取所有dex到同一目录,运行
      d2j-dex2smali.sh classes.dex —force -o tmp
      d2j-dex2smali.sh classes2.dex —force -o tmp
    2. 合并为同一dex
      d2j-smali.sh -o classes.dex tmp
    3. 删除apk的旧dex文件,将dex加入apk中
      aapt add demo.apk classes.dex

CVE/CNVD list

报告记录&poc: 最近fuzz出了不少crash,提交记录git: https://github.com/gandalf4a/crash_report 其中CVE记录如下: (不定期持续更新) 2025 CVE-2025-22134:heap-buffer-o...