吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 16566|回复: 173
收起左侧

[Web逆向] 极x壁纸 - 图片请求数据解密

    [复制链接]
爱飞的猫 发表于 2021-7-26 02:44
本帖最后由 jixun66 于 2021-7-26 02:48 编辑

这个网站不知道从哪找的加密程序,强行开开发者工具会比较吃内存/CPU,只好想别的办法了。

1.png

准备操作

  1. 安装并配置好 Charles 反代工具,启动并确保能正常抓取流量。
  2. 安装好编辑器,如 VSCode。
  3. NodeJS,用来本地运行代码片段。

访问主页并等待加载完毕,将所有 JS 资源文件都保存下来:

  1. 右键 https://bz.zzzmh.cn/ 下的 js 目录
  2. 选择 “Save All...”,保存到一个目录下。

2.png


使用 Map Local 把文件都改为从本地获取:

  1. 右键 https://bz.zzzmh.cn/ 下的 js 目录
  2. 选择 Map Local
  3. 点击 Local Path 的 Choose 按钮,选择 Charles 保存资源的 js 目录。

3.png
4.png


原始网页引入的代码存档:

js_原始.7z (236.71 KB, 下载次数: 16)


现在可以使用编辑器打开这个 js 目录了。

因为不是很想解决这个反调试功能,只好自己加一些用来帮助调试的“调试器”了:

直接将下述代码随便塞到一个文件的顶部:

(function() {
  const container = document.createElement('div');
  const console = document.createElement('pre');
  const input = document.createElement('textarea');
  const exec = document.createElement('button');

  const log = (text) => {
    console.appendChild(document.createTextNode(text));
  };

  const clear = () => {
    console.textContent = '';
  };

  input.cols = 60;
  input.rows = 8;
  exec.textContent = 'exec';
  exec.type = 'button';
  exec.onclick = () => {
    eval(input.value);
  };
  container.appendChild(input);
  container.appendChild(exec);
  container.appendChild(console);
  document.body.insertAdjacentElement('afterbegin', container);
})();

然后刷新浏览器就可以看到一个输入框和执行按钮,可以直接运行一些简单的代码并获取结果。

比如遇到加密字符串的时候,直接复制过来就能看到解密后的文字了:

5.png

随后观察 Charles 抓包到的内容,可以发现这么一则请求:

POST https://api.zzzmh.cn/bz/v3/getData
{
  "size": 23,
  "current": 0,
  "sort": 0,
  "category": 0,
  "resolution": 0,
  "color": 0,
  "categoryId": 0
}

{
  "msg": "success",
  "result": "ak+...省略...wE=",
  "code": 0,
  "ts": 123456789
}

感觉这个是我们要找的回应,所以直接检索 getData 看看能找到什么:

6.png

(VSCode 左侧的第二个图标是全局搜索,搜索到结果后点进去后进行格式化代码处理)

看起来是被 Babel 处理过的代码(async/await 降级),而下面的处理代码却可以直接访问 ["data"]["result"] 对象的成员,怀疑这个接口对返回值进行了处理之后才返回。

“Ctrl-左键” _0x3b1f45 跳转到定义,可以看到很多类似 xxx = yyy("1234") 的代码:

7.png

看起来很像是 Webpack 打包后的 require 调用,分别对他们选中、按下 F2 并更名为 httpLib

8.png

随后进行全局检索关键字 8e44,进入第一个找到的内容:

9.png

看起来第一个函数就是我们想找的,直接改一改变量名看看:

10.png

可以看到又调用了一个叫 ed08 的包,暂命名为 decipherLib,继续重复查找过程…

11.png

找到后下拉可以看到一串像是密钥一样的内容。因为我们知道上图中的关键字 decipher,于是一路折叠这些函数,直到模块底部:

12.png

可以看到导出了一些函数,在这里就可以很方便的更名/查找函数了。

直接改名与左侧的名称相同,然后进去看看:

13.png

稍微看一看这三个函数,感觉第一层的 4e50b7 只是简单的 base64 解码,4d16fb 是编码,而中间的 58af99 则像是对内容进行解密。没有看到其他依赖,直接复制进去并传入抓包得到的返回值进去看看:

14.png

得到结果了,可以试试移植到本地了。

移植

复制粘贴出来,然后进行一点点小清理就能得到类似下述的代码:

decoder.src.7z (3.56 KB, 下载次数: 16)

