吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 12559|回复: 41
收起左侧

[Web逆向] 某德地图矢量瓦片逆向(快速wasm逆向),c/c++/c#可调用,执行wasm2c翻译出来的c代码一

  [复制链接]
Frhvjhhv 发表于 2021-8-12 06:00


本文仅供学习交流使用,如有侵权,联系我删除。
由于篇幅过长,本篇分析wasm的网页加载流程,下一篇分析如何
执行wasm2c翻译出来的c代码

一般来说对于webassmebly的逆向,有两种选择,一个是扣js在nodejs等含有wasm运行时的环境中运行(缺点需要wasm运行时),另一种就是分析算法,自己写算法(缺点是耗时时间长)。那么有没有一种不用分析算法且可以脱离wasm运行时的快速逆向方法呢?当然是有的。即执行wasm2c翻译出来的c代码,快速wasm逆向,c/c++/c#/python可调用,
我们打开高德地图,

04b11ef1fe504341c7e4091ed3c7d88.png

看到如图所示的url,即矢量瓦片:
[Asm] 纯文本查看 复制代码
https://vdata04.amap.com/nebula/v3?key=bfe31f4e0fb231d29e1d3ce951e2c780&msg=7188355d0c44c5dabfd17b014f888bbf2321f2116e4354556cf52a9d7782368fadbd71091671a8ef05353af85941de664fc42793f4791a5029cb4a2342f3f7a3dc4b4432685cb09c6504dd1bd958c96d8f61f1098710c56cea2a50cac26c1a58&p=2

经过跟踪可以看到关键点:
[JavaScript] 纯文本查看 复制代码
b.prototype.bw = function(g, A, I, t, B, i, Q, C, e, o, E, h, a) {
            a = A.join(";"),
            a = this.parent.PW.transform('["' + a + '","' + E + '"]'),
            g = g + ("?key=" + this.parent.key) + "&msg=" + a,
        return g += "&p=2",
        makeFetchRequest(this.parent.Uh, g, function(A, i) {
            A ? h(A) : setTimeout(function() {
                l.pQ(i, B, I, C, e, Q, t, o, h, g)
            }, 10)
        })
    }


关键的句子是his.parent.PW.transform('["' + a + '","' + E + '"]'),即把经纬度坐标经过加密,然后访问url。跟进去
21e2f78d5b6258b0b7dee0d24fa4177.png

就可以发现他是如何初始化wasm以及调用wasm的。
首先把那一大串base64编码的的字符串解码成buffer,然后调用
[JavaScript] 纯文本查看 复制代码
function initSync(A) {
        var i = {
            wbg: {}
        };
        return i.wbg.__wbg_new_59cb74e423758ede = function() {
            return addHeapObject(new Error)
        }
        ,
        i.wbg.__wbg_stack_558ba5917b466edd = function(A, i) {
            var g = passStringToWasm0(getObject(i).stack, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc)
              , i = WASM_VECTOR_LEN;
            getInt32Memory0()[A / 4 + 1] = i,
            getInt32Memory0()[A / 4 + 0] = g
        }
        ,
        i.wbg.__wbg_error_4bb6c2a97407129a = function(A, i) {
            try {
                console.error(getStringFromWasm0(A, i))
            } finally {
                wasm.__wbindgen_free(A, i)
            }
        }
        ,
        i.wbg.__wbindgen_object_drop_ref = function(A) {
            takeObject(A)
        }
        ,
        i.wbg.__wbindgen_throw = function(A, i) {
            throw new Error(getStringFromWasm0(A, i))
        }
        ,
        i = loadSync(A, i).instance,
        wasm = i.exports
    }
来加载wasm。其中i是wasm的导入函数,直接扣即可。
加载wasm之后调用了RSAPublicKeyPair函数,跟进去可以发现调用了wasm里面的rsapublickeypair_new函数
693d0496902ffbb96c59aac7d168482.png
紧接着执行了this.instance.init(),即调用了wasm里面的$rsapublickeypair_init函数
af1461edb60a0b612d8e20dcc93b529.png


这上面均是RSA算法初始化的过程,即-加载wasm同时加载导入函数-初始化-加载RSA公钥

分析过RSA算法初始化的过程之后。我们来看看他是如何加密的‘
[JavaScript] 纯文本查看 复制代码
 function passStringToWasm0(A, i, g) {//A是待加密字符串,i是wasm里面的函数,g是前面rsapublickeypair_new函数返回的内存地址
        if (void 0 === g) {
            var I = cachedTextEncoder.encode(A)
              , t = i(I.length);
            return getUint8Memory0().subarray(t, t + I.length).set(I),
            WASM_VECTOR_LEN = I.length,
            t
        }
        for (var B = A.length, Q = i(B), C = getUint8Memory0(), e = 0; e < B; e++) {
            var o = A.charCodeAt(e);
            if (127 < o)
                break;
            C[Q + e] = o
        }


首先他把字符串变成了ascll格式,然后调用了i函数__wbindgen_malloc:
cc403da09aeb9965149c191a00a5e00.png

从函数名字__wbindgen_malloc就可以看出,为待加密的字符串分配内存空间
然后C[Q + e] = o直接把加密的字符串写入内存。
之后调用了wasm.rsapublickeypair_encode(8, this.UW, i, g)函数进行加密。参数 this.UW是前面rsapublickeypair_new函数返回的内存地址,i是待加密的字符串分配内存空间的地址,g是加密的字符串长度
[JavaScript] 纯文本查看 复制代码
    up.prototype.encode = function(A) {
        try {
            var i = passStringToWasm0(A, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc)
              , g = WASM_VECTOR_LEN;
            return wasm.rsapublickeypair_encode(8, this.UW, i, g),
            getStringFromWasm0(I = getInt32Memory0()[2], t = getInt32Memory0()[3])
        } finally {
            var I = getInt32Memory0()[2]
              , t = getInt32Memory0()[3];
            wasm.__wbindgen_free(I, t)
        }
    }

加密之后取了uint8array内存地址为8和12处(对应 I=getInt32Memory0()[2], t = getInt32Memory0()[3]))的数,然后跟踪可以发现I,也就是内存地址8处的数即为加密后字符串的内存地址,内存12处即为加密后字符串的长度,有地址和长度,加密的字符串就出来了。。







接下来的流程可以不要,如果你是扣代码或者分析算法可以走,便于分析,如果执行wasm2c翻译出来的c代码,就不需要。
没有什么好说的,直接扣就行了。

如上图,扣完之后写了一个html,输入待价密字符串,点击按钮,就会在页面上写出加密的内容,为了便于调试,我们在wasm加载完成之后直接注入一些脚本
85d59c1e655f0a34c55294b7cb5c1d1.png
这样在wasm的调试页面就直接可以搜索了,非常方便(这里感谢@jixun66)大神在我上个帖子评论区https://www.52pojie.cn/forum.php ... 379690&pid=37592798指出

88c9ed6bada083212e2800752ae4da7.png


免费评分

参与人数 22威望 +2 吾爱币 +117 热心值 +19 收起 理由
13699513436 + 1 热心回复!
lvyan0929 + 1 + 1 谢谢@Thanks!
meishanwl + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
liuxuming3303 + 1 + 1 谢谢@Thanks!
itachi137 + 1 + 1 我很赞同!
wuai1023a + 1 热心回复!
ljzh7798 + 1 + 1 谢谢@Thanks!
ruineng + 1 + 1 用心讨论,共获提升!
Lugia + 1 + 1 谢谢@Thanks!
sohu-Scass + 1 热心回复!
MXGT + 1 我很赞同!
lingyun011 + 1 热心回复!
石碎大胸口 + 1 + 1 谢谢@Thanks!
gaosld + 1 + 1 用心讨论,共获提升!
MichaelWin + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
pdcba + 1 + 1 谢谢@Thanks!
涛之雨 + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Stoneone + 1 谢谢@Thanks!
helian147 + 1 + 1 用心讨论,共获提升!
笙若 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
chinawolf2000 + 1 + 1 热心回复!
唐小样儿 + 1 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

jiejie1572 发表于 2021-8-12 10:56
写的挺详细   就是看不懂
HarckerG 发表于 2021-8-12 11:30
cptw 发表于 2021-8-12 13:18
13502501892 发表于 2021-8-12 14:45
挺详细   能换个交流方法不
唐小样儿 发表于 2021-8-12 14:55
写得这么好,评分走起来
jck114 发表于 2021-8-12 15:47
给大牛鼓掌&#128079;&#128079;
Tamluo 发表于 2021-8-12 20:52
腻害,写得忒详细了
Robofly 发表于 2021-8-13 09:20
写的真详细,but看不懂
xiong930626 发表于 2021-8-13 18:10
好专业、感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 11:31

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表