js逆向解加密-公共资源交易平台

286 阅读6分钟

今天再和大家分享一个js逆向案例-公共资源交易平台

前言:你是否遇过,在主页里取到的链接url进入不到详情界面,这种情况就是,放在主页url是假的,是加密过的。那为什么你正常上网站点击进得去真的详情页呢?因为在你点击的那一刻,程序将你点击的假url迅速解密,这时你点击的就是一个真的url。这篇文章教你如何破解这种加密。

1 目标需求:

目标网站 :ggzy.zwfwb.tj.gov.cn/xwzx/index.…

需求:获取到新闻标题和文章内容。

如图:

首页:ggzy.zwfwb.tj.gov.cn/xwzx/index.…

image.png 详情页:ggzy.zwfwb.tj.gov.cn/zwyw/3MNQpB…

image.png

获取详情页的信息

找到文章位置,一般都是在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)

抓到的文件信息为:

image.png 跟上面是一样的。

这样是不是把这些代码包装成一个方法,传入详情页url,就可以得到每一个详情页文章内容,所以,下一步是将页面上的所有详情页url拿到

2 获取详情页url

这个url一般都是找a标签的链接,可以先获取主页的html文件,然后解析a标签里的链接。

image.png 就是这玩意,只要解析出来就行

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)#更直观一点

image.png

结果为这个,都拿下来了,试一下

报错了了

image.png 是没拿到数据,比较一下上面的url

http://ggzy.zwfwb.tj.gov.cn/zwyw/3MNQpBiHOQAxmJKQV8H4aw.jhtml 就是数字和那一串字母不一样。并且用主页提取的url,连网页都进不去。

image.png 肯定不会将一个没用的url挂在主页,那么就是加密了,那一串数字和那一串字符肯定存在着某种联系。

3 js逆向解加密

首先我们想一下,我们要怎么进入这个详情页?就是点击一下,但是主页的url是假的,我们点击了一个假的url进入了真的url,肯定是我们点击的时候,程序进行了解密。就是一开始先在内部进行加密,生成一个假的在主页上,在你点击的时候迅速解密,使你点击了一个真的url。

3.1 事件监听

选中一个a标签,进行事件监听,点击click展开,点击a跳转。

image.png

image.png 跳转到了点击事件函数

3.2 调试

加了个断点,点击运行,发现hh就是假的url

image.png 一直向下一步一步调试,ccc就是要解密的字段

image.png 再继续调试,一直到这里,这玩意诸位可知道是什么?它是一个对称加密算法(具体的我前面的文章有讲) 那么接下来就是加密环节了,继续调试

image.png 到了这里大家都猜到了一些吧,了解AES的都清楚,它加密后是有两个等号的,而ddd就是加密后的参数,继续调试 image.png 到了这里真url就出来了,接下来就是讲js代码扣过来了。

image.png

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传进去运行一下。

image.png 这里有个报错,首先上面的那行代码是获取一个属性值的意思,得到的是后面这个target的值

image.png target指明点击标签在何处打开,该网站中是blank是在新标签页中打开目标文档,一般都是一样的,所以这里直接给赋值就行。(这一部分是关键代码,能不删就不删)

image.png

再运行,还是报错,这里CryptoJS是一个 JavaScript 加密库 是要进行导包的,导个包,下一步

image.png s没有,s是个值,看看是什么

image.png 图片描述这这这,好像是密钥啊

问题不大。据我观察,这几个链接的密钥都是一样的,所以可以直接赋值 下一步就出来了

image.png

然后就简单了,只要将假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)

结果:

image.png

爬虫挺简单,但是网站要设防的话有点难,对程序员的要求比较高,至于我为什么爬天津的,因为额...就天津设防了,我们大江西没有设防。

好了完结撒花。。。我也是刚学,如果有什么不对或者不足的地方,请各位大佬多多指教