傻瓜式绕过加速乐反爬机制
2021-02-27   # 开发

加速乐是如何反爬的

以 cnvd 为例,访问会跳转两次,第一次返回 cookie __jsluid_s=6a027a76583f43e463722e69d0247a0a,并且页面会通过 js 设置cookie __jsl_clearance_s=1614408251.231|-1|hWPBUGndFSVIOaYhUtUilmZPgng%3 并跳转,如图

image-20210227144641727

然后带着得到的 __jsluid_s__jsl_clearance_ 继续访问cnvd,这里是第一次跳转,返回的是一大堆 js 代码,混淆比较严重,解混淆后还是很难审计。这段 js 的主要作用就是重新生成 __jsl_clearance_ 并且会检查一些常见的爬虫特征之类的,然后跳转。

image-20210227145300400

带着新生成的 cookie 第二次跳转访问 cnvd 就可以获取到真正的内容了,这个 cookie 有效时间大概有20分钟左右,而且这个 cookie 也就是 __jsl_clearance_、 __jsluid_s 有对 User-Agent 签名,cookie 和 User-Agent 是对应的。

image-20210227150311716

绕过思路

原来就是通过 selenium 模拟浏览器 去访问 cnvd ,获取 cookie 和 User-Agent,但是最近这个方法不行了,在第二次访问得到的那一堆 js 代码里应该检测机制,导致 selenium 访问的时候并不会第二次跳转

解混淆后可以发现,最终设置 cookie 和跳转的代码在这,测试了一下,用 selenium+chromedriver 模拟浏览器 去访问的话根本就没有执行到这,使用正常浏览器访问的话则能够执行到这并跳转。

image-20210227151208568

入口的函数是 go() ,可以看到在函数里有很多这种 if 然后 return !![] ,这里应该就是各种检测如果不满足就直接 return,

image-20210227151834477

直接暴力点,把 js 代码扣出来, 然后直接把所有 return !![] 删了。让他能够执行到 设置 cookie 和 跳转的代码,设置 cookie 和跳转的代码是被包裹在 setTimeout 函数里的,会延时执行,所以还得把他从 setTimeout 扣出来。

还有一个坑,每次返回的 js 代码其实格式是有好几种的,所以正则得写好,而且我们只要获取 cookie 就行,所以把跳转的代码也直接删了。

上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
def get_cookies(self):
chrome_options = Options()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--headless')

chrome_options.add_argument('user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36')
#chrome_options.add_argument("--proxy-server=http://127.0.0.1:8080")
driver = webdriver.Chrome(executable_path='/pyspider/chromedriver',chrome_options=chrome_options)
driver.get("https://www.cnvd.org.cn/")

# 扣出源码里的js
pageSource = driver.page_source
pageSource = pageSource.split("<script>")[1]
pageSource = pageSource.split("</script>")[0]

# 处理js代码
pageSource = "var t;"+pageSource
temp_pageSource = pageSource.split("setTimeout");
temp_pageSource[-1] = re.sub(r'location\[.*?\](.*?)location\[.*?\](.*?)location\[.*?\](\;|\)\;|\;\}|\)\;\}),_0x(\w{3,7})\)\;', '',temp_pageSource[-1])
pageSource = 'setTimeout'.join(temp_pageSource)
pageSource = re.sub(r'_0x(\w{0,6})\[_0x(\w{0,6})\(\'0x(\w{0,6})\'\,\'.{0,6}\'\)\+\'\w{0,6}\'\]\(setTimeout\,function\(\)\{', '', pageSource)
pageSource = re.sub(r'setTimeout\(function\(\)\{','', pageSource)
pageSource = pageSource.replace("return!![];","")

# 执行js代码 获取 __jsl_clearance_s
ccc = driver.execute_script(pageSource+";return document.cookie")

# 获取 cookie
cj = driver.get_cookies()
cookie = ''
for c in cj:
cookie += "'"+c['name'] + "':'" + c['value'] + "',"
cookie = ast.literal_eval('{'+cookie+'}')

# 把cookie 中的 __jsl_clearance_s 替换为新的
cookie['__jsl_clearance_s']=ccc.split("=")[1]

# 获取 user-agent
agent = driver.execute_script("return navigator.userAgent")

driver.quit()

return cookie,agent