JS逆向 | 原来,大家对于atob和btoa都有误解?不止base64这么简单!

声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢!

引言

 故事是这样的,有位读者朋友需要模拟登录一个网站:
 aHR0cDovL3d3dy56bGRzai5jb20v

 我进去一看,很简单啊,不就是RSA加密么?
在这里插入图片描述
 一顿操作猛如虎,把涉及RSA的全部扣下来,然后用Python的base64.b64encode代替 btoa 函数调用即可(由于这里的RSA加密为NoPadding模式,因此对相同明文加密返回的密文都是相同的。RSA的具体相关不在本文讨论范围之内,后面会再出详细教程),结果对比如下:
在这里插入图片描述
 嗯?为什么结果不一样?检查过代码,确定并没有检查浏览器环境啥的,翻车了…
 恰在这时候,又一位读者问了我一个问题,为啥下面这两个也会不一样?有兴趣的可以自行试一下:

"IcORUmfDlcOPDsOSwr06fMKgBMKcTQ=="

在这里插入图片描述
 难道JS的 atob 和 btoa,不等于Python的base64中的 b64decode 和 b64encode 么?

原理分析

 想直接看答案的可以跳过此部分。

 btoa和atob是window对象的两个函数,其中btoa是binary to ASCII,用于将binary的数据用ASCII码表示,即Base64的编码过程,而atob则是ASCII to binary,用于将ASCII码解析成binary数据,即Base64的解码过程[1]

 ASCII码大家基本都知道,这里讲下binary是什么。

 binary 是JS字符集的另外一个子集,它类似于 ASCII 字符集,但是字符的码点(charCode)不再限制到 127, 它包含了255 以内的字符。binary string设计的目的不是用于代表字符, 而是代表二进制数据。由 binary string 代表的二进制数据大小是原始数据的两倍,然而这对于最终用户是不可见的, 因为JavaScript strings 的长度是以2字节为单位进行计算的。比如, “Hello world” 这个字符串属于 ASCII 子集, 而 ÀÈÌÒÙ 不属于ASCII码[2],但属于binary。

 所以btoa和atob其实还涉及了编码问题,我们只需要找出相同编码进行替换即可。在node.js环境中,提供了一个 Buffer 类,用于操作二进制及Base64转码。而在Python环境中,有一个 Latin1 编码[3]与JS的binary相同,因此可以构造代码了。

代码实现

一、node.js环境

 1.直接安装btoa-atob库(不推荐)

 2.通过Buffer类实现转换

// atob
var s = new Buffer.from("待解码的字符", "base64").toString("binary")
// btoa
var s = new Buffer.from("待编码的字符", "binary").toString("base64")

二、Python环境

 通过Latin1编码进行转换

import base64
# atob
s = base64.b64decode("待解码的字符".encode("utf8")).decode("latin1")
# btoa
s = base64.b64encode("待编码的字符".encode("latin1")).decode("utf8")

三、成果展示

在这里插入图片描述
在这里插入图片描述

参考资料

[1] https://my.oschina.net/itblog/blog/1613977
[2] https://developer.mozilla.org/zh-CN/docs/Web/API/DOMString/Binary
[3] https://baike.baidu.com/item/latin1/1183590?fr=aladdin

 欢迎关注我的公众号“逆向新手”,逆向系列将持续更新!
在这里插入图片描述

发布了3 篇原创文章 · 获赞 3 · 访问量 39

猜你喜欢

转载自blog.csdn.net/weixin_45216614/article/details/103946626