吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3004|回复: 19
收起左侧

[Web逆向] 对于某网站预览文档分析

  [复制链接]
flt 发表于 2023-3-12 15:32
本帖最后由 flt 于 2023-3-12 15:48 编辑

背景

某网站资源页面存在预览,有的只有部分,有的能显示全部。对于文字版文档,文件是矢量版,看起来效果很好。

预览数据抓包

在页面内打开一个没有打开的文档,抓包找到大量svg文件请求:

1

1
链接(已隐藏部分数据):

https://preview.*****.com/resource/oss/preview/rbm-preview-product/rbm/*******/svg/6.svg?Expires=167*****11&Signature=qK47**********rYq43G6Q%3D

将抓包数据导入apifox,删除cookie和header测试是否存在验证,结果证明不存在除了url param外的其他认证。

2

2

寻找根源请求数据

上文已经找到了每一页预览的请求,但是由于Signature的存在还是无法实现自动请求。刷新页面,搜索上述链接可能的关键词preview

3

3
观察到有一个疑似请求:

https://www.****.com/soft/Preview/FirstLoadPreviewJson?softID=33****78&fileaddress=&type=3&product=1&v=2&FullPreview=false

响应内容是一个json:

{
    "code": 0,
    "success": false,
    "data": {
        "IsSuccess": true,
        "IsRar": true,
        "SoftExt": null,
        "Html": "\r\n\u003cstyle\u003e\r\n  {{请求内容过长忽略}}  \u003e\r\nHHHHHHisrar",
        "PreviewPage": 0,
        "TotalPage": 0,
        "rarPreviewInfo": [
            {
                "FileId": 38****99,
                "Html": "\r\n\u003cdiv class=\"multiple-date-preview-file\" data-index=\"3****499\"\u003e\r\n    \u003cdiv class=\"preview-main\"\u003e\r\n        \r\n        \u003cimg data-original=\"https://preview.***.com/resource/oss/preview/rbm-preview-product/rbm/38****99/svg/1.svg?Expires=1678604711\u0026Signature=7w%2BPVktPi********5Lha0%3D\" onselectstart=\"return false\" /\u003e\u003cimg data-original=\"https://preview.***.com/resource/oss/preview/rbm-preview-product/rbm/38****99/svg/2.svg?Expires=16****4711\u0026Signature=zt20********BQ1RGZDlTaB0%3D\" onselectstart=\"return false\" /\u003e\u003c  {{以下存在类似内容,忽略}}    \u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003cscript\u003e\r\n    document.oncontextmenu = function () {\r\n        window.event.returnValue = false;\r\n    };\r\n    var pageNum = 9;\r\n    var hasPreview = true;\r\n    if (pageNum \u0026\u0026 window.setDocumentPageNum) {\r\n        window.setDocumentPageNum(pageNum, hasPreview);\r\n    }\r\n\u003c/script\u003e\r\n\r\n",
                "SoftName": "************.docx",
                "IconClassName": "icon-doc-doc",
                "TotalPage": 9,
                "PreviewPage": 9,
                "IsMedia": false,
                "Url": null
            },
            {
                "FileId": 3****500,
                "Html": "{{类似上文}}",
                "SoftName": "********.docx",
                "IconClassName": "icon-doc-doc",
                "TotalPage": 5,
                "PreviewPage": 5,
                "IsMedia": false,
                "Url": null
            }
        ]
    },
    "msg": "预览错误",
    "message": null
}

PS:上文中的"msg": "预览错误"对任意都相同,忽略。

经分析,上文的第一个Html内容基本无效,都时限制用户的脚本。
rarPreviewInfo中的Html内容格式化后如下:

<div class="multiple-date-preview-file" data-index="38****99">
    <div class="preview-main">

        <img 
            data-original="https://preview.***.com/resource/oss/preview/rbm-preview-product/rbm/38****99/svg/1.svg?Expires=167****711&Signature=7w%2************86WF5Lha0%3D" 
            onselectstart="return false" 
        />
        <img
            data-original="https://preview.***.com/resource/oss/preview/rbm-preview-product/rbm/38****99/svg/2.svg?Expires=167****711&Signature=zt206U***********1RGZDlTaB0%3D" 
            onselectstart="return false" 
        />
        <!-- {{以下类似内容忽略}} -->
    </div>
</div>
<script>
    document.oncontextmenu = function () {
        window.event.returnValue = false;
    };
    var pageNum = 9;
    var hasPreview = true;
    if (pageNum && window.setDocumentPageNum) {
        window.setDocumentPageNum(pageNum, hasPreview);
    }
</script>

显然,preview链接被直接返回了,经检验该链接可以直接请求。
最后导入apifox验证后可以确定无需特殊headers或cookies。

最小化请求链接和寻找相关参数

当前链接参数:

4

4

SoftID可以直接在文档页面的链接中可以找到:

https://www.****.com/soft/33****78.html

上文的33****78即为softID

type, product, v参数不知道用途,对任意文档都是相同的,疑似网站作者还没有实现,直接引用原文了。

FullPreview原本是false,改为true就直接返回全部内容的预览了.....

分析返回的json

测试了多个文档后确定一下结论:

5

5

demo代码

代码无法运行,因为关键域名被"*"替代

import requests
from re import findall, sub
from hashlib import md5

HTML_FORMAT ='''
<html>

<head>
<title>{title}</title>
</head>

<body>
{body}
</body>

</html>
'''

def writefile(filename,text):
    filename = sub(r"""[\*\/\\\|\<\>\? \:\.\'\"\!]""", "", filename)
    unique = md5(text.encode())
    filename += "_"+unique.hexdigest()[:5]
    filename+=".html"
    print("Writing "+filename)
    # print("-=-=-=-=\n",text,"\n-=-=-=-=")
    with open(filename+'.html', 'w', encoding="utf-8") as f:
        f.write(text)

def main():
    softID=input("ID: ")
    url = "https://www.*******.com/soft/Preview/FirstLoadPreviewJson?softID={}&type=3&product=1&v=2&FullPreview=true"
    response = requests.get(url.format(softID))
    if response.status_code!=200:
        print("ERROR")
        print(response.status_code)
        return -1
    ret=response.json()["data"]
    if not ret["IsSuccess"]:
        print("ERROR: IsSuccess option is not true")
        print(ret)
    if not ret['IsRar']:
        print("Not rar")
        print("TotalPage=%d" % ret['TotalPage'])
        print("SoftExt=%s" % ret['SoftExt'])
        try:
            html=ret["Html"]
            print(ret)
        except:
            print(ret)
            exit(1)
        # replace "data-original" to "src" for showing in browser
        html=html.replace("data-original", "src")
        writefile(f"{softID}",html)
    else:
        print("is RAR")
        rar=ret['rarPreviewInfo']
        for file in rar:
            html=file["Html"]
            title=file["SoftName"]
            # replace "data-original" to "src" for showing in browser
            # html=html.replace("data-original", "src")
            urls=findall("(?<=data-original=\")https://preview.*******.com/\\S+(?=\")",html)
            l=[]
            for url in urls:
                if "jpg" in url:
                    l.append(f"<img src={url} />")
                    continue
                page=requests.get(url,cookies=response.cookies)
                if not page.status_code==200:
                    print(page)
                    print(page.status_code)
                    print(page.text)
                assert page.status_code==200
                l.append(page.text)
            format_html=HTML_FORMAT.format(title=title,body="\n".join(l))
            writefile(title,format_html)

if __name__  == "__main__":
    while True:
        main()

免费评分

参与人数 5吾爱币 +11 热心值 +5 收起 理由
涛之雨 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
sudie0023 + 1 + 1 用心讨论,共获提升!
felixchao + 1 + 1 我很赞同!
cntjgaowei + 1 + 1 谢谢@Thanks!
helian147 + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| flt 发表于 2023-3-12 16:05
xihaxiaowangzi 发表于 2023-3-12 16:00
感谢大神的指点,要是能直接解析下载就好了

上述demo可以下载形成html版本,用浏览器打印为pdf即可。但是出于版权不能公开,这里之分享思路。
xihaxiaowangzi 发表于 2023-3-12 16:00
xihaxiaowangzi 发表于 2023-3-12 16:32
本帖最后由 xihaxiaowangzi 于 2023-3-12 16:39 编辑

已经很感谢了  
a90120411 发表于 2023-3-12 21:39
第一张图暴露了
sdieedu 发表于 2023-3-12 21:42
xihaxiaowangzi 发表于 2023-3-12 16:00
感谢大神的指点,要是能直接解析下载就好了

到底啥网站?提示一下
YueJunior 发表于 2023-3-13 01:54
感谢分享!
emptynullnill 发表于 2023-3-13 09:40
思路很棒,感谢分享
xihaxiaowangzi 发表于 2023-3-13 10:04
本帖最后由 xihaxiaowangzi 于 2023-3-13 12:59 编辑
emptynullnill 发表于 2023-3-13 09:40
思路很棒,感谢分享
解析出来的网页 内容是空的
helian147 发表于 2023-3-13 22:32
xihaxiaowangzi 发表于 2023-3-13 10:04
解析出来的网页 内容是空的

打断点调试一下,仔细看返回的值
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-23 16:03

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表