|
吾爱游客
发表于 2017-10-9 12:48
1、申 请 I D:ttimasdf
2、个人邮箱:ttimasdf(at)qq.com
3、原创技术文章:
Github: ttimasdf
Blog
简单破解macOS版Surge
简单说明一下要破解一个OSX(唔……马上就要叫macOS了)程序所需要的知(tao)识(lu)和小工具。毕竟作为工具小子,会用工具就是成功的一大半。
0xFF 入门知识
x86汇编 总该会一点的。印一个cheat sheet对着看就行。
C语言 需要有一定了解,毕竟反汇编结果都是以伪C语言形式呈现。
常识 注册按钮英文是register,激活叫activate,被捉奸是revoked,等等。
0x00 工具ID
A 一键反编译。静态分析大杀器。Hopper Disassembler OS X 下的反汇编软件,下试用版就行,也可以用PYG的破解版。对 Obj-C 有独特的理解,毕竟时髦unsign(可选)自己写的小工具,强制移除一个macho文件(类似于win的PE文件)的数字签名。mac下数字签名是几乎所有程序都有的,下文会讲两个绕过签名的方式,这是其中之一。
0x01 字符串查找
这里选取的软件是 OS X 下著名的“网络加速工具” Surge。从官方网站下载下来的软件是一个 Surge.app 的文件夹,名为[name].app 的文件夹是OS X软件的组织方式。在 Surge.app/Contents/MacOS/ 下找到软件真正的可执行文件。分别载入 Hopper和IDA。Shift-F12打开IDA字符串窗口, Ctrl-F 搜索 register,一不小心就找到一个 registerButtonPressed
0x02 查找引用
想想也知道,这是一个按钮事件,还是注册按钮的。绑定它上面的函数一定是注册相关的关键函数。双击进入反汇编窗口在这里查找数据引用。说一点IDA这里的好,所有的字符串名字都被自动命名为与字符串内容相关的名字比如 sel_registerButtonPressed 。非常直观。虽然反编译出来的代码里Obj-C引入的 CFString 字符串引用都瞎得不能看……可还是很好用哒!注意,这里不能使用 x 键直接搜索这个字符串的引用。这里我走了点弯路。开始我以为它跳到的函数一定是注册相关的函数,跳到了xref直接把变量命名为了 registerButtonPressed ,后来我又看了看逻辑发现是个死胡同的时候,仔细看了看调用语句,是这样一句。
# IDA
__text:000000010009E6FC lea rax, registerButtonPressed
# Hopper
000000010009e6fc lea rax, qword [ds:sub_10009e785] | 从命名规则来看, registerButtonPressed 这个字符串被当成了一个函数呀!虽然这个函数也跟注册有点关系(点击注册信息后获取信息的函数),可刚刚我们看到它是个字符串诶。直到这里,我才注意到 code reference 和 data reference 的区别,关于这个话题这里有一篇详细的文章。总之,大体区别是,我们在一行代码上点击 x 查找 shu ju yin yong,是对当前汇编语句的“参数”(operand)进行的查找,而data reference是对这个语句所在内存地址的引用的查找,我平时习惯在函数名上弹xref窗,所以才看不出区别。但是在这个字符串上,应该查看的是数据引用。数据引用的查看,可以用IDA的 Cross Reference subview。汇编注释里,默认也显示一个。显示的数量可以在设置里改。
0x03 修改关键函数
跳转过去后,发现这个函数被绑定到 __WindowController_registerButtonPressed__ 里,而那个控制器里向某个变量里储存了一个函数。
Hopper
================ B E G I N N I N G O F P R O C E D U R E ================
-[WindowController registerButtonPressed:]:
000000010009e2bd push rbp ; Objective C Implementation defined at 0x10029a338 (instance)
000000010009e2be mov rbp, rsp
000000010009e2c1 sub rsp, 0x30
000000010009e2c5 mov rax, qword [ds:imp___got___NSConcreteStackBlock]
000000010009e2cc mov qword [ss:rbp+var_28], rax
000000010009e2d0 mov dword [ss:rbp+var_20], 0xc2000000
000000010009e2d7 mov dword [ss:rbp+var_1C], 0x0
000000010009e2de lea rax, qword [ds:sub_10009e322] ; 关键函数(因为整个方法里面只有这个变量类型是函数 ˊ_>ˋ )
000000010009e2e5 mov qword [ss:rbp+var_18], rax
000000010009e2e9 lea rax, qword [ds:0x100257d20]
000000010009e2f0 mov qword [ss:rbp+var_10], rax
000000010009e2f4 call qword [ds:imp___got__objc_retain]
000000010009e2fa mov qword [ss:rbp+var_8], rax
000000010009e2fe mov rsi, qword [ds:0x1002ae0b0] ; @selector(refresh:), argument "selector" for method imp___got__objc_msgSend
000000010009e305 lea rdx, qword [ss:rbp+var_28]
000000010009e309 mov rdi, rax ; argument "instance" for method imp___got__objc_msgSend
000000010009e30c call qword [ds:imp___got__objc_msgSend]
000000010009e312 mov rdi, qword [ss:rbp+var_8]
000000010009e316 call qword [ds:imp___got__objc_release]
000000010009e31c add rsp, 0x30
000000010009e320 pop rbp
000000010009e321 ret
; endp | 这个函数就是点击按钮以后触发的事件。跟进去以后就是啦!
IDA
__text:000000010009E322 ; =============== S U B R O U T I N E =======================================
__text:000000010009E322
__text:000000010009E322 ; Attributes: bp-based frame
__text:000000010009E322
__text:000000010009E322 ked_doActivate proc near ; DATA XREF: -[WindowController registerButtonPressed:]+21o
__text:000000010009E322
__text:000000010009E322 var_48 = qword ptr -48h
__text:000000010009E322 var_40 = dword ptr -40h
__text:000000010009E322 var_3C = dword ptr -3Ch
__text:000000010009E322 var_38 = qword ptr -38h
__text:000000010009E322 var_30 = qword ptr -30h
__text:000000010009E322 var_28 = qword ptr -28h
__text:000000010009E322
__text:000000010009E322 push rbp
__text:000000010009E323 ...
__text:000000010009E336 call ked_getValid ; 让这个函数的返回值为2!
__text:000000010009E33B cmp eax, 2
__text:000000010009E33E jnz loc_10009E410 ; 不是2就死了
__text:000000010009E344 ...
__text:000000010009E39C mov rsi, cs:selRef_initWithTitle_message_cancelButtonTitle_cancelAction_
__text:000000010009E3A3 lea rdx, cfstr_SurgeHasBeenAc ; "Surge has been activated. Thanks for your purchase. Enjoy now!"
__text:000000010009E3AA lea r8, cfstr_Ok ; "OK"
__text:000000010009E3B1 lea r9, [rbp+var_48]
__text:000000010009E3B5 xor ecx, ecx
__text:000000010009E3B7 mov rdi, rbx
__text:000000010009E3BA call r12 ; _objc_msgSend | 0x04 应用签名
OS X的软件“安全”这一点应该毋庸置疑,因为默认的设置下,苹果系统只允许花一百美元一年在苹果进行防沉迷认证的程序员写的程序运行在系统上,一旦程序员走火入魔发放恶意软件,向苹果举报,它就会被revoked,系统的GateKeeper就会阻止程序运行。而且系统会无条件,没有白名单的拒绝被篡改后签名失效的程序和虚假签名的程序。算是一个不大不小的问题。解决办法,不是改签就是删掉签名咯。
0x0401 删除数字签名
unsign这个小程序可以删除一个 mach-o binary里面的签名认证。mac虽然拒绝假签名,但我们穷逼就是没钱苹果也得让着,没有签名的程序手动添加白名单凑合凑合就能用。用这个程序把应用里面所有的二进制文件的签名验证全部删除就可以了,此脚本删除app里面其他所有的已签名文件。
uns(){ ~/unsign "$1";mv "$1" ~ ; mv "$1.unsigned" "$1";}
uns 'Surge.app/Contents/MacOS/Surge'
uns 'Surge.app/Contents/Applications/Surge Dashboard.app/Contents/MacOS/Surge Dashboard'
uns 'Surge.app/Contents/Applications/surge-cli'
find . -name _CodeSignature | xargs -I% rm -R "%" | 0x0402 修改数字签名
这个方法本来是苹果为被黑阔暗算的小苦逼们准备的,可以覆盖程序原来的签名并写入新的验证文件。照猫画虎的给surge写了一个批量签名小脚本。使用要求:一百美元一年的mac developer ID(),系统安装任意版本的XCode。
#!/bin/bash
# https://jbavari.github.io/blog/2 ... ectron-applications
app="$PWD/Surge.app"
# iden是钥匙串里相应证书的 Common Name
iden="Mac Developer: thisiscertificatecommonname (XXXXXXXXXX)"
sign(){
codesign --deep --force --verify --verbose -s "$iden" $1
}
find $app -name _CodeSignature | xargs -I% rm -R "%"
sign "$app/Contents/Frameworks/Sparkle.framework/Sparkle"
sign "$app/Contents/Frameworks/Sparkle.framework/Versions/A"
sign "$app/Contents/Applications/Surge Dashboard.app"
sign "$app" |
摘自本人去年的一篇博客,文字稍有轻浮,望海涵 |
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|