MacBook Air安装双系统

如果只能在linux windows osx当中选其一,兼顾了图形界面和命令行的osx当仁不让。

不过最近升级了512G的Mac,发觉得现阶段双系统才是正解,有些osx下不适合做的,就不勉强,火候一过事情就焦。

我选择的是osx + linux mint,折腾前,建议还是先准备好一个osx的安装u盘。由于涉及分区表操作,弄不好连系统的recovery都废,重装就在所难免了(我就是不小心把分区表弄坏了,只能重启进入internet版的recovery,不过提示下载失败,没能重装,最后还是在windows下制作的osx启动u盘)

安装过程主要参考的是这篇文章,用的是Macbook Air 2017。不过安装linux时,我并没有开启ext4文件系统加密,给osx留了100G,然后2G给/boot,剩下的给/

基本上安装过程不会有问题,装好以后才是麻烦的开始。

首先是键盘布局,进入linux以后:

sudo dpkg-reconfigure keyboard-configuration

然后选择Generic 105-key (Intl) PC,English(UK)。试了半天,唯一能让键盘布局正确的选项,否则~总是被映射为±

接下来是亮度调节,为了让mac的亮度调节快捷键工作,编辑/usr/share/X11/xorg.conf.d/20-intel.conf

Section "Device"
        Identifier  "card0"
        Driver      "intel"
        Option      "Backlight"  "intel_backlight"
        BusID       "PCI:0:2:0"
EndSection

还要检查一下~/.viminfo的权限是不是666,或者owner是当前用户,不然vim的配置文件会不起作用

接下来要配置L2TP的VPN,Mint默认没有提供,需要自己安装

sudo add-apt-repository ppa:nm-l2tp/network-manager-l2tp
sudo apt-get update
​sudo apt-get install network-manager-l2tp network-manager-l2tp-gnome

重启后在网络管理里面就能添加vpn了,不过由于我的目标版本比较老,还需要额外配置一下

首先安装ike-scan扫描目标网络,然后把加密所用的算法填写到VPN的高级选项里,除此之外还要装一个strongswan-plugin-openssl,原因也是因为目标算法比较老。

OSX下安装mfoc

这次重装系统以后,打算尽可能不用虚拟机了,所有工具能移植的移植,不能移植的就找替代品,全部原生使用。brew可以安装大部分常用工具,个别brew更新不及时的工具就需要自己下载编译,比如mfoc

首先安装编译mfoc所需的环境工具:

brew install libtool
brew install automake
brew install autoconf
brew install libusb
brew install pkg-config
brew install glib

然后下载libnfc,并编译安装:

git clone https://github.com/nfc-tools/libnfc
cd libnfc
autoreconf -vis
./configure --with-drivers=acr122_pcsc
make install

如果一切顺利就可以下载安装mfoc了,方法类似:

git clone https://github.com/nfc-tools/mfoc
cd mfoc
autoreconf -vis
./configure
make install

为了正常运行mfoc以及nfc-list,osx系统还需要做一些额外的配置,否则会出现nfc-list找不到设备之类的情况

首先要关闭sip,开机按command+R进入恢复模式,然后执行

csrutil disable

接下来保证pcscd服务正常运行,在主系统增加一个kext

/System/Library/Extensions/DUMMY.kext/Contents/Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!-- This is a dummy driver which binds to ACR122U. It -->
<!-- contains no actual code; its only purpose is to -->
<!-- prevent Apple's USBHID driver from exclusively -->
<!-- opening the device. -->
<plist version="1.0">
   <dict>
      <key>CFBundleDevelopmentRegion</key>
      <string>English</string>
      <key>CFBundleIconFile</key>
      <string />
      <key>CFBundleIdentifier</key>
      <string>com.ACR122U.dummy.kext</string>
      <key>CFBundleInfoDictionaryVersion</key>
      <string>6.0</string>
      <key>CFBundlePackageType</key>
      <string>KEXT</string>
      <key>CFBundleSignature</key>
      <string>????</string>
      <key>CFBundleVersion</key>
      <string>1.0.0d1</string>
      <key>IOKitPersonalities</key>
      <dict>
         <!-- The ACR122U USB interface -->
         <key>ACR122U</key>
         <dict>
            <key>CFBundleIdentifier</key>
            <string>com.ACR122U.dummy.kext</string>
            <key>IOClass</key>
            <string>com.ACR122U.dummy.kext</string>
            <key>IOProviderClass</key>
            <string>IOUSBInterface</string>
            <key>bConfigurationValue</key>
            <integer>1</integer>
            <key>bInterfaceNumber</key>
            <integer>0</integer>
            <key>idProduct</key>
            <integer>XXXXXXXXXXXXXXXXXXXXX</integer>
            <key>idVendor</key>
            <integer>XXXXXXXXXXXXXXXXXXXXX</integer>
         </dict>
      </dict>
      <key>OSBundleLibraries</key>
      <dict>
         <key>com.apple.iokit.IOUSBFamily</key>
         <string>1.8</string>
      </dict>
   </dict>
</plist>

其中idProduct和idVendor可以通过

system_profiler SPUSBDataType

获得,最后执行

sudo kextload -verbose /System/Library/Extensions/DUMMY.kext

加载kext

osx下编译android内核

如果是在linux系统下编译android的内核,基本不会有什么大的问题,但osx就稍微顽皮一些。

以nexus 5的内核编译为例,首先下载编译内核用的arm-eabi-gcc工具:

git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/

然后下载内核源代码

git clone https://android.googlesource.com/kernel/msm.git

之后切换代码到需要的branch

$ cd msm/
$ git branch -a

  * master
    remotes/origin/HEAD -> origin/master
    remotes/origin/android-msm-2.6.35
    remotes/origin/android-msm-3.9-usb-and-mmc-hacks
    remotes/origin/android-msm-flo-3.4-jb-mr2
    remotes/origin/android-msm-flo-3.4-kitkat-mr0
    remotes/origin/android-msm-flo-3.4-kitkat-mr1
    remotes/origin/android-msm-hammerhead-3.4-kitkat-mr1
...
$ git checkout origin/android-msm-hammerhead-3.4-kitkat-mr1

以上都是常规步骤,针对osx还有一些必须的改动:


增加两个头文件elf.h和features.h到内核源码的scripts/mod下面,头文件下载

修改scripts/mod/mk_elfconfig.c和scripts/mod/modpost.h两个文件,将<elf.h>改成 “elf.h”

将scripts/recordmcount.c中的<elf.h>修改为 “mod/elf.h”

修改kernel/timeconst.pl,将defined(@array)的修改为@array


最后再编译即可:

export ARCH=arm
export CC=arm-eabi-
export CROSS_COMPILE=arm-eabi-
make hammerhead_defconfig
make menuconfig
make -k

OSX下调试Flash插件

其实无论调试什么,都会发现lldb的功能朴实的让人心急如焚。比如Windows调试器基本都会自动记录上一次的断点信息,每次调试时根据模块位置重新下好端点。

lldb可能天生就是为源码调试准备的,一旦没有源码,根据模块名+偏移的下端点方式它是无论如何都不能识别。好在它提供了python接口,方便开发调试插件弥补自身的缺陷。

所以与其说lldb是个调试器,不说它是个SDK,只有基于它开发出来的图形调试器才具备实用性。

那就来看看一些在Windows调试时不值得一提的简单操作,在lldb下该如何达阵

附加Flash进程


用Safari打开指定页面后,执行以下脚本lldb就会附加到包含Flash的进程上了

pid=$(ps aux | grep WebKit.Plugin | grep 64 | awk '{print $2}'|sort| tail -1) 
lldb -p $pid

搜索内存中的指定常数


由于没有查看memory layout的命令,只能借助vmmap,先找到比如malloc的内存区域,然后再逐一生成查找命令。以下命令用于从WebKit找到HeapSpray的特定字符:

pid=$(ps aux | grep Build | grep web | awk '{print $2}' | sort | tail -1)
vmmap $pid | grep "WebKit Malloc " | grep "-" | awk '{print $3}' | awk -F '-' '{print "memory find -e '$1'","0x" $1, "0x" $2}

在模块固定偏移下断点


这个听起来是最稀松平常的任务了,比如打算在Flash的0x78A4C0偏移处下一个断点,而且要在每次lldb附加后自动完成。首先要编写一个lldb的插件,完成Flash模块基地址的查找和断点地址的计算,最后下断点:

import lldb
import shlex
import optparse
import time

def obreak(debugger, command, result, dict):
  command_args = shlex.split(command)
  parser = create_obreak_options()
  try:
    (options, args) = parser.parse_args(command_args)
  except:
   return
  if len(args) > 0:
    offset = int(args[0], 16)
  else:
    offset = 0x78A4C0
  target = debugger.GetSelectedTarget()
  base = 0
  for mod in target.modules:
    if mod.file.GetFilename() == "FlashPlayer-10.6":
      for sec in mod.sections:
        if sec.name == "__TEXT":
          base = sec.get_addr().load_addr
  address = base+offset
  target.BreakpointCreateByAddress(address) 

def create_obreak_options():
  usage = "usage: %prog -f offset"
  description='''break on offset_belongs_to_Flash'''
  parser = optparse.OptionParser(description=description, prog='obreak',usage=usage)
  parser.add_option("-f", "--offset", dest="offset", help="break on certain offset of Flash", metavar="OFFSET")
  return parser

def __lldb_init_module (debugger, dict):
  parser = create_obreak_options()
  obreak.__doc__ = parser.format_help()
  debugger.HandleCommand('command script add -f %s.obreak obreak' % __name__)

但这还不够,还需要在.lldbinit.rc文件中增加一些辅助代码,保证上述插件的自动执行

command script import ~/path_to_obreak.py
target stop-hook add -o "script '--loading script--'"
target stop-hook add
obreak
target stop-hook disable 2
target stop-hook disable 3

OSX下调试WebKit

Safari的解析和渲染引擎WebKit是开源的项目,并提供了很多脚本方便调试。在OSX下分析一个漏洞还是头一回,用到的技巧大都取自WebKit官方的一篇JS引擎漏洞分析

准备环境


首先当然是要下载Webkit的源码,以前写过如何在Ubuntu环境里下载编译WebKit,当时只考虑了最新版本,所以直接从官网下载代码压缩包。

但如果是分析漏洞,一般要根据testcase的描述找到对应版本的WebKit,然后用svn和git下载指定版本的代码。

官方的建议的命令是

svn co -r 200796 http://svn.webkit.org/repository/webkit/trunk webkitDir

由于我查看的testcase信息来自于WebKit的Github镜像,所以用git下载的源码。

不过国内访问git的速度实在不怎么样,最后就用VPS从美国先git clone好整个源码树,然后压缩传回本地

根据testcases找到对应的branch编号以后,再切换过去

git reset --hard 6711d17

原理分析


为了尽快分析清楚漏洞的原理,当然要直接调用WebKit去解析testcase,先编译debug的程序:

./Tools/Scripts/set-webkit-configuration --asan
./Tools/Scripts/build-webkit --debug

然后就可以使用DumpRenderTree直接调用编译好的WebKit来解析引发问题的testcase了

VM=WebKitBuild/Debug/ && DYLD_FRAMEWORK_PATH=$VM lldb $VM/DumpRenderTree LayoutTests/js/regress-155776.html

真实环境下的调试


一旦问题分析清楚,必须回到Safari下才算是真正的利用过程起点。编译release版的程序:

./Tools/Scripts/build-webkit --release

然后使用提供的辅助脚本,就能自动将WebKit库注入到浏览器中,使Safari运行在刚刚编译好的WebKit之上:

./Tools/Scripts/run-safari