今天再和大家分享一个js逆向案例-公共资源交易平台
前言:你是否遇过,在主页里取到的链接url进入不到详情界面,这种情况就是,放在主页url是假的,是加密过的。那为什么你正常上网站点击进得去真的详情页呢?因为在你点击的那一刻,程序将你点击的假url迅速解密,这时你点击的就是一个真的url。这篇文章教你如何破解这种加密。
1 目标需求:
目标网站 :ggzy.zwfwb.tj.gov.cn/xwzx/index.…
需求:获取到新闻标题和文章内容。
如图:
首页:ggzy.zwfwb.tj.gov.cn/xwzx/index.…
详情页:ggzy.zwfwb.tj.gov.cn/zwyw/3MNQpB…
获取详情页的信息
找到文章位置,一般都是在index的html文件中,只需要将p之间的内容拼接起来就行
代码实现,这里使用的是bs4来解析的,具体的不多赘述,不是重点
# jiaoyi.py
import requests
from bs4 import BeautifulSoup
url = 'http://ggzy.zwfwb.tj.gov.cn/zwyw/3MNQpBiHOQAxmJKQV8H4aw.jhtml'
head = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
}
res = requests.get(url, headers=head)
html = res.text
# 解析HTML
soup = BeautifulSoup(html, 'lxml')
# 提取文章标题
title = soup.find('div', class_='content-title').text
# 提取文章内容
content_div = soup.find('div', class_='content-article')
content = ""
for p in content_div.find_all('p'):
content += p.text + "\n"
# 将标题和内容写入到txt文件中
with open(f'{title}.txt', 'w', encoding='utf-8') as file:
file.write("文章标题: " + title + "\n\n")
file.write("文章内容: \n" + content)
抓到的文件信息为:
跟上面是一样的。
这样是不是把这些代码包装成一个方法,传入详情页url,就可以得到每一个详情页文章内容,所以,下一步是将页面上的所有详情页url拿到
2 获取详情页url
这个url一般都是找a标签的链接,可以先获取主页的html文件,然后解析a标签里的链接。
就是这玩意,只要解析出来就行
url='http://ggzy.zwfwb.tj.gov.cn/xwzx/index.jhtml'
head={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
}
res=requests.get(url,headers=head)
html=res.text
html = etree.HTML(res.text)
lis = html.xpath('//ul[@class="article-list2"]/li/div/a/@href')
for li in lis:
print(li)#更直观一点
结果为这个,都拿下来了,试一下
报错了了
是没拿到数据,比较一下上面的url
http://ggzy.zwfwb.tj.gov.cn/zwyw/3MNQpBiHOQAxmJKQV8H4aw.jhtml
就是数字和那一串字母不一样。并且用主页提取的url,连网页都进不去。
肯定不会将一个没用的url挂在主页,那么就是加密了,那一串数字和那一串字符肯定存在着某种联系。
3 js逆向解加密
首先我们想一下,我们要怎么进入这个详情页?就是点击一下,但是主页的url是假的,我们点击了一个假的url进入了真的url,肯定是我们点击的时候,程序进行了解密。就是一开始先在内部进行加密,生成一个假的在主页上,在你点击的时候迅速解密,使你点击了一个真的url。
3.1 事件监听
选中一个a标签,进行事件监听,点击click展开,点击a跳转。
跳转到了点击事件函数
3.2 调试
加了个断点,点击运行,发现hh就是假的url
一直向下一步一步调试,ccc就是要解密的字段
再继续调试,一直到这里,这玩意诸位可知道是什么?它是一个对称加密算法(具体的我前面的文章有讲)
那么接下来就是加密环节了,继续调试
到了这里大家都猜到了一些吧,了解AES的都清楚,它加密后是有两个等号的,而ddd就是加密后的参数,继续调试
到了这里真url就出来了,接下来就是讲js代码扣过来了。
3.3 调试js代码
function f(hh){
var aa = hh.split("/");
var aaa = aa.length;
var bbb = aa[aaa - 1].split('.');
var ccc = bbb[0];
var cccc = bbb[1];
var r = /^\+?[1-9][0-9]*$/;
var ee = $(this).attr('target');
if (r.test(ccc) && cccc.indexOf('jhtml') != -1) {
var srcs = CryptoJS.enc.Utf8.parse(ccc);
var k = CryptoJS.enc.Utf8.parse(s);
var en = CryptoJS.AES.encrypt(srcs, k, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
var ddd = en.toString();
ddd = ddd.replace(/\//g, "^");
ddd = ddd.substring(0, ddd.length - 2);
var bbbb = ddd + '.' + bbb[1];
aa[aaa - 1] = bbbb;
var uuu = '';
for (i = 0; i < aaa; i++) {
uuu += aa[i] + '/'
}
uuu = uuu.substring(0, uuu.length - 1);}
}
将复制的js代码包装到一个函数中,方便后面调用,前面知道,hh就是假的url,将一个假的url传进去运行一下。
这里有个报错,首先上面的那行代码是获取一个属性值的意思,得到的是后面这个target的值
target指明点击标签在何处打开,该网站中是blank是在新标签页中打开目标文档,一般都是一样的,所以这里直接给赋值就行。(这一部分是关键代码,能不删就不删)
再运行,还是报错,这里CryptoJS是一个 JavaScript 加密库 是要进行导包的,导个包,下一步
s没有,s是个值,看看是什么
这这这,好像是密钥啊
问题不大。据我观察,这几个链接的密钥都是一样的,所以可以直接赋值 下一步就出来了
然后就简单了,只要将假url解密,再传让文件保存函数就可以了。
4 文件保存
js代码:
function f(hh){
const CryptoJS = require('crypto-js');
var aa = hh.split("/");
var aaa = aa.length;
var bbb = aa[aaa - 1].split('.');
var ccc = bbb[0];
var cccc = bbb[1];
var r = /^\+?[1-9][0-9]*$/;
var ee = '_blank';
if (r.test(ccc) && cccc.indexOf('jhtml') != -1) {
var srcs = CryptoJS.enc.Utf8.parse(ccc);
var k = CryptoJS.enc.Utf8.parse("qnbyzzwmdgghmcnm");
var en = CryptoJS.AES.encrypt(srcs, k, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
var ddd = en.toString();
ddd = ddd.replace(/\//g, "^");
ddd = ddd.substring(0, ddd.length - 2);
var bbbb = ddd + '.' + bbb[1];
aa[aaa - 1] = bbbb;
var uuu = '';
for (i = 0; i < aaa; i++) {
uuu += aa[i] + '/'
}
uuu = uuu.substring(0, uuu.length - 1);}
return uuu;
}
# jiaoyi.py
import requests
from bs4 import BeautifulSoup
import execjs
from lxml import etree
def get_page_info(url):
head = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
}
res = requests.get(url, headers=head)
html = res.text
# 解析HTML
soup = BeautifulSoup(html, 'lxml')
# 提取文章标题
title = soup.find('div', class_='content-title').text
# 提取文章内容
content_div = soup.find('div', class_='content-article')
content = ""
for p in content_div.find_all('p'):
content += p.text + "\n"
# 将标题和内容写入到txt文件中
with open(f'{title}.txt', 'w', encoding='utf-8') as file:
file.write("文章标题: " + title + "\n\n")
file.write("文章内容: \n" + content)
url='http://ggzy.zwfwb.tj.gov.cn/xwzx/index.jhtml'
head={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
}
res=requests.get(url,headers=head)
html=res.text
html = etree.HTML(res.text)
lis = html.xpath('//ul[@class="article-list2"]/li/div/a/@href')
for href in lis:
# 默认返回的列表
print(href)
# 调用js,执行js代码
with open(r'jiaoyi.js', 'r', encoding='utf-8')as f:
js_code = f.read()
js_code = execjs.compile(js_code)
real_url = js_code.call('f', href)
get_page_info(real_url)
结果:
爬虫挺简单,但是网站要设防的话有点难,对程序员的要求比较高,至于我为什么爬天津的,因为额...就天津设防了,我们大江西没有设防。
好了完结撒花。。。我也是刚学,如果有什么不对或者不足的地方,请各位大佬多多指教