其他
Fairplay DRM与混淆实现的研究
总第479篇
2021年 第049篇
什么是DRM?
Apple上DRM的实现:即Fairplay DRM
LC_ENCRYPTION_INFO中的标记
Fairplay的Open
Fairplay的Decrypt Page
SINF和SUPF文件
结构
SINF
SUPF
混淆原理和一些实现
LLVM Pass
makeOpaque
不透明谓词(Opaque Predicate)
可逆变换
MBA表达式(Mixed Boolean-Arithmetic Expression)
不透明常量(Opaque Constant)
控制流平坦化
非直接跳转(Indirect Branch)
跨函数混淆 + 调用约定混淆
Fairplay混淆的弱点
函数边界识别
非直接跳转
数据流混淆
结束语
什么是DRM?
US8934624B2: Decoupling rights in a digital content unit from download US8165286B2: Combination white box/black box cryptographic processes and apparatus ES2373131T3: Safe distribution of content using descifrado keys
Apple上DRM的实现:Fairplay DRM
LC_ENCRYPTION_INFO中的标记
Fairplay的Open
char const* executable_path,
long long cpu_type,
long long cpu_subtype,
rp6S0jzg** out_handle
)
mach_msg_header_t header;
mach_msg_body_t body;
mach_msg_ool_descriptor_t ool;
NDR_record_t ndr;
uint32_t size;
uint64_t cpu_type;
uint64_t cpu_subtype;
};
struct FPResponse{
mach_msg_header_t header;
mach_msg_body_t body;
mach_msg_ool_descriptor_t ool1; //supf文件映射
mach_msg_ool_descriptor_t ool2; //unk,正比与加密内容的尺寸
uint64_t unk1;
uint8_t unk2[136];
uint8_t unk3[84];
uint32_t size1;
uint32_t size2;
uint64_t unk5;
};
Fairplay的Decrypt Page
rp6S0jzg *hanlde,
unsigned long long offset,
unsigned char const* src,
unsigned char * dst
)
SINF和SUPF文件
结构
SINF
sinf.schm: itun
sinf.schi.user: 0xdeadbeef
sinf.schi.key : 0x00000005
sinf.schi.iviv: 0x12345678901234567890123456789012
sinf.schi.righ.veID: 0x000007d3
sinf.schi.righ.plat: 0x00000000
sinf.schi.righ.aver: 0x01010100
sinf.schi.righ.tran: 0xdc64f80c
sinf.schi.righ.sing: 0x00000000
sinf.schi.righ.song: 0x59a73c58
sinf.schi.righ.tool: P550
sinf.schi.righ.medi: 0x00000080
sinf.schi.righ.mode: 0x00002000
sinf.schi.righ.hi32: 0x00000004
sinf.schi.name: User Name
sinf.schi.priv: (432 Bytes Private Key)
sinf.sign: (128 Bytes Private)
SUPF
Segment 0x0: arm64, Keys: 0x36c/4k, sha1sum = e369546960d805dd1188d42e3350430c7e3a0025
Fairplay Certificate:
Data:
Version: 3 (0x2)
Serial Number:
33:33:af:08:07:08:af:00:01:af:00:00:10
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=Apple Inc., OU=Apple Certification Authority, CN=Apple FairPlay Certification Authority
Validity
Not Before: Jul 8 00:48:29 2008 GMT
Not After : Jul 7 00:48:29 2013 GMT
Subject: C=US, O=Apple Inc., OU=Apple FairPlay, CN=AP.3333AF080708AF0001AF000010
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (1024 bit)
Modulus:
00:b0:01:16:4b:62:b2:37:8d:60:12:4f:02:15:15:
a0:32:1b:e8:ed:44:ed:e9:17:5b:ec:9e:5d:11:24:
5a:66:2f:dc:a3:25:aa:52:70:e1:09:22:09:4b:65:
0f:67:f5:82:dc:af:78:9b:4c:45:f3:b4:f4:77:aa:
fc:a3:b2:84:c3:8b:09:c6:2e:55:f5:14:85:07:ac:
ae:0d:ff:ff:ca:41:3b:44:cb:52:b6:28:60:55:23:
35:8d:26:71:c6:12:a5:e0:72:58:09:3c:4a:9e:b6:
63:df:2a:91:94:27:eb:65:0a:b2:36:45:11:c1:91:
43:58:12:d9:e5:18:a1:ad:db
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment, Data Encipherment, Key Agreement
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
7B:07:34:81:A5:75:D0:F6:11:BB:D2:36:3F:79:93:4B:A1:70:EB:CF
X509v3 Authority Key Identifier:
keyid:FA:0D:D4:11:91:1B:E6:B2:4E:1E:06:49:94:11:DD:63:62:07:59:64
Signature Algorithm: sha1WithRSAEncryption
06:11:4e:87:ed:b1:08:70:c2:0d:e4:d2:94:bb:7f:ee:50:18:
c0:2a:21:34:0e:99:1f:bf:60:a2:58:d0:0c:28:3d:03:5b:ab:
4e:72:69:ba:41:52:45:b2:29:27:4a:c8:ba:7f:b5:9b:63:78:
b1:68:41:40:59:3f:05:8a:57:74:c5:63:30:cc:f3:20:41:c0:
3c:65:d4:0d:22:47:f3:97:76:e6:d6:3c:eb:e7:20:78:10:59:
fd:96:09:82:c3:41:f0:5f:d0:3e:91:44:6d:77:3f:a5:d9:da:
f0:f7:53:ad:94:61:28:1c:4c:40:3b:17:2b:dd:e3:00:df:77:
71:22
RSA Signature: 6aeb00124d62f75f5761f7c26ec866a061f0776be7e84bfad4b6a1941dbddfdb3bd1afdcc5ef305877fa5bee41caa37b1a9d4ce763cf7d2cb89efa60660a49dd5ddff0f46eee7cd916d382f727d912e82b6e0a62e8110c195e298481aa8c8162faac066ef017c6c2c508700d7adb57e0c988af437621e698946da1b09adf89e9
混淆原理和一些实现
LLVM Pass
makeOpaque
不透明谓词(Opaque Predicate)
bool y = ((x * x % 4) == 0 || (x * x % 4) == 1);
foo2();
if ( false )
junk_code();
else
foo2();
uint32_t x = rand();
bool y = ((x * x % 4) == 0 || (x * x % 4) == 1);
if ( !y )
junk_code();
else
foo2();
可逆变换
异或
仿射变换(Affine transformation)
它的一般表达式为:
这里是一个的矩阵,是一个维向量,是一个维向量。所以它也可以表示为:
当时,仿射函数就是线性函数。 那么,在MBA混淆中,仿射函数在有限域上即可表示为:
其中且互质,则的逆函数为:
其中是在有限域上的乘法逆元,满足。
uint32_t a, r_a;
//如果满足
(a * r_a) % UINT32_MAX == 1;
//那么 a 和 r_a 互为模反元素
uint32_t y1 = a * x + c;
//那么满足
x == ra * y1 + (- ra * c)
uint32_t x = 0xdeadbeef;
uint32_t c = 0xbeefbeef;
//则 -ra * c = 0x57f38dcb,且
((x * 4872655123) + 0xbeefbeef) * 3980501275 + 0x57f38dcb == x
/*
可在lldb中验证如下
(lldb) p/x uint32_t x=0xdeadbeef; (uint32_t)(((x * 4872655123) + 0xbeefbeef) * 3980501275 + 0x57f38dcb)
(uint32_t) $8 = 0xdeadbeef
*/
MBA表达式(Mixed Boolean-Arithmetic Expression)
那么,线性MBA表达式是多项式MBA表达式的一种特殊形式:
类似的,在Fairplay混淆中用到的MBA表达式为:
x - c = (x ^ ~c) + ((2 * x) & ~(2 * c + 1)) + 1;
MBA改写(MBA rewrites):将一个运算改写为MBA表达式(比如上文中改写)。 插入一致性(Insertions of identities):假设是使用MBA混淆过的表达式的某一部分,是中的可逆函数,则有成立,是仿射函数。
不透明常量(Opaque Constant)
,是的逆:,。 是要隐藏的常量。 是变量组成的值为的MBA表达式(类似)。
控制流平坦化
非直接跳转(Indirect Branch)
LUT[i] = PC;
//执行跳转
jmp/call LUT[makeOpaque(i)]
跨函数混淆 + 调用约定混淆
Fairplay混淆的弱点
函数边界识别
非直接跳转
w10 = qword[x12 + (EQ * 0xB + w19) << 3]
//0xB代表两个基本块的在LUT中的下标差
数据流混淆
结束语
参考文献
Eyrolles, N. (2017). Obfuscation with Mixed Boolean-Arithmetic Expressions: reconstruction, analysis and simplification tools (Doctoral dissertation, Université Paris-Saclay) https://github.com/obfuscator-llvm/obfuscator https://github.com/HikariObfuscator/Hikari https://github.com/keystone-engine/keypatch https://eshard.com/posts/d810_blog_post_1
作者简介
阅读更多