猿人学-练习平台-第三题(ob混淆及检测)保姆级教程

336 阅读6分钟

题目链接:www.python-spider.com/challenge/3

题目的最终目的是求100页数据之和

image.png

一 分析

  1. 分析目的

加密参数是啥?参数在哪里?

  1. 分析过程

找到数据所在的请求包

image.png 通过curl转python本地请求测试
curl地址

import requests
headers = {
    "accept": "application/json, text/javascript, */*; q=0.01",
    "accept-language": "zh-CN,zh;q=0.9,en-GB;q=0.8,en-US;q=0.7,en;q=0.6",
    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
    "origin": "https://www.python-spider.com",
    "priority": "u=1, i",
    "referer": "https://www.python-spider.com/challenge/3",
    "sec-ch-ua": "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"126\", \"Google Chrome\";v=\"126\"",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "\"Windows\"",
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-origin",
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
    "x-requested-with": "XMLHttpRequest"
}
cookies = {
    "HMACCOUNT": "9E91DB5F595FBD76",
    "sessionid": "r8imncwfgycnhzwdvk6h1y33tfel9098",
    "Hm_lvt_337e99a01a907a08d00bed4a1a52e35d": "1720796710",
    "no-alert": "true",
    "sign": "1721146993~YWlkaW5nX3dpbjE3MjExNDY5OTI2Nzg=|d5d049538309316e16ce5b63553af0a7",
    "m": "091b9eb11943954e1a0e99b9ff7713b4|1721198310000",
    "Hm_lpvt_337e99a01a907a08d00bed4a1a52e35d": "1721198312"
}
url = "https://www.python-spider.com/api/challenge3"
data = {
    "page": "1"
}
response = requests.post(url, headers=headers, cookies=cookies, data=data)

print(response.text)
print(response)

这里就只有cookie参数有嫌疑,一个一个的删除就能看到只有m参数才是有用的

3.分析结果

header中加密的m参数才是关键参数

二 找加密参数

找加密参数的时候记得浏览器保持干净或者以访客模式访问 image.png

这里可以看大同一个请求请求了两次,而且在第一次请求完以后就发现m参数就已经有了,所以可以判定m参数一定是在这个请求就生成了,但是第一次的请求结果在浏览器中是看不到的,所以可以通过抓包软件或者通过curl第一次的请求就可以发现返回了一个script标签包裹的js

由于是script文件的加载可以通过监听script的加载在浏览器中找到该js文件

image.png 刷新网页 时候记得将m这个cookie参数删除,这里我已经删除了 image.png 开始刷新网页!!!!!!!!!!!!!!!!!!!! 这个就是我们要的文件了 image.png 代码收缩后就只有四大段,定义了一个b函数和b函数和a列表,两个自执行的函数 image.png 面对这几段展开的js代码,是不是开始懵逼了!!!!!don't be 担心 两种方法可以快速定位 1 2.1 猜测

> 既然是cookie 那么肯定是要写入的, 记住document[cookie] = xxxx,或者window这两个关键词  

2 2.2 hook

> 既然我们知道加密参数是从这个js运行结束后生成的,那么在js文件顶部打上断点
Object.defineProperty(document,'cookie',{
    set:function(val){ 
        debugger; return val
}})

image.png 通过下一个断点的运行就能看到上一个断点的运行位置 image.png document['cookie'] = xxx image.png

现在开始扣代码把!!!!!!!!!!!! 现在我们知道第四段是在生成cookie,那前面三段是干啥了呢,先扣下来到本地运行一下
发现报了一个莫名其妙的错误

image.png 这个可以看到是在g["setCookie"]调用的 这就意味着 j 这个参数结果是false,这里实际调用的就是 h 这个函数 image.png 这里由于本地是出现了错误的,但是线上是没有的,所以我们可以在 j 这个参数的位置打上一个断点

image.png image.png 这就能看出来线上返回了一个true,但是线下确实一个false

image.png

k['test'](g['removeCookie']['toString']())

这段代码意思比较简单,用正则判断了一个字符串

g['removeCookie']['toString']()
// 线上
"function(){return'dev';}"
// 线下
"function() { return 'dev'; }"

可以很明显的看到是有区别的,线上没有换行符,修改一下线下的代码 image.png 缩成一行在运行看结果就发现没有问题了,至此就解决了第一个小问题了

接着来!!!!!!!!!!!

剩下一个b函数和后面的cookie生成代码由于不知道b函数和后面的cookie生成代码 由于不知道b会不会有问题 我们可以简单的测试调用一下,全局中随便找一个调用了$b函数的测试

调用结果如下,很明显也有某个地方和线上不一致了,但是不知道是哪里,但是这个错误很明显的就是有什么东西在吃疯狂吃内存,如果是要吃内存简单的猜测可能就是死循环之类的 image.png 这里看到有两处使用了for循环

自执行函数内部 image.png

f 函数原型上 image.png

方法一 认真排查篇 由于吃内存的话你的断点会执行很久,所以可以先在线下debug一下 直接在函数的下一步打断点看是否可以马上执行到该断点,测试发现可以,那就可以排除上面那个for的问题了 image.png 断点直接点在第二个for循环的位置 image.png 发现这里一直在跑,

this['fnwxbJ']['length'] 这个长度每次循环都会更新 导致无限循环

问题找到了,为啥线下会出这个问题呢?还是从最新的源头开始和线上做对比 这个死循环的函数是从上面开始调用的,所以在最开始调用的地方打断点查看 image.png

image.png 就问你熟悉不?所以也应该知道如何修改了撒

修改后 运行不卡顿,很顺畅!!!!!!!!!! image.png

最后就是看cookie是怎么生成的了

image.png 可以直接抠出来

开始补代码 缺啥补啥 image.png 当你补完M在补完B函数 时候 发现运行又卡住了,这个时候你很气!!!!!!!!!,我也很气!!!!!!!! 气没办法还是得看,打上断点一个一个看
这个M函数的大致意思就是有a0这个列表这么多事件,每个循环拿一列表一个数,每个数都有对应的事件,然后就执行呗,就这么回事是,我们debug每个case事件都看一下 哪里会存在死循环就行,不必深究 image.png

执行到这个的时候可能会有点懵逼,线上可以执行一下看看会是什么结果,但是只要是这里没有卡住就可以不用管的 image.png 发现是undefined image.png

调式到下面这个事件的时候就要注意一下了 他修改了console对象,当你打印日志的时候就会死循环执行了,直接干掉他

image.png

最后在缺啥补上就基本ok了 最后运行一下看看结果

image.png

image.png

发现不是m 而是munderfined 为啥 虽然后面的结果是对的

找到m生成相关的核心js

image.png

image.png

这就能看到实际调了上 只有 V(Y) 才是最关键的,但是本着研究到底的原则,还是可以看下把 顺带看下 人生苦短,何必python? 是在哪儿出现的 underfined 实际上是调用的M()

image.png 就是这儿了,好了

完结 撒花 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!