最近在淘宝上,搜到过csgo的黑科技,买了之后老板会给你发1天的,7天的,包年的密钥。
我在想,我把别人做好的辅助,外面套一个壳,管理系统,那我不也可以卖挂?(非法哈哈)
抱着学习的心态我就开始了尝试
首先我在服务器端(老板)这里生成密钥:
server.py如下
import secrets
import sqlite3
import tkinter as tk
from tkinter import messagebox, scrolledtext
from cryptography.fernet import Fernet
from datetime import datetime, timedelta
# 硬编码的Fernet密钥
fernet_key = b'BCAmf6ysMlDpauFJsw7YiviqyLboPMqQBhjgEY9vF3E='
fernet = Fernet(fernet_key)
conn = None
cursor = None
# 加密程序的密钥
def encrypt_program_key(program_key):
encrypted_key = fernet.encrypt(program_key.encode()).decode()
return encrypted_key
# 存储加密密钥和过期时间到数据库
def store_encrypted_key(encrypted_key, expiry_time):
cursor.execute('INSERT INTO access_keys (key, expiry) VALUES (?, ?)', (encrypted_key, expiry_time))
conn.commit()
# 创建数据库和表
def init_db():
global conn, cursor
conn = sqlite3.connect('keys.db')
cursor = conn.cursor()
cursor.execute('CREATE TABLE IF NOT EXISTS access_keys (key TEXT PRIMARY KEY, expiry TEXT)')
conn.commit()
# 生成密钥并存储
def generate_multiple_keys():
for _ in range(333): # 生成 333 个 1 天的密钥
program_key = secrets.token_hex(16) # 示例生成程序密钥
encrypted_key = encrypt_program_key(program_key)
expiry_time = (datetime.now() + timedelta(days=1)).isoformat() # 1 天后过期
store_encrypted_key(encrypted_key, expiry_time)
for _ in range(334): # 生成 334 个 7 天的密钥
program_key = secrets.token_hex(16)
encrypted_key = encrypt_program_key(program_key)
expiry_time = (datetime.now() + timedelta(days=7)).isoformat() # 7 天后过期
store_encrypted_key(encrypted_key, expiry_time)
for _ in range(333): # 生成 333 个永久密钥
program_key = secrets.token_hex(16)
encrypted_key = encrypt_program_key(program_key)
expiry_time = "Never" # 永久密钥
store_encrypted_key(encrypted_key, expiry_time)
messagebox.showinfo("Keys Generated", "1000 keys have been generated and stored in the database.")
# 显示所有加密后的程序密钥及其过期时间
def show_all_keys():
cursor.execute('SELECT key, expiry FROM access_keys')
keys = cursor.fetchall()
text_display.delete(1.0, tk.END) # 清空当前内容
if keys:
keys_display = "\n".join([f"{fernet.decrypt(encrypted_key.encode()).decode()} (Expires: {expiry})" for (encrypted_key, expiry) in keys])
text_display.insert(tk.END, keys_display)
else:
text_display.insert(tk.END, "No keys found.")
# 创建主窗口
root = tk.Tk()
root.title("Key Generator")
# 初始化数据库
init_db()
# 创建并放置组件
btn_generate_keys = tk.Button(root, text="Generate 1000 Keys", command=generate_multiple_keys)
btn_generate_keys.pack(pady=5)
btn_show_keys = tk.Button(root, text="Show All Keys", command=show_all_keys)
btn_show_keys.pack(pady=5)
# 添加一个可滚动的文本框来显示密钥
text_display = scrolledtext.ScrolledText(root, width=70, height=20)
text_display.pack(pady=5)
# 运行主循环
root.mainloop()
# 关闭数据库连接
conn.close()
运行的实际效果如下:
点击generate 1000,会修改数据库文件keys.db,增加新的密钥。点show all keys就可以看到所有的密钥。
client.py如下
import sqlite3
import tkinter as tk
from tkinter import messagebox
from cryptography.fernet import Fernet
from datetime import datetime
import subprocess # 导入subprocess模块
import requests
import ctypes
import sys
import ntplib
def get_executable_path():
if getattr(sys, 'frozen', False):
return os.path.join(sys._MEIPASS, 'regbh.exe')
else:
return 'regbh.exe' # 替换为实际路径
# 检查是否有管理员权限
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
def get_network_time():
try:
response = requests.get('http://worldtimeapi.org/api/timezone/Asia/Shanghai', timeout=5)
response.raise_for_status() # 检查请求是否成功
data = response.json()
return datetime.fromisoformat(data['utc_datetime'].replace('Z', '+00:00'))
except requests.RequestException as e:
print(f"Could not retrieve time from network: {e}")
sys.exit("Exiting the program due to network time retrieval failure.")
# 如果没有管理员权限,重新启动脚本并请求权限提升
if not is_admin():
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)
sys.exit()
# 全局变量
fernet_key = b'BCAmf6ysMlDpauFJsw7YiviqyLboPMqQBhjgEY9vF3E=' # 硬编码的密钥
fernet = Fernet(fernet_key)
conn = None
cursor = None
# 在初始化数据库时调用 get_db_path()
def init_db():
global conn, cursor
db_path = get_db_path()
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
def get_db_path():
if getattr(sys, 'frozen', False):
# 如果是打包后的可执行文件
return os.path.join(sys._MEIPASS, 'keys.db')
else:
# 开发环境中使用原始的文件路径
return 'keys.db'
def check_key():
user_key = entry_key.get()
# 查询数据库中的所有加密密钥和过期时间
cursor.execute('SELECT key, expiry FROM access_keys')
results = cursor.fetchall()
if results:
current_time = get_network_time().replace(tzinfo=None) # 获取网络时间并移除时区信息
for encrypted_key, expiry in results:
# 解密数据库中的密钥
try:
decrypted_key = fernet.decrypt(encrypted_key.encode()).decode()
except Exception as e:
messagebox.showerror("Error", f"Decryption failed: {e}")
return
# 检查过期时间
if expiry != "Never":
expiry_time = datetime.fromisoformat(expiry.replace('Z', '+00:00')).replace(tzinfo=None) # 移除时区信息
if expiry_time < current_time:
continue # 如果过期,则跳过当前密钥
# 比较解密后的密钥与用户输入的密钥
if user_key == decrypted_key:
messagebox.showinfo("Access Granted", f"Access granted. Key: {decrypted_key} (Expires: {expiry})")
# 执行可执行文件
subprocess.Popen([get_executable_path()])# 注意修改路径为你的可执行文件的实际路径
return # 找到匹配的密钥,成功后返回
# 如果没有找到匹配的密钥
messagebox.showerror("Access Denied", "Invalid or expired key.")
else:
messagebox.showerror("Access Denied", "No keys found.")
# 创建主窗口
root = tk.Tk()
root.title("Key Validator")
# 初始化数据库
init_db()
# 创建并放置组件
label_key = tk.Label(root, text="Enter your access key:")
label_key.pack(pady=5)
entry_key = tk.Entry(root, width=40)
entry_key.pack(pady=5)
btn_check = tk.Button(root, text="Check Key", command=check_key)
btn_check.pack(pady=10)
# 运行主循环
root.mainloop()
# 关闭数据库连接
conn.close()
上面是客服端的代码(买家),运行之后:
如果输入错误就会报错。如果输入刚才卖家里面show all keys 里面正确的就可以成功,
写给大家看看最终效果:
要达到这个效果,我们还需要把刚才客服端的server.py代码运行得到的keys.db已经我们的辅助可执行文件xxx.exe还有我们的client.py通过下面打包成一个可执行文件。xxx.exe是我们的游戏辅助文件。
pyinstaller --onefile --add-data "XXX.exe;." --add-data "keys.db;." check_local.py
然后就在dist文件夹下面生成了可以给卖家的可执行文件:
值得注意的是:
- 当可执行文件被运行时,PyInstaller 会创建一个临时目录,并将打包时包含的所有数据文件(例如
regbh.exe
和keys.db
)提取到这个临时目录中。 - 这个临时目录的位置由
sys._MEIPASS
指定。代码中使用的os.path.join(sys._MEIPASS, '文件名')
语句会获取这些文件在临时目录中的实际路径。
csgopy因此如果能找到这个打包后的可执行文件运行过程中的临时文件名称,可以直接越过验证过程,因此,你的游戏辅助界面不能透露这个xxx.exe的名称,不然一搜就搜出来了。
我还对于密钥数据库, 进行了fernet加密,这样就算有了.db文件里面的密钥也是加密的。
最后,大家只需要把自己的xxx.exe替代我项目中的regbh.exe就可以自己开发一个密钥管理系统了。