【JS逆向】如何绕过防爬虫—破解JS生成的COOKIE
前言:
12月的某一天在某不知名QQ群中,一位朋友提出提取代理IP的API不可用问题,而且是一个我两年前就用过的api,我抱着好奇的心态就去看了一下。
本次技术分享,主要以http://www.66ip.cn作为例子。有兴趣的朋友可以自己尝试。
被加密的api:http://www.66ip.cn/mo.php?sxb=&tqsl=10&port=&export=&ktip=&sxa=&submit=%CC%E1++%C8%A1&textarea=
发现问题:
首先用浏览器打开,确定接口没有问题,可用。

接下来用软件爬取,发现网页果然没有正常返回。返回的时一段js代码。

问题分析
那么单独来分析一下这段js,本人js废,有任何错误欢迎加我探讨。
首先看第一行代码
window.onload=setTimeout("iv(33)", 200);
初步判断这个页面会经过js的执行跳转,而跳转的目标会从iv函数返回。下面进行断点分析。

发现eval函数执行的po变量为:document.cookie='_ydclearance=acc937cc64a08b2d6a58cd86-4632-4a3b-84e5-f64a73604c79-1545273903; expires=Thu, 20-Dec-18 02:45:03 GMT; domain=.66ip.cn; path=/'; window.document.location=document.URL
修改js确定一下猜测。将
window.onload=setTimeout("iv(33)", 200)
改为
console.log(iv(33)
再将
eval("qo=eval;qo(po)
修改为
return po
运行结果输出正常

那么思路基本上确定了,第一次访问网页—>获取js—>执行js获得cookie
—> 使用cookie再次访问网页。
另外,再多次测试中发现,这段js并非固定,函数名和参数都会改变,所以在解决问题的时候需要使用正则获取一下我们需要的数据。
问题解决

这里直接贴源代码了
python代码
#coding=utf-8
import requests
import execjs
import re
URL = "http://www.66ip.cn/mo.php?sxb=&tqsl=10&port=&export=&ktip=&sxa=&submit=%CC%E1++%C8%A1&textarea="
def parseCookie(string):
String = string.replace("document.cookie='","")
String = String.replace("'; window.document.location=document.URL","")
return String
def getHtml(url, cookie=None):
header = {
"Host": "www.66ip.cn",
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0',
'Upgrade-Insecure-Requests': '1',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 OPR/56.0.3051.116 (Edition B2)',
'Accept-Encoding': 'deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cookie': cookie,
}
html = requests.get(url=url, headers=header, timeout=30).content
return html
text = getHtml(URL)#第一次获取源代码
js_fun = ''.join(re.findall(r'(function .*?)', text))#获取js
js_arg = ''.join(re.findall(r'setTimeout(\"\D+((\d+))\"', text))#获取参数
js_name = ''.join(re.findall(r'function (\w+)', text))#获取函数名
js_fun = js_fun.replace('eval("qo=eval;qo(po);")','return po')#修改js,使其返回结果
js_ctx = execjs.compile(js_fun)#js初始化
str_cookie = js_ctx.eval(js_name+"("+js_arg+")")#执行js获得结果
setcookie = parseCookie(str_cookie)#处理结果获得cookie
text = getHtml(URL,setcookie)#第二次带cookie获取源代码
print(text)
易语言源代码:
模块下载:https://yunquejunweb.oss-cn-beijing.aliyuncs.com/%E8%A1%8C%E4%BA%91%E6%A8%A1%E5%9D%97.ec
常量header-
Host: www.66ip.cn
Proxy-Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 OPR/56.0.3051.116 (Edition B2)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8
Accept-Encoding: deflate
Accept-Language: zh-CN,zh;q=0.9
.版本 2
.支持库 spec
.子程序 获取
.局部变量 tmp, 文本型
.局部变量 regex, 正则表达式类
.局部变量 js_str, 文本型
.局部变量 js_name, 文本型
.局部变量 js_age, 文本型
.局部变量 cookie, 文本型
tmp = 到文本 (网页访问S (“http://www.66ip.cn/mo.php?sxb=&tqsl=10&port=&export=&ktip=&sxa=&submit=%CC%E1++%C8%A1&textarea=http%3A%2F%2Fwww.66ip.cn%2F%3Fsxb%3D%26tqsl%3D10%26ports%255B%255D2%3D%26ktip%3D%26sxa%3D%26radio%3Dradio%26submit%3D%25CC%25E1%2B%2B%25C8%25A1”, , ,cookie, , #header, , , , , “”, ))
regex.创建 (“(function .*?)”, tmp)
js_str = regex.取子匹配文本 (1, 1)
regex.创建 (“setTimeout(” + #引号 + “(\D+)((\d+))” + #引号, tmp)
js_name = regex.取子匹配文本 (1, 1)
js_age = regex.取子匹配文本 (1, 2)
js_str = 文本替换 (js_str, , , , “eval(” + #引号 + “qo=eval;qo(po);” + #引号 + “)”, “return po”)
cookie = 文本取出中间文本 (JS运行 (js_str, js_name, js_age), “cookie='”, “'; window”)
tmp = 到文本 (网页访问S (“http://www.66ip.cn/mo.php?sxb=&tqsl=10&port=&export=&ktip=&sxa=&submit=%CC%E1++%C8%A1&textarea=http%3A%2F%2Fwww.66ip.cn%2F%3Fsxb%3D%26tqsl%3D10%26ports%255B%255D2%3D%26ktip%3D%26sxa%3D%26radio%3Dradio%26submit%3D%25CC%25E1%2B%2B%25C8%25A1”, , ,cookie, , #header, , , , , “”, ))
调试输出 (tmp)
.子程序 JS运行, 文本型, 公开
.参数 JS代码, 文本型
.参数 函数名, 文本型
.参数 参数, 文本型, 可空
.局部变量 js, 对象
.局部变量 return, 文本型
js.创建 (“ScriptControl”, )
js.写属性 (“Language”, “JavaScript”)
js.数值方法 (“AddCode”, JS代码)
return = js.通用方法 (“eval”, 函数名 + “(” + 参数 + “)”).取文本 ()
返回 (retur)
共有 0 条评论