当前位置: 首页 > news >正文

base64魔改算法 | jsvmp日志分析并还原

前言

上一篇我们讲了标准 base64 算法还原,为了进一步学习 base64 算法特点,本文将结合 jsvmp 日志,实战还原出 base64 魔改算法。

为了方便大家学习,我将入参和上篇文章一样,入参为 Hello, World!

插桩

在js代码中,找到 运算符 位置以及 apply 插桩点,结合插桩日志框架,代码插桩如下:

jsvmp源码:https://t.zsxq.com/B5aRh

base64魔改算法 | jsvmp日志分析并还原

日志分析

代码执行后,日志如下:

1:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 0 ] 结果: 722:  函数: [Function: push] 调用者: [ 72 ] 参数: [ 72 ] 结果: 13:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 1 ] 结果: 1014:  函数: [Function: push] 调用者: [ 72, 101 ] 参数: [ 101 ] 结果: 25:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 2 ] 结果: 1086:  函数: [Function: push] 调用者: [ 72, 101, 108 ] 参数: [ 108 ] 结果: 37:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 3 ] 结果: 1088:  函数: [Function: push] 调用者: [ 72, 101, 108, 108 ] 参数: [ 108 ] 结果: 49:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 4 ] 结果: 11110:  函数: [Function: push] 调用者: [ 72, 101, 108, 108, 111 ] 参数: [ 111 ] 结果: 511:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 5 ] 结果: 4412:  函数: [Function: push] 调用者: [ 72, 101, 108, 108, 111, 44 ] 参数: [ 44 ] 结果: 613:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 6 ] 结果: 3214:  函数: [Function: push] 调用者: [72, 101, 108, 108,111,  44,  32
] 参数: [ 32 ] 结果: 715:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 7 ] 结果: 8716:  函数: [Function: push] 调用者: [72, 101, 108, 108,111,  44,  32,  87
] 参数: [ 87 ] 结果: 817:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 8 ] 结果: 11118:  函数: [Function: push] 调用者: [72, 101, 108, 108,111,  44,  32,  87,111
] 参数: [ 111 ] 结果: 919:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 9 ] 结果: 11420:  函数: [Function: push] 调用者: [72, 101, 108, 108,111,  44,  32,  87,111, 114
] 参数: [ 114 ] 结果: 1021:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 10 ] 结果: 10822:  函数: [Function: push] 调用者: [72, 101, 108, 108,111,  44,  32,  87,111, 114, 108
] 参数: [ 108 ] 结果: 1123:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 11 ] 结果: 10024:  函数: [Function: push] 调用者: [72, 101, 108, 108, 111,44,  32,  87, 111, 114,108, 100
] 参数: [ 100 ] 结果: 1225:  函数: [Function: charCodeAt] 调用者: Hello, World! 参数: [ 12 ] 结果: 3326:  函数: [Function: push] 调用者: [72, 101, 108, 108, 111,44,  32,  87, 111, 114,108, 100,  33
] 参数: [ 33 ] 结果: 1327:  0 + 3 ====> 328:  函数: [Function: slice] 调用者: [72, 101, 108, 108, 111,44,  32,  87, 111, 114,108, 100,  33
] 参数: [ 0, 3 ] 结果: [ 72, 101, 108 ]29:  函数: [Function: slice] 调用者: [ 72, 101, 108 ] 参数: [] 结果: [ 72, 101, 108 ]30:  3 - 3 ====> 031:  72 & 255 ====> 7232:  101 & 255 ====> 10133:  108 & 255 ====> 10834:  72 << 16 ====> 471859235:  101 << 8 ====> 2585636:  4718592 | 25856 ====> 474444837:  4744448 | 108 ====> 474455638:  4744556 >> 18 ====> 1839:  18 & 63 ====> 1840:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 18 ] 结果: w
第 41:  4744556 >> 12 ====> 115842:  1158 & 63 ====> 643:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 6 ] 结果: 444:  4744556 >> 6 ====> 7413345:  74133 & 63 ====> 2146:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 21 ] 结果: X47:  4744556 & 63 ====> 4448:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 44 ] 结果: u
第 49:  函数: [Function: apply] 调用者: [Function: t4] 参数: [ null, [ 72, 101, 108 ] ] 结果: [ 'w', '4', 'X', 'u' ]50:   + w ====> w
第 51:  w + 4 ====> w4
第 52:  w4 + X ====> w4X
第 53:  w4X + u ====> w4Xu
第 54:  0 + 3 ====> 355:  3 + 3 ====> 656:  函数: [Function: slice] 调用者: [72, 101, 108, 108, 111,44,  32,  87, 111, 114,108, 100,  33
] 参数: [ 3, 6 ] 结果: [ 108, 111, 44 ]57:  函数: [Function: slice] 调用者: [ 108, 111, 44 ] 参数: [] 结果: [ 108, 111, 44 ]58:  3 - 3 ====> 059:  108 & 255 ====> 10860:  111 & 255 ====> 11161:  44 & 255 ====> 4462:  108 << 16 ====> 707788863:  111 << 8 ====> 2841664:  7077888 | 28416 ====> 710630465:  7106304 | 44 ====> 710634866:  7106348 >> 18 ====> 2767:  27 & 63 ====> 2768:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 27 ] 结果: +69:  7106348 >> 12 ====> 173470:  1734 & 63 ====> 671:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 6 ] 结果: 472:  7106348 >> 6 ====> 11103673:  111036 & 63 ====> 6074:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 60 ] 结果: S75:  7106348 & 63 ====> 4476:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 44 ] 结果: u
第 77:  函数: [Function: apply] 调用者: [Function: t4] 参数: [ null, [ 108, 111, 44 ] ] 结果: [ '+', '4', 'S', 'u' ]78:  w4Xu + + ====> w4Xu+79:  w4Xu+ + 4 ====> w4Xu+480:  w4Xu+4 + S ====> w4Xu+4S
第 81:  w4Xu+4S + u ====> w4Xu+4Su
第 82:  3 + 3 ====> 683:  6 + 3 ====> 984:  函数: [Function: slice] 调用者: [72, 101, 108, 108, 111,44,  32,  87, 111, 114,108, 100,  33
] 参数: [ 6, 9 ] 结果: [ 32, 87, 111 ]85:  函数: [Function: slice] 调用者: [ 32, 87, 111 ] 参数: [] 结果: [ 32, 87, 111 ]86:  3 - 3 ====> 087:  32 & 255 ====> 3288:  87 & 255 ====> 8789:  111 & 255 ====> 11190:  32 << 16 ====> 209715291:  87 << 8 ====> 2227292:  2097152 | 22272 ====> 211942493:  2119424 | 111 ====> 211953594:  2119535 >> 18 ====> 895:  8 & 63 ====> 896:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 8 ] 结果: K97:  2119535 >> 12 ====> 51798:  517 & 63 ====> 599:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 5 ] 结果: h
第 100:  2119535 >> 6 ====> 33117101:  33117 & 63 ====> 29102:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 29 ] 结果: U103:  2119535 & 63 ====> 47104:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 47 ] 结果: F105:  函数: [Function: apply] 调用者: [Function: t4] 参数: [ null, [ 32, 87, 111 ] ] 结果: [ 'K', 'h', 'U', 'F' ]106:  w4Xu+4Su + K ====> w4Xu+4SuK
第 107:  w4Xu+4SuK + h ====> w4Xu+4SuKh
第 108:  w4Xu+4SuKh + U ====> w4Xu+4SuKhU
第 109:  w4Xu+4SuKhU + F ====> w4Xu+4SuKhUF
第 110:  6 + 3 ====> 9111:  9 + 3 ====> 12112:  函数: [Function: slice] 调用者: [72, 101, 108, 108, 111,44,  32,  87, 111, 114,108, 100,  33
] 参数: [ 9, 12 ] 结果: [ 114, 108, 100 ]113:  函数: [Function: slice] 调用者: [ 114, 108, 100 ] 参数: [] 结果: [ 114, 108, 100 ]114:  3 - 3 ====> 0115:  114 & 255 ====> 114116:  108 & 255 ====> 108117:  100 & 255 ====> 100118:  114 << 16 ====> 7471104119:  108 << 8 ====> 27648120:  7471104 | 27648 ====> 7498752121:  7498752 | 100 ====> 7498852122:  7498852 >> 18 ====> 28123:  28 & 63 ====> 28124:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 28 ] 结果: W125:  7498852 >> 12 ====> 1830126:  1830 & 63 ====> 38127:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 38 ] 结果: o
第 128:  7498852 >> 6 ====> 117169129:  117169 & 63 ====> 49130:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 49 ] 结果: J131:  7498852 & 63 ====> 36132:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 36 ] 结果: L133:  函数: [Function: apply] 调用者: [Function: t4] 参数: [ null, [ 114, 108, 100 ] ] 结果: [ 'W', 'o', 'J', 'L' ]134:  w4Xu+4SuKhUF + W ====> w4Xu+4SuKhUFW
第 135:  w4Xu+4SuKhUFW + o ====> w4Xu+4SuKhUFWo
第 136:  w4Xu+4SuKhUFWo + J ====> w4Xu+4SuKhUFWoJ
第 137:  w4Xu+4SuKhUFWoJ + L ====> w4Xu+4SuKhUFWoJL
第 138:  9 + 3 ====> 12139:  12 + 3 ====> 15140:  函数: [Function: slice] 调用者: [72, 101, 108, 108, 111,44,  32,  87, 111, 114,108, 100,  33
] 参数: [ 12, 15 ] 结果: [ 33 ]141:  函数: [Function: slice] 调用者: [ 33 ] 参数: [] 结果: [ 33 ]142:  3 - 1 ====> 2143:  函数: [Function: push] 调用者: [ 33, 0 ] 参数: [ 0 ] 结果: 2144:  3 - 1 ====> 2145:  函数: [Function: push] 调用者: [ 33, 0, 0 ] 参数: [ 0 ] 结果: 3146:  3 - 1 ====> 2147:  33 & 255 ====> 33148:  0 & 255 ====> 0149:  0 & 255 ====> 0150:  33 << 16 ====> 2162688151:  0 << 8 ====> 0152:  2162688 | 0 ====> 2162688153:  2162688 | 0 ====> 2162688154:  2162688 >> 18 ====> 8155:  8 & 63 ====> 8156:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 8 ] 结果: K157:  2162688 >> 12 ====> 528158:  528 & 63 ====> 16159:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 16 ] 结果: f
第 160:  2162688 >> 6 ====> 33792161:  33792 & 63 ====> 0162:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 0 ] 结果: D163:  2162688 & 63 ====> 0164:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 0 ] 结果: D165:  函数: [Function: apply] 调用者: [Function: t4] 参数: [ null, [ 33, 0, 0 ] ] 结果: [ 'K', 'f', 'D', 'D' ]166:  w4Xu+4SuKhUFWoJL + K ====> w4Xu+4SuKhUFWoJLK
第 167:  w4Xu+4SuKhUFWoJLK + f ====> w4Xu+4SuKhUFWoJLKf
第 168:  w4Xu+4SuKhUFWoJLKf + = ====> w4Xu+4SuKhUFWoJLKf=169:  w4Xu+4SuKhUFWoJLKf= + = ====> w4Xu+4SuKhUFWoJLKf==170:  12 + 3 ====> 15171:  函数: [Function: t4] 调用者: Object [global] {'@faceless': <ref *1> Object [global] {global: [Circular *1],queueMicrotask: [Function: queueMicrotask],clearImmediate: [Function: clearImmediate],setImmediate: [Function: setImmediate] {[Symbol(nodejs.util.promisify.custom)]: [Getter]},structuredClone: [Getter/Setter],clearInterval: [Function: clearInterval],clearTimeout: [Function: clearTimeout],setInterval: [Function: setInterval],setTimeout: [Function: setTimeout] {[Symbol(nodejs.util.promisify.custom)]: [Getter]},atob: [Getter/Setter],btoa: [Getter/Setter],performance: [Getter/Setter],fetch: [AsyncFunction: fetch],window: [Circular *1]},arguments: undefined,optimizedBase64Encode: [Function: t4]
} 参数: [ 'Hello, World!' ] 结果: w4Xu+4SuKhUFWoJLKf==
w4Xu+4SuKhUFWoJLKf==

