声明
本文章中所有内容仅供学习交流,相关链接做了脱敏处理,若有侵权,请联系我立即删除!
案例目标
接口:
aHR0cHM6Ly93d3cuZG91eWluLmNvbS9hd2VtZS92MS93ZWIvdXNlci9wcm9maWxlL290aGVyLw==
以上均做了脱敏处理,Base64 编码及解码方式:
import base64
# 编码
# result = base64.b64encode('待编码字符串'.encode('utf-8'))
# 解码
result = base64.b64decode('待解码字符串'.encode('utf-8'))
print(result)
案例分析
抓包
个人主页相关信息在 /aweme/v1/web/user/profile/other/ 接口中:
请求参数,sec_user_id、webid 固定值,用户标识,清除浏览器缓存 msToken 则为空,cookie 参数,X-Bogus 为关键算法逻辑加密值:
逆向分析
主页内容是通过 ajax 加载的,直接 XHR 断点,断 X-Bogus 或者接口都行:
向上跟栈:
_0x5f1fc4 为 jsvmp 初始化位置,在 _0x1218ef 函数中生成了 X-Bogus 参数的值:
_0x1f515e 为一长串字节码,也是 jsvmp 最明显的特征,加密代码块经过 AST、汇编后转成了字节码:
接着向上跟栈看看,打印 _0x113c4d 会发现一些关键内容,后面再分析:
XHR 断点后,向上跟栈的位置都在 _0x1218ef 函数中, 里面有大量的 if-else 流程控制语句:
_0x1f1790、_0xc26b5e 都是从 _0xcc6308 中取值:
_0xcc6308 是 _0x1218ef 函数开始定义的一个数组:
后面大量的流程判断最后都是往里面赋值:
根据 _0x2458f0 决定进入哪个代码块进行相应的计算然后赋值:
_0x2458f0 由 _0x3f0f70 计算后经过位运算得到,_0x3f0f70 是根据索引 _0x217611 从 _0x2232d0 中取值得到,_0x2232d0 为之前提到的字节码,对应着算法逻辑,打断点跟栈的时候会发现不论是单步跟还是直接下个断点都会不断在 _0x1218ef 函数的各个 if-else 中跳来跳去,很难找到 X-Bogus 参数的生成逻辑,所以这里通过插桩逆向推算法逻辑,把 _0x1218ef 函数复制下来,折叠后会发现所有的流程都在 if (!_0x3eb330) 和 if (_0x3eb330) 中走,底下各是一个大的 for 循环:
在各自的第一个 for 语句下面插桩看看字节码中走的逻辑流程:
下面 if (_0x3eb330) 处也一样,打下日志断点,刷新网页控制台即会打印日志:
复制最后生成的 X-Bogus 值,在日志里面搜索一下,找到第一个位置,会发现上一条日志的 X-Bogus 值明显少了一个 0,找到 0 第一次出现的位置,0 是在 null 之后生成的,将日志保存一份,免得刷新控制台就清空了,看着也很麻烦:
位置2 就在 if (_0x3eb330) 里面,再根据索引位置下条件断点,断过去看看 0 怎么生成的:
刷新网页,断住后的第一个位置是不对的,先点下一个断点,再单步往后跟栈,到下图位置,再点就会跳出去:
打印一下里面内容:
0 即是经过 charAt 方法检索如下的固定字符串第 14 个位置的字符得到的:
'Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe='.charAt(13)
为什么时13 呢,如下图所示,因此接下来就需要找到 13 是怎么来的:
整个扣算法的过程都大同小异,找到第一次出现的位置,根据上面一行的索引,打下条件断点,单步向下跟,找到生成逻辑即可,需要细心和耐心,很多值都不是固定的,比如 post、user-agent 等等,关键方法如下,跟着跟着都会看到的:
""" X-Bogus: DFSz sdVu ikbA Nx-h tGoD Ul9W X7ng 七组 """
// canvas
function _0x5bc542(_0x485b15) {
var _0x166e4e, _0x1e1a65 = document['createElement']('canvas');
_0x1e1a65['width'] = -0x2587 + -0x643 * 0x1 + 0x2bfa,
_0x1e1a65['height'] = -0x10 * 0x147 + -0x1c3e + -0x22 * -0x16f;
var _0x53dffa = _0x1e1a65['getContext']('2d');
_0x53dffa['font'] = '14px\x20serif',
_0x53dffa['fillText']('龘ฑภ경', -0xba1 * 0x1 + 0x10bf + -0x51c, -0x172e + 0x871 * 0x1 + 0xec9),
_0x53dffa['shadowBlur'] = -0x2cd + -0x13 * -0x1b + -0x2 * -0x67,
_0x53dffa['showOffsetX'] = 0x5 * -0x635 + 0x293 * -0x2 + -0x8 * -0x486,
_0x53dffa['showColor'] = 'lime',
_0x53dffa['arc'](0x1 * -0x505 + -0x1db8 + 0x22c5, -0x1 * 0x907 + -0x670 + 0xf7f, 0x26be + -0x1183 + -0x1533, -0x1 * -0xb08 + -0x1230 + 0x728, 0x2225 + 0x15c4 + -0x37e7 * 0x1),
_0x53dffa['stroke'](),
_0x166e4e = _0x1e1a65['toDataURL']();
for (var _0x52eb40 = 0x1820 + -0x24b5 + -0x1 * -0xc95; _0x52eb40 < -0x170d + -0x9b * -0x3a + -0xbf1; _0x52eb40++)
_0x485b15 = (0x1e9a * -0xb + 0x8007 + -0x9af2 * -0x3) * _0x485b15 + _0x166e4e['charCodeAt'](_0x485b15 % _0x166e4e['length']) >>> 0x692 + 0x1f * 0xa7 + 0x13 * -0x169;
return _0x485b15;
}
// Uint8Array
function _0x398111(_0x267827, _0x34c400, _0x491abf, _0x53552b, _0x485a00, _0x40f22d, _0x21e442, _0xde84ad, _0xe79142, _0x190d11, _0x37cd1a, _0x345281, _0x226bae, _0x1ad2b3, _0x1abb7a, _0xe484aa, _0x55924d, _0x76995e, _0x190851) {
var _0x1ed20d = new Uint8Array(-0x35f * 0x8 + 0xe7d + 0xc8e);
return _0x1ed20d[0xab5 * 0x1 + -0x1cd * -0x14 + -0x2eb9] = _0x267827,
_0x1ed20d[0x2279 + -0x125f + -0x1 * 0x1019] = _0x37cd1a,
_0x1ed20d[-0xa * -0x265 + 0x10 * -0x17e + -0x10] = _0x34c400,
_0x1ed20d[-0x19 * -0x46 + -0x9cf + 0x1 * 0x2fc] = _0x345281,
_0x1ed20d[-0x2082 + 0x224a * -0x1 + -0x2 * -0x2168] = _0x491abf,
_0x1ed20d[-0x1 * 0x2fb + 0xa59 + -0x759] = _0x226bae,
_0x1ed20d[0x1 * -0x229b + -0x15bf + 0x3860] = _0x53552b,
_0x1ed20d[-0x20e2 + -0x224f * 0x1 + 0x4338] = _0x1ad2b3,
_0x1ed20d[0x10cd + 0x35 * 0x1 + -0x10fa] = _0x485a00,
_0x1ed20d[-0x1de * -0xe + 0x4e4 + -0x73 * 0x45] = _0x1abb7a,
_0x1ed20d[0x1 * -0x22fe + -0x3cb * 0x8 + 0x4160] = _0x40f22d,
_0x1ed20d[0x5b5 + 0xd6 * 0x29 + -0x9 * 0x470] = _0xe484aa,
_0x1ed20d[-0x115 + 0x3 * -0x45a + -0xe2f * -0x1] = _0x21e442,
_0x1ed20d[0x9cf + -0x59f + -0x423] = _0x55924d,
_0x1ed20d[0x1 * 0x9d9 + -0x95 * -0x11 + 0xe * -0x168] = _0xde84ad,
_0x1ed20d[0x2 * -0x49d + 0x5 * -0x455 + 0x1ef2] = _0x76995e,
_0x1ed20d[-0x2c * 0xb0 + -0x1335 + 0x3185] = _0xe79142,
_0x1ed20d[-0xd * -0xc4 + 0x1d7f + -0x2762 * 0x1] = _0x190851,
_0x1ed20d[0x151 * 0x1d + 0x2 * -0xb17 + -0xfed] = _0x190d11,
String['fromCharCode']['apply'](null, _0x1ed20d);
}
_0x1f3b8d = function(_0x260a4b) {
for (var _0x3d2639 = _0x260a4b['length'] >> -0x20e4 + 0x1 * -0x46 + -0x1 * -0x212b, _0x20f7c7 = _0x3d2639 << 0x14d1 + -0xb1b + 0x7 * -0x163, _0x1afb1d = new Uint8Array(_0x3d2639), _0x4d22bb = 0x8dd * 0x1 + 0x1fff + 0x20b * -0x14, _0x2511bf = 0x1bd * 0x10 + 0x147e + -0x2af * 0x12; _0x2511bf < _0x20f7c7; )
_0x1afb1d[_0x4d22bb++] = _0x19ae48[_0x260a4b['charCodeAt'](_0x2511bf++)] << 0x1a6c + 0x1025 * -0x1 + 0x1 * -0xa43 | _0x19ae48[_0x260a4b['charCodeAt'](_0x2511bf++)];
return _0x1afb1d;
}
结果验证:
V:爬虫与逆向路的驿站