马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 Furau 于 2023-10-1 14:42 编辑
《Ren'Py强化之旅:Windows下引擎潜力探索》04.外置PE文件实现renpy资源加密解密
转载请标注Furau.com
前置说明
第一个综合练习程序,利用PE的特性实现一个加解密程序
RSA算法简介:https://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95
方便大家理解过程我绘制了一个流程图:
下面是我制作的demo,一份最小演示程序。
RSA生成公钥私钥:
[RenPy] 纯文本查看 复制代码 import rsa
import time
# 生成公钥私钥
key_strength = 128
start_time = time.time()
(public_key, private_key) = rsa.newkeys(key_strength * 8)
print('Time consumed:', time.time() - start_time)
with open('public_key.pem', 'w+') as f:
f.write(public_key.save_pkcs1().decode())
with open('private_key.pem', 'w+') as f:
f.write(private_key.save_pkcs1().decode())
加密程序:
[RenPy] 纯文本查看 复制代码 import rsa
import time
# 加密程序
with open('public_key.pem', 'r') as f:
public_key = rsa.PublicKey.load_pkcs1(f.read().encode())
# 需要加密的文件
with open(file='main_menu.png', mode='rb') as f:
data_to_encrypt = f.read()
key_strength = 128
split_length = int(key_strength - 11)
data_length = int(len(data_to_encrypt))
if data_length % split_length == 0:
split_count = int(data_length / split_length)
else:
split_count = int(data_length / split_length + 1)
start = time.time()
encrypted_data = bytes()
for i in range(split_count):
a = i * split_length
b = a + split_length
encrypted_chunk = rsa.encrypt(data_to_encrypt[a:b], public_key)
encrypted_data = encrypted_data + encrypted_chunk
print('Encryption time:', time.time() - start)
# 加密后的文件
with open(file='encrypted_image.png', mode='wb') as f:
f.write(encrypted_data)
解密程序:(我编写了一个GUI页面,方便大家理解交互)
[RenPy] 纯文本查看 复制代码 import tkinter as tk
import rsa
import time
from tkinter import messagebox
def decrypt_image():
with open(file='private_key.pem', mode='r') as f:
key = rsa.PrivateKey.load_pkcs1(f.read().encode())
with open(file='game/gui/encrypted_image.png', mode='rb') as f:
edata = f.read()
key_strength = 128
v_length = len(edata)
v_sq = int(key_strength)
split_count = int(v_length / v_sq)
start = time.time()
# 解密
v_s = bytes()
for i in range(split_count):
a = i * key_strength
b = a + key_strength
v_text = rsa.decrypt(edata[a:b], key)
v_s = v_s + v_text
decryption_time = time.time() - start
messagebox.showinfo("激活(解密成功!)", "解密资源成功!\nDecryption Time: {:.2f} seconds".format(decryption_time))
# 路径按照自己的包体进行定义
with open(file='game/gui/main_menu.png', mode='wb') as f:
f.write(v_s)
def on_button_click():
input_value = input_entry.get()
if input_value == '123':
decrypt_image()
root = tk.Tk()
root.title("键入激活码")
root.geometry("300x100")
input_label = tk.Label(root, text="输入激活码:")
input_label.pack()
input_entry = tk.Entry(root)
input_entry.pack()
button = tk.Button(root, text="Decrypt", command=on_button_click)
button.pack()
root.mainloop()
构建包体
向目录中置入对应的文件,加密后的和解密的key文件+私钥文件置入
分发的目录结构一览
完整demo效果:
总结:
1.因为PE文件的开放性质,理论上PE可以写的更小,更脏(不容易被反编译),性能更高(可以使用不同语言比如CPP,win32asm,basic,Go等等可以自己产生标准PE的语言编写,不同的语言的代码混淆器产生的文件也不相同)
2.外置PE的优点就是目录干净,对本体的影响最小,即使本体被解包,资源也需要单独解密。
3.笔者仅仅给出demo思路,可以理解完整流程后,编制属于自己的加密解密程序,可以尝试把笔者给出的demo改成内嵌到Renpy中(方法可以参考前面的几个帖子)
4.外置加密和内置加密各有不同的优点,内置可以无缝的配合renpy进行交互操作,外置更适合小型工作室,因为需求明确,可以外包出去让专业人员去编制特定的key文件。内置与renpy交互更加完美,也可以使用DLL按照我第一个帖子的方法尽可能的给用户最好的交互
5.编写配置合理外置PE解密,可以拖延破解时间到2周甚至一个月
工程文件:https://www.123pan.com/s/ADdHjv-hdMd3.html
|