某安全设备前端加解密爆破案例

VSole2023-08-09 15:30:04

某天,我大哥让我帮忙弄个设备的网页爆破脚本,说是前端加密了,算法看不懂是啥

于是打开网页瞅瞅(不贴登录界面图了,省的得罪人)

先查看网页源代码

一个简单的form表单,126行仅一个submit按钮,91行form也没有额外的提交事件

F12打开控制台,看看提交按钮的监听事件

有一个submit事件,点击链接跳转到login.js

又调用了evtMainAuth()函数,Ctrl+F搜索login.js中的evtMainAuth

265266行maUsermaPass进行了处理,来看下这两个对象是如何定义的

第7行定义了变量

132133行进行了赋值,返回的是name值为ap的input框,就是登录页面的用户名和密码框

再来看加密函数

用户名仅做了去空字符处理,密码使用了$.fn.en进行处理,当前页面没有找到这个函数的定义,直接在266行打断点,然后登录一次

然后点击控制台右侧的进入函数内部(或者直接F11)

先是进入了Jqueryval()函数,这个不管

然后来到了jquery.plugin.js

找到了fn.en的定义

d.fn.en = function (a) {    f = l();    return 0 >= this.length && "string" === d.type(a) ? 0 >= a.length ? "" : h(a) : this.each(function () {        var b = d(this), a = b.val(), c;        0 >= a.length || (c = b.data("v"),        "string" === d.type(c) && 0 < c.length && (b.val(c),            b.removeData("v")),            c = h(a),            b.val(c),            b.data("v", a),            b.one("input propertychange", k))    })}

其中的函数l()

function l() {    for (var a = 0; 0 >= a || 255 <= a;)        a = Math.floor(255 * Math.random());    return a}

函数h()

function g(a) {    var b = "";    16 > a && (b = "0");    return b + a.toString(16)}function h(a) {    for (var b = [g(f)], e, c = 0, d = a.length; c < d; ++c)        e = a.charCodeAt(c),            255 >= e ? b.push(g(e ^ f)) : (b.push(g(Math.floor(e / 256) ^ f)),                b.push(g(e % 256 ^ f)));    return b.join("").toUpperCase()}

开始分析加密算法

先看fn.en函数

第1行l()函数的返回值赋值给定义的变量f

l()函数代码如下

  • Math.random()是返回一个0<= number <1的随机数
  • Math.floor()是返回小于等于给定数字的最大整数

也就是说,l()返回了一个0<= number < 255的随机数

接着看fn.en,接下来是一个return语句,但用到了三目运算,为了方便阅读,这里将代码进行格式化

this.length为0且a的变量类型为string时,返回8~16行的三目运算结果,否则,返回20~29行的函数

这里在控制台看一下

  • this在函数中为函数所属的对象,就是fn,过程中并没有见到对fnlength进行修改,所以恒为0
  • a是传入的密码,肯定为string类型

故返回值为8~16行的三目运算结果

再来看8~16行的表达式

a(传入的密码)长度为0时,返回空字符串,否则返回h(a)的结果

h()就是加密的具体函数了,分析一下h()函数

先看循环的步数,起始是c=0,结束条件是c<d(a.length),每步步长是++c

也就是对a字符串进行遍历

b的初始值是[g(f)],看看g()函数

  • a小于16时,返回的是0+a的16进制字符串,例如a=13,返回的是”0d”
  • a大于等于16时,返回的是a的16进制字符串,例如a=18,返回的是”12”

g函数也就是将10进制转换为16进制字符串

数组b的初始值也就是[f的16进制字符串],f取值范围是0<=f<255,也就是初始值为”00”至”ff”

e变量每步会执行e = a.charCodeAt(c),也就是遍历获取a字符串的每个字符的ASCII值

然后进行一个三目运算,e<=255时,b数组添加g(e^f),否则添加g(Math.floor((e/256)^f)

X^Y,是按位异或,每一个对应的位,两个不相同返回1,相同则返回0

例如


200^255200    =1100 1000255    =1111 1111结果  =0011 0111十进制  =55
55^10055    =0011 0111100    =0110 0100结果  =0101 0011十进制  =83

再回到e,当e>255的时候,就超出了ASCII的范围,属于UNICODE字符串了,先e/256再去按位异或f,再向b添加e对256取余后和f的按位异或结果

e<=255,在ASCII时(a-zA-Z0-9特殊符号都在其中了),仅需正常返回g(e^f)即可

所以算法流程如图

搞清楚算法后,开始编写加密及解密脚本

对了,还有个数学知识,a^b=c,那么c^b=a

加密脚本

#!/usr/env python# author Waximport randomimport sys
def getKey():    return int(255 * random.random())
def octToHexStr(number):    if number < 16:        return '0' + str(hex(number))[2:]
    return str(hex(number))[2:]
def en(data, key):    enData = ""    if data == "":        return enData
    if key == '':        key = getKey()
    enData += octToHexStr(key)
    for chr in data:        e = ord(chr)        if e <= 255:            enData += octToHexStr(e^key)        else:            enData += octToHexStr(int(e/256) ^ key)            enData += octToHexStr(e % 256 ^ key)
    return enData.upper()
if __name__ == '__main__':    if len(sys.argv) > 1 and len(sys.argv) <=3:        data = sys.argv[1].strip()        key = ''        if sys.argv[2]:            key = int(sys.argv[2])
        print('data:'+data)        print('key :'+str(key))        print(en(data, key))    else:        print('usage:')        print('\tpython encrypt.py data')        print('\tpython encrypt.py data key_oct')

解密脚本


#!/usr/env python# author Waximport sys
def de(enData):    key = HexStrToOct(enData[0:2])    enData = enData[2:]    data = ""
    while len(enData)/2 > 0:        chrHexStr = enData[0:2]        data += chr(HexStrToOct(chrHexStr)^key)        enData = enData[2:]
    return data
def HexStrToOct(hexStr):    return int.from_bytes(bytes.fromhex(hexStr))
if __name__ == '__main__':    if len(sys.argv) == 2:        enData = sys.argv[1]        print(de(enData))    else:        print('usage:')        print('\tpython decrypt.py data')

测试一下,先登录一次,密码输入的是12345

加密结果是8DBCBFBEB9B8

前两位8D就是生成的随机数,十进制是141

测试加解密脚本

datakey
本作品采用《CC 协议》,转载必须注明作者和本文链接
目前nacos越来越广泛,大多数的企业在使用微服务架构的时候,基本上都会选择nacos作为注册中心和配置中心。
函数h()是function g { var b = ""; 16 > a && ; return b + a.toString}function h { for e = a.charCodeAt, 255 >= e ?55^10055 =0011 0111100 =0110 0100结果 =0101 0011十进制 =83. def octToHexStr: if number < 16: return '0' + str[2:]. for chr in data: e = ord if e <= 255: enData += octToHexStr else: enData += octToHexStr
mimikatz的这个功能从本质上是解析Windows的数据库文件,从而获取其中存储的用户哈希。
Cuckoo沙箱将在几秒钟内为您提供一些详细的分析结果,概述该文件在隔离环境中执行时的情况。在2010年夏天开启该工作之后,第一个测试版于2011年2月5日发布,这是Cuckoo第一次公开发布。2011年3月,在谷歌Code Summer of 2011期间,Cuckoo再次被选为蜜网项目的支持项目,在此期间Dario Fernandes加入了该项目并扩展了其功能。恶意软件在执行过程中创建、删除和下载的文件。
该漏洞是CGI脚本在处理authentication.cgi请求,来读取POST参数中的"password"参数的值时造成的缓冲区溢出。
前言 明天就是大年初一,很多电影也上映,看电影前很多人都喜欢去『豆瓣』看影评,所以我爬取44130条『豆瓣』的用户观影数据,分析用户之间的关系,电影之间的联系,以及用户和电影之间的隐藏关系。 爬取观影数据 数...
冰蝎流量免杀初探
2022-12-20 09:11:06
本文仅针对冰蝎流量改造进行初步探讨,熟悉一下整个流程,真的要绕流量设备,估计还需要其他的技巧。
下面所讲的大部分操作是基于拿到华为云用户泄漏的AK、SK或者凭证而进行的一系列操作。0x01 初始访问 1、元数据 华为云元数据地址:http://169.254.169.254,需要注意直接访问是看不到openstack目录的,下面列举几个常见的目录:
js逆向一直没有相关了解,虽然目前渗透遇见的不是很多,大多数遇见的要么不加密,要么无法实现其加密流程,不过最近看到了一个较为简单的站点正好能够逆向出来,就做了简单记录。本文旨在介绍js逆向的一些基础思路,希望能对初学js前端逆向的师傅有所帮助。
定位把整个apk拖入jadx-gui后,初始化检索之后可以直接通过网址进行定位。!看到此处,它判断的这3个URL接口名称,恰是支付的,估计是它排除掉不是它的接口。结果就是,该HOOK代码并没有触发,也就是并没有执行到此处,但是我们发现当前class处几乎每个函数都是加密相关,我对他们进行了逐一HOOK,最终发现encypt函数有了反应。
VSole
网络安全专家