实战过程中,当看到 w4Xu+4SuKhUFWoJLKf== 这个字符后,看起来像是 base64 编码,所以通过 atob 尝试解码,得到 Ã\x85îû\x84®*\x15\x05Z\x82K),显然不对。

那分析日志吧!

29:  函数: [Function: slice] 调用者: [ 72, 101, 108 ] 参数: [] 结果: [ 72, 101, 108 ]30:  3 - 3 ====> 031:  72 & 255 ====> 7232:  101 & 255 ====> 10133:  108 & 255 ====> 10834:  72 << 16 ====> 471859235:  101 << 8 ====> 2585636:  4718592 | 25856 ====> 474444837:  4744448 | 108 ====> 474455638:  4744556 >> 18 ====> 1839:  18 & 63 ====> 1840:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 18 ] 结果: w
第 41:  4744556 >> 12 ====> 115842:  1158 & 63 ====> 643:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 6 ] 结果: 444:  4744556 >> 6 ====> 7413345:  74133 & 63 ====> 2146:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 21 ] 结果: X47:  4744556 & 63 ====> 4448:  函数: [Function: charAt] 调用者: Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe= 参数: [ 44 ] 结果: u

看到这段日志,有什么发现吗?

上篇文章讲过,如果是 3 个字节值通过位运算得到一个 4 个字节值,即:72, 101, 108 ===> 18, 6, 21, 44

