提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一. pyinstaller 打包
-
打开控制台,Pyinstaller -F -w 猜数游戏.py(该命令会去除控制台,运行即运行仅程序窗口)按下回车
-
打包成功后控制台显示successful
-
随后py文件夹下会生成一个dist的文件
-
双击打开dist文件,有一个exe的程序,这个就是py打包成的,双击打开文件即可。
-
常用参数 含义
-i 或 -icon 生成icon -F 创建一个绑定的可执行文件 -w 使用窗口,无控制台 -C 使用控制台,无窗口 -D 创建一个包含可执行文件的单文件夹包(默认情况下) -n 文件名
二. 反编译由pyinstaller打包的exe文件
-
首先看程序图标,就知道是不是由pyinstaller编译的
-
之后再命令行中输入此命令,即会出现一个文件夹
- 这时,我们打开PYZ-00.pyz_extracted 文件夹,发现里面全是.pyc文件,且没有加密,就可以进行下一步了
- 或者我们可以找到主程序的文件,修改后缀名为.pyc即可
- 下面我们需要将.pyc放入16进制编辑器中,将正常的 pyc 文件中的 magic 和 时间戳 复制过来,因为第一行缺少magic与时间
- 接着就可以将他反编译成.py文件
- 看看代码
三. RC4加密
3.1RC4算法原理
- RC4生成一种称为密钥流的伪随机流,与明文异或结合,从而加密,解密时与密文进行异或操作,那么,他就是一种对称加密算法
- 密钥流由KSA与PRGA组成
- 实现方法:根据秘钥生成S盒,利用PRGA生成秘钥流,秘钥与明文异或产生密文
3.1.1 KSA(密钥调度算法)及根据秘钥生成S表
- RC4首先用KSA完成对大小为256字节的数组S的初始化(按照升序,给每个字节赋值0,1,2,3,4,5,6…,254,255)及替换,替换时使用密钥
- 直接构造一个S[256],遍历0-255,然后创建临时K[256],用于存储种子秘钥,长度不够循环填充直到K被填满,根据T[i]将S[i]与S中的另外一个字节对换,对S的操作仅仅是交换,唯一改变的是位置,但里面的元素是没变的还是0-255
s_box = list(range(256)) #这里没管秘钥小于256的情况,小于256不断重复填充即可
j = 0
for i in range(256):
j = (j + s_box[i] + ord(key[i % len(key)])) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
#print(type(s_box)) #for_test
return s_box
3.1.2 PRGA生成密钥流
res = []
i = j =0
for s in plain:
i = (i + 1) %256
j = (j + box[i]) %256
box[i], box[j] = box[j], box[i]
t = (box[i] + box[j])% 256
k = box[t]
res.append(chr(ord(s)^k)) #直接与每一个字节明文相异或
3.2 脚本实现
import codecs
MOD = 256
def KSA(key):
key_length = len(key)
# create the array "S"
S = list(range(MOD)) # [0,1,2, ... , 255]
j = 0
for i in range(MOD):
j = (j + S[i] + key[i % key_length]) % MOD
S[i], S[j] = S[j], S[i] # swap values
return S
def PRGA(S):
i = 0
j = 0
while True:
i = (i + 1) % MOD
j = (j + S[i]) % MOD
S[i], S[j] = S[j], S[i] # swap values
K = S[(S[i] + S[j]) % MOD]
yield K
def get_keystream(key):
S = KSA(key)
return PRGA(S)
def encrypt_logic(key, text):
# For plaintext key, use this
key = [ord(c) for c in key]
keystream = get_keystream(key)
res = []
for c in text:
val = ("%02X" % (c ^ next(keystream))) # XOR and taking hex
res.append(val)
return ''.join(res)
def encrypt(key, plaintext):
plaintext = [ord(c) for c in plaintext]
return encrypt_logic(key, plaintext)
def decrypt(key, ciphertext):
ciphertext = codecs.decode(ciphertext, 'hex_codec')
res = encrypt_logic(key, ciphertext)
return codecs.decode(res, 'hex_codec').decode('utf-8')
if __name__ == '__main__':
print(decrypt("1592539037299", "08985BCFBF8C87583190")) # 解密
print(encrypt("1592539037299", "test123NEW")) # 加密
四. stream.exe
- 结合上文学习,进行解包与一次反编译,得代码
- 发现是RC4加密
import base64
def gen(key):
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + ord(key[i % len(key)])) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
i = j = 0
data = []
for _ in range(50):
i = (i + 1) % 256
j = (j + s[i]) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
data.append(s[(s[i] + s[j]) % 256])
return data
def encrypt(text, key):
result = ''
for c, k in zip(text, gen(key)):
result += chr(ord(c) ^ k)
result = base64.b64encode(result.encode()).decode()
return result
text = input('Flag: ')
key = 'As_we_do_as_you_know'
enc = encrypt(text, key)
if enc == 'wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl':
print('yes!')
return None
None('try again...')
- 题目函数设置的很友好,就是原封不动的RC4加密
- 对称加密法,则解密时gen函数不用变
- 密钥同样不变
- 编程如下:
import base64
def gen(key):
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + ord(key[i % len(key)])) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
i = j = 0
data = []
for _ in range(50):
i = (i + 1) % 256
j = (j + s[i]) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
data.append(s[(s[i] + s[j]) % 256])
return data
def decrypt(text, key):
result = ''
text = base64.b64decode(text).decode()
for c, k in zip(text, gen(key)):
result += chr(ord(c) ^ k)
return result
text='wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl'
key = 'As_we_do_as_you_know'
print(decrypt(text, key))
- flag{python_reverse_is_easy_with_internet}