目标:商品搜索翻页接口
直接搜索h5st就可以搜到,所有可疑位置都打上断点,然后翻页,最终断点位置:
window.PSign.sign(colorParamSign)是异步代码,colorParamSign是传入的参数,执行后把包含h5st的结果signedParams传递给了回调。
首先分析一下参数colorParamSign
也就一个body看着像加密的,并且上面就能看到赋值位置。明文如下图,传入了一个SHA256的函数加密
这都把饭喂到嘴边了,没道理吃不下,先不用去研究这个函数,直接拿着明文去试一下sha256加密的结果是否一致,不一致再去看加密函数。
加密结果如下:
跟网站结果一致,确实是用了标准的sha256加密,东哥诚不欺我。
加密参数就算拿到了,接下来抠window.PSign.sign
很显然,又是强行喂饭,生怕我抠不出来。都直接写明了调用了window.PSign的sign加密,那是不是可以直接搜window.PSign的赋值位置?
果然,这里new了一个ParamsSign。那就直接找ParamsSign的位置呗。
这不就来了!!!
把整个ParamsSign函数抠出
同时window.PSign = new ParamsSign的代码也抠出。
跑一下,补一下必须的环境,需要补的环境文章末尾提供
某东需要补的东西不多,主要是有node环境检测、原型链检测
这里顺便给大家提一嘴,过程比较杂就不贴图了,打字~
首先检测了node特有的process,这个我们浏览器环境是没有的,所以要删除掉。怎么知道的?该补的环境补完后发现怎么都拿不到正确的响应,代理了一下globalThis发现的。这一步完事后,发现还是拿不到正确的响应,环境实在找不到问题了,就打断点调试本地代码(优先看try,if这种容易被引入歧途的位置),在可疑位置debug,看看各个函数的参数,结果是从哪里开始不一样的,然后就一步一步走,最终让我发现了这里
因为我们环境里是要补document.all的,所以这里检测了document.all.proto === HTMLAllCollection.prototype,这里不能简单的补原型关系了,因为后面还有一句0 !== document.all,天杀的,all写在document中一样不走正确的逻辑。
然后在这里打断点,看看t.bu8进行了几次赋值,结果都是什么,就发现t.bu8这里一直是0,那不就简单了,还补啥原型啊,直接:
整这些花里胡哨的干啥,写死完事。
这些检测点做完就能拿到正确的结果了
哦对,东哥都强行喂饭了,那我也再喂一喂,这个加密是在异步中完成的,我们本地如何拿到结果?就这么拿
请求结果
成功拿到响应数据~~~
环境也双手奉上:
window = global;
__pro__ = process;
CSSRuleList = function () {
}
CSSStyleDeclaration = function () {
}
DOMRectList = function () {
}
DOMStringList = function () {
}
DOMTokenList = function () {
}
DataTransferItemList = function () {
}
FileList = function () {
}
HTMLAllCollection = function () {
}
HTMLCollection = function () {
}
HTMLFormElement = function () {
}
HTMLSelectElement = function () {
}
MediaList = function () {
}
MimeTypeArray = function () {
}
NamedNodeMap = function () {
}
NodeList = function () {
}
Plugin = function () {
}
PluginArray = function () {
}
SVGLengthList = function () {
}
SVGNumberList = function () {
}
SVGPointList = function () {
}
SVGStringList = function () {
}
SVGTransformList = function () {
}
SourceBufferList = function () {
}
StyleSheetList = function () {
}
TextTrackCueList = function () {
}
TextTrackList = function () {
}
TouchList = function () {
}
MutationObserver = function () {
}
WebKitMutationObserver = function () {
}
PromiseRejectionEvent = function () {
}
dispatchEvent = function () {
}
// regeneratorRuntime = {}
window.crypto = {}
XMLHttpRequest = function () {
}
window.document = {
querySelector: function () {
},
all: [],
createElement: function (args) {
console.log("document_createElement_args:", args)
if (args === 'script') {
return {
parentNode: {},
}
}
if (args === 'canvas') {
return {
getContext: function () {
return {
fillRect: function () {
},
arc: function () {
},
stroke: function () {
},
fillText: function () {
},
}
},
toDataURL: function () {
return ""
}
}
}
return {}
},
documentElement: {},
createEvent: function (args) {
console.log("document_createEvent_args:", args)
},
getElementsByTagName: function (args) {
console.log("document_getElementsByTagName_args:", args)
if (args == 'head') {
return [
{
appendChild: function () {
return ''
}
}
]
}
return []
},
head: {
childElementCount: 35
},
body: {
childElementCount: 33
},
cookie: '脱敏处理,自己补',
}
localStorage = {
getItem: function (key) {
return null
},
removeItem: function (key) {
return delete localStorage[key]
},
setItem: function (key, value) {
localStorage[key] = value
}
}
navigator = {
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
webdriver: false,
languages: [
"zh-CN",
"zh",
"en"
],
plugins: {
"0": {
"0": {},
"1": {}
},
"1": {
"0": {},
"1": {}
},
"2": {
"0": {},
"1": {}
},
"3": {
"0": {},
"1": {}
},
"4": {
"0": {},
"1": {}
}
},
platform: 'Win32',
hardwareConcurrency: 12,
}
location = {
'host': '脱敏处理,自己补',
}
delete global;
delete process;
delete Buffer;
delete setImmediate;
个人gongzhong号,不定期大厂逆向案例分享,欢迎关注!!!