把.m 编译成 c
$xcrun -sdk iphoneos clang -rewrite-objc -F Foundation -arch armv7 main.m
man security
Security是Mac系统中钥匙串和安全模块的命令行管理工具,(图形化工具为Keychain Access.app)。
钥匙串(Keychain)实质上就是一个用于存放证书、密钥、密码等安全认证实体的仓库,在计算机中保存为一个.keychain的文件。
# 语法
security [-hilqv] [-p prompt] [command] [command_options] [command_args]
名称:安全-钥匙串和安全框架的命令行界面
概要:安全性[-hilqv] [-p提示符] [命令] [command_options] [command_args]
描述:一个简单的命令行界面,可让您管理钥匙串,操纵钥匙和证书,以及从命令行执行安全框架能够执行的几乎所有操作。默认情况下,安全性将执行提供的命令并报告是否出现任何错误。如果提供了-i或-p选项,则安全性将进入交互模式,并允许用户输入多个在stdin上的tiple命令。从标准输入中读取EOF时,安全性将退出。
以下是可用选项的完整列表:
-h如果未指定任何参数,则显示所有命令的列表。如果提供了参数,请显示用法对于每个指定的命令。此选项本质上与help命令相同。
-i以交互方式运行安全性。将显示提示(默认情况下为“安全性”>),并且用户将能够在stdin上键入命令,直到遇到EOF。
-l在安全退出之前,运行/usr/bin/leaks -nocontext
自行查看您执行的命令是否泄漏。
-p提示此选项暗含-i选项,但将默认提示更改为指定的参数代替。
-q将使安全性不再那么冗长。
-v将使安全性更加冗长。
- 子命令列表如下
- create-keychain 创建钥匙串并加入搜索列表
- list-keychains 显示或设置钥匙串搜索列表
- default-keychain 显示或设置默认的钥匙串
- login-keychain 显示或设置登录钥匙串
- delete-keychain 删除钥匙串并从搜索列表移除
- lock-keychain 锁定制定的钥匙串
- unlock-keychain 解锁制定的钥匙串
- set-keychain-settings 设置钥匙串配置
- set-keychain-password 设置钥匙串密码
- dump-keychain 显示一个或多个钥匙串的内容
- create-keypair 创建非对称密钥对
- add-generic-password 向钥匙串中添加通用密码项
- find-generic-password 查找通用密码项
- delete-generic-password 删除通用密码项
- add-internet-password 向钥匙串中添加网络密码项
- find-internet-password 查找网络密码项
- delete-internet-password 删除网络密码项
- add-certificates 向钥匙串种添加证书
- find-certificate 查找证书
- delete-certificate 从钥匙串种删除证书
- find-identity 查找认证实体(证书+私钥)
- set-identity-preference
- get-identity-preference
- create-db
- export
- import
- cms 编码或解码CMS信息(PKCS#7)
- install-mds 安装/重装MDS 数据库
- add-trusted-cert 添加可信证书(只包含公钥,无私钥)
- remove-trusted-cert 删除可信证书
- dump-trusted-setting 显示信任配置
- user-trust-settings-enable 显示或管理用户级别的信任配置
- trust-settings-export 导出信任配置
- trust-settings-import 导入信任配置
- verify-cert 验证证书
- authorize 授权操作
- authorizationdb 变更授权策略数据库
- execute-with-privileges 带特权执行工具
- leaks 在本进程中运行/usr/bin/leaks
- error 显示指定错误码的描述信息
- create-filevaultmaster-keychain 创建一个带密钥对的钥匙串,用于FileVault恢复(FileVault是苹果系统里的一项保密机制,会自动透明地对主目录的内容进行实时加密和解密)
示例:
# 显示或设置钥匙串搜索列表
security list-keychains
# 显示或设置默认的钥匙串
security default-keychain
# 创建 create-keychain [-P] [-p <password>] [keychainFiles...]
security create-keychain -p 123456 lz_test.keychain
# 删除钥匙串
security delete-keychain
# 解锁钥匙串 unlock-keychain [-u] [-p <password>] [keychainFile]
security unlock-keychain -p '1234' ~/Library/Keychains/login.keychain
security unlock-keychain -p '123456' ~/Library/Keychains/lz_test.keychain
# export
# import
# -k <keychain> 指定要导入项目到哪个钥匙串中
# -t <type> 指定要导入的项目类型,可取值为: pub | priv | session | cert | agg
# -f <format> 指定导入项目的格式,可取值为:openssl | openssl1 | openssl2 | bsafe | raw | pkcs7 | pkcs8 | pkcs12 | netscape | pemseq
# -w 标明包装了私钥,导入时要解开
# -x 标明导入后,私钥无法提取私钥
# -P <password> 直接输入导入项目密码,默认会使用GUI输入密码
# -a 指定键值对属性,可以重复出现多次
# -A 所有程序可以使用导入的项目
# -T 指定可以使用导入项目的程序,可以重复出现多次
import <inputfile> [-k <keychain>] [-t <type>] [-f format] [-w] [-P passphrase] [options...]
export [-k keychain] [-t type] [-f format] [-w] [-p] [-P passphrase] [-o outfile]
# find-certificate [-a] [-c name] [-e emailAddress] [-m] [-p] [-Z] [keychain...]
# find-identity [-p policy] [-s string] [-v] [keychain...]
# -p 按指定用途策略查找,可重复出现以指定多项,可用值有: basic, ssl-client, ssl-server, smime, eap, ipsec, ichat, codesigning, sys-default, sys-kerberos-kdc ,macappstore, appleID
# -s 为-p指定的策略提供参数
# -v 只显示有效的,默认显示所有。
# 如果未指定keychain,则使用默认的搜索列表
security find-identity -v -p codesigning #显示默认搜索列表中有效地认证实体
security find-identity -v
codesign
- 语法
codesign -s identity [-i identifier] [-r requirements] [-fv] [path ...]
codesign -v [-R requirement] [-v] [path|pid ...]
codesign -d [-v] [path|pid ...]
codesign -h [-v] [pid ...]
- option
-d
,--display
。在给定的路径上显示有关代码的信息。-f
,--force
。签名时,使codesign替换给定路径上的任何现有签名。-s
,--sign
identity。在使用此标识指定的路径上对代码签名-v
,--verbose
。设置(带有数字值)或增加输出的详细级别。 没有详细选项,将不产生任何输出-v
,--verify
。请求验证代码签名。 如果还请求其他动作(签名,显示等)-vv--entitlements path
。签名时,将文件放在给定的路径上,并将其内容作为授权数据嵌入签名中-i
。指定identifier-o
。指定flag
- 用法
security find-identity -v -p codesigning
# 1) E62BA1F68D1391E4FE07EBF45049C7A648D8B445 "iPhone Developer: 泽 梁 (WVZ5JP3N7M)"
# 2) 9DBA1F6F3F55F19C4D061CCFE8B3E80AF20F4F6D "iPhone Developer: 泽 梁 (ARB84Y67A9)"
# 4) 74C538AE567879DED76B50C81489762FEC29F441 "Apple Development: 泽 梁 (WVZ5JP3N7M)"
# 签名
codesign -s 'iPhone Developer: Thomas Kollbach (7TPNXN7G6K)' Example.app
# 为了重新设置签名,你必须带上 -f 参数,有了这个参数,codesign 会用你选择的签名替换掉已经存在的那一个:
codesign -f -s 'iPhone Developer: Thomas Kollbach (7TPNXN7G6K)' Example.app
# codesign 还可以为你提供有关一个可执行文件签名状态的信息
codesign -vv -d ./empty.app
# Authority=Apple Distribution: Beijing Rongzhi Technology Co., Ltd. (58Y74FY8QK)
# Authority=Apple Worldwide Developer Relations Certification Authority
# Authority=Apple Root CA
# Authority 开头的那三行。这三行告诉你到底是哪一个证书为这个 app 设置了签名。在这里当然是我的证书,iPhone Developer: Thomas Kollbach (7TPNXN7G6K)。我的这个证书则是被证书 Apple Worldwide Developer Relations Certification Authority 设置了签名的,依此类推这个证书则是被证书 Apple Root CA 设置了签名。
# 检查一下签名是否完好
codesign --verify empty.app
echo "hello" > empty.app/hello.txt
codesign --verify empty.app
# empty.app: a sealed resource is missing or invalid
rm -rf empty.app/hello.txt
codesign --verify empty.app
# 可以尝试查看签名信息中具体包含了什么授权信息:
codesign -d --entitlements - empty.app
- Provisioning Profiles 文件存放在
~/Library/MobileDevice/Provisioning Profiles
目录下。 - 配置文件并不是一个 plist 文件,它是一个根据密码讯息语法 (Cryptographic Message Syntax) 加密的文件
- 可以用
security
来看看一个.mobileprovision
文件内部是什么样子:
security cms -D -i ~/Library/MobileDevice/Provisioning\ Profiles/12a5178b-11a9-412e-8ba3-6aa78da89d12.mobileprovision
# DeveloperCertificates 这项,这一项是一个列表,包含了可以为使用这个配置文件的应用签名的所有证书。如果你用了一个不在这个列表中的证书进行签名,无论这个证书是否有效,这个应用都无法运行
# 如果你打开的是一个用于开发测试的证书,你会看到一项 ProvisionedDevices,在这一项里包含了所有可以用于测试的设备列表。因为配置文件需要被苹果签名,所以每次你添加了新的设备进去就要重新下载新的配置文件。
otool
位于 Xcode开发工具链 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
下的 usr/bin
目录下
otool -h 打印Mach-O头
otool -l empty 打印加载命令Load Commands 也会把Mach Header打出来
otool -L empty 打印共享库 这里的L是link的意思
class-dump
- class-dump
- 简介:class-dump 是一个工具,它利用了 Objective-C 语言的运行时特性,将存储在 Mach-O 文件中的头文件信息提取出来,并生成对应的 .h 文件。
- 只能导出OC的哦。我安装有MonkeyDev,他安装了classdump.通过which class-dump获得安装路径为:
$which class-dump
=>/opt/MonkeyDev/bin/class-dump
- 用法
$class-dump -H MachO文件Path -o 导出头文件需要存放路径
$class-dump -H WeChat -o ~/Desktop/wechatHeader
ASLR (Address Space Layout Randomization)
- 小黄书第93页
- 每次进程启动时,同一进程的所有模块在虚拟内存中的起始地址都会产生随机偏移
- 但是他的大小是不会变的
- 可以在LLDB下使用 image命令拿到本次的ASLR地址
$image list -o -f
- IDA,Hopper 反汇编出来的是 基地址 也就是没有偏移前的地址
- 偏移后模块基地址 = 偏移前模块基地址 + ASLR偏移
- funcA的偏移后的地址 = 偏移前符号地址 + ASLR偏移
- 比如NiXaingDemo中的 aslr = 0x00000000029bc000
[ViewController loadrequest]偏移后的Address = 00000001000068d0 + 0x00000000029bc000
= 0x1029c28d0
lldb中在 0x1047da924 下断点 br s -a 0x1029c28d0
[BeiNiClass beiNiFunction7] 偏移后的Address = 0000000100006864 + 0x00000000029bc000
=0x1029c2864 下断点 br s -a 0x1029c2864
Theos
- /opt/theos/bin/nic.pl -> 选择模块创建项目 一般是Tweak 写代码
- make 把当前的工程编译一下
- make package后会生成一个deb包
- make install安装 ,会把安装包拷贝到手机上,需要连接到手机 exprot THEOS_DEVICE_IP = 10.2.198.1.23 再 make install
##logify.py
在 ~/.bash_profile 文件下 添加 alias logify="/opt/theos/bin/logify.pl"
- logify 头文件path (> tweak.xm路径)【这个是写入文件的可以不加】
#CaptinHook
- wiki
- 提供了一系列方法用来hook NSObject
CHDeclareClass
CHOptimizedMethod
CHConstructor{
CHLoadLateClass
CHHook
CHClassHook
CHDeclareMethod//添加新方法
CHPropertyRetainNonatomic//添加新属性
}
yololib
- yololib 可执行文件path dylibpath
- /usr/local/bin/yololib "$TARGET_APP_PATH/$APP_BINARY" "Frameworks/$.framework/$"
- /usr/local/bin/yololib "$TARGET_APP_PATH/$APP_BINARY" "$.dylib"
#otool
- otool -l exec | grep crypt 查看文件加密信息
- otool -L yourApp.app/yourApp 查看Mach-O(可执行二进制文件)引用的framework与dylib
- otool -h + 文件名 //查看头部
- otool -hv + 文件名
- otool -s __TEXT __text xxx //二进制
- otool -tv xxx|head -n 10 //可视化
install_name_tool 动态库的依赖动态库路径修改工具
- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool [-change old new] ... [-rpath old new] ... [-add_rpath new] ... [-delete_rpath old] ... [-id name] input
- -change 修改依赖路径
- -id 修改动态库本身的install_path
- 扩展知识点
- install Name 本质是一个路径,告诉连接器在运行时在哪里找到需要的库
- @executable_path 这个变量表示可执行程序所在的目录
- @loader_path 这个变量表示每一个被加载的 binary (包括可执行程序, dylib, framework 等) 所在的目录. 在一个进程中, 对于每一个模块, @loader_path 会解析成不用的路径, 而 @executable_path 总是被解析为同一个路径(可执行程序所在目录).
- @rpath 将告诉动态链接器去本地的列表搜索这个库。
lipo
lipo -info QQKSong 查看二进制文件信息 => QQKSong are: armv7 arm64 lipo QQKSong -thin arm64 -output ../arm64 => 提取arm64架构
lipo -create thin_onew thin_two -output fat
IDA IDA调试技巧
- ida常用快捷键
/opt
- 编译后把 binary 拖到 ~/Documents/bin 目录下
- 在 ~/.bash_profile 文件下 添加 alias binary="~/Documents/bin"
acextract 导出 Assets.car的资源图片
mkdir -p ~/AssetsOutput
acextract -i ~/Assets.car -o ~/AssetsOutput
restore-symbol 对bin进行符号还原
- 编译
cd restore-symbol && make
- 对OC方法进行符号还原
restore-symbol origin_mach_o_file -o mach_o_with_symbol
- 对block进行符号还原; 等IDA反编译完成后,把 ~/Documents/opt/ida_search_block.py 或者 ~/Documents/opt/restore-symbol/search_oc_block/ida_search_block.py cp到 待还原的bin目录下
- 在IDA点File -> Script file, 选ida_search_block.py 会生成 一个 block_symbol.json 文件,下方的命令 -j 就是选json文件
restore-symbol origin_mach_o_file -o mach_o_with_block_symbol -j block_symbol.json
ida-swift-demangle 一个ida脚本来解析swift函数名
- 等IDA分析完成后 点File -> Script file,选 ~/Documents/opt/ida-swift-demangle.py 或者 ~/Documents/opt/ida-swift-demangle/ida-swift-demangle.py ,copy到ida分析的bin目录下比较好
frida-ios-dump 一键砸壳和查看进程id bundleid
- 下载源码,切换分支 起别名 frida-ios-dump
- 连上手机 端口转发 并使用
$ iproxy 2222 22
$ frida-ios-dump -l //查看所有的进程 可以用 grep 过滤
$ frida-ios-dump Display name or Bundle identifier 砸到电脑的下载目录
sbr 使用Python脚本强化LLDB调试器 例子
cd ~/Documents/opt
mkdir lldbScript
touch sbr.py
然后在 ~/.lldbinit 文件写下 command script import ~/Documents/opt/lldbScript/sbr.py 重启即可
LLDB别名/正则表达式和Python脚本的集合
- 下载源码 然后在 ~/.lldbinit 文件写下 command script import ~/Documents/opt/LLDB/lldb_commands/dslldb.py
Hopper Disassembler
- 理论知识:能通过 Mach-O 做代码分析代码的一个重要原因就是机器语言可以反推成汇编语言,是可逆的。原因就是在同一种架构平台下,每一条汇编指令都有与之对应的唯一的机器指令,这种反推行为一般叫反编译。但是 汇编语言不能百分百反推oc等高级语言,因为有些不同但相似的代码,编译成汇编语言是一模一样的。比如具有相同元素的结构体和数组,编译后汇编语言就是一样的。所以说不能百分百还原,但是因为部分代码还是相似的,所以还是可以看个大概的。下面就借助 Hopper disassembler 工具将 Mach-O 文件的机器语言代码反编译成汇编代码、OC伪代码或者Swift伪代码。参考
- 在左边的控制面板中,可以通过字符串搜索字段,函数名类名等等
- 控制面板上面的导航条不同颜色代表了不同的含义
- 蓝色 部分表示代码(code)
- 黄色 部分表示程序(procedure)
- 绿色 部分表示ASCII字符串(string)
- 紫色 部分表示数据(data)
- 灰色 部分是不能识别的类型 红色小箭头表示当前你的光标所在的位置
- 一旦一个可执行文件被加载入Hopper,你就可以使用键盘或者界面上顶部的工具条改变它的类型。
- 导航条上面 Transformations 上的 DACPU 此工具条包含了你能设置的(D即Date,A即ASCII,依此类推)类型按钮,这些字母同样也有快捷键,你可以直接通过快捷键直接进行类型转换。 Date类型有一些具体的表示形式:比如当你第一次选择这个类型时,Hopper将这个你选择的一块区域转换为字节型,如果你再次选择它,这个字节将会被转换为一个16位的整数型,然后再是32位的整数型,依此类推。Hopper提供了一个“取消”/“重做”的功能,让你可以随意的去更改和探索可执行文件。
- Data :当Hopper认为数据中的一块区域表示常量的时候,这块区域将被设置为data(数据)类型。例如一段int数组,这样的情况就会被设置。
- ASCII : 一个以空值为终止的C字符串。
- Code :一个指令。
- Procedure (程序):一旦确定它是由Hopper重新构建的函数的一部分,则该字节接受该类型。
- Undefined (无法识别):这是目前为止还未被Hopper探索的一块区域。
- D 按键不断点击,在汇编代码区会有不同的变化
- 再右边的 View Mode 的4个按钮代表了4种不同的显示方式依次为
- 显示模式
- 汇编模式
- Hopper将一行一行的汇编代码,这是很多反汇编软件都提供的一种模式。
- 第一栏(蓝色数字处)代表指令的地址位置。它在每条指令、操作元(或者寄存器)的最前端。作为一项选择,在应用的偏好设置中,你能选择在地址和伪指令(the instruction mnemonic)之间显示指令编码。
- 在边缘,你能看到一些有眼色的箭头服务好。这些箭头代表指令可能跳转的位置。例如,在0x100002d82和0x100002db4地址之间的蓝色箭头代表了在0x100002d82的je指令如果满足je判断的条件,则跳转至0x100002db4这个位置。当这个指令跳转为向高地址(向下跳转)跳转时,则箭头为蓝色。如果这个指令向上(向低地址)跳转时,则箭头为红色。
- 需要注意的是在左边两个竖条(红和蓝),如果你点击红色栏,你将在相应的地址设置一个断点,如果你点击蓝色栏,你将在相应的地址设置一个书签。
- 控制浮动图表模式
- 控制浮动图表模式将程序以更具有结构化的方式显示出来。
- 在此界面上你仍然可以进行编辑一些事项,比如备注和标签。鼠标可以从一个基础块移动到另一个基础块;简单地移动鼠标至当前的基础块上,使用你键盘上的方位键来跳转至最近的基础块。如果你按下向上或者向下的按键,鼠标光标将移至最近的基础块,不过请使用相同的栏目。同样,你按右键、左键也移到对应的位置。
- 在右边的控制面板中(检测窗),你会发现存在该模式的总览图。控制浮动图表的组成展示了当前程序展示的一个整体缩略图,被称为“迷你图”。每一个方块代表一个基础块,其中的线表示它们之间的联系。在“迷你图”中,我们可以看到一个蓝色的基础块,基础块被填充为蓝色意味着光标的位置在此基础块中。在高亮灰色方块表示当前你所看到的控制浮动图表部分。你可以直接在这个“迷你图”中点击移动它。
- 图表上的这些节点可以被修饰。例如,当你认为某块与某块具有密切联系时,可以对它们进行分组。选择这些节点并在“检测窗”点击“Group Nodes(组节点)”按钮。
- 你也能给一个节点设置一个你常用背景色,或者插入一段文本。
- 伪代码模式
- 在这个模式中,Hopper将尝试着生成一些“假”代码,功能上相当于原始的CPU指令,但是它们更像是Objective-C的函数。
- 这种模式让你分析以及阅读更加容易,不过你需要记住的是这些并不是“魔法”,有时,它并不能够将构建一个该程序完美的“假”代码展现出来,并且有些部分可能不会显示出来。因为Hopper可能将它们定义为没有联系的代码(也称之为dead code),为了尽量的避免这个问题,你可以尝试在界面的上方切换相应复选框。
- 十六进制模式
- 汇编模式
- 图表模式用红绿蓝三种线
- 红色代表条件不成立时执行
- 绿色代表条件成立
- 代表执行