Recentemente, fiz engenharia reversa de um determinado JavaScript e meu objetivo era restaurar a função de criptografia nele para o código Python.
Código-fonte JavaScript:
function i(n) {
return 4294967295 & n
}
function o(n, e, t, r, i, o) {
return (t >>> 5 ^ e << 2) + (e >>> 3 ^ t << 4) ^ (n ^ e) + (o[3 & r ^ i] ^ t)
}
function(n, e) {
var t, r, a, s, c, l, d = n.length, u = d - 1;
for (r = n[u],
a = 0,
l = 0 | Math.floor(6 + 52 / d); l > 0; --l) {
for (s = (a = i(a + 2654435769)) >>> 2 & 3,
c = 0; c < u; ++c)
t = n[c + 1],
r = n[c] = i(n[c] + o(a, t, r, c, s, e));
t = n[0],
r = n[u] = i(n[u] + o(a, t, r, u, s, e))
}
return n
}
Após um período de análise, o método de criptografia desse código JS é TEA.
Muito obrigado pela postagem no blog de lifanxin: python percebe o algoritmo de criptografia tea/xtea/xxtea___lifanxin's blog-CSDN blog_python xxtea
Esta postagem de blog implementa o algoritmo de criptografia e descriptografia TEA com a ajuda da função c_uint32() da biblioteca ctype no ambiente Python. Como o Python não tem restrições sobre tipos inteiros e o JavaScript lida com inteiros de 32 bits como ints de 32 bits assinados, os números que excedem o intervalo se tornarão números negativos, enquanto as operações do Python são todas números positivos. Para fazer com que os resultados da execução do Python tenham números positivos e negativos como o JavaScript, é necessário processar levemente os resultados das operações do Python:
for i in range(len(v)):
v[i]=c_int32(v[i]).value
O código Python completo para testar a criptografia TEA é o seguinte:
Os dados no programa principal devem converter a string antes da criptografia em um conjunto de listas inteiras por meio de um algoritmo de criptografia.
key é uma lista de números inteiros obtidos submetendo strings de chave ao mesmo algoritmo.
Não vou entrar em detalhes de como vêm os dados e os números-chave, porque eles podem ser encontrados em JavaScript e a criptografia é relativamente simples. Este artigo explica o algoritmo de criptografia TEA e essas duas listas precisam ser substituídas em parâmetros para operações de criptografia.
## TEA加密算法原文:https://blog.csdn.net/A951860555/article/details/120120400
## 下面是我在上述博主原文基础上稍加修改的代码
from ctypes import c_uint32, c_int32
def MX(z, y, total, key, p, e):
temp1 = (z.value>>5 ^ y.value<<2) + (y.value>>3 ^ z.value<<4)
temp2 = (total.value ^ y.value) + (key[(p&3) ^ e.value] ^ z.value)
return c_uint32(temp1 ^ temp2)
def encrypt(n, v, key):
# delta是TEA加密算法的重要参数
delta = 2654435769
rounds = 6 + 52//n
total = c_uint32(0)
z = c_uint32(v[n-1])
e = c_uint32(0)
while rounds > 0:
total.value += delta
e.value = (total.value >> 2) & 3
for p in range(n-1):
y = c_uint32(v[p+1])
v[p] = c_uint32(v[p] + MX(z,y,total,key,p,e).value).value
z.value = v[p]
y = c_uint32(v[0])
v[n-1] = c_uint32(v[n-1] + MX(z,y,total,key,n-1,e).value).value
z.value = v[n-1]
rounds -= 1
# 这是我改进的地方:把unsigned int处理成signed int,超出32bit范围的正整数会变成负数。
for i in range(len(v)):
v[i]=c_int32(v[i]).value
return v
if __name__ == "__main__":
# 加密前的源字符串
ss='appid=201807308440|ctxid=9d23cc620e0dfb601f27711dcec30c64|r=0.48592600736230795'
# data是将加密前的字符串经过下面简单的加密算法转换成一组整数列表。
# 这加密算法比较简单,可以在JavaScript里扒出来。
data = []
ss_len = len(ss)
data = [0]*((ss_len>>2)+2)
data[-1] = ss_len
for i in range(ss_len):
data[i >> 2] |= ord(ss[i]) << ((3 & i) << 3)
'''
data = [1768976481, 808598884, 925906993, 876097587, 1669083188, 1684633716, 845429053, 912483123, 811937842, 912418404, 845558064, 825308983, 1667588964, 912470067, 1030913076, 942943792, 909261109, 859254832, 808661558, 3488055, 79]
'''
# key是密钥经过加密算法后而成的四个整数
key = [1631074661, 926431333, 909271864, 1698128180]
# key的数是怎么来的,这里不作赘述,因为它们都可以在JavaScript里找得到。
# 本文讲解的是TEA加密算法,需要将这两个列表代入encrypt参数进行加密运算。
length = len(data)
# TEA加密
res=encrypt(length, data, key)
print(res)
'''
输出结果:
[716085371, -477396898, 91038733, -105793381, -1817301194, -535430222, 1390850599, 140015488, -1430794631, 1855466254, -24428639, 1179447845, -1111913346, 586757153, -37658271, 1089200005, 848481124, 1301543136, -1437420864, -183487679, 1196366267]
'''