function decrypt(input) {
  const key = [
    0x91, 0x34, 0x5b, 0x41, 0xbf, 0x74, 0x77, 0x6a, 0x87, 0xae, 0xfb, 0x50,
    0x33, 0x61, 0x44, 0xad, 0x90, 0xcd, 0x17, 0xd2, 0xde, 0x8e, 0xc9, 0xf5,
    0x81, 0x5a, 0x21, 0x16, 0xe1, 0x32, 0xef, 0x14, 0xd4, 0x0f, 0xa2, 0x85,
    0x76, 0xe9, 0xc3, 0x72, 0x47, 0x98, 0x82, 0x8b, 0xaf, 0xca, 0xee, 0x92,
    0xfc, 0xa1, 0xa5, 0x5e, 0xb0, 0xf2, 0x78, 0x69, 0x55, 0x68, 0xaa, 0x94,
    0x43, 0x19, 0x65, 0x6c, 0x10, 0x97, 0x6f, 0xf6, 0x75, 0xb7, 0x4d, 0x59,
    0xe3, 0x9e, 0xbc, 0x70, 0x6b, 0xff, 0x56, 0x79, 0x58, 0x9b, 0x84, 0x45,
    0xe2, 0xf8, 0x8f, 0xb6, 0x8a, 0x39, 0xe7, 0x0c, 0x8d, 0x96, 0x5f, 0x7f,
    0x54, 0x7c, 0x9a, 0xe4, 0x49, 0x2b, 0xc4, 0x1c, 0x2e, 0x73, 0x1e, 0x7a,
    0xb5, 0x7d, 0xbd, 0xb3, 0x03, 0xf9, 0xcb, 0xf3, 0x35, 0x4e, 0xb8, 0x01,
    0x0b, 0xb9, 0xd9, 0xb1, 0xfd, 0x13, 0x29, 0x7e, 0xd5, 0x83, 0xe5, 0x22,
    0x3f, 0x08, 0x48, 0xdd, 0xd7, 0xc1, 0x3c, 0xe8, 0x66, 0x2f, 0x89, 0x99,
    0xea, 0x2d, 0x3b, 0x40, 0xa0, 0x31, 0x53, 0x95, 0x88, 0xc7, 0xba, 0x00,
    0xda, 0xac, 0xd8, 0x18, 0x0e, 0x30, 0x1d, 0x2c, 0xdc, 0xd1, 0x38, 0xa4,
    0x26, 0x25, 0x04, 0xce, 0x67, 0x0a, 0xa7, 0x37, 0x71, 0xe6, 0x6e, 0x36,
    0x24, 0xec, 0xb2, 0xf4, 0x8c, 0x46, 0xdb, 0x05, 0xc2, 0xb4, 0xd0, 0xc0,
    0x4f, 0x64, 0x28, 0x06, 0xc6, 0xa6, 0xed, 0xf7, 0x27, 0x5d, 0x9d, 0x15,
    0x07, 0x1a, 0xfe, 0x1b, 0xd3, 0x51, 0x3a, 0x86, 0x4c, 0xbe, 0x02, 0x5c,
    0xd6, 0x62, 0xf0, 0x09, 0x3d, 0x3e, 0xf1, 0x63, 0xeb, 0x1f, 0xc8, 0x57,
    0x11, 0xcc, 0xbb, 0xdf, 0xc5, 0xab, 0x42, 0x4a, 0x12, 0xa3, 0x80, 0xa9,
    0xe0, 0x2a, 0x20, 0xa8, 0x6d, 0x60, 0x0d, 0xfa, 0x4b, 0x9c, 0xcf, 0x23,
    0x9f, 0x52, 0x93, 0x7b
  ];
  let idxA = 0;
  let idxB = 0;
  let result = [];
  for (let i = 0; i < input.length; i++) {
    idxA = (idxA + 0x1) & 0xff;
    idxB = (key[idxA] + idxB) & 0xff;

    let tmp = key[idxA];
    key[idxA] = key[idxB];
    key[idxB] = tmp;

    const realKeyIdx = (key[idxA] + key[idxB]) & 0xff;
    result.push(input[i] ^ key[realKeyIdx]);
  }
  return result;
}
function fromUTF8Array(input) {
  return Buffer.from(input).toString("utf-8");
}

function b64Decode(input) {
  return new Int8Array(Buffer.from(input, "base64"));
}
function decipherFn(_0x37db15) {
  return fromUTF8Array(decrypt(b64Decode(_0x37db15)));
}

module.exports = {
  decipherFn,
};

另外这个 decrypt 函数看起来像是预先初始化密钥盒的 rc4,具体就不知道了。

注意:使用到的 Buffer 为 node.js 平台专有 API,浏览器无法正常执行。

如果需要移植到 python,直接拿这个代码改改就好。

拼接链接

