V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hsuehly
V2EX  ›  程序员

各位彭于晏们,最牛逼的纯前端加密,欢迎挑战。

  •  1
     
  •   hsuehly · 246 天前 · 6016 次点击
    这是一个创建于 246 天前的主题,其中的信息可能已经有所发展或是发生改变。

    闲来没事,简简单单写了一个 demo ,欢迎各位大佬前来挑战,地址: https://hsuehly.github.io/wasm_test/ 期待宴晏们各显神通。

    44 条回复    2023-08-26 10:20:49 +08:00
    maybedk
        1
    maybedk  
       246 天前
    不就是多对多加密么,研究过一点
    hsuehly
        2
    hsuehly  
    OP
       246 天前
    @maybedk 嗯,不错,可以尝试破解一下
    tool2d
        3
    tool2d  
       246 天前
    1. 查看在 wasm 代码,有一个 syscall/js.stringVal 入口,下断点。断在了'syscall/js.stringVal': (_0x2bfa63,_0x135c65,_0x549bc9)=>{

    2. 往下找,附近有一个 const _0x5d948b = _0x17e230[_0x3631d8..的语句。把这个_0x5d948b 变量传到外面,就是加密后的文字了。

    大部分时候,把 wasm 当成黑盒 RPC API 调用就可以了。没必要白盒破解算法的。
    tool2d
        4
    tool2d  
       246 天前
    wasm 加密有个很严重的问题,就是他最后一定会和 JS 进行交互,想办法把计算后的数据给传出去。

    这步不可能省略,一般都是 stringVal/setStringVal 之类的,很容易出问题。

    还不如 JS 里套一层 JS 虚拟机进行算法加密,至少可以模糊掉 JS 交互部分。
    DreamNya
        5
    DreamNya  
       246 天前   ❤️ 1
    a='test'
    b=window.encrypt(a)
    c=window.decrypt(b)
    a==c

    前端破解加密方式和 key 其实没啥用,我直接调用你的接口达成目的就行了,不需要知道你具体是怎么保证正常运行的。
    可能一些后端程序缺少环境才需要破你的加密方式(比如自动签到、自动爬虫)。
    shui14
        6
    shui14  
       246 天前
    wasm 只是增加成本而已,它不是破不了,最起码的,node py 都有现成工具先转 c 再分析,或者直接调用它
    这些都是防君子防不了小人,前端加密,法务兜底

    wasm 最大的意义在于抹平差异,比如 webgpu 当前变动大,还有一些传统软件成为部分可能,ffmpeg ,opencv ,tensorflow 等等,再一个它或许可以像 docker 一样,成为边缘计算的容器,比 serverless function 更近一步,加密混淆纯属路走歪了,绝对的安全在后端(边缘节点),当前这些叫混淆“加盐”
    hsuehly
        7
    hsuehly  
    OP
       246 天前 via iPhone
    @DreamNya 不错不错,那如果我整个页面的生命周期只调用一次加密函数,和解密函数,然后我在 wasm 中判断第二次调用,给你返回错误的密文该怎么破
    hsuehly
        8
    hsuehly  
    OP
       246 天前 via iPhone
    @shui14 你可以尝试在后端程序直接调用一下我写的 wasm
    DreamNya
        9
    DreamNya  
       246 天前
    @hsuehliuyang 把你调用加密函数的函数 hook 掉置空,然后等我来调用,伪装成网页正常的调用…… 类似于破解禁止重放攻击
    hsuehly
        10
    hsuehly  
    OP
       246 天前 via iPhone
    @DreamNya 但是你只能调一次啊
    gps949
        11
    gps949  
       246 天前
    AES-CBC?
    bigha
        12
    bigha  
       246 天前
    @hsuehliuyang

    这不是随便调嘛

    ```
    import requests

    r=requests.Session()

    pdata={
    'group':'ceshi',
    'action':'decrypt',
    'para':'NB_00edbf52008972d16934ab5a45d68a21d7aa6f3ba0d6b3a8d5e61cafd2c0c4777ced03'
    }

    response=requests.get("https://rpc.ping8.top/business/invoke",params=pdata)
    print(response.text)
    ```

    ![7afbd1b6257c4f6078ed8.png]( https://tu.ping8.top/file/7afbd1b6257c4f6078ed8.png)
    santom
        13
    santom  
       246 天前
    你这个长度无限的吗?
    hsuehly
        14
    hsuehly  
    OP
       246 天前 via iPhone
    @bigha wasm 限制我去了,你之前逆的那个写了
    hsuehly
        15
    hsuehly  
    OP
       246 天前 via iPhone
    @gps949 不错,可以找一下 key 藏在哪个地方
    tmtstudio
        16
    tmtstudio  
       246 天前
    @tool2d #4 大佬试过套虚拟机的方案吗,对性能影响大吗
    lisxour
        17
    lisxour  
       246 天前
    @tool2d #4 一般都用 wasm 做 hash 之类的计算,你就算在 js 层拿到结果没啥用,你不破解算法,你也模拟不了请求
    lisxour
        18
    lisxour  
       246 天前
    @tmtstudio 只要网站不需要非常繁重的 js 运算,对于使用者来说,不会有感官上的慢,但在代码层面可能会慢几倍,甚至十几倍都有可能。
    tool2d
        19
    tool2d  
       246 天前
    @lisxour "你不破解算法,你也模拟不了请求"

    以前一直研究游戏的通讯协议,后端有无数种方法可以限制非法调用。总觉得前端这种明文调用,又想分享,又想加密,出发点就挺矛盾的。

    我游戏客户端的话,把加密和陷阱做的很复杂,全部走自定义二进制协议,基本上想脱离客户端,后端去模拟请求,是不太可能的事情。
    hsuehly
        20
    hsuehly  
    OP
       246 天前
    @tool2d wasm 也算虚拟机,逆向加密肯定是先解算法找到 key 优先,这样效率是最高的,最后不行了才会上自动化,现在看来在 wasm 里写加密逻辑还是比较安全的,当然你可以把 wasm 当作库直接调用,但是我可以在 wasm 里直接判断环境,不是我的环境直接终止运行
    bigha
        21
    bigha  
       246 天前
    @lisxour 你看我也没破解楼主的算法,也可以模拟请求,你不信,你试试

    https://code.ping8.top/dKdNj-o4mUd/raw

    所以前端加密就是个伪命题,不管伪装的有多厉害,总能被破解,

    当然作为防守的一方,针对 ip 整一些限流之类的手段也很常见
    tool2d
        22
    tool2d  
       246 天前
    @hsuehliuyang 真想限制第三方的非法请求,在后端写 3 句加密代码,能顶上前端写 10 句。

    你在 wasm 里判断环境,难度挺大的,就是一个全封闭的环境,连调用最基础的时间和随机数,都需要 JS 去供给。
    hsuehly
        23
    hsuehly  
    OP
       246 天前
    @tool2d 你可以试一下在 python 或者 nodejs 或者其他有 wasmruntime 的语言运行一下,你看可以运行成功不
    hsuehly
        24
    hsuehly  
    OP
       246 天前
    @hsuehliuyang 更简单的,把我的 wasm 文件放在你的网页上试一下
    tool2d
        25
    tool2d  
       246 天前
    @hsuehliuyang wasm 本来就是跨平台的啊,绑定输入输出 API 就可以了。

    如果非要说不能移植,那你可能 wasm 调用的 js ,强依赖于某个浏览器 API 。

    重赏之下,必有勇夫。你 V2 发一个 10 万悬赏帖,肯定有人能把你 key 给破出来。
    lisxour
        26
    lisxour  
       246 天前
    @bigha #21 那是楼主写的后端就有问题,假设我一个接口有一个 time 、sign 参数,其余参数加不加密并不是重点

    1. time 参数和服务器不能差太多(甚至可以和服务器对时,以便转换成服务器时间)
    2. time 参数不能隔太久(以防重放,当然也有 csrftoken 方案,但是这里 time 也是能达到这种效果的)
    3. sign 参数是用其他参数计算出来的

    这种情况下,你写死了 para 提交,服务器就能判断出来,必须得破解 sign 算法,才能模拟提交

    加密这种东西得和后端相辅相成,只在 js 端做没啥意义
    MaydayV
        27
    MaydayV  
       246 天前
    这个长度真的,太牛了哈哈哈哈


    NB_d532d5371e2df4b7378f236b33ee12705ee21b8fb5e88426f7a35c28e83d3d9d663fa32cf379542fe4c855ce9e925af984f609a497e6ebe922b3991de17efabd4e954f40be6aecf8c8e890bcf4d39d2809452b14e510b38f7b1c3fc3bb7a5323f9d7526fa0c628528b25d1fe88f64b8a0e398cc6508cc6f5381cce2a444fd1d5dd6ba348a8ecc5c7d1769a823b4aaef722a72be93ba55071d42301cd6fec1585ad9c11c5b0c16dd1ee5da3f5daad6d614eb1d23d6442101417d46cb99e25166a908950f524a4291dae198ff50a79907dfb981eaf43a7a957430e89bc5a71778ec679f2d3a51d94d6e80dad0c2f83cbbca552b0d3635316b93e82b1b930d077cbbc9769287bf4df339009c798545c9defab8c5f4be041fb53613869447b1e06d0b1349749921ebf89d2883d8d19033b3adee5d51e1acbd9b9bc3762c75c2f86de5ffc9ef91381bb08d354dcb97c9ceb4267afe64e928e02b68b16d880a92afef80708ab0fd37045cdd28ec1dbbb406911a9782a1c11c8ca1a2de4fccfd89f11008c48440a1c9bb5cbcd25e07cdb7db20f390511aeb6d0acf4e688df6aad08ec8b17fb4c85cec5f13d8e076177965be2cefa29de25c970cfc4c6f36910f96dde0a48c69dbc2ea1c2e125ec99ec94855dc6b60a6a60c14c900d7d20f650780fa45f16e442c2812bdaf65e87cfa5ebd690dcec9586f83b2a1600b06c9f14f2ced779f3c891a0fda0302264cd9e3351c187cc5e869981763e5cb8995a208f3325350f1f783b38a07bdea3727e162956df55eeb1641f05d209c6490cd3c10276c3c8b789731c4aa487ddc41e22d9cd2b6ce50053cd0c82e406bd0a8c8fc7d60518dfd819b2b3177f4d9e57f397979caa39bbb910c50b313f6b5ceafa1b271c34e561ccfe376f4f25cbf9e94e73a1ee9d3de0b50261ed2d1adbb121f8ee0e24315f313fdf3a355022c2be48e3ea17a265e2a868d83366ed19e866b574f5345f08c1f5f1c342167d15c288ce7e8efce6bc1b85140eb9b5b53b1fc112ae8877642f79d75f3ffce380dc5f30c2aab8696649bfdd193b34a0894a46ecb5dfb6745974fa5d8c5e117e842bf6f513f59da500df35598d8f590ad40b81f56564b6493637b0ea18ce3f8bc9f2d038c26b38d9ea2959d885227e3f33aee7f616b2237b7f2eda8e82434502f3c306453d65fd90005caa61dc4352a609bce773be45af1340b78c5827cde744cfd1d049af135f0efb17c21b9d49d29e7018a28a04acac556c519e6b7d2a344e25087c394518f959d63bbf58b00ac11be6805e494125f013772278ef0dad43e8606224a386e25a7587d31302132cb090fde4c9ed53a5487717fb5313f2747f5428e3157ca53437489d2e39221879271efadc5e65a4fa20450c8312dbaa03494a1f857d35e6e381cc36eea7faac99f6974b2a48f3cea2efcc1a364a006f5a7346cd494f0dd4f1241d80322a287238208eab51af9abb34b3cc5e84c85b06e0660c0f03dfa3e653b0f2b3bbadd0920c80656313facdfcf6fdfe155e8dc91907f136b31922184e09d6624c4074dee7585fe79d810f7fcfe0a426ac873734a8c9e198bb4e6cc25a045b1455298e3e8aa19a66d959f397f3f04d505f218b3e5e92303dd7671ff2b9aa9e0578fdfaad31745f876839409c03587158c5513bedc45559f51c16ebd0c4b58a03d44246369705e91fc75d8055b550b2709cfbb53c79ff9f5871d5c30e6c35d0dce8ca432c83a6c23bdb373913558219e526778105893c20655eb86bedaa2a2596f7577522e2febec4084916156fe9d4f141007d5d01c67749aeec96e6c8c09c5df4e36ae31b12df02d5639be558f6140f7c3b690af837d3d5a1803d637a10b75dd3fb5af6edd99b3a5e07f0d9adfa90ebbd3f593a68717f6c13ba14454bcd628c2c803e6e3def82c702162466366d528f96e0cc0fdaab6eb24e0d9b019bb029f6ae8e5f077b2241b2af03b4566357aac11715dd3771c6c682a51c168d833e6be7a3c2872dce940ba307c06421fabae5b697ea32f5bf83e00669004dcb56c23e09011253f94f7a25db9b07dfd1ed4047782db3c080ce4f1c800c08dc4e149e533c96ce72fd83a842886ad50a36e58c8c8e1faccaa049ff426c8477f77ce989780fdeb74b38baf82bc2e3e2630c248a68d5c82cbdbbbfef22d32679ba1f9be18ffc162badf990127f1daf5ca31364c2492e4c30d33bbb576187842bed658df2c190676ecf949dff1ef75e445c52d5e1e3cae703a7883a3f35b184b334bc72908960b7ec819ed575eebb4897aa02330c6d10ff5df9fe6e0502067476f5b789840919cac5afc7f0150af69a93eff8757e634200661f054b4d593546cd7d6ccdaa595962302fbcfc71d843125891b26d0f9d857ec39dfda671af1d716474090acaaaaa81dd449f05dcf8b89d9ffe319270de17864c283b73f29e91a40f8d6d7666c9daf3e775e52a9beb67013eb132b60447646cd68273f25a8f6ec5457ecf7140a71b3ca59cf6a0fa4182a83cf38245c6d4a198db59232bce3e92e39aaa5169e15dd5240f65cca9754d71a2841ba88e33b2f5908359ae23e1560320f098d9a7b33e27a675f7d09d50896d6ffa075aad41611f7092869e768bfcbe330901711b8e901b58daede4bc64fb9dd897b371a2a2fc0da35c6e3bd26dbbc8bc14e073287389b732c4cfce75918d79b9f9fb9fb5ea90ad136b65f14f32a6a92335e9e171afcd86a5b6de93764e23b77a9c96ed4921b47992c40174722550bc3d83a6b344fc99e486754f04c9302f1595683687fd09703a1f5500ab421eb8398f36d3cbb491ba79120e70c6a585eadb38f9861e39dbd982382610c32162da0e
    bigha
        28
    bigha  
       246 天前
    @lisxour 那必须的 如果和后端联动起来 那才是彻底把路子堵死了
    hsuehly
        29
    hsuehly  
    OP
       246 天前
    @MaydayV 秀儿
    kuanat
        30
    kuanat  
       246 天前 via Android   ❤️ 5
    OP 发了不少帖子了,一直想证明前端利用 wasm 做混淆很难破解。这个结论本身没问题,你要逆向 wasm 的内部逻辑就要走汇编调试那一套。只靠单纯的前端技术应付不了,但是在做逆向的人眼里,没什么区别。

    这里大部分回复的都是在说,wasm/js 的交互机制决定了,多数时间把 wasm 当黑盒,用 RPC 方式调用就好了。没有必要去理会内部实现。

    这里讨论的隐藏前提是用混淆手段防机器人的,基于加密参数限制非 web 客户端对于后端 api 的调用。

    然后 OP 提出,这个加密逻辑全生命流程只能执行一次。说实话我想象不到这样的代码的应用场景,特别是防机器人的方面。(比较接近的是类似微信读书,原始 html 用 canvas 重渲染然后删掉原始数据)

    对于 RPC 调用的应对,OP 认为可以在 wasm 内部做针对外部环境的检测。这一点我从根本上就不认同。

    因为从根本上,客户端就不是可信的运行环境。别说浏览器了,手机 app 为什么都要做 root 越狱检测,都是一样的道理。这是个技术之外的哲学问题,你能判断自己是不是生活在虚拟世界里吗?

    至于实践方面,我是比较赞同 @tool2d 的,基于虚拟机的混淆,模糊掉控制流和调用逻辑,给逆向的人造成的烦躁感远比 wasm 大多了。

    而且虚拟机类型的混淆是可以高度自动化的,你可以每天都变换生成参数和算法。然而逆向虚拟机类混淆是没有什么自动化手段的。
    hsuehly
        31
    hsuehly  
    OP
       246 天前
    @kuanat 更正一下
    对于 RPC 调用的应对,我认为可以在 wasm 内部限制解密的次数
    对于直接把 wasm 当库调用,我可以在里面判断环境
    你们把 wasm 当黑盒,那你们肯定不清楚里面做了什么,所以上面两项破解条件,就是理解 wasm 里做了什么
    hsuehly
        32
    hsuehly  
    OP
       246 天前
    @hsuehliuyang 要破解上面两项,就要知道 wasm 里面做了什么
    LifStge
        33
    LifStge  
       246 天前
    wasm 还是比较好分析的 主要还是看代码量了 导入导出 太规范了 反倒容易分析 确实就楼上说的 没必要分析逻辑的 只需要找指定的接口
    自动化调用强依赖 js 的话 直接内置个浏览器就行了啊
    wasm 的处理流程 直接就是用 ghidra 啥的 二进制分析工具 分析流程就是了 比纯看 wasm 汇编方便不少
    找到关键接口 直接整个模块转 c 代码 修改或添加代码 再编译回去 然后拦截替换就行了 js 端就不用说了吧 混淆也就是分析费力 但是一般也不需要分析那么多 直接改代码 拦截替换就行了.
    felixlong
        34
    felixlong  
       246 天前
    @hsuehliuyang 你这套方案还不如直接用 Flutter 写你的整个 Web 呢。那样比你这个安全多了。
    cherryas
        35
    cherryas  
       246 天前
    从干活的角度不如昨天的强制关闭调试窗口
    Sh4ww
        36
    Sh4ww  
       246 天前   ❤️ 1
    现实是,主流的平台或者厂商没几个用 wasm 的
    LifStge
        37
    LifStge  
       246 天前
    wasm 二进制内容 修改逻辑不多的话 直接 用 wasm-dis 转文本格式 然后修改添加逻辑后 再用 wasm-as 转回二进制就行 也不需要反编译到 c 改完再编译回去(这样麻烦点吧了).
    hsuehly
        38
    hsuehly  
    OP
       246 天前
    如果大家仔细看 wasm 里的内容的话,会发现里面的函数也进行了混淆,但是好像没有人提这一点
    linuxsogood
        39
    linuxsogood  
       246 天前
    @hsuehliuyang #7 跟游戏外挂一下,直接修改内存不就好了,光凭前端你还能阻挡住不能改内存吗?
    AEP203
        40
    AEP203  
       246 天前
    不知道啥玩意 JS 混淆器,前端代码除了一堆花指令没啥特别的,有空再还原下 wasm ,前端代码: https://codefile.io/f/bKSY6N3nSW
    yuezk
        41
    yuezk  
       245 天前
    hsuehly
        42
    hsuehly  
    OP
       245 天前 via iPhone
    @yuezk 对 ob 的
    hsuehly
        43
    hsuehly  
    OP
       245 天前 via iPhone
    @yuezk 期待大佬更新关于 wasm 的
    yuezk
        44
    yuezk  
       245 天前
    @hsuehliuyang #43 对 wasm 不熟,在 MDN 上查了一下,但那些指令理解起来还是很费劲。单从内容看,wasm 是用 Go 编译的,用了 crypto/aes 和 crypt/cipher 模块,算法应该是 AES-CBC 。但是我对 Go 和 wasm 的指令都不熟悉,对 AES-CBC 了解过一些,核心算法是对加密内容分成每 16byte 一块,然后和 key 进行 XOR 操作。查找了一下 wasm 中的 xor 操作,整个文件的 xor 操作一共也就是 93 处。对于那些熟悉算法的和 wasm 指令的人来说破解应该不难。

    另外,即便不理解算法,也有可能从内存中的 dump 中读取,看到过类似 aes-finder 的工具,不过没有实操过。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   871 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 21:07 · PVG 05:07 · LAX 14:07 · JFK 17:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.