TX 某产品登录加密分析 Python3 RSA OAEP
【注意:此文章为博主原创文章!转载需注意,请带原文链接,至少也要是txt格式!】
某天因为需要调用腾讯某产品内部的一些数据,但是无奈没有API接口,那么只有通过类似爬虫的方式进行登录,然后调用相关功能点。
如上图所示,首先就需要登录,然后获取登录态,这里通过抓包发现,密码是被加密然后进行base64编码之后传递到服务端的。那么首先就应该找出密码加密的方式,如下图:
登录之前首先获取公钥KEY,通过访问 https://xxxx.xxxx.com/api/global/GetEncryptKey 那么后续应该会用这个KEY来进行加密操作。
这里搜索一下密码关键词,看看在哪里进行加密。其实这里我走了一个弯路,因为登录密码字段是password,所以我搜索的这个关键词,但是就因为搜索的这个关键词,结果导致浪费了很久的时间。可以看到我之前的断点分析,都是浪费时间的结果,如下图:
就因为这个关键词太广了,结果导致分析的时间都用在了错误的地方。没有直戳要害!
好,下面开始正式分析。
根据密钥KEY接口返回的信息得到关键‘publicKey’字段:
这里直接搜索“publicKey”然后定位到代码如下图:
这里关键代码展示出来,如下:
t.generateKeys = function() {
var e = p.generateKeyPairSync("rsa", {
modulusLength: 4096,
publicKeyEncoding: {
type: "pkcs1",
format: "pem"
},
privateKeyEncoding: {
type: "pkcs1",
format: "pem",
cipher: "aes-256-cbc",
passphrase: ""
}
})
, t = e.publicKey
, n = e.privateKey;
return {
publicKey: t,
privateKey: n
}
}
,
t.encrypt = function(t, n) {
try {
var r = e.from(t, "utf8")
, o = p.publicEncrypt(n, r).toString("base64");
return o
} catch (e) {
return ""
}
}
,
t.decrypt = function(t, n) {
var r = e.from(t, "base64");
return p.privateDecrypt({
key: n.toString(),
passphrase: ""
}, r).toString("utf8")
}
,
t.getEncryptKey = function() {
return b.apply(this, arguments)
}
从代码中不难发现,它的代码加密类型是pkcs1,用的是rsa加密方式。
从图中就已经看的很明确了。var r = e.from(t, "utf8")
对重点代码进行了详细说明。
, o = p.publicEncrypt(n, r).toString("base64");
这里我们跟进publicEncrypt
这个函数。
跟随是n的值为空,h = e.padding ? e.padding : n ? 1 : 4;
所以这里结果h就是4
也就是说,函数走入了红色圈内。红色圈内说明用的是sha1的方式。
到这里基本也就分析透了,程序使用的是Node.js crypto.publicEncrypt()
默认的方式进行的密码加密,通过朋友提示,可以先使用 RSA加密工具 测试一下。这里把KEY还有密码输入后,得出密钥,经过测试没有问题,可以登录系统,如下图:
最后一步就是写出Python脚本代码,实现自动登录,这里参考了官方的示例 https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html 最终python代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
def encrypt_password(): from Crypto.Cipher import PKCS1_OAEP from Crypto.PublicKey import RSA rsa_key = b"""-----BEGIN PUBLIC KEY----- MIICCgKCAgEAvrOaIR+zQSkEDi4Ac5wrEvYxM68LhHtGTy8pHceyPLKtK0c7PnS1 3VT7oafyXLVpNWR/R+bvFwGrA0URMqRzMQxYtr7T0sgiaZbgXZO+OyQh26005OKj ydA1oCCb06+v6/qp1d+FXVg847tUK0TqkGOCNXPaCDElNoH/A4B4sikWCVtY87V1 42wBpI4mdPDw33w4+5/uHBuhltOpQRPSTuQlCNP5SaotAIcZNfzw0a0VJ5illxnZ oGAAjh1Di7xU+TH3PiwyP8pG2jYg4qT9YLbhdMuuCerBnKw6F3cD/qEUsChFQ2d3 14KzCV6/QDLuYadSMdX+cj/k40dCqbyvCfQA8fZAhUXWnBRPqyXQs8PQQSow2Lse aNiKyTAUW06d93H3DzoPE2NsLQMHTr72b+Hb7eAeXBrrp8o0j/3sNKDspVNtvzdm nUF4nYmG0u4XsspbXwHpCa6mCTV7hm5F7MffE+RdDOukvNwPdBYRh+T5nunxXZwi X0mf5eR/9+w3+vJ48liRQ6ToQ0C+jVRnJzXK5ceyNk0Jb+U80v7zHxEugqbfQppW MvWTiYKadcsFuwsdEDe98x3t2Ml09A8suid5I/Bhk176WUmHOk0+fxJ2ZGNhcwYm qW+37k5AYOTtVWRnGeC573i9mj6jlDg5T8RGD+htzUSXDLNIGatZA7MCAwEAAQ== -----END PUBLIC KEY----- """ message = "12345678" ##登录系统的密码 key = RSA.importKey(rsa_key) cipher = PKCS1_OAEP.new(key) ciphertext = cipher.encrypt(message.encode('utf-8')) return base64.b64encode(ciphertext).decode() |
以上就是完整的分析过程。