吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4425|回复: 124
上一主题 下一主题
收起左侧

[Web逆向] 【JS逆向】某漫画网站图片还原逆向

  [复制链接]
跳转到指定楼层
楼主
littlewhite11 发表于 2025-3-10 11:32 回帖奖励
本帖最后由 littlewhite11 于 2025-3-10 11:38 编辑

逆向目标

  • 网址:aHR0cHM6Ly93d3cuc3VraW1hLm1lL2Jvb2svdGl0bGUvQlQwMDAwMTg1NDgwLw==
  • 目标:漫画图片还原

抓包分析

打开网站,我们随便点击一个章节,可以看到请求回来的图片是打乱的。

而网页上的图片是正常显示的,那么在前端肯定是通过某种方式对乱序图片进行了还原,我们需要做的就是分析出图片的还原逻辑,从而模拟还原图片。

先简单看一下网页的html结构,可以看到承载图片的地方存在canvas标签,那我们可以认为它是通过canvas将乱序的图片一块一块绘制上去的。

逆向分析

我们可以尝试搜索图片链接来开始图片还原逻辑的分析,可以看到在某一个html文件中存在相关图片链接。

我们在PAGES_INFO中下断,刷新网页,成功断住。

可以看到PAGES_INFO是一个数组,里面的每一个对象应该就是网页上的漫画图片了,其中shuffle_map很可能和图片还原顺序有关。

既然离不开PAGES_INFO这个对象,那我们就直接搜索该关键词,看哪里用到,能够在某一个js文件中看到PAGES_INFO被使用。

跳转到该js文件,直接下断,成功断住。

我们先简单分析一下代码逻辑。

// 将图片数组赋值给 _pages
_pages = pages === undefined ? PAGES_INFO : pages;

if (pageNum !== 1) {
    for (var v = 0; v < getPagePerWindow(); v++) {
        try {
            setReadPageCount(v + pageNum);
        } catch (e) {
        }
    }
}
// 应该代表要开始在 canvas 上绘图了
setPaintingAnimation();
limit = pageNum + (getPagePerWindow() === 2 ? 8 : 6);
for (var i = pageNum - (getPagePerWindow() === 2 ? 9 : 7); i < limit; i++) {
    if (i < 1 || i > MAX_PAGE) {
        continue;
    }
    // 对 _page 进行处理,
    page = _pages.filter(function (v) {
        return PAGEMAP[v.page_number] === i;
    })[0];
    try {
        canvas_number = PAGEMAP[page.page_number];
        pagelist[canvas_number] = {
            'page_url': page.page_url,
            'shuffle_map': JSON.parse(page.shuffle_map)
        };
    } catch (e) {
        debug(e);
        continue;
    }
    if (oldPageNumList.indexOf(canvas_number) < 0) {
        // paintCanvas 是绘图的真正逻辑
        paintCanvas(canvas_number);
    }
    oldPageNumList = oldPageNumList.filter(function (v) {
        return (v !== canvas_number);
    });
    newPageNumList.push(canvas_number);
}
clearOldIMemory(oldPageNumList);
oldPageNumList = newPageNumList;
newPageNumList = [];

可以通过动态调试得出,paintCanvas就是绘图的真正逻辑,我们直接跟进去这个函数。

paintCanvas的逻辑并不难,图片还原的逻辑就在imgonload回调函数中。

那我们就直接分析这个回调函数即可。

// 获取 img 标签的宽度
var width = this.width;
// 获取 img 标签的高度
var height = this.height;
window.canvasWidth = width;
window.canvasHeight = height;
xZoom = $(window).width() / (width * numOfPages);
yZoom = $(window).height() / height;
window.ratio = xZoom / yZoom; // window set
$(canvas).css('width', '100%');

// 横向图片块数
xSplitCount = Math.floor(width / BLOCKLEN);
// 纵向图片块数
ySplitCount = Math.floor(height / BLOCKLEN);

// 索引,用于在图片数组中取对应的图片信息
count = 0;
// 设置 canvas 相关信息
ctx = setupCanvas(canvas, width, height) || createCanvas(i, width, height);

// 遍历图片数组,在 canvas 上还原
// 根据双层 for 循环的逻辑可知,是从上往下,从左往右的顺序进行还原
for (var i = 0; i < xSplitCount; i++) {
    for (var j = 0; j < ySplitCount; j++) {
        // _map 就是前文的 shuffle_map
        _x = _map[count][0];  // 数组中图片的 x
        _y = _map[count][1];  // 数组中图片的 y
        w = BLOCKLEN;  // 每块图片的宽度,128
        h = BLOCKLEN;  // 每块图片的高度,128
        x = i * BLOCKLEN;
        y = j * BLOCKLEN;
        _w = BLOCKLEN;  // 每块图片的宽度
        _h = BLOCKLEN;  // 每块图片的宽度
        ctx.drawImage(this, x, y, w, h, _x, _y, _w, _h);
        count += 1;
    }
}
unsetPaintingAnimation();
img.onload = null;
img.src = '//:0';

从上面的代码可以基本分析出还原逻辑了,最后还需要知道ctx.drawImage这个函数的作用是什么,我就直接问AI了。

结合双层for循环的代码,我们就可以知道还原逻辑了:

从上往下、从左往右按每块大小128*128遍历打乱的图片,然后根据shuffle_map的数组绘制到canvas中对应的位置

那我们直接用python代码进行还原,其中restored_img = deepcopy(img)的原因有两点

1.如果restored_img = img的话,相当于对img边还原边修改,最后还原结果是错的。

2.如果直接创建空白图像,就会缺少底下的部分原图,因为打乱的图片除了有48块拼图外,底下的小部分原图是没有被打乱的。

from PIL import Image
from typing import List
from copy import deepcopy

def restore_image(
        shuffle_map: List,  # 还原数组 
        img_path: str,   # 乱序图片路径
        output_img_path: str  # 输出的还原后的图片路径
):
    # 加载被打乱的图像
    img = Image.open(img_path)
    # 宽高
    block_size = 128
    # 深拷贝一份原图,在原图基础上还原
    restored_img = deepcopy(img)
    count = 0
    for i in range(6):
        for j in range(8):
            _x = shuffle_map[count][0]
            _y = shuffle_map[count][1]
            x = i * block_size
            y = j * block_size
            cropped = img.crop((x, y, x + block_size, y + block_size))
            restored_img.paste(cropped, (_x, _y, _x + block_size, _y + block_size))
            count += 1
    restored_img.save(output_img_path)

从网页上下载一张乱图,并获得对应的还原数组,可以成功还原。

我们再尝试请求一个章节的漫画,并进行还原。

成功!!!

免费评分

参与人数 36威望 +1 吾爱币 +52 热心值 +33 收起 理由
motor007 + 1 + 1 我很赞同!
笙若 + 1 + 1 谢谢@Thanks!
KONKAv983 + 1 + 1 谢谢@Thanks!
RosenLiang + 1 + 1 我很赞同!
Tisfy + 1 我很赞同!
zjqs1 + 1 我很赞同!
wdj500 + 1 + 1 热心回复!
fg411 + 1 + 1 我很赞同!
zzdong123 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
ZeLin99 + 1 + 1 我很赞同!
allspark + 1 + 1 用心讨论,共获提升!
lovepluto6 + 1 + 1 我很赞同!
TFBOYS_GDW + 1 + 1 我很赞同!
bebest1 + 1 + 1 思路讲的很清晰,非常有用,支持
sudaji + 1 热心回复!
qmd + 1 + 1 强大
isuzu + 1 + 1 学习了。之前也遇到过类似的网站,这下有思路了
wangbt901111 + 1 + 1 我很赞同!
xqj007 + 1 + 1 谢谢@Thanks!
mikina + 1 + 1 用心讨论,共获提升!
SMZ048 + 1 用心讨论,共获提升! 图片是内衣教父漫画
pkyou + 1 + 1 用心讨论,共获提升!
psking + 1 + 1 谢谢@Thanks!
weiwei1680 + 1 真不错
抱歉、 + 1 用心讨论,共获提升!
xlln + 1 + 1 我很赞同!
小朋友呢 + 2 + 1 已经处理,感谢您对吾爱破解论坛的支持!
sinmu + 1 + 1 用心讨论,共获提升!
shanhu5235 + 1 + 1 讲解的非常详细
pxq + 1 + 1 谢谢@Thanks!
涛之雨 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Yao2903 + 1 + 1 --------
helian147 + 1 + 1 热心回复!
wanfon + 1 + 1 热心回复!
smfc + 1 我很赞同!
FitContent + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

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

推荐
CoderPiero 发表于 2025-3-10 11:52
很有意思的反爬策略,下下来乱码了还得自己重新拼凑才能看到正确的内容,网站也挺有意思的,可惜是日语
推荐
 楼主| littlewhite11 发表于 2025-3-11 14:59 |楼主
推荐
tadd 发表于 2025-3-10 11:40
4#
 楼主| littlewhite11 发表于 2025-3-10 11:41 |楼主
tadd 发表于 2025-3-10 11:40
老色批的技术宅

那可不是哈,我们研究的是技术
5#
shaunkelly 发表于 2025-3-10 12:50
littlewhite11 发表于 2025-3-10 11:41
那可不是哈,我们研究的是技术

哈哈,当然是技术
6#
zhedery 发表于 2025-3-10 13:27
漫画宅的福音……为什么不看电影呢?
7#
 楼主| littlewhite11 发表于 2025-3-10 13:41 |楼主
zhedery 发表于 2025-3-10 13:27
漫画宅的福音……为什么不看电影呢?

emmm,只研究技术,其他的不归我管
8#
goldcrane1 发表于 2025-3-10 14:02
花样越来越多啦,感谢分享,经验+1
9#
wapython 发表于 2025-3-10 14:11
感谢分享,学到了!!
10#
walykyy 发表于 2025-3-10 14:38
都是高手啊,各种解锁
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-3-25 07:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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