某解析wasm逆向

目标网址:aHR0cHM6Ly92aXAueWV5dWxpbmdmZW5nLmNvbS8=
aHR0cHM6Ly8xMTAuNDIuMi4yNDc6OTA5MC94cGxheWVyL2FwaS5waHA=

1、首先打开f12抓包并按下播放
某解析wasm逆向

注意这之前要先过掉下面的检测
Date.prototype.valueOf = () => 1701318661525
某解析wasm逆向

2、发现视频地址如下
某解析wasm逆向
继续往上找 api.php很可疑
某解析wasm逆向

用通过调用堆栈发现下面很可疑、但是代码太难看了
某解析wasm逆向
解混淆后看一下
某解析wasm逆向

可以看出params参数就是下面这行代码生成的
IIiIIi11 = encrypt(JSON["stringify"](iI1iiii));

控制台打印一下encrypt
某解析wasm逆向
然后在如图所示的位置下一个断点、并点击播放
打印一下argument、继续单步进入
某解析wasm逆向
然后就进入了wasm中
某解析wasm逆向
在wasm中搜索一下md5,aes之类的关键词并下断点
最后在crypto/cipher.newCBC和crypto/cipher.newCBC和crypto/aes.NewCipher这两个地方下断点
为什么呢?因为这玩意是Go编译的,看前面使用了Go对象就知道
在网上搜索了一下
Go AES加密
某解析wasm逆向
是不是很相似、接下来就是就是找key和iv了
encrypt函数就一个参数是代加密的明文 很显然key和iv是在程序运行时获取的
根据上面的Go的AES实现我们可以知道key是NewCipher时传入的,iv是newCBC时传入的(图中key和iv一样所以没有)
某解析wasm逆向
某解析wasm逆向

打上断点后 运行
某解析wasm逆向

可以看到成功在NewCipher处断住了 查看一下值
某解析wasm逆向

可以看到173648位置的’abcdef1234567890’很可疑
继续运行到newCBC
某解析wasm逆向

同样打印一下173824位置处有个’1234567890abcdef’
某解析wasm逆向

验证一下上面的猜测
先看encrypt(‘1’)的值
某解析wasm逆向
很不对劲 为什么是null呢?
调试发现encrypt和decrypt都只能使用一次,使用了之后要么是改变了某个全局变量要么是wasm内部改了一些东西,反正就是不能用了
点击播放按钮刷新,断住查看
某解析wasm逆向

encrypt(‘1’)的值是’hlUV9j5EVfhgSWGjL4okdg==’
先用JS复现、代码如下

t = '1';
key = CryptoJS.enc.Utf8.parse('abcdef1234567890');
iv = CryptoJS.enc.Utf8.parse('1234567890abcdef');
result = CryptoJS.AES.encrypt(t, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString();

某解析wasm逆向
发现结果一毛一样,就是标准的AES_CBC加密
但是到这还没完
我们实际使用的时候会发现和CryptoJS的结果不完全对的上
encrypt(s)的结果
某解析wasm逆向 CryptoJS
某解析wasm逆向

就是后面的有点对不上,而且encrypt(s)同样的s每次结果都不太一样
一看就是在在wasm中加盐了,因为有decrypt直接使用decrypt输出一下结果看看
某解析wasm逆向

果然多了个timeout和fingerprint,每次都有变化就是因为timeout这个时间戳在变
fingerprint很好找(ps:好像随便的填都行”.padEnd(8,0))
某解析wasm逆向
某解析wasm逆向

对应的python代码

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
def add_to_16(value):
while len(value) % 16 != 0:
value += '\0'
return str.encode(value)
def AesEncryptCBC(origData):
iv = '1234567890abcdef'
key = 'abcdef1234567890'
cipher = AES.new(add_to_16(key), AES.MODE_CBC, add_to_16(iv))
paddedData = pad(origData.encode('utf-8'), AES.block_size)
encryptedData = cipher.encrypt(paddedData)
return base64.b64encode(encryptedData).decode()

def AesDecryptCBC(t):
iv = '1234567890abcdef'
key = 'abcdef1234567890'
cipher = AES.new(add_to_16(key), AES.MODE_CBC, add_to_16(iv))
decryptedData = cipher.decrypt(base64.b64decode(t))
decrypted_text = unpad(decryptedData, AES.block_size).decode('utf-8')
return decrypted_text

某解析wasm逆向

最后这样分析只是基于这是标准的AES、魔改或函数名改了都会很wasm里面还有一个比较值得一看的函数$runtime.stringFromBytes 当时没想到用decrypt解密时就是看这个的
某解析wasm逆向

在JS中是靠下面这两个函数写入wasm中的 某解析wasm逆向

最后还有一点就是python模拟请求的时候要注意一下,JS中请求是下面这样的
某解析wasm逆向
python中就要使用json不能是params或data
某解析wasm逆向

因水平有限,若有错误之处、还请指出😄
某解析wasm逆向

给TA打赏
共{{data.count}}人
人已打赏
技术文档

在电脑上直接调试微信WxApkg小程序

2023-12-22 20:38:14

源码分享

PHP如何检测字符串里有没有繁体字

2021-9-9 1:29:00

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
有新私信 私信列表
搜索