这个直接正常点击下载然后观察解密后数据与下载链接的关系即可。

如果你还是想知道怎么生成的话,参考下述整理好的代码:

var urlBase = "https://doge.zzzmh.cn";

function getUrl(imageId, isPng, imgType) {
  var end = "";
  if (0x0 == imgType) {
    end = "/thumbs";
  } else if (0x1 == imgType) {
    end = "/fhd";
  } else if (0x2 == imgType) {
    end = "?response-content-disposition=attachment";
  }

  const ext = isPng ? ".png" : ".jpg";
  return urlBase + "/wallpaper/origin/" + imageId + ext + end;
}

后记

现在对抗 devtools 的工具已经越来越多了…

本次实验基本上是绕过了 devtools(更改代码与注入一个 “简陋” devtools 到页面进行调试)。

实际研究的时候走了一些弯路,包括尝试干掉反调试;不知道是 devtools 的问题还是网页做了一些检测,一开就占满 CPU 与内存。

最后:仅供学习交流之用,勿做商业用途。

免费评分

参与人数 65威望 +2 吾爱币 +152 热心值 +55 收起 理由
momoxi + 1 热心回复!
zhixiangwangluo + 1 + 1 谢谢@Thanks!
luyers + 1 谢谢@Thanks!
panda123cry + 1 + 1 我很赞同!
a5112725 + 1 + 1 我很赞同!
derstiga + 1 + 1 我很赞同!
T626 + 1 + 1 用心讨论,共获提升!
8848klm + 1 + 1 谢谢@Thanks!
wkiwi + 1 + 1 我很赞同!
swts + 1 + 1 谢谢@Thanks!
第三世界 + 1 热心回复!
封尘OL + 1 + 1 用心讨论,共获提升!
b13362384989 + 1 + 1 用心讨论,共获提升!
空若野 + 1 + 1 牛批拉克丝,学习了。
zhenkaixin852 + 1 + 1 谢谢@Thanks!
lighterleon + 1 谢谢@Thanks!
JinxBoy + 1 用心讨论,共获提升!
qi032 + 1 + 1 我很赞同!
lyslxx + 1 + 1 我很赞同!
hy8051hy + 1 谢谢@Thanks!
观弈山人 + 1 谢谢@Thanks!
onething + 1 + 1 热心回复!
fuso + 1 + 1 我很赞同!
Fly51700 + 1 + 1 我很赞同!
yuyi0 + 1 + 1 用心讨论,共获提升!
经典柚子 + 1 + 1 我很赞同!
chandel + 1 + 1 我很赞同!
danguanai + 1 + 1 我很赞同!
submarine1620 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
tonyiyong + 1 + 1 我很赞同!
和马 + 1 + 1 我很赞同!
cncqw + 1 我很赞同!
zhelinali + 1 + 1 谢谢@Thanks!
javahaonan + 1 + 1 谢谢@Thanks!
5omggx + 1 用心讨论,共获提升!
zzzbbbccc + 1 用心讨论,共获提升!
jhlee0133 + 1 + 1 我很赞同!
ZHHua + 1 + 1 我很赞同!
kxkxy5505 + 1 + 1 我很赞同!
森林生灵 + 1 + 1 这个似乎跟wps壁纸有着异曲同工之妙
seeyoubug + 1 + 1 热心回复!
xf199320 + 1 + 1 感谢
gpb123q + 1 学习了
Hmily + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
sirilee + 1 我很赞同!
朝闻道夕死可矣 + 1 我很赞同!
rbBuff + 1 我很赞同!
ZiZ6bvD9H + 1 + 1 谢谢@Thanks!
chenyang33207 + 1 + 1 谢谢@Thanks!
LeeCocoR + 1 + 1 谢谢@Thanks!
QIFENGYUXI + 1 + 1 用心讨论,共获提升!
Realtan + 1 用心讨论,共获提升!
zhaozhao1 + 1 + 1 谢谢@Thanks!
-yuy- + 1 + 1 用心讨论,共获提升!
216288461 + 1 热心回复!
korisy + 1 + 1 用心讨论,共获提升!
玩的时候 + 1 + 1 热心回复!
gba626 + 1 我很赞同!
wxc941112 + 1 用心讨论,共获提升!
aaa179888 + 1 热心回复!
thinkpad_420 + 1 + 1 我很赞同!
Bizhi-1024 + 1 用心讨论,共获提升!
lgc81034 + 1 我很赞同!
GuiXiaoQi + 1 我很赞同!
冰棍好烫啊 + 2 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

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

逍遥一仙 发表于 2021-7-26 13:11
本帖最后由 逍遥一仙 于 2021-7-26 14:13 编辑

已翻译为易语言,仅供参考(base64解码使用E2EE支持库){:301_997:}
另,这种加密叫ob混淆,反混淆的话,可以论坛搜索ast




.版本 2
.支持库 e2ee

.子程序 解码, 文本型
.参数 内容, 文本型
.局部变量 key, 字节集
.局部变量 idxA, 整数型
.局部变量 idxB, 整数型
.局部变量 i, 整数型
.局部变量 temp, 整数型
.局部变量 real, 整数型
.局部变量 out, 字节集

key = { 145, 52, 91, 65, 191, 116, 119, 106, 135, 174, 251, 80, 51, 97, 68, 173, 144, 205, 23, 210, 222, 142, 201, 245, 129, 90, 33, 22, 225, 50, 239, 20, 212, 15, 162, 133, 118, 233, 195, 114, 71, 152, 130, 139, 175, 202, 238, 146, 252, 161, 165, 94, 176, 242, 120, 105, 85, 104, 170, 148, 67, 25, 101, 108, 16, 151, 111, 246, 117, 183, 77, 89, 227, 158, 188, 112, 107, 255, 86, 121, 88, 155, 132, 69, 226, 248, 143, 182, 138, 57, 231, 12, 141, 150, 95, 127, 84, 124, 154, 228, 73, 43, 196, 28, 46, 115, 30, 122, 181, 125, 189, 179, 3, 249, 203, 243, 53, 78, 184, 1, 11, 185, 217, 177, 253, 19, 41, 126, 213, 131, 229, 34, 63, 8, 72, 221, 215, 193, 60, 232, 102, 47, 137, 153, 234, 45, 59, 64, 160, 49, 83, 149, 136, 199, 186, 0, 218, 172, 216, 24, 14, 48, 29, 44, 220, 209, 56, 164, 38, 37, 4, 206, 103, 10, 167, 55, 113, 230, 110, 54, 36, 236, 178, 244, 140, 70, 219, 5, 194, 180, 208, 192, 79, 100, 40, 6, 198, 166, 237, 247, 39, 93, 157, 21, 7, 26, 254, 27, 211, 81, 58, 134, 76, 190, 2, 92, 214, 98, 240, 9, 61, 62, 241, 99, 235, 31, 200, 87, 17, 204, 187, 223, 197, 171, 66, 74, 18, 163, 128, 169, 224, 42, 32, 168, 109, 96, 13, 250, 75, 156, 207, 35, 159, 82, 147, 123 }
连续赋值 (0, idxA, idxB)
out = Base64解码 (#常量1, , )
.计次循环首 (取字节集长度 (out), i)
    idxA = 位与 (idxA + 1, 255)
    idxB = 位与 (key [idxA + 1] + idxB, 255)
    temp = key [idxA + 1]
    key [idxA + 1] = key [idxB + 1]
    key [idxB + 1] = temp
    real = 位与 (key [idxA + 1] + key [idxB + 1], 255)
    out [i] = 位异或 (out [i], key [real + 1])
.计次循环尾 ()
返回 (到文本 (out))

点评

虽然跳过了 UTF-8 转文本过程,但 JSON 也不太可能会有非 ANSI 范围内容… 应该也没啥大问题 这个加密感觉很多网站都有类似的实现,以前日过 AST 树,但是通用性不太好,写起来麻烦。 直接带着混淆日也没啥大  详情 回复 发表于 2021-7-26 20:36

免费评分

参与人数 4吾爱币 +5 热心值 +3 收起 理由
fengbolee + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
爱飞的猫 + 1 + 1 跳过了 UTF-8 转文本过程,但 JSON 也不太可能会有非 ANSI 范围内容… 应该.
hnwang + 1 + 1 我很赞同!
ofo + 1 参考下大佬的易写方式

查看全部评分

不负韶华 发表于 2021-7-26 06:46
头像被屏蔽
Wits 发表于 2021-7-26 08:04
x800600 发表于 2021-7-26 08:08
楼主能力很强,值的我们去收藏
Alexxxu 发表于 2021-7-26 08:13
感谢分享,认真进修进修,提高自己的能力
aroundoft 发表于 2021-7-26 08:29
感谢大佬分享
GuiXiaoQi 发表于 2021-7-26 08:31
大佬就是大佬
caidesi520 发表于 2021-7-26 08:37
感谢分享,认真进修进修,提高自己的能力
laishiming 发表于 2021-7-26 08:42

感谢分享,认真进修进修,提高自己的能力
Nantree 发表于 2021-7-26 08:43
emmmm这个可以收藏一波。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2024-4-20 13:13

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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