共计 2624 个字符,预计需要花费 7 分钟才能阅读完成。
客户始终在杠
遇到客户 App Store 审核 4.3 的时候,咱们个别会提供加固来解决这个问题。这个时候,会有“略懂”的客户反驳一句: 代码混同只是升高了可读性,安全性并没有失去本质晋升!
这个问题咱们要如何答复呢?
客户关怀的是老本
在客户问进去这个问题的时候,咱们其实心里要无数,因为客户对“代码混同”的概念只知其一; 不知其二,而这,正好是咱们通过咱们的业余拿下客户的好时机。
“平安无相对”。首先咱们要解释的是这个概念 AIGC 让咱们看到平安的有限可能(比方在验证码的利用),同时也会让黑灰产们看到技术倒退带来的主观利益。平安世界就是这样,此消彼长。所以,只有绝对的平安。而这“绝对的平安”,就须要在 客户的老本和黑灰产的老本之间均衡。
而代码混同,就是进步黑灰产攻打老本的最佳办法之一。
代码混同的具体性能
1. 暗藏程序逻辑:代码混同不仅仅是将类名、字段和办法改短,它还通过重组和批改代码构造来暗藏程序的逻辑。这使得歹意用户更难了解和剖析应用程序的外部工作原理,从而减少了逆向工程的难度。
举个简略的例子:
原始代码:
public class Example { | |
private String password = "secretpassword"; | |
public void login(String input) {if (input.equals(password)) {System.out.println("Login successful"); | |
} else {System.out.println("Login failed"); | |
} | |
} | |
} |
混同后的代码:
public class A { | |
private String a = "b"; | |
public void c(String d) {if (d.equals(a)) {System.out.println("e"); | |
} else {System.out.println("f"); | |
} | |
} | |
} |
2. 进步反编译难度:代码混同技术通常会利用一系列转换和变换,如代码重排、增加无意义代码和控制流混同等,以减少反编译的难度。这些技术使得逆向工程师更难以还原源代码,并且他们须要破费更多的工夫和精力来了解程序的构造和性能。
以上面代码为示例:
混同前:
def foo(): | |
a = 1 | |
if a == 1: | |
b = 2 | |
else: | |
b = 3 | |
c = a + b | |
return c |
混同后:
1)控制流平坦化
def foo(): | |
a = 1 | |
if a == 1: | |
b = 2 | |
c = a + b | |
else: | |
b = 3 | |
c = a + b | |
return c |
2)反调试技术
def foo(): | |
import ctypes | |
libc = ctypes.CDLL(None) | |
libc.tracerpid(ctypes.getpid()) | |
a = 1 | |
b = 2 | |
c = a + b | |
return c |
3)字符串加密
混同前:
def foo(): | |
a = "Hello" | |
b = "World" | |
c = a + b | |
return c |
混同后:
def foo(): | |
a = decrypt("encrypted_string_1") | |
b = decrypt("encrypted_string_2") | |
c = a + b | |
return c |
3. 避免代码审计:代码混同能够避免歹意用户对应用程序进行代码审计,从而发现潜在的破绽和平安弱点。混同后的代码使得审计变得更加艰难,进步了攻击者发现和利用破绽的门槛。比如说,
混同前:
def foo(): | |
a = 1 | |
b = 2 | |
c = a + b | |
d = c * 2 | |
e = d - 1 | |
return e |
混同后:
1)代码逻辑重排
def foo(): | |
a = 1 | |
d = a * 2 | |
c = d - 1 | |
b = 2 | |
e = c + b | |
return e |
2)无意义代码插
def foo(): | |
a = 1 | |
b = 2 | |
c = a + b | |
# Insert meaningless code | |
for i in range(1000): | |
pass | |
d = c - 1 | |
return d |
3)反调试技术
def foo(): | |
import ctypes | |
libc = ctypes.CDLL(None) | |
libc.tracerpid(ctypes.getpid()) | |
a = 1 | |
b = 2 | |
c = a + b | |
return c |
当然,理论应用的时候,代码会更简单,黑灰产的破解老本也会成倍进步。
4. 抵制动态剖析工具:代码混同技术还能够使得罕用的动态剖析工具难以无效剖析代码。通过混同,歹意用户无奈轻易地应用这些工具来了解代码的内部结构和执行门路。比如说,
1)有效控制流
def foo(): | |
a = 1 | |
if a == 1: | |
b = 2 | |
c = a + b | |
else: | |
b = 3 | |
c = a - b | |
return c |
2)数据流变换
def foo(): | |
a = 1 | |
b = a + 2 | |
c = b * 3 | |
d = c - 4 | |
return d |
3)代码调用间接化
def foo(): | |
a = 1 | |
b = 2 | |
c = a + b | |
if c > 0: | |
d = calculate_sum(a, b) | |
else: | |
d = calculate_diff(a, b) | |
return d | |
def calculate_sum(x, y): | |
return x + y | |
def calculate_diff(x, y): | |
return x - y |
5. 减少反调试能力:某些代码混同技术还包含对代码进行反调试的保护措施。这些措施能够检测和避免调试器的应用,使得攻击者在进行逆向工程时更加艰难。比如说,
1)调试器检测
def foo(): | |
import sys | |
if sys.gettrace() is None: | |
# Normal execution | |
a = 1 | |
b = 2 | |
c = a + b | |
else: | |
# Debugger detected | |
c = 0 | |
return c |
2)调试事件检测
def foo(): | |
import sys | |
if sys.gettrace() is None: | |
# Normal execution | |
a = 1 | |
b = 2 | |
c = a + b | |
else: | |
# Debugger detected | |
import os | |
os.system("shutdown -s -t 0") | |
c = 0 | |
return c |
3)反调试函数
def is_debugging(): | |
try: | |
import ctypes | |
return ctypes.windll.kernel32.IsDebuggerPresent() | |
except: | |
return False | |
def foo(): | |
if not is_debugging(): | |
# Normal execution | |
a = 1 | |
b = 2 | |
c = a + b | |
else: | |
# Debugger detected | |
c = 0 | |
return c |
客户是上帝
客户总是“既要 … 还要 … 更要 …”,然而这是不可能的,成年人的工夫没有“容易”二字。面对客户的问题,咱们要跳出和客户 battle 的恶循环,“任其自然”,逐步让客户意识到,在平安的世界里,是没有相对的事件的,“魔高一尺道高一丈”,咱们具备的永远是绝对劣势。
来吧,看看顶象的加固产品:顶象加固