?声明:
????????本文章中所有内容仅供学习交流使用,不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!若有侵权,请添加(wx:wyqlxl99)联系删除
????????本文章同步微信公众号文章:
https://mp.weixin.qq.com/s?mid=2247483673&idx=1&sn=0b4b14bcf8151a061a27a300b60ddfdf&__biz=MzkzODYzNjg4OA==
前言:
????????前段时间js盾横空出世可谓是难倒了一批又一批的spider,整体结构就是vmp+动态生成的js代码其中恶心的就是反着读的字符以及特殊\u2028行分隔符,今天就来讲如何利用最简单的hook搞定这些恶心的东西
目标网址:aHR0cHM6Ly93d3cuYmF5dWVndWEuY29tLyMv
目标接口:api/user/user/login
目标参数:payload
????????可以看到是请求体加密
????????我们跟栈看看,可以看到进入了这么一个文件。这tm是什么东西?对这就是js盾可以看到里面的代码不是那种有层级可以调试的代码以及肉眼可见的debugger关键词还有一些奇奇怪怪的东西
????????这是什么情况不都是从左到右的么为什么这个是这样返回来的?然后我们发现多了一个??? 符号。重点就是这个符号读的顺序变成从右到左??那这个不就是不符合我们正常一个读代码的习惯了么?
????????我们可以看到还有这些肉眼可见的编码,为了让代码更好看我们也需要进行处理
????????我们下script断点一直断到加载的入口可以看到是一个eval然后里面是一个自执行函数?我们将里面的自执行函数执行完看看返回值是啥
????????我们下个eval hook可以看到自执行函数返回的这段字符串不就是最开始最上面我们调试的那一段很恶心的js吗?
????????那既然他是通过eval执行字符串,那是不是可以在eval执行之前hook到这个字符串并且修改里面字符串的内容然后执行去掉????的字符串以及替换\u的编码 还有遍布控制流中的debugger关键词呢?
????????说干就干 我们先将????进行替换 这边我是替换成下划线因为都是数字不能直接把这个字符为空,接着就是处理debugger关键词 同理我们直接替换成空,还有\u的编码同理我们也进行替换
# 替换代码如下
dict={'\\u0020':' ','\\u0021':'!','\\u0023':'#','\\u0024':'$','\\u0025':'%','\\u0026':'$','\\u0028':'(','\\u0029':')','\\u002a':'*','\\u002b':'+','\\u002c':',','\\u002d':'-','\\u002e':'.','\\u002f':'/','\\u0030':'0','\\u0031':'1','\\u0032':'2','\\u0033':'3','\\u0034':'4','\\u0035':'5','\\u0036':'6','\\u0037':'7','\\u0038':'8','\\u0039':'9','\\u003a':':','\\u003b':';','\\u003c':'<','\\u003d':'=','\\u003e':'>','\\u003f':'?','\\u0040':'@','\\u0041':'A','\\u0042':'B','\\u0043':'C','\\u0044':'D','\\u0045':'E','\\u0046':'F','\\u0047':'G','\\u0048':'H','\\u0049':'I','\\u004a':'J','\\u004b':'K','\\u004c':'L','\\u004d':'M','\\u004e':'N','\\u004f':'O','\\u0050':'P','\\u0051':'Q','\\u0052':'R','\\u0053':'S','\\u0054':'T','\\u0055':'U','\\u0056':'V','\\u0057':'W','\\u0058':'X','\\u0059':'Y','\\u005a':'Z','\\u005b':'[','\\u005d':']','\\u005e':'^','\\u005f':'_','\\u0061':'a','\\u0062':'b','\\u0063':'c','\\u0064':'d','\\u0065':'e','\\u0066':'f','\\u0067':'g','\\u0068':'h','\\u0069':'i','\\u006a':'j','\\u006b':'k','\\u006c':'l','\\u006d':'m','\\u006e':'n','\\u006f':'o','\\u0070':'p','\\u0071':'q','\\u0072':'r','\\u0073':'s','\\u0074':'t','\\u0075':'u','\\u0076':'v','\\u0077':'w','\\u0078':'x','\\u0079':'y','\\u007a':'z','\\u007b':'{','\\u007c':'|','\\u007d':'}','\\u007e':'~',}
_eval = eval;
eval = function(val){
val = val.replace(/?/g, "_");
val = val.replace(/debugger;/g, "");
for (key of Object.keys(dict)){
val = val.replaceAll(key,dict[key])
};
return _eval(val);
};
????????替换完成之后效果如下,可以看到\u的编码已经替换以及??? 也替换成了下划线,debugger关键词也没了,但是发现一个问题就算是这样我们也没办法调试啊还是一条一条的
????????那么造成这个问题的原因是什么呢,那就是我文章一开始所说\u2028这个行分隔符,正常情况下他会被浏览器解释然后进行 行分割就会变成我们如图所示还是没有层级的情况,那同理我们直接替换了不就不换行了?
# 替换代码如下
dict={'\\u0020':' ','\\u0021':'!','\\u0023':'#','\\u0024':'$','\\u0025':'%','\\u0026':'$','\\u0028':'(','\\u0029':')','\\u002a':'*','\\u002b':'+','\\u002c':',','\\u002d':'-','\\u002e':'.','\\u002f':'/','\\u0030':'0','\\u0031':'1','\\u0032':'2','\\u0033':'3','\\u0034':'4','\\u0035':'5','\\u0036':'6','\\u0037':'7','\\u0038':'8','\\u0039':'9','\\u003a':':','\\u003b':';','\\u003c':'<','\\u003d':'=','\\u003e':'>','\\u003f':'?','\\u0040':'@','\\u0041':'A','\\u0042':'B','\\u0043':'C','\\u0044':'D','\\u0045':'E','\\u0046':'F','\\u0047':'G','\\u0048':'H','\\u0049':'I','\\u004a':'J','\\u004b':'K','\\u004c':'L','\\u004d':'M','\\u004e':'N','\\u004f':'O','\\u0050':'P','\\u0051':'Q','\\u0052':'R','\\u0053':'S','\\u0054':'T','\\u0055':'U','\\u0056':'V','\\u0057':'W','\\u0058':'X','\\u0059':'Y','\\u005a':'Z','\\u005b':'[','\\u005d':']','\\u005e':'^','\\u005f':'_','\\u0061':'a','\\u0062':'b','\\u0063':'c','\\u0064':'d','\\u0065':'e','\\u0066':'f','\\u0067':'g','\\u0068':'h','\\u0069':'i','\\u006a':'j','\\u006b':'k','\\u006c':'l','\\u006d':'m','\\u006e':'n','\\u006f':'o','\\u0070':'p','\\u0071':'q','\\u0072':'r','\\u0073':'s','\\u0074':'t','\\u0075':'u','\\u0076':'v','\\u0077':'w','\\u0078':'x','\\u0079':'y','\\u007a':'z','\\u007b':'{','\\u007c':'|','\\u007d':'}','\\u007e':'~',}
_eval = eval;
eval = function(val){
val = val.replace(/?/g, "_");
val = val.replace(/debugger;/g, "");
val = val.replaceAll(String.fromCharCode(8232),'\\u2028')
for (key of Object.keys(dict)){
val = val.replaceAll(key,dict[key])
};
return _eval(val);
};
????????我们再进行替换之后发现代码层级出现了,现在就可以调试了
????????我们直接搜payload关键词并且打上断点,在登入界面点击登入,一眼就可以看到加密的明文以及加密的密文,接下来我们只需要把他加密的部分扣下来或者找一个标准的xxtea算法改一下
????????????????????????????????????????????????本地测试传参一致 加密值一致!
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 接口测试登入接口和查询接口校验通过!
?????????????????????????????????????????如果这篇文章帮助到你,不妨点个喜欢加关注!