声明:本文仅限学习交流使用,禁止用于非法用途、商业活动等。否则后果自负。如有侵权,请告知删除,谢谢!本教程也没有专门针对某个网站而编写,单纯的技术研究
一、本期逆向
1.网站:aHR0cDovL2JhY2t0ZXN0LjEwanFrYS5jb20uY24vYmFja3Rlc3QvYXBwLmh0bWwjL215c3RyYXRlZ3k=
ojbk,点击登录就是滑块很好,妙啊
2.先看下有哪些加密,获取滑块的接口勒直接拿没加密
3.验证滑块的时候勒有前一步还有一个getGS的接口
看下表单也就一个uname是加密的
crnd看着有点像随机的字符串
4.接下来看下提交登录了,登录这一块该说不说还挺牛逼。。。
uname、passwd、passwdSalt总共三个参数
5.看看getTicket滑块校验,明文没啥好说的直接提交
6.最后校验的时候还发现了一个 hexin-v,这个校验了时间,好了开始盘它
二、getGS分析
1.果然crnd是个随机数,固定就好不管它了,uname就是个rsa的加密,啊这,就这
2.照着还原一下代码咯,就这样吧,下一个搞滑块
import rsa
import math
class Hex2B64:
base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
hexChars = "0123456789abcdefghijklmnopqrstuvwxyz"
__doc__ = """
用法示例:
HB = Hex2B64()
rt = HB.encrypt("5555")
print(rt)
print(HB.decrypt(rt))
对应的Javascript代码👇
base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
hexChars = "0123456789abcdefghijklmnopqrstuvwxyz";
const hex2b64 = (d) => {
let a = '', i = 0;
for (; i + 3 <= d.length; i += 3) {
a += base64Chars.charAt(parseInt(d.substring(i, i + 3), 16) >> 6) + base64Chars.charAt(parseInt(d.substring(i, i + 3), 16) & 63);
}
if (i + 1 === d.length) {
a += base64Chars.charAt(parseInt(d.substring(i, i + 1), 16) << 2);
} else if (i + 2 === d.length) {
a += base64Chars.charAt(parseInt(d.substring(i, i + 2), 16) >> 2) + base64Chars.charAt((parseInt(d.substring(i, i + 2), 16) & 3) << 4);
}
return a.padEnd(Math.ceil(a.length / 4) * 4, '=');
};
const b64tohex = (b64) => {
let hex = "", bits = 0, bitsCount = 0;
for (let i = 0, len = b64.length; i < len && b64[i] !== "="; ++i) {
const charIndex = base64Chars.indexOf(b64[i]);
if (charIndex < 0) continue;
if (bitsCount === 0) {
hex += hexChars[charIndex >> 2];
bits = charIndex & 3;
} else if (bitsCount === 1) {
hex += hexChars[(bits << 2) | (charIndex >> 4)];
bits = charIndex & 15;
} else if (bitsCount === 2) {
hex += hexChars[bits] + hexChars[charIndex >> 2];
bits = charIndex & 3;
} else {
hex += hexChars[(bits << 2) | (charIndex >> 4)] + hexChars[charIndex & 15];
bits = 0;
}
bitsCount++;
}
return hex + (bitsCount === 1 ? hexChars[bits << 2] : "");
}
console.log(hex2b64('5555'));
console.log(b64tohex("VVU="));
"""
def encrypt(self, cipher_text: str) -> str:
"""
@param cipher_text: 密文
@return:
"""
new_cipher_text, idx = '', 0
for idx in range(0, len(cipher_text), 3):
if idx + 3 > len(cipher_text):
break
new_cipher_text += self.base64Chars[trans(int(cipher_text[idx: idx + 3], 16) >> 6)] + self.base64Chars[trans(int(cipher_text[idx: idx + 3], 16) & 63)]
if idx + 1 == len(cipher_text):
new_cipher_text += self.base64Chars[trans(int(cipher_text[idx: idx + 1], 16) << 2)]
elif idx + 2 == len(cipher_text):
new_cipher_text += self.base64Chars[trans(int(cipher_text[idx: idx + 2], 16) >> 2)] + self.base64Chars[trans(trans(int(cipher_text[idx: idx + 2], 16) & 3) << 4)]
return new_cipher_text.ljust(math.ceil(len(new_cipher_text) / 4) * 4, '=')
def decrypt(self, cipher_text: str) -> str:
"""
@param cipher_text: 密文
@return:
"""
new_cipher_text, bits, bits_count = "", 0, 0
for i in range(len(cipher_text)):
if cipher_text[i] == "=":
break
char_index = self.base64Chars.find(cipher_text[i])
if char_index < 0:
continue
if bits_count == 0:
new_cipher_text += self.hexChars[trans(char_index >> 2)]
bits = trans(char_index & 3)
elif bits_count == 1:
new_cipher_text += self.hexChars[trans(trans(bits << 2) | trans(char_index >> 4))]
bits = trans(char_index & 15)
elif bits_count == 2:
new_cipher_text += self.hexChars[bits] + self.hexChars[trans(char_index >> 2)]
bits = trans(char_index & 3)
else:
new_cipher_text += self.hexChars[trans(trans(bits << 2) | trans(char_index >> 4))] + self.hexChars[trans(char_index & 15)]
bits = 0
bits_count += 1
return new_cipher_text + (self.hexChars[trans(bits << 2)] if bits_count == 1 else "")
def public_encrypt(cipher_text: str, public: str, key_size: str) -> rsa.encrypt:
return rsa.encrypt(cipher_text.encode(), rsa.PublicKey(int(public, 16), int(key_size, 16)))
三、dologinreturnjson2登录滑块及表单分析
1.继续跟进、好家伙备注都不删除,点个赞
2.简简单单还原下登录的加密吧,用的加密还挺多:md5、sha256、hmac_sha256
import hashlib
def Hashlib(cipher_text: str, model="md5") -> str:
"""
hashlib 加密
@param cipher_text:
@param model:
@return:
"""
if hasattr(hashlib, model.lower()):
return getattr(hashlib, model)(cipher_text.encode()).hexdigest()
raise Exception("模块不存在...")
let encoder = new TextEncoder("utf-8"), DEFAULT_STATE = [], ROUND_CONSTANTS = [], n = 2, nPrime = 0;
while (nPrime < 64) {
let isPrime = true;
for (let factor = 2; factor <= n / 2; factor++) {
if (n % factor === 0) {
isPrime = false;
}
}
if (isPrime) {
if (nPrime < 8) {
DEFAULT_STATE[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
}
ROUND_CONSTANTS[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
nPrime++;
}
n++;
}
function getFractionalBits(n) {
return ((n - (n | 0)) * Math.pow(2, 32)) | 0;
}
function convertEndian(word) {
return (word >>> 24) | (((word >>> 16) & 255) << 8) | ((word & 65280) << 8) | (word << 24);
}
function rightRotate(word, bits) {
return (word >>> bits) | (word << (32 - bits));
}
function hmac(data) {
let STATE = DEFAULT_STATE.slice(), length = data.length, bitLength = length * 8,
newBitLength = (512 - ((bitLength + 64) % 512) - 1) + bitLength + 65, round, MRound, M = new Uint32Array(64),
bytes = new Uint8Array(newBitLength / 8), words = new Uint32Array(bytes.buffer);
bytes.set(data, 0);
bytes[length] = 128;
words[words.length - 1] = convertEndian(bitLength);
for (let block = 0; block < newBitLength / 32; block += 16) {
let workingState = STATE.slice();
for (round = 0; round < 64; round++) {
if (round < 16) {
MRound = convertEndian(words[block + round]);
} else {
let gamma0x = M[round - 15], gamma1x = M[round - 2];
MRound = M[round - 7] + M[round - 16] + (rightRotate(gamma0x, 7) ^ rightRotate(gamma0x, 18) ^ (gamma0x >>> 3)) + (rightRotate(gamma1x, 17) ^ rightRotate(gamma1x, 19) ^ (gamma1x >>> 10));
}
M[round] = MRound |= 0;
let t1 = (rightRotate(workingState[4], 6) ^ rightRotate(workingState[4], 11) ^ rightRotate(workingState[4], 25)) + ((workingState[4] & workingState[5]) ^ (~workingState[4] & workingState[6])) + workingState[7] + MRound + ROUND_CONSTANTS[round],
t2 = (rightRotate(workingState[0], 2) ^ rightRotate(workingState[0], 13) ^ rightRotate(workingState[0], 22)) + ((workingState[0] & workingState[1]) ^ (workingState[2] & (workingState[0] ^ workingState[1])));
for (let i = 7; i > 0; i--) {
workingState[i] = workingState[i - 1];
}
workingState[0] = (t1 + t2) | 0;
workingState[4] = (workingState[4] + t1) | 0;
}
for (round = 0; round < 8; round++) {
STATE[round] = (STATE[round] + workingState[round]) | 0;
}
}
return new Uint8Array(new Uint32Array(STATE.map(function (val) {
return convertEndian(val)
})).buffer);
}
function hmac_sha256(inputKey, inputData) {
inputKey = typeof inputKey === "string" ? encoder.encode(inputKey) : inputKey;
inputData = typeof inputData === "string" ? encoder.encode(inputData) : inputData;
if (inputKey.length > 64)
inputKey = hmac(inputKey);
if (inputKey.length < 64) {
const tmp = new Uint8Array(64);
tmp.set(inputKey, 0);
inputKey = tmp;
}
let inherentKey = new Uint8Array(64), outpointKey = new Uint8Array(64),
msg = new Uint8Array(inputData.length + 64), result = new Uint8Array(64 + 32);
for (let i = 0; i < 64; i++) {
inherentKey[i] = 54 ^ inputKey[i];
outpointKey[i] = 92 ^ inputKey[i];
}
msg.set(inherentKey, 0);
msg.set(inputData, 64);
result.set(outpointKey, 0);
result.set(hmac(msg), 64);
return Array.prototype.map.call(hmac(result), byte => ('0' + parseInt(byte).toString(16)).slice(-2)).join('');
}
// console.log(hmac_sha256("kNJzKtvcGuRRnftcHVcP", "6512bd43d9caa6e02c990b0a82652dca"));
3.好了,看看滑块的搞了什么飞机,ok没啥玩意
四、hexin-v的分析
这个勒找的时候有一点小坑,不过也没啥照着扣就行了,怎么找到的就自己找了
五、结果
好了又水一篇文章~~
。。。。。。。。。
。。。。。。。。
。。。。。。
。。。
。