所以,我们判断,它大概是 标准base64或者变种 base64算法,由于我们验证过,它不是标准base64,所以它应该是变种base64

那么,既然知道它大概是变种base64,那我们还需要一步一步去日志还原吗?

答案肯定不需要的。

我们只需要拿着 base64标准算法模板去改就行。俗称:套模板,大大节省我们的时间,而且也不容易出错!

标准 base64 算法模版:https://t.zsxq.com/sphu5

首先控制入参一样,即:Hello, World!

分析日志发现,首先它把标准的 base64 算法,码表由 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 变成了 Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=

其次是:

31:  72 & 255 ====> 7232:  101 & 255 ====> 10133:  108 & 255 ====> 108

每次位运算之前,都进行了 & 255 操作。

所以我们只需要微调代码,如下:

function processGroup(a, b, c) {a = a & 255; // 追加内容b = b & 255; // 追加内容c = c & 255; // 追加内容var combined = (a << 16) | (b << 8) | c;return [base64Chars.charAt((combined >> 18) & 63),base64Chars.charAt((combined >> 12) & 63),base64Chars.charAt((combined >> 6) & 63),base64Chars.charAt(combined & 63)];
}

最后,我们再验证一下,发现结果也是 w4Xu+4SuKhUFWoJLKf==,和日志结果一致,说明我们还原成功!

完整代码:https://t.zsxq.com/ROTc7

下一篇文章我们分析 RC4 jsvmp算法,学习它的日志特点。

请添加图片描述

http://www.dtcms.com/a/300170.html

相关文章:

  • 在 Dell PowerEdge T440 上通过 iDRAC9 安装 Proxmox VE
  • Flutter开发实战之网络请求与数据处理
  • bmp280的压力数据采集(i2c设备驱动+设备树编写)
  • ACO-OFDM 的**频带利用率**(单位:bit/s/Hz)计算公式
  • 建筑施工场景下漏检率↓76%!陌讯多模态融合算法在工程安全监控的落地实践
  • OpHReda精准预测酶最佳PH
  • 进制间的映射关系
  • 2025牛客暑期多校第4场——G
  • Polyhedral Approaches in Combinatorial Optimization组合优化中的多面体方法(下)
  • Java实现大根堆与小根堆详解
  • 每日面试题15:如何解决堆溢出?
  • 如何检查服务器数据盘是否挂载成功?
  • Android-三种持久化方式详解
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-32,(知识点:模数转换器,信噪比,计算公式,)
  • 深入理解C语言快速排序与自省排序(Introsort)
  • 【每天一个知识点】GAN(生成对抗网络,Generative Adversarial Network)
  • Compose笔记(三十八)--CompositionLocal
  • 安卓学习记录1——持续更新ing
  • React组件中的this指向问题
  • 三防平板支持DMR对讲有什么用?实现高效集群调度
  • 如何理解“测试场景”与“测试要点”的区别和联系?
  • Linux系统架构核心全景详解
  • 从0到1学Pandas(六):Pandas 与数据库交互
  • KiCad 与 CircuitMaker 使用方法分享:从零开始学电子设计
  • JavaWeb(苍穹外卖)--学习笔记11(Filter(过滤器) 和 Interceptor(拦截器))
  • Windows开发,制作开发软件安装程序(一)
  • MySQL的底层原理--InnoDB数据页结构
  • 关于GateWay网关
  • 基于HMM的词性标注方法详解(HMM+Viterbi,例题分析)
  • 【专业扫盲】电压/电流反馈和串联/并联反馈