JS逆向之企业信息x系统Cookie传递

篇幅有限

完整内容及源码关注公众号:ReverseCode,发送

目标

http://www.gsxt.gov.cn/corp-query-entprise-info-xxgg-100000.html

分析

POST http://www.gsxt.gov.cn/affiche-query-area-info-paperall.html?noticeType=21&areaid=100000&noticeTitle=&regOrg=110000

  • 参数:
    • noticeType=21 通知类型, 失信企业固定21
    • areaid=100000 无论在哪个区域, 固定是100000
    • noticeTitle= 通知标题, 可以为空
    • regOrg= 通知的区域id, 可以从省份标签上获取
  • 请求体数据:
    • draw: 1 点击分页按钮的次数, 可以省略
    • start: 0 起始索引号
    • length: 10 长度, 固定是10, 设置多了也无效

直接访问该接口时,状态521,返回如下js混淆加密代码。

尝试给请求头中加上cookie__jsluid_h=f6db0fc02adff8425bebcd8ed1b5fffc; SECTOKEN=7445298838033400749; __jsl_clearance=1619443187.64|0|nGqWRKwajO%2BeHI6CP7Mt50EbdcU%3D;,正常返回如下结果。

__jsluid_h

打开fiddler,刷新页面抓包http://www.gsxt.gov.cn/corp-query-entprise-info-xxgg-100000.html,一共访问了三次该页面,前两次521第三次正场返回请求页面。

第一次请求时服务端向服务器塞入第一个__jsluid_h关键cookie

Set-Cookie: __jsluid_h=01737b0139a221e260d1061c68b4232f; max-age=31536000; path=/; HttpOnly

并向浏览器返回一段混淆过的js,内容如下,主要功能应该是设置cookie。

<script>document.cookie=('_')+('_')+('j')+('s')+('l')+('_')+('c')+('l')+('e')+('a')+('r')+('a')+('n')+('c')+('e')+('=')+((+true)+'')+((1+[2])/[2]+'')+(-~false+'')+(3+6+'')+(2+2+'')+(-~[2]+'')+(~~false+'')+((2)*[4]+'')+((1+[0])/[2]+'')+(9-1*2+'')+('.')+((2)*[2]+'')+(6+'')+(1+6+'')+('|')+('-')+(-~0+'')+('|')+('w')+('Y')+('p')+('A')+('F')+('R')+('%')+(1+1+'')+('B')+(-~(4)+'')+('X')+('x')+('m')+('W')+('Y')+((1<<2)+'')+('j')+('P')+('a')+('Q')+([3]*(3)+'')+('t')+('Q')+(1+7+'')+('T')+('P')+('Z')+('i')+('E')+('%')+(3+'')+('D')+(';')+('m')+('a')+('x')+('-')+('a')+('g')+('e')+('=')+(3+'')+(3+3+'')+(~~''+'')+(~~false+'')+(';')+('p')+('a')+('t')+('h')+('=')+('/');location.href=location.pathname+location.search</script>

我们将这段js放入浏览器中执行,如我们所料,正是返回第二个__jsl_clearance关键性cookie。

__jsl_clearance

第二次请求http://www.gsxt.gov.cn/corp-query-entprise-info-xxgg-100000.html时,浏览器发送了__jsl_clearance和__jsluid_h两个关键cookie,服务端接收后并返回了一段混淆后的js,这次没有向浏览器塞入cookie。

Cookie: __jsluid_h=01737b0139a221e260d1061c68b4232f; __jsl_clearance=1619430857.467|-1|wYpAFR%2B5XxmWY4jPaQ9tQ8TPZiE%3D

SECTOKEN

第三次请求http://www.gsxt.gov.cn/corp-query-entprise-info-xxgg-100000.html时,浏览器携带了两个关键性Cookie,不过这次__jsl_clearance和之前的值发生变化,怀疑是第二次请求返回的js做了手脚。

Cookie: __jsluid_h=01737b0139a221e260d1061c68b4232f; __jsl_clearance=1619430857.529|0|WGn9gKxiPtYUHAGBZ1a%2B%2F3o9sJE%3D

这次请求不仅正常的返回了页面内容,而且还往请求头中塞入了第三个SECTOKEN关键性Cookie。

Set-Cookie: SECTOKEN=7448433543385710812; Expires=Sat, 14-May-2089 13:03:34 GMT; Path=/; HttpOnly

请求数据

在上面的三个cookie加持下,终于成功的返回了我们想要的数据,接下来就是分析这三个cookie在代码中如何拿到。

爬虫实现

通过requests的session对象,自动合并cookie信息,并设置请求头。

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36',
}
session = requests.session()
session.headers = headers

第一次请求

通过第一次请求,服务端往客户端返回__jsluid_h作为第一个关键cookie,根据返回的js通过正则表达式拿到script标签中的js逻辑,并去除后面无用jslocation.href...

response = session.get(index_url)
js1 = re.findall('<script>(.+?)</script>', response.content.decode())[0].replace('document.cookie=', '').replace(
    'location.href=location.pathname+location.search', '')
context = js2py.EvalJs()    
context.execute('cookies2 =' + js1)
cookies = context.cookies2.split(';')[0].split('=')
session.cookies.set(cookies[0], cookies[1])  # 到此拿到第两个cookie
print(session.cookies)

第二次请求

第二次请求携带了前面两个关键性cookie,并返回了一段js。这里我们的cookie都存在了session中,所以不用额外处理。通过正则取出第二次返回的js中script标签中的内容。

就算格式化后这段代码都难以阅读,我们通过ob混淆专解测试版V0.1进行反混淆,重新审视这段js。

逻辑就是通过调用go函数往document中塞入cookie,我们在function go(_0x2323c8)最后返回document['cookie'],把setTimeout的时间设置久一点。

通过上面分析我们可以通过第二次请求返回的js进行修改后,python调用生成cookie传递后被修改的__jsl_clearance关键cookie。不过很多对象在python调用时不可用,如window,document,location等等,我们可以通过jsdom库npm install jsdom实现浏览器的上下文。

const jsdom = require("jsdom");
const {JSDOM} = jsdom;
const dom = new JSDOM();
window = dom.window;
document = window.document;
location = new Array();

就这段js存入文件后,python读取文件,使用execjs实现调用,返回第二个__jsl_clearance关键性cookie,为获取SECTOKEN埋下伏笔。

with open(r'第二次请求.js', encoding='utf-8', mode='r') as f:
    JsData = f.read()
cookie = execjs.compile(JsData).call('request')
print(cookie)

在python中为了调用go函数,还需要在js中新创建一个request函数,让go函数的数据返回给python作为cookie存入session中。

# 添加jsdom实现浏览器上下文
js2 = '''const jsdom = require("jsdom");const {JSDOM} = jsdom;const dom = new JSDOM();window = dom.window;document = window.document;location = new Array();''' + \
      re.findall('<script>(.+?)</script>', session.get(index_url).content.decode('utf-8'))[0]
# 正则获取document['cookie'],由于每次个数不一样我们取最后一个
cookies2_1 = re.findall(r"document\[.*?\]=(.*?)location", js2, re.S)[-1]
# 将document['cookie']内容返回给go函数
js3 = re.sub("};go", "return " + cookies2_1 + "};go", js2, 1)
# 获取调用go函数时里面的参数
request = re.findall(r"go\({(.*?)}\)", js3, re.S)[-1]
# 通过python修改js生成一个request方法
final_js = js3+"\nfunction request() {return go({"+request+"})}"
# js调用request方法返回cookie并将新的__jsl_clearance塞给session中
cookies3 = execjs.compile(final_js).call('request').split(';')[0].split('=')
session.cookies.set(cookies3[0], cookies3[1])
print(cookies3)

第三次请求

利用新的__jsl_clearance和__jsluid_h发送第三次请求,服务端会向客户端返回新Cookie SECTOKEN,接下来我们打印出所有的cookie。

session.get(index_url)
cookies = requests.utils.dict_from_cookiejar(session.cookies)
print(cookies)
{
    '__jsl_clearance': '1619446283.778|0|DFaPnxb5OqsBcRBkaxTSCax2qLA%3D',
    'HttpOnly': None,
    'JSESSIONID': 'e80d7db0e1fe65e65ab6a29e8cc4',
    'SECTOKEN': '7448640433386424422',
    '__jsluid_h': '2c8e0b64535955d16c6db3072464d199',
    'tlb_cookie': 'S172.16.12.67'
}

数据抓取

url = 'http://www.gsxt.gov.cn/affiche-query-area-info-paperall.html?noticeType=21&areaid=100000&noticeTitle=&regOrg=110000'

data = {
    # 'draw': '0',
    'start': '0',
    'length': '10'
}

# 准备请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36',
    # 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
    # 'Referer': 'http://www.gsxt.gov.cn/corp-query-entprise-info-xxgg-100000.html',
    # 'Cookie': '__jsluid=fb0718dce34ccf53c4b94d15e9ab13d5; SECTOKEN=7178252594204902863; __jsl_clearance=1546475343.133|0|QZ7AOWMecndqD4CZG4hqoBAHtVw%3D;'
}

response = requests.post(url, cookies=cookies, data=data, headers=headers)
print(response.status_code)
print(response.content.decode())

完整源码请关注微信公众号:ReverseCode,回复:JS逆向

完整内容见威信公众号:ReverseCode

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

onejane

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值