小马同学的技术博客

Stay hungry. Stay Foolish. - Steve Jobs. 求知若渴,虚心若愚!


  • 首页

  • 标签

  • 分类

  • 归档

  • 关于

Theos

发表于 2018-12-02 | 更新于 2019-10-19 | 分类于 逆向实战

1.安装签名⼯工具ldid

  • 先确保安装了了brew

    1
    $ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • 利用brew安装ldid

    1
    $ brew install ldid

2.修改环境变量量

  • 编辑⽤户的配置⽂件

    1
    $ vim ~/.bash_profile
  • 在.bash_profie⽂件后⾯加⼊以下2⾏

    1
    2
    export THEOS=~/theos
    export PATH=$THEOS/bin:$PATH
  • 让.bash_profiel配置的环境变量⽴即生效(或者重新打开终端)

    1
    $ source ~/.bash_profile

3.下载theos

  • 建议在$THEOS目录下载代码(也就是刚才配置的~/theos目录)
    1
    $ git clone --recursive https://github.com/theos/theos.git $THEOS

4.新建tweak项⽬

  • cd 到一个存放项⽬代码的⽂件夹(⽐如桌面)

    1
    2
    $ cd ~/Desktop
    $ nic.pl
  • 选择[11.] iphone/tweak
    新建tewak项目

  • 填写项目信息

  • Project Name
  • 项⽬名称
  • Package Name
  • 项⽬ID(随便写)
  • Author/Maintainer Name
  • 作者
  • 直接敲回车按照默认做法就⾏(默认是Mac上的⽤户名)
  • [iphone/tweak] MobileSubstrate Bundle filter
  • 需要修改的APP的Bundle Identifier(喜⻢拉雅FM的是com.gemd.iting)
  • 可以通过Cycript查看APP的Bundle Identifier
  • [iphone/tweak] List of applications to terminate upon installation
  • 直接敲回车按照默认做法就⾏
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Project Name (required): ting_tweak
    Package Name [com.yourcompany.ting_tweak]: com.mj.ting
    Author/Maintainer Name [MJ Lee]:
    [iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]:
    com.gemd.iting
    [iphone/tweak] List of applications to terminate upon installation (space-
    separated, '-' for none) [SpringBoard]:
    Instantiating iphone/tweak in ting_tweak/...
    Done.

5. 编辑Makefile

  • 在前面加⼊入环境变量,写清楚通过哪个IP和端口访问手机
  • THEOS_DEVICE_IP
  • THEOS_DEVICE_PORT

    1
    2
    3
    4
    5
    6
    7
    8
    export THEOS_DEVICE_IP=127.0.0.1
    export THEOS_DEVICE_PORT=10010
    include $(THEOS)/makefiles/common.mk
    TWEAK_NAME = ting_tweak
    ting_tweak_FILES = Tweak.xm
    include $(THEOS_MAKE_PATH)/tweak.mk
    after-install::
    install.exec "killall -9 SpringBoard"
  • 如果不希望每个项⽬的Makefile都编写IP和端⼝环境变量,也可以添加到⽤用户配置⽂件中

  • 编辑完毕后,$ source ~/.bash_profile让配置⽣生效(或者重启终端)
    1
    2
    3
    4
    5
    6
    $ vim ~/.bash_profile
    export THEOS=~/theos
    export PATH=$THEOS/bin:$PATH
    export THEOS_DEVICE_IP=127.0.0.1
    export THEOS_DEVICE_PORT=10010
    $ source ~/.bash_profile

6.编写代码

  • 打开Tweak.xm⽂文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    %hook XMAdAnimationView
    - (id)initWithImageUrl:(id)arg1 title:(id)arg2 iconType:(long long)arg3
    jumpType:(long long)arg4
    {
    return nil;
    }
    %end

    %hook XMSoundPatchPosterView
    - (id)initWithFrame:(struct CGRect)arg1
    {
    return nil;
    }
    %end

7.编译-打包-安装

  • 编译

    1
    make
  • 打包成deb

    1
    make package
  • 安装(默认会⾃动重启SpringBoard)

    1
    make install

8.可能遇到的问题

make package的错误:

1
2
3
4
5
6
7
8
9
10
11
$ make package
Can't locate IO/Compress/Lzma.pm in @INC (you may need to install the
IO::Compress::Lzma module) (@INC contains: /Library/Perl/5.18/darwin-
thread-multi-2level /Library/Perl/5.18 /Network/Library/Perl/5.18/darwin-
thread-multi-2level /Network/Library/Perl/5.18 /Library/Perl/Updates/5.18.2
/System/Library/Perl/5.18/darwin-thread-multi-2level
/System/Library/Perl/5.18 /System/Library/Perl/Extras/5.18/darwin-thread-
multi-2level /System/Library/Perl/Extras/5.18 .) at
/Users/mj/theos/bin/dm.pl line 12.
BEGIN failed--compilation aborted at /Users/mj/theos/bin/dm.pl line 12.
make: *** [internal-package] Error 2

  • 是因为打包压缩⽅方式有问题,改成gzip压缩就⾏
  • 修改dm.pl⽂件,⽤ # 号注释掉下面两句:

    1
    2
    3
    4
    $ vim $THEOS/vendor/dm.pl/dm.pl
    // 将下面两行用 # 注释掉
    use IO::Compress::Lzma;
    use IO::Compress::Xz;
  • 修改deb.mk⽂件第6行的压缩方式为gzip

    1
    2
    $ vim $THEOS/makefiles/package/deb.mk
    _THEOS_PLATFORM_DPKG_DEB_COMPRESSION ?= gzip

make的错误1:

1
2
3
4
$ make
Error: You do not have an SDK in
/Library/Developer/CommandLineTools/Platforms/iPhoneOS.platform/Developer/S
DKs

  • 是因为多个Xcode导致路径(有可能安装了了好⼏个Xcode),需要指定⼀下Xcode
    sudo xcode-select --switch
    1
    /Applications/Xcode.app/Contents/Developer/

make的错误2:

1
2
3
$ make
> Making all for tweak xxx...
make[2]: Nothing to be done for `internal-library-compile'.

  • 是因为之前已经编译过,有缓存导致的,clean一下即可
    1
    2
    $ make clean
    $ make

10.theos资料查询

  • 目录结构:https://github.com/theos/theos/wiki/Structure[https://github.com/theos/theos/wiki/Structure]
  • 环境变量:http://iphonedevwiki.net/index.php/Theos[http://iphonedevwiki.net/index.php/Theos]
  • Logos语法:http://iphonedevwiki.net/index.php/Logos[http://iphonedevwiki.net/index.php/Logos]
  • %hook、%end:hook⼀个类的开始和结束
  • %log:打印方法调⽤用详情
  • 可以通过Xcode -> Window -> Devices and Simulators查看⽇日志
  • HBDebugLog:跟NSLog类似
  • %new :添加一个新的⽅方法
  • %c(className) :生成⼀个Class对象,⽐如%c(NSObject),类似于
    NSStringFromClass()、objc_getClass()
  • %orig:函数原来的代码逻辑
  • %ctor:在加载动态库时调⽤
  • %dtor:在程序退出时调⽤用
  • logify.pl:可以将⼀个头⽂件快速转换成已经包含打印信息的xm文件
1
logify.pl xx.h > xx.xm
  • 如果有额外的资源文件(比如图片),放在项目的layout⽂件夹中,对应着⼿手机的根路径/

11.theos-tweak的实现过程

  • 编写Tweak代码
  • $ make:编译Tweak代码为动态库(*.dylib)
  • $ make package:将dylib打包为deb文件
  • $ make install:将deb⽂件传送到⼿机上,通过Cydia安装deb
  • 插件将会安装在/Library/MobileSubstrate/DynamicLibraries文件夹中
  • *.dylib:编译后的Tweak代码
  • *.plist:存放着需要hook的APP ID
  • 当打开APP时
  • Cydia Substrate(Cydia已⾃自动安装的插件)会让APP去加载对应的dylib
  • 修改APP内存中的代码逻辑,去执行dylib中的函数代码
  • 所以,theos的tweak并不会对APP原来的可执行文件进行修改,仅仅是修改了内存中的代码逻辑
  • 疑问
  • 未脱壳的APP是否支持tweak?
  • 支持,因为tweak是在内存中实现的,并没有修改.app包中的可执行⽂文件
  • tweak效果是否永久性的?
  • 取决于tweak中⽤用到的APP代码是否被修改过
  • 如果⼀旦更新APP,tweak会不会失效?
  • 取决于tweak中⽤到的APP代码是否被修改过
  • 未越狱的⼿机是否支持tweak?
  • 不支持
  • 能不能对Swift\C函数进行tweak?
  • 可以,方式跟OC不不一样
  • 能不能对游戏项目进⾏tweak?
  • 可以
  • 但是游戏大多数是通过C++\C#编写的,⽽且类名、函数名会进⾏混淆操作

12. logify.pl注意点

  • logify.pl⽣生成的xm⽂文件,有很多时候是编译不通过的,需要进⾏一些处理
  • 删掉__weak
  • 删掉inout
  • 删掉协议,⽐如
  • 或者声明⼀下协议信息@protocol XXTestDelegate;
  • 删掉- (void).cxx_destruct { %log; %orig; }
  • 替换HBLogDebug(@” = 0x%x”, (unsigned int)r);为HBLogDebug(@” = 0x%@”, r);
  • 替换类名为void,⽐如将XXPerson 替换为void
  • 或者声明⼀一下类信息@class XXPerson;

加壳脱壳

发表于 2018-11-25 | 分类于 逆向实战

iOS | 加壳脱壳 | Objective-C

1.加壳

加壳_1


什么是加壳 ?
利用特殊的算法,对可执行文件的编码进行改变(比如压缩、加密),以达到保护程序代码的目的
加壳_2

2. 脱壳

  • 什么是脱壳?
    摘掉壳程序,将未加密的可执行文件还原出来(有些人也称为“砸壳”)

  • 脱壳主要有2种方法:硬脱壳、动态脱壳
    脱壳

3.iOS中的脱壳工具

  • iOS中有很多好用的脱壳工具
    • Clutch:https://github.com/KJCracks/Clutch
    • dumpdecrypted: https://github.com/stefanesser/dumpdecrypted/
    • AppCrackr、Crackulous

4. 如何验证可执行文件是否已经脱壳?

  • 查看Load Commands -> LC_ENCRYPTION_INFO -> Crypt ID的值,0 代表 未加密
    验证是否脱壳

  • 通过otool命令行也可以:otool -l 可执行文件路径 | grep crypt

5.Clutch - 配置

  • 下载最新的Release版: https://github.com/KJCracks/Clutch/releases
    Clutch_1

  • 建议去掉版本号,改名为Clutch
    Clutch_2

  • 将Clutch文件拷贝到iPhone的/usr/bin目录
    Clutch_3

  • 如果在iPhone上执行Clutch指令,权限不够,赋予“可执行的权限”
    Clutch_4

6.Clutch – 使用

  • 列出已安装的APP:Clutch -i
    Clutch使用_1

  • 输入APP序号或者Bundle Id进行脱壳操作:Clutch -d APP序号或BundleId
    Clutch使用_2

  • 脱壳成功后会生成一个ipa文件
    Clutch使用_3

7.dumpdecrypted

  • 下载源代码,然后在源代码目录执行make指令进行编译,获得dylib动态库文件
    dumpdecrypted_1

  • 将dylib文件拷贝到iPhone上(如果是root用户,建议放 /var/root 目录)

  • 终端进入dylib所在的目录
  • 使用环境变量 DYLD_INSERT_LIBRARIES 将dylib注入到需要脱壳的可执行文件(可执行文件路径可以通过ps -A查看获取)
  • DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib 可执行文件路径
    dumpdecrypted_2

  • .decrypted文件就是脱壳后的可执行文件
    dumpdecrypted_3


  • 在使用过程中,可能会遇到以下错误:
    dumpdecrypted_4

  • 原因:对dylib所在的文件夹权限不够

  • 解决方案:将dylib放在用户所在文件夹,比如
  • 如果是root用户,请将dylib放在/var/root目录
  • 如果是mobile用户,请将dylib放在/var/mobile目录

Mach-O

发表于 2018-11-04 | 更新于 2018-11-25 | 分类于 逆向实战

iOS | Mach-O | Objective-C

1.APP从开发到安装到手机的过程

APP从开发到安装到手机_1

APP从开发到安装到手机_2

2.逆向APP的思路

  • 界面分析
    Cycript、Reveal

  • 代码分析
    1> 对Mach-O文件的静态分析
    2> MachOView、class-dump、Hopper Disassembler、ida等

  • 动态调试
    1> 对运行中的APP进行代码调试
    2> debugserver、LLDB

  • 代码编写
    1> 注入代码到APP中
    2> 必要时还可能需要重新签名、打包ipa

3.class-dump

  • 顾名思义,它的作用就是把Mach-O文件的class信息给dump出来(把类信息给导出来),生成对应的.h头文件

  • 官方地址:http://stevenygard.com/projects/class-dump/
    class-dump

  • 下载完工具包后将class-dump文件复制到Mac的/usr/local/bin目录,这样在终端就能识别class-dump命令了

  • 常用格式
    1> class-dump -H Mach-O文件路径 -o 头文件存放目录
    2> -H表示要生成头文件
    3> -o用于制定头文件的存放目录

4.代码的编译过程

代码编译过程_1

不同的OC代码,编译出来的汇编代码可能是一样的:
代码编译过程_2

5.Hopper Disassmbler

  • Hopper Disassmbler能够将Mach-O文件的机器语言代码反编译成汇编代码、OC伪代码或者Swift伪代码

  • 常用快捷键
    找出哪里引用了这个方法:Shift + Option + X

6.动态库共享缓存(dyld shared cache)

  • 从iOS3.1开始,为了提高性能,绝大部分的系统动态库文件都打包存放到了一个缓存文件中(dyld shared cache)
    缓存文件路径:/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX

  • dyld_shared_cache_armX的X代表ARM处理器指令集架构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    v6
    iPhone、iPhone3G
    iPod Touch、iPod Touch2

    v7
    iPhone3GS、iPhone4、iPhone4S
    iPad、iPad2、iPad3(The New iPad)
    iPad mini
    iPod Touch3G、iPod Touch4、iPod Touch5

    v7s
    iPhone5、iPhone5C
    iPad4

    arm64
    iPhone5S、iPhone6、iPhone6 Plus、iPhone6S、iPhone6S Plus
    iPhoneSE、iPhone7、iPhone7 Plus、iPhone8、iPhone8 Plus、iPhoneX、iPhoneXR、iPhoneXS
    iPad5、iPad Air、iPad Air2、iPad Pro、iPad Pro2
    iPad mini with Retina display、iPad mini3、iPad mini4
    iPod Touch6
  • 所有指令集原则上都是向下兼容的

  • 动态库共享缓存一个非常明显的好处是节省内存
  • 现在的ida、Hopper反编译工具都可以识别动态库共享缓存

动态库共享缓存

7.动态库的加载

  • 在Mac/iOS中,是使用了/usr/lib/dyld程序来加载动态库
    dyld:
    1> dynamic link editor,动态链接编辑器
    2> dynamic loader,动态加载器

  • dyld源码
    https://opensource.apple.com/tarballs/dyld/

8.从动态库共享缓存抽取动态库

  • 可以使用 dyld 源码中的 launch-cache/dsc_extractor.cpp
    1> 将#if 0前面的代码删除(包括#if 0),把最后面的#endif也删掉
    2> 编译dsc_extractor.cpp
    clang++ -o dsc_extractor dsc_extractor.cpp
    3> 使用dsc_extractor
    ./dsc_extractor 动态库共享缓存文件的路径 用于存放抽取结果的文件夹

9.Mach-O

  • Mach-O是Mach object的缩写,是Mac\iOS上用于存储程序、库的标准格式

  • 属于Mach-O格式的文件类型有
    Mach-O_Type

  • 可以在xnu源码中,查看到Mach-O格式的详细定义: https://opensource.apple.com/tarballs/xnu/
    1> EXTERNAL_HEADERS/mach-o/fat.h
    2> EXTERNAL_HEADERS/mach-o/loader.h


常见的Mach-O文件类型:

  • MH_OBJECT
    1> 目标文件(.o)
    2> 静态库文件(.a),静态库其实就是N个.o合并在一起

  • MH_EXECUTE:可执行文件
    .app/xx

  • MH_DYLIB:动态库文件
    1> .dylib
    2> .framework/xx

  • MH_DYLINKER:动态链接编辑器
    /usr/lib/dyld

  • MH_DSYM:存储着二进制文件符号信息的文件
    .dSYM/Contents/Resources/DWARF/xx(常用于分析APP的崩溃信息)

10.Mach-O的基本结构

  • 官方描述
    https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/MachOTopics/0-Introduction/introduction.html

  • 一个Mach-O文件包含3个主要区域
    1> Header
    文件类型、目标架构类型等
    2> Load commands
    描述文件在虚拟内存中的逻辑结构、布局
    3> Raw segment data
    在Load commands中定义的Segment的原始数据

Mach-O结构

11.窥探Mach-O的结构

命令行工具:

  • file:查看Mach-O的文件类型
    file 文件路径
  • otool:查看Mach-O特定部分和段的内容
  • lipo:常用于多架构Mach-O文件的处理
    1> 查看架构信息:lipo -info 文件路径
    2> 导出某种特定架构:lipo 文件路径 -thin 架构类型 -output 输出文件路径
    3> 合并多种架构:lipo 文件路径1 文件路径2 -output 输出文件路径

GUI工具
MachOView: https://github.com/gdbinit/MachOView

12.Universal Binary(通用二进制文件)

  • 通用二进制文件
    1> 同时适用于多种架构的二进制文件
    2> 包含了多种不同架构的独立的二进制文件

  • 因为需要储存多种架构的代码,通用二进制文件通常比单一平台二进制的程序要大

  • 由于两种架构有共同的一些资源,所以并不会达到单一版本的两倍之多

  • 由于执行过程中,只调用一部分代码,运行起来也不需要额外的内存

  • 因为文件比原来的要大,也被称为“胖二进制文件”(Fat Binary)

13.dyld和Mach-O

  • dyld用于加载以下类型的Mach-O文件
    1> MH_EXECUTE
    2> MH_DYLIB
    3> MH_BUNDLE

  • APP的可执行文件、动态库都是由dyld负责加载的

Reveal

发表于 2018-11-03 | 更新于 2018-11-04 | 分类于 逆向实战

iOS | Reveal | Objective-C

Reveal

  • Reveal是一款调试iOS程序UI界面的神器
  • 官网:https://revealapp.com
  • 下载:https://revealapp.com/download/
    1> 建议下载至少Reveal4版本,支持USB连接调试,速度快。低版本的只能WiFi连接调试

调试环境配置

  • iPhone上安装Reveal Loader:
    Reveal Loader

  • 安装完Reveal Loader后,打开【设置】,选择需要调试的APP
    选择需要调试的APP

  • 找到Mac的Reveal中的RevealServer文件,覆盖iPhone的/Library/RHRevealLoader/RevealServer文件
    RevealServer

  • 重启SpringBoard或者重启手机,可以在iPhone上输入终端命令
    1> 重启SpringBoard:killall SpringBoard
    2> 重启手机:reboot

选择USB方式

usb

开始调试

AppStore

Cycript

发表于 2018-10-29 | 更新于 2018-11-11 | 分类于 逆向实战

iOS | Cycript | Objective-C

Cycript

  • Cycript是Objective-C++、ES6(JavaScript)、Java等语法的混合物
  • 可以用来探索、修改、调试正在运行的Mac\iOS APP
  • 官网:http://www.cycript.org/
  • 文档:http://www.cycript.org/manual/
  • 通过Cydia安装Cycript,即可在iPhone上调试运行中的APP
    Cycript

Cycript 的开启和关闭

  • 开启
    1> cycript
    2> cycript -p 进程ID
    3> cycript -p 进程名称
    Cycript_open_close
  • 取消输入:Ctrl + C
  • 退出:Ctrl + D
  • 清屏:Command + R

ps命令

  • 安装adv-cmds
    ps
  • ps命令是process status的缩写,使用ps命令可以列出系统当前的进程
    1> 列出所有的进程
    ps –A
    ps aux
    2> 搜索关键词
    ps –A | grep 关键词

常用语法

  • UIApp
    [UIApplication sharedApplication]
  • 定义变量
    var 变量名 = 变量值
  • 用内存地址获取对象
    #内存地址
  • ObjectiveC.classes
    已加载的所有OC类
  • 查看对象的所有成员变量
    *对象
    常用语法

  • 递归打印view的所有子控件(跟LLDB一样的函数)
    view.recursiveDescription().toString()
  • 筛选出某种类型的对象
    choose(UIViewController)
    choose(UITableViewCell)

封装Cycript - .cy文件编写

  • 我们可以将常用的Cycript代码封装在一个.cy文件中
  • exports参数名固定,用于向外提供接口
    cy文件编写

封装Cycript - 存放和使用.cy文件:
1> 将.cy文件存放到/usr/lib/cycript0.9目录下
2> 在Cycript中引用.cy文件,并使用它提供的接口
cy文件存放、使用

SSH(下)

发表于 2018-10-23 | 更新于 2018-10-28 | 分类于 逆向实战

iOS | SSH | Objective-C

1.通过USB进行SSH登录

  • 默认情况下,由于SSH走的是TCP协议,Mac是通过网络连接的方式SSH登录到iPhone,要求iPhone连接WiFi
    SSH_Default

  • 为了加快传输速度,也可以通过USB连接的方式进行SSH登录
    1> Mac上有个服务程序usbmuxd(它会开机自动启动),可以将Mac的数据通过USB传输到iPhone:
    /System/Library/PrivateFrameworks/MobileDevice.framework/Resources/usbmuxd
    SSH_USB

2.usbmuxd的使用

  • 下载usbmuxd工具包(下载v1.0.8版本,主要用到里面的一个python脚本:tcprelay.py)
    https://cgit.sukimashita.com/usbmuxd.git/snapshot/usbmuxd-1.0.8.tar.gz
    如果下载失败,可尝试点此下载:usbmuxd-1.0.8.tar.gz
  • 将iPhone的22端口(SSH端口)映射到Mac本地的10010端口
    1> cd ~/Documents/usbmuxd-1.0.8/python-client
    2> python tcprelay.py -t 22:10010
    加上-t参数是为了能够同时支持多个SSH连接
    tcprelay
  • 注意:要想保持端口映射状态,不能终止此命令行(如果要执行其他终端命令行,请新开一个终端界面)
  • 不一定非要10010端口,只要不是保留端口就行

  • 端口映射完毕后,以后如果想跟iPhone的22端口通信,直接跟Mac本地的10010端口通信就可以了
  • 新开一个终端界面,SSH登录到Mac本地的10010端口(以下方式2选1)
    1> ssh root@localhost -p 10010
    2> ssh root@192.168.31.26 -p 10010
    注:(1) localhost是一个域名,指向的IP地址是192.168.31.26,本机虚拟网卡的IP地址
    (2) usbmuxd会将Mac本地10010端口的TCP协议数据,通过USB连接转发到iPhone的22端口
  • 远程拷贝文件也可以直接跟Mac本地的10010端口通信
    1> scp -P 10010 ~/Desktop/test.txt root@localhost:~/test
    2> 将Mac上的~/Desktop/test.txt文件,拷贝到iPhone上的~/test路径
    注意:scp的端口号参数是大写的-P

3.sh脚本文件

  • 我们可以将经常执行的一系列终端命令行(比如:刚才提到的端口映射、ssh登录)放到sh脚本文件中(shell),然后执行脚本文件
    testCD_sh
  • 可以通过sh、bash、source命令来执行sh脚本文件
    sh、bash:
    1> 当前shell环境会启动一个子进程来执行脚本文件,执行后返回到父进程的shell环境
    2> 执行cd时,在子进程中会进入到cd的目录,但是在父进程中环境并没有改变,也就是说目录没有改变
    source:
    1> 在当前的shell环境下执行脚本文件
    2> 执行cd后会跳转到cd的目录
    sh_bash_source

4.iOS终端的中文乱码问题

  • 默认情况下,iOS终端不支持中文输入和显示
  • 解决方案:新建一个~/.inputrc文件,文件内容是
    1> 不将中文字符转化为转义序列 :
    set convert-meta off
    2> 允许向终端输出中文:
    set output-meta on
    3> 允许向终端输入中文:
    set meta-flag on
    set input-meta on
  • 如果是想在终端编辑文件内容,可以通过Cydia安装一个vim(软件源http://apt.saurik.com)
    VI IMproved

SSH(上)

发表于 2018-10-17 | 更新于 2018-10-27 | 分类于 逆向实战

iOS | SSH | Objective-C

1.Mac远程登录到iPhone

  • 我们经常在Mac的终端上,通过敲一些命令行来完成一些操作
    terminal
  • iOS和Mac OS X都是基于Darwin(苹果的一个基于Unix的开源系统内核),所以iOS中同样支持终端的命令行操作
    1> 在逆向工程中,我们经常会通过命令行来操纵iPhone
  • 为了能够让Mac终端中的命令行能作用在iPhone上,我们得让Mac和iPhone建立连接
    1> 通过Mac远程登录到iPhone的方式建立连接
    Mac与iPhone连接

2.SSH、OpenSSH

SSH:
1> Secure Shell的缩写,意为“安全外壳协议”,是一种可以为远程登录提供安全保障的协议
2> 使用SSH,可以把所有传输的数据进行加密,“中间人”攻击方式就不可能实现,能防止DNS欺骗和IP欺骗
SSH


OpenSSH:
1> 是SSH协议的免费开源实现
2> 可以通过OpenSSH的方式让Mac远程登录到iPhone


使用OpenSSH远程登录:

  • 在iPhone上通过Cydia安装OpenSSH工具(软件源http://apt.saurik.com)
    OpenSSH-Cydia
  • OpenSSH的具体使用步骤可以查看Description中的描述
    OpenSSH-Description

使用OpenSSH远程登录 - 使用步骤:

  • SSH是通过TCP协议通信,所以要确保Mac和iPhone在同一局域网下,比如连接着同一个WiFi
    1> 在Mac的终端输入ssh 账户名@服务器主机地址
    2> 比如ssh root@192.168.31.26(这里的服务器是手机)
    3> 初始密码alpine
  • 登录成功后就可以使用终端命令行操作iPhone
  • 退出登录命令是exit

SSH的版本:

  • SSH协议一共2个版本
    1> SSH-1
    2> SSH-2
  • 现在用的比较多的是SSH-2,客户端和服务端版本要保持一致才能通信
  • 查看SSH版本(查看配置文件的Protocol字段)
    1> 客户端:/etc/ssh/ssh_config
    2> 服务端:/etc/ssh/sshd_config

3.root、mobile

  • iOS下有2个常用账户:root、mobile
    1> root:最高权限账户,$HOME是/var/root
    2> mobile:普通权限账户,只能操作一些普通文件,不能操作系统级别的文件,$HOME是/var/mobile
  • 登录mobile用户:root mobile@服务器主机地址
  • root和mobile用户的初始登录密码都是alpine
    iPhone-account
  • 最好修改一下root和mobile用户的登录密码(登录root账户后,分别通过passwd、passwd mobile完成)
    iPhone-account-password

4.SSL、OpenSSL

很多人会将SSH、OpenSSH、SSL、OpenSSL搞混

  • SSL
    1> Secure Sockets Layer的缩写,是为网络通信提供安全及数据完整性的一种安全协议,在传输层对网络连接进行加密
  • OpenSSL
    1> SSL的开源实现
    2> 绝大部分HTTPS请求等价于:HTTP + OpenSSL
  • OpenSSH的加密就是通过OpenSSL完成的
    SSL、OpenSSL

5.SSH的通信过程

SSH的通信过程可以分为3大主要阶段:
1> 建立安全连接
2> 客户端认证
3> 数据传输

6.建立安全连接

  • 在建立安全连接过程中,服务器会提供自己的身份证明
    建立安全连接
  • 如果客户端并无服务器端的公钥信息,就会询问是否连接此服务器
    SSH-Login

服务器身份信息变更:

  • 在建立安全连接过程中,可能会遇到以下错误信息:提醒服务器的身份信息发生了变更
    服务器身份信息变更
  • 如果确定要连接此服务器,删除掉之前服务器的公钥信息就行
    1> ssh-keygen -R 服务器IP地址
  • 或者直接打开known_hosts文件删除服务器的公钥信息就行
    1> vim ~/.ssh/known_hosts

7.SSH的客户端认证方式

  • SSH-2提供了2种常用的客户端认证方式
    1> 基于密码的客户端认证
    a.使用账号和密码即可认证
    2> 基于密钥的客户端认证
    a.免密码认证
    b.最安全的一种认证方式
  • SSH-2默认会优先尝试“密钥认证”,如果认证失败,才会尝试“密码认证”

8.SSH - 基于密钥的客户端认证

SSH-秘钥认证


  • 在客户端生成一对相关联的密钥(Key Pair):一个公钥(Public Key),一个私钥(Private Key)
    1> ssh-keygen
    2> 一路敲回车键(Enter)即可
    3> OpenSSH默认生成的是RSA密钥,可以通过-t参数指定密钥类型
    4> 生成的公钥:~/.ssh/id_rsa.pub
    5> 生成的私钥:~/.ssh/id_rsa
  • 把客户端的公钥内容追加到服务器的授权文件(~/.ssh/authorized_keys)尾部
    1> ssh-copy-id root@服务器主机地址
    2> 需要输入root用户的登录密码
    3> ssh-copy-id会将客户端~/.ssh/id_rsa.pub的内容自动追加到服务器的~/.ssh/authorized_keys尾部
  • 注意:由于是在~文件夹下操作,所以上述操作仅仅是解决了root用户的登录问题(不会影响mobile用户)

可以使用ssh-copy-id将客户端的公钥内容自动追加到服务器的授权文件尾部,也可以手动操作:

  • 复制客户端的公钥到服务器某路径
    1> scp ~/.ssh/id_rsa.pub root@服务器主机地址:~
    2> scp是secure copy的缩写,是基于SSH登录进行安全的远程文件拷贝命令,把一个文件copy到远程另外一台主机上
    3> 上面的命令行将客户端的~/.ssh/id_rsa.pub拷贝到了服务器的~地址
  • SSH登录服务器
    1> ssh root@服务器主机地址
    2> 需要输入root用户的登录密码
  • 在服务器创建.ssh文件夹
    1> mkdir .ssh
  • 追加公钥内容到授权文件尾部
    1> cat ~/id_rsa.pub >> ~/.ssh/authorized_keys
  • 删除公钥
    1> rm ~/id_rsa.pub

文件权限问题:
如果配置了免密码登录后,还是需要输入密码,需要在服务器端设置文件权限
1> chmod 755 ~
2> chmod 755 ~/.ssh
3> chmod 644 ~/.ssh/authorized_keys

9.22端口

  • 端口就是设备对外提供服务的窗口,每个端口都有个端口号(范围是0~65535,共2^16个)
  • 有些端口号是保留的,已经规定了用途,比如
    1> 21端口提供FTP服务
    2> 80端口提供HTTP服务
    3> 22端口提供SSH服务(可以查看/etc/ssh/sshd_config的Port字段)
    4> 更多保留端口号:https://baike.baidu.com/item/%E7%AB%AF%E5%8F%A3%E5%8F%B7/10883658#4_3
  • iPhone默认是使用22端口进行SSH通信,采用的是TCP协议
    22端口

越狱环境搭建

发表于 2018-10-09 | 更新于 2018-10-21 | 分类于 逆向实战

iOS | 越狱环境搭建 | Objective-C

1.准备

  • 调试设备:
    1> 建议至少iPhone5s(因为从5s开始支持arm64架构)
    2> 或者至少是iPad Air、iPad mini2等支持arm64架构的设备

  • 系统版本:
    1> 版本不能太高,最好保证能够完美越狱
    2> 戳这里查看手机是否可以越狱
    选择系统版本 -> 选择设备 -> 查看是否支持越狱(最好支持完美越狱)

2.iOS Jailbreak(iOS越狱)

利用iOS系统的漏洞,获取iOS系统的最高权限(Root),解开之前的各种限制(合法行为)

优点:

  • 打造个性化、与众不同的iPhone
    1> 自由安装各种实用的插件、主题、APP
    2> 修改系统APP的一些默认行为

  • 自由安装非AppSore来源的APP
    1> “付费APP”秒变“免费APP”
    2> 未越狱iPhone安装APP的途径: AppStore、真机调试、通过证书打包签名ipa安装

  • 灵活管理文件系统,让iPhone可以像U盘那样灵活

  • 给开发者提供了逆向工程的环境

缺点:

  • 不予保修
  • 费电,越狱后的iOS系统会常驻一些进程,耗电速度约提升10%~20%
  • 在新的iOS固件版本出来的时候,不能及时地进行更新
    1> 每个新版本的固件,都会修复上一个版本的越狱漏洞,使越狱失效
    2> 如果需要保持越狱状态,要等待新的越狱程序发布时,才能升级相应的固件版本
  • 不再受iOS系统默认的安全保护,容易被恶意软件攻击,个人隐私有被窃取的风险
  • 如果安装了不稳定的插件,容易让系统变得不稳定、变慢,甚至出现“白苹果”等问题

完美越狱:

  • 越狱后的iPhone可以正常关机和重启

不完美越狱:

  • iPhone一旦关机后再开机时,屏幕就会一直停留在启动画面,也就是“白苹果”状态
  • 或者能正常开机,但已经安装的破解软件都无法正常使用,需要将设备与PC连接后,使用软件进行引导才能使用
  • 一般说来,在苹果发布新的iOS固件后,针对该固件的不完美越狱会先发布,随后完美越狱才可能发布
  • 一般较新的系统版本,均为不完美越狱

越狱方法推荐:
PP助手:http://jailbreak.25pp.com/

如何判断是否越狱成功?

  • 桌面是否有Cydia
    桌面是否有Cydia
  • 工具判断(eg. PP助手)
    工具判断(比如PP助手)

3.Cydia

1> 越狱后的“App Store”
可以在Cydia中安装各种第三方的软件(插件、补丁、APP)

2> 作者
Jay Freeman (saurik)
Cydia

Cydia安装软件的步骤:
1>添加软件源(不同软件的软件源可能不同)
添加软件源
2>进入软件源找到对应的软件,开始安装
安装软件

SpringBoard

  • SpringBoard就是iOS的桌面
  • 有时候通过Cydia安装完插件后,可能会出现以下界面
    重启SpringBoard

4.必备软件安装

Apple File Conduit “2”

  • Apple File Conduit “2”补丁的作用:
    1> 可以访问整个iOS设备的文件系统
    2> 类似的补丁还有:afc2、afc2add
  • 软件源:
    1> http://apt.saurik.com
    2> http://apt.25pp.com
    Apple File Conduit "2"

AppSync Unified

  • AppSync Unified补丁的作用:
    1> 可以绕过系统验证,随意安装、运行破解的ipa安装包
  • 软件源:
    1> http://apt.25pp.com
    AppSync Unified

iFile

  • iFile的作用:
    1> 可以在iPhone上自由访问iOS文件系统
    2> 类似的还有Filza File Manager、File Browser
  • 软件源:
    1> http://apt.thebigboss.org/repofiles/cydia
    iFile

PP助手

  • PP助手的作用:
    1> 可以利用PP助手自由安装海量APP
  • 软件源:
    1> http://apt.25pp.com/
    iFile

Mac必备:

  • iFunBox
    1> 管理文件系统

  • PP助手
    1> 自由安装海量APP
    2> 卸载APP
    3> 备份APP为ipa安装包(iOS9开始,不再支持备份APP)


建议安装顺序:
建议安装顺序


安装包

  • 通常情况下
    1> 通过Cydia安装的安装包是deb格式的(结合软件包管理工具apt)
    2> 通过PP助手安装的安装包是ipa格式的
  • 如果通过Cydia源安装deb失败
    1> 可以先从网上下载deb格式的安装包
    2> 然后打开 iFunBox -> 文件系统,将deb安装包放到/var/root/Media/Cydia/AutoInstall
    3> 重启手机,Cydia就会自动安装deb
  • 比如,下图是iFile 2.2.0-1所需的deb安装包
    点击下载iFile安装包
    iFile安装包安装

5.如何在iOS代码中判断设备是否越狱?

1> 针对不同iOS版本的判断方法可能不一样
2> 最简单的一种方法:判断手机上是否安装了Cydia

1
[[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"];

当然,不同系统版本判断方法可能不太一样,仅用这个方法判断是不严谨的,如果需要更完善的方法的同学们可自行谷歌

LLVM-Clang 插件开发

发表于 2018-10-03 | 分类于 编译原理

iOS | LLVM | Objective-C

Clang 插件开发-准备

$ cd LLVM_ALL/llvm/tools/clang/tools
$ mkdir Your_Plugin_Dir_Name
新建文件夹(自己的插件,eg. 我的文件夹命名为 mz-plugin,后面以我自己的文件目录讲解,各位同学在实践的时候请注意替换为自己的文件夹目录)

在 clang/tools 目录下 CMakeLists.txt 文件最下方添加我们自己的插件目录: add_clang_subdirectory(mz-plugin),这样,clang 在编译时就会加载我们插件目录下的插件

$ cd mz-plugin
$ touch MZPlugin.cpp
$ touch CMakeLists.txt

编辑 CMakeLists.txt,添加下面这行:
add_llvm_loadable_module(MZPlugin MZPlugin.cpp)

1
2
3
4
5
6
// 如果有多个 cpp 文件,可以如下:
add_llvm_loadable_module(MZPlugin
MZPlugin1.cpp
MZPlugin2.cpp
MZPlugin3.cpp
)

编写插件

编写 C++ 文件,当然是用 IDE 方便了,在 llvm_xcode 目录下执行 cmake -G Xcode ../llvm 生成的模板工程,首次打开选择 Automatically Create Schemes 方式创建scheme
Automatically Create Schemes

找到我们自己的插件 cpp 文件 Loadable modules/MZPlugin/MZPlugin.cpp,编写插件:
插件cpp文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendPluginRegistry.h"

using namespace clang;
using namespace std;
using namespace llvm;

namespace MZPlugin {

class MZConsumer : public ASTConsumer {
public:
// 重写 HandleTranslationUnit,在每编译完成一个语法树时都会调用此方法
void HandleTranslationUnit(ASTContext &Ctx) {
cout << "MZPlugin-HandlerTranslationUnit,编译完成一个语法树" << endl;
}
};

// 继承 PluginASTAction,重写两个方法
class MZAction: public PluginASTAction {
public:
unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &ci, StringRef isFile) {
return unique_ptr<MZConsumer> (new MZConsumer);
}

bool ParseArgs(const CompilerInstance &ci, const vector<string> &args) {
return true;
}
};
}

/**
注册插件

1.static clang::FrontendPluginRegistry::Add<MZPlugin::MZAction>
2.泛型 声明 Add 类型,指定 MZPlugin 的 MZAction
3.官方给的示例用的 X 就按官方的来吧

@param "MZPlugin" 插件名称
@param clang-plugin." 插件描述
*/
static FrontendPluginRegistry::Add<MZPlugin::MZAction>
X("MZPlugin", "The MZPlugin is my first clang-plugin.");

编译插件

编写完成之后,选择我们的插件 target,编译出 .dylib 插件文件:
编译插件

编译成功之后,会在 llvm_xcode/Debug/lib/ 目录下生成 MZPlugin.dylib文件

使用插件

在Xcode 项目中指定加载插件动态库:Build Settings -> Other C Flags:
-Xclang -load -Xclang 动态库全路径 -Xclang -add-plugin -Xclang 插件名称

eg.-Xclang -load -Xclang /Users/username/Desktop/项目/LLVM_ALL
/llvm_xcode/Debug/lib/MZPlugin.dylib -Xclang -add-plugin -Xclang MZPlugin

Other C Flags

已经安耐不住激动的心情了么,编译项目,结果会报错,因为 Xcode Build Settings Compiler for C/C++/Objective 默认编译器使用的是 Default compiler(Apple LLVM 9.0),不让我们选择我们自己的编译器,我们还需要最后一步,Hack Xcode,然后才能修改默认的编译器

Hack Xcode

下载 XcodeHacking.zip,解压,修改 HackedClang.xcplugin/Contents/Resources/HackedClang.xcspec,将 ExecPath 位置 替换为我们刚才用 ninja 编译好的 clang 的全路径
eg. /Users/username/Desktop/项目/LLVM_ALL/llvm_release/bin/clang
HackedClang.xcspec

然后执行下面两行指令将这两个文件移至 Xcode 包中:
$ sudo mv HackedClang.xcplugin xcode-select -print-path/../PlugIns
/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins

$ sudo mv HackedBuildSystem.xcspec xcode-select -print-path/Platforms
/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications

完成之后,重启 Xcode,这时,我们就可以修改 Xcode 默认的编译器了
Compiler for C/C++/Objective

选择 Clang LLVM Trunk,然后进行编译,这时候我们观察下便以信息,会发现,刚才我们输出我们在 HandleTranslationUnit 方法中的信息已经成功输出
success

总结

至此我们已经完成了一个简单的插件开发,如果需要开发更牛逼的功能,我们还需要对编译原理、语义分析等进行更深入的了解,感兴趣的童鞋可以深入研究

编译器王者-LLVM

发表于 2018-09-24 | 更新于 2018-10-03 | 分类于 编译原理

iOS | LLVM | Objective-C

LLVM 是什么?

LLVM-logo

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
官网:https://llvm.org/

LLVM 项目是模块化、可重用的编译器以及工具链技术的集合,美国计算机协会(ACM)将其2012年软件系统奖项颁给了LLVM,之前曾获得此奖项的软件和技术包括:Java、Apache、Mosaic、the World Wide Web、Smalltalk、UNIX、Eclipse等

创始人: Chris Lattner,亦是Swift之父

  • 有些文章把 LLVM 当做 Low Level Virtual Machine(低级虚拟机)的缩写简称,官方描述如下:
  • The name “LLVM” itself is not an acronym; it is the full name of the project.
    “LLVM” 不是首字母缩略词,它是项目的全称

传统的编译器架构

传统编译器架构
传统编译器架构:

  • Frontend:前端(词法分析、语法分析、语义分析、生成中间代码)
  • Optimizer:优化器(中间代码优化)
  • Backend:后端(生成对应平台、设备、架构机器码)

LLVM架构

传统编译器架构
不同的前端后端使用统一的中间代码 LLVM Intermediate Representation(LLVM IR)

统一中间代码的优点:
1> 如果需要支持一种新的编程语言,只需要实现一个新的前端
2> 如果需要支持一种新的硬件设备,只需要实现一个新的后端
3> 优化阶段是一个通用的阶段,它针对的是统一的 LLVM IR,不论是支持新的编程语言,还是支持新的硬件设备,都不需要对优化阶段做修改

相比之下,GCC 的前端和后端没有分的太开,前端后端耦合在一起。所以 GCC 为了支持一门新的语言,或者支持一个新的目标平台,就变得非常困难

LLVM 现在被作为实现各种静态和运行时编译语言的通用基础结构(GCC家族、JAVA、.NET、Python、Ruby、Scheme、Haskell等)

Clang

1> 什么是 Clang ?
Clang 是 LLVM 项目的一个子项目,基于 LLVM 架构 C/C++/Objective-C 的编译器前端

官网:http://clang.llvm.org/

2> 相比于 GCC,Clang 具有如下有点:
编译速度快:在某些平台上,Clang 的编译速度显著的快过 GCC(Debug 模式下编译 OC 速度比 GCC 快 3 倍)
占用内存小:Clang 生成的 AST(语法树) 所占用的内存是 GCC 的五分之一左右
模块化设计:Clang 采用基于库的模块化设计,易于 IDE 继承及其他用途的作用
诊断信息可读性强:在编译过程中,Clang 创建并保留了大量详细的元数据(metadata),有利于调试和错误定位
设计清晰简单,容易理解,易于扩展增强

Clang 与 LLVM

传统编译器架构
广义的 LLVM:整个 LLVM 架构
狭义的 LLVM:LLVM 后端(代码优化、目标代码生成等)

传统编译器架构

OC源文件的编译过程

命令行查看编译的过程:$ clang -ccc-print-phases main.m
OC源文件编译器过程1
输入 main.m => 预处理器,预处理(include、import、宏定义…),输出 cpp 文件 => compiler 编译成中间代码 ir => 后端,目标代码 => 链接动态库等 => 适合 ** 架构的代码

查看preprocessor(预处理)的结果:$ clang -E main.m

1
2
3
4
5
6
7
8
9
#include <stdio.h>

#define AGE 30
int main(int argc, const char * argv[]) {
int a = 10;
int b = 20;
int c = a + b + AGE;
return 0;
}

OC源文件编译过程2
执行上面的命令行之后,发现预处理器将 <stdio.h> 中代码引了进来,而且将 AGE 宏 也替换成了 30

词法分析

词法分析,生成 Token:$ clang -fmodules -E -Xclang -dump-tokens main.m
OC源文件编译过程2
将代码中每个部分生成 token,’int’、’main’、’(‘、’int’、’argc’ …,一遍后面分析,Loc=main.m:13:9表示 main.m 13 行第 9 个字符

语法树 - AST

语法分析,生成语法树(AST,Abstract Syntax Tree):$ clang -fmodules -fsyntax-only -Xclang -ast-dump main.m

词法分析之后将 Token 拼接、联系起来,生成语法树:
OC源文件编译过程2

LLVM IR

LLVM IR 有3中表示形式(但本质是等价的,就好比水可以有气体、液体、固体3中形态)

1>text:便于阅读的文本格式,类似于汇编语言,扩展名 .ll,$ clang -S -emit-llvm main.m
2>memory:内存格式
3>bitcode:二进制格式,扩展名 .bc,$ clang -c -emit-llvm main.m

1
2
3
void test(int a, int b) {
int c = a + b - 3;
}

上面代码生成 text 格式中间代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
define void @test(i32, i32) #0 {
// 定义一个局部变量 int a
%3 = alloca i32, align 4
// 定义一个局部变量 int b
%4 = alloca i32, align 4
// 定义一个局部变量 int c
%5 = alloca i32, align 4
// 将 0(第一个参数)的值赋给 3,即 a
store i32 %0, i32* %3, align 4
// 将 1(第二个参数)的值赋给 4,即 b
store i32 %1, i32* %4, align 4
// 读取 3 的值给 6,即 a
%6 = load i32, i32* %3, align 4
// 读取 4 的值给 7,即 b
%7 = load i32, i32* %4, align 4
// 6 + 7,即 a + b,给 8
%8 = add nsw i32 %6, %7
// 8 - 3,即 a + b - 3
%9 = sub nsw i32 %8, 3
// 将 a + b - 3 的结果给 5,即 c,即 c = a + b - 3
store i32 %9, i32* %5, align 4
ret void
}

IR 基本语法:
1> 注释以分号 ; 开头
2> 全局标识符以@开头,局部标识符以%开头
3> alloca,在当前函数栈帧中分配内存
4> i32,32bit,4个字节的意思
5> align,内存对齐
6> store,写入数据
7> load,读取数据

官方语法参考:
https://llvm.org/docs/LangRef.html


上面带大家简单熟悉了下 LLVM,感兴趣的童鞋可以进入官网自行深入研究。光了解是不是有点无趣呢,接下来,我们来开发一个我们自己的编译器插件

LLVM、Clang 源码下载

下载LLVM
\$ https://git.llvm.org/git/llvm.git/
大小 661.3 M,仅供参考

下载clang
\$ cd llvm/tools
$ git clone https://git.llvm.org/git/clang.git/
大小 242.9 M,仅供参考

源码编译

我们在终端可以敲 clang 命令,是因为在 Xcode …/XcodeDefault.xctoolchain/user/bin目录下已经安装了Clang,并且MAC 默认用的是 Xcode 内置的 Clang。既然我们要开发自己的编译器插件,所以在源码下载完成之后,我们需要编译我们自己的 Clang

安装 cmake 和 ninja(先安装brew,https://brew.sh)
1> $ brew install cmake
2> $ brew install ninja

注:ninja 如果安装失败,可以直接从 github 获取 release 版放入 /usr/local/bin中,https://github.com/ninja-build/ninja/releases


在LLVM源码统计目录下新建一个 llvm_build目录(最终会在 llvm_build 目录下生成 build.ninja)

/LLVM_ALL/llvm
/LLVM_ALL/llvm_build
/LLVM_ALL/llvm_release
/LLVM_ALL/llvm_xcode

$ cd llvm_build
$ cmake -G Ninja ../llvm(指定 llvm 源码位置,会将 llvm 源码在llvm_build 目录下生成 ninja 的模板,注:llvm 路径需根据自己的 llvm 目录相对于 llvm_build 的位置) 成功的标识:llvm_build 目录下生成 build.ninja 文件

指定LLVM编译目标路径:
$ cmake -G Ninja ../llvm -DCMAKE_INSTALL_PREFIX=LLVM的安装路径
(eg.) $ cmake -G Ninja ../llvm -DCMAKE_INSTALL_PREFIX=/users/username/Desktop/项目/LLVM_ALL/llvm_release/

更多 cmake 相关选项,可以参考:https://llvm.org/docs/CMake.html


依次执行编译、安装指令
$ ninja
编译完毕后, llvm_build 目录大概 21.61 G(仅供参考)
$ ninja install
安装完毕后,安装目录大概 12.21 G(仅供参考)


生成 Xcode 模板工程,使用 Xcode 进行编译
$ cd llvm_xcode
$ cmake -G Xcode ../llvm

应用与实践

1> libclang、libTooling
官方参考:https://clang.llvm.org/docs/Tooling.html
应用:语法树分析、语言转换等

2> Clang 插件开发
官方参考:
https://clang.llvm.org/docs/
https://clang.llvm.org/docs/ClangPlugins.html
https://clang.llvm.org/docs/ExternalClangExamples.html
https://clang.llvm.org/docs/RAVFrontendAction.html
应用:代码检查(命名规范、代码规范)等

3> Pass开发
官方参考:http://llvm.org/docs/WritingAnLLVMPass.html
应用:代码优化、代码混淆等

4> 开发新的编程语言
https://llvm-tutorial-cn.readthedocs.io/en/latest/index.html
https://kaleidoscope-llvm-tutorial-zh-cn.readthedocs.io/zh_CN/latest

12
小马同学

小马同学

iOS小白一枚,写这个博客,首先是为了总结,通过写作来提高自己的写作和表达能力。其次是想把自己理解的东西分享给大家,与大家进行交流,也希望大家可以指出我的不足并提供宝贵的意见!

18 日志
4 分类
14 标签
GitHub E-Mail 简书
© 2019 小马同学
主题 – NexT.Muse v6.4.0
总访问量次 | 总访客人 |