JS逆向-Bitcoin浏览器交易x-apikey参数加密逆向
JS逆向-Bitcoin浏览器交易x-apikey参数加密逆向
本文仅作学习交流,敏感信息已做加密处理。
实战网址:aHR0cHM6Ly93d3cub2tsaW5rLmNvbS96aC1oYW5zL2J0Yy90eC1saXN0
分析过程
刷新页面,会看到具体get请求中会有一个加密协议头
x-apikey,这个就是需要逆向的加密字段
- 首先源代码里搜索
apikey

可以看到这里有一个encryptApiKey的定义,点进去,应该就是这里,直接把这一串复制下来
{
key: "encryptApiKey",
value: function() {
var e = this.API_KEY
, t = e.split("")
, n = t.splice(0, 8);
return e = t.concat(n).join("")
}
}, {
key: "encryptTime",
value: function(e) {
var t = (1 * e + c).toString().split("")
, n = parseInt(10 * i.o.mathRandom(), 10)
, r = parseInt(10 * i.o.mathRandom(), 10)
, o = parseInt(10 * i.o.mathRandom(), 10);
return t.concat([n, r, o]).join("")
}
}, {
key: "comb",
value: function(e, t) {
var n = "".concat(e, "|").concat(t);
return a.A.btoa(n)
}
}, {
key: "getApiKey",
value: function() {
var e = (new Date).getTime()
, t = this.encryptApiKey();
return e = this.encryptTime(e),
this.comb(t, e)
}
}
- 刷新页面,下断点

可以看到,代码执行到这里停住了,就说明我们找对地方了,进一步查看堆栈调用,发现上一步调用地方在下面的getApiKey定义里,那基本可以确定getApiKey就是生成x-apiKey的地方,接下来再来分析具体加密方法逻辑 - 查看
getApiKey方法,分析加密逻辑
key: "getApiKey",
value: function() {
var e = (new Date).getTime()
, t = this.encryptApiKey();
return e = this.encryptTime(e),
this.comb(t, e)
}
首先 var e ,这就是获取一个时间戳,不需要说明什么,直接看t,t调用了上面的
encryptApiKey方法,直接具体看这个方法
var e = this.API_KEY
, t = e.split("")
, n = t.splice(0, 8);
return e = t.concat(n).join("")
e 这里就是一个固定值,可以在上面看到,this.API_KEY = "a2c903cc-b31e-4547-9299-b6d07b7631ab"
t = e.split("") 就是把 API_KEY 拆分成字符数组 ["a","2","c","9"...] 这种
n = t.splice(0,8) 就是删除t的前八位并返回 也就是返回 a2c903cc
最后return返回 就是t和n组合成新的字符数组,n添加在t后面,因为t在前面转换成了字符数组,所以需要join连接成字符串 也就是 -b31e-4547-9299-b6d07b7631aba2c903cc
接下来看 encryptTime(e)
key: "encryptTime",
value: function(e) {
var t = (1 * e + c).toString().split("")
, n = parseInt(10 * i.o.mathRandom(), 10)
, r = parseInt(10 * i.o.mathRandom(), 10)
, o = parseInt(10 * i.o.mathRandom(), 10);
return t.concat([n, r, o]).join("")
}
t 把 1* e +c 的结果转字符串,e是我们传入的时间戳,然后再转字符数组,c在前面有定义,是个常量,直接拿下来,c = 1111111111111
n,r,o这里,都是获取一个0-9的随机数
return返回也类似,t和n,r,o组成新的字符数组,然后再连接成字符串
再看this.comb(t, e)
key: "comb",
value: function(e, t) {
var n = "".concat(e, "|").concat(t);
return a.A.btoa(n)
}
e 和 t 是我们传入的就是
encryptApiKey()和encryptTime()返回的数据
"".concat(e, "|"):这里的 "" 是一个空字符串,concat 方法用于将多个字符串拼接在一起。e 是第一个字符串,"|" 是第二个字符串,所以这部分代码的结果是将 e 和 | 拼接在一起
最后再通过btoa函数进行base64编码即可。 btoa(n) 是 JavaScript 中的一个函数,用于将字符串 n 进行 Base64 编码。
最终Py代码
import requests
import random
import time
import base64
def getAPiKey():
api_key = "a2c903cc-b31e-4547-9299-b6d07b7631ab"
t = list(api_key)
n = t[:8]
t = t[8:]
t.extend(n)
return "".join(t)
def encryptTime(e):
c = 1111111111111
t = list(str(1 * e + c)) # 将e和c的和转换为字符串,然后拆分为字符列表
n = int(10 * random.random()) # 生成0到9之间的随机整数
r = int(10 * random.random())
o = int(10 * random.random())
return ''.join(t + [str(n), str(r), str(o)]) # 将t和随机数列表连接起来,然后转换为字符串
def comb(e,t):
n = "".join([e, "|", t])
# Python的base64编码函数需要字节,所以我们先编码为字节
n_bytes = n.encode('utf-8')
# 使用base64.b64encode进行编码
return base64.b64encode(n_bytes).decode('utf-8')
def getUrl():
timestamp = int(round(time.time() * 1000))
t = getAPiKey()
e = encryptTime(timestamp)
resut = comb(t, e)
page = input("请输入要查看的页数:")
offset = 20*int(page)
url = 'https://www.oklink.com/api/explorer/v1/btc/transactionsNoRestrict?offset={}&limit=20&t={}'.format(offset, timestamp)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
"x-apiKey":resut
}
response = requests.get(url, headers=headers)
response_data = response.json() # 解析 JSON 数据
print(response_data)
if __name__ == '__main__':
getUrl()
运行结果
