李恒道 发表于 2023-1-8 02:29

【嶺上開花】油猴实战劫持人脸识别

本帖最后由 李恒道 于 2023-1-8 02:45 编辑

感谢
感谢涛之雨大佬在我失恋的日子里看我特别痛苦所以用我的支付宝花呗请我吃饭
害得我一边忍受失恋的折磨一边打工还上次的日料钱
在此我不得不说一句
码头拎搞吧,给你置办卡地亚,2023,祝我涛神名满天下
前文

其实封包过明显更简单但是我就是要补出来环境
我要魔改出来一个自动答题过人脸的变态考试专版APP
嘿,就是玩

目标

某起

开始

首先点击按钮提示
直接源代码里搜索一下

发现通过m.f判断
因为是webpack打包,往上找m

m来自ba39
直接打断往里追或者搜索ba39都可以
找到了函数,前方的n.d是webpack的环境定义头,直接忽略,发现m.f的f来自于i

我们继续找i

发现i来自763d
继续找763d
发现这个函数的f取决于变量d

而d在下方,默认为假,下方有两个赋值d的,一个是函数,一个是直接调用,我们先忽略函数,直接看调用的s
https://bbs.tampermonkey.net.cn/data/attachment/forum/202212/14/225606ada3h2t51347tvet.png
调用一下打个断点往里追
找到了
function s(e) {
            var t = arguments.length > 1 && void 0 !== arguments ? arguments : {}
            , n = arguments.length > 2 ? arguments : void 0;
            o((function(i) {
                i.callHandler(e, t, (function(e) {
                  var t = e;
                  if ("string" == typeof e)
                        try {
                            t = JSON.parse(e)
                        } catch (e) {}
                  n && n(t)
                }
                ))
            }
            ))
      }
e是调用事件名,t是变量,n是回调函数
我们调用了o来回调执行函数,那我们去看看o
      function o(e) {
            if (window.WebViewJavascriptBridge)
                e(window.WebViewJavascriptBridge);
            else if (i()) {
                if (window.WVJBCallbacks)
                  return window.WVJBCallbacks.push(e),
                  !1;
                window.WVJBCallbacks = ;
                var t = document.createElement("iframe");
                t.style.display = "none",
                t.src = "wvjbscheme://__BRIDGE_LOADED__",
                document.documentElement.appendChild(t),
                setTimeout((function() {
                  document.documentElement.removeChild(t)
                }
                ), 0)
            } else
                a() && document.addEventListener("WebViewJavascriptBridgeReady", (function() {
                  e(window.WebViewJavascriptBridge)
                }
                ), !1)
      }
这里可以看到在检测各种桥,我们来搞个最基本的
window.WebViewJavascriptBridge吧
调用e(window.WebViewJavascriptBridge);会把我们的函数传进去
去回调
                i.callHandler(e, t, (function(e) {
                  var t = e;
                  if ("string" == typeof e)
                        try {
                            t = JSON.parse(e)
                        } catch (e) {}
                  n && n(t)
                }
那我们就需要实现callHandler函数,检测是否是getRuntimeEnvironment
如果是的话就去回调第三个参数,第三个参数是个函数,接受一个e
我们应该传入一个对象
然后会对n传入这个对象
n则是
(function(e) {
            d = "app" === e.platform
      }
      )
代表我们传入的对象必须包含platform,并且是app
开始
直接上油猴
window.WebViewJavascriptBridge = {
    callHandler: (name, obj, callback) => {
       xxxxx
       防恶意利用删除代码
       balabala

    }
}
就会发现我们已经过了APP功能性检测
https://bbs.tampermonkey.net.cn/data/attachment/forum/202212/14/230553k6bcweuwdzgezewb.png
目前已经在网页模拟出来了我们的APP环境
我们可以在最后调用标明一个
console.log('遇到未处理的事件'+name+')
来看我们到底需要补什么环境函数和数据
第一个碰到的就是genSign
但是问题来了
网页本身就可以计算sign,难道我们要再使用脚本实现一遍吗?
为什么不开脚本好好的,开了脚本却要自己实现一遍?
我们翻一下堆栈,发现了一个有意思的爆出错误
https://bbs.tampermonkey.net.cn/data/attachment/forum/202212/14/233821lq1ntetvg37e3vi2.png
这里可以看到调用genSign之前设置了一个定时器,到时间就触发一个自定义错误
那上方肯定有一个try函数
往上继续找堆栈,果然找到了
https://bbs.tampermonkey.net.cn/data/attachment/forum/202212/14/233911tj86ojzzfcofp9nt.png
如果调用genSign函数到时还没有返回
就直接触发异常让catch抓到错误然后走原来的网页逻辑
那我们不需要处理genSign,直接在callHandler检测到并且返回一个undefined即可

开始分析摄像头

然后我们分析摄像头触发一下按钮发现调用了examPushSign事件
https://bbs.tampermonkey.net.cn/data/attachment/forum/202212/14/234116ad7pbjdwpb3mr3m7.png
翻一下堆栈,发现使用了t.image
https://bbs.tampermonkey.net.cn/data/attachment/forum/202212/14/234143t1ryckk11vb0zzyt.png
除此以外一个没动
我们抓个包看看提交的参数是什么%2F9j%2F4AAQSkZJRgABAQEAAQABAAD%2F2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj%2F2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj%2FwAARCAKAAoADASIAAhEBAxEB%2F8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL%2F8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWW
很明显是一个url编码掉的,再解码看看/9j/4AAQSkZJRgABAQEAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAKAAoADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWW这种带/ 数字和连续HwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBg的字符,很难不让人联想到是base64转了图片
我们尝试复制粘贴一下
随便找个
https://tool.chinaz.com/tools/imgtobase
然后在这个图片前加个data:image/jpeg;base64,表示是一个base64图片,发现直接解码成功!
那我们基本就理清他的回调逻辑了,油猴上比较简单,我们可以直接打开一个文件选择器,接受图片之后base64掉传回给网页
理论建立完毕
实战开始

补充


其实可以在callHandle里手动触发错误,关于这个的处理方案就当作一个小想法了~因为比较无关紧要

我们继续
当点击按钮触发摄像头拍照后
直接回调文件选择
这里我就干脆封出来一个函数
获取到file对象之后转成base64,去掉前缀,然后回调callback
这里没用promise是因为原来的WebViewJavascriptBridge不是一个async对象,我们保持一致
function receivePicture(callback){
    let input=document.createElement('input');
    input.setAttribute('type', 'file');
    input.setAttribute('multiple', 'multiple');
    input.accept="image/*"
    input.addEventListener('change',(e)=>{
      const file=e.target.files
      const reader = new FileReader();
      reader.addEventListener('load', ()=> {
            callback(reader.result.replace('data:image/jpeg;base64,',""))
      });
      reader.readAsDataURL(file);

    })
    input.click()
}
然后直接些对应的调用
收到base64之后包装一下返回去
      if(name==='examPushSign'){
            receivePicture(xxxxx)
            return
      }
我们接下来测试一下效果
https://bbs.tampermonkey.net.cn/data/attachment/forum/202212/15/004610yxdhor4hhffohaoa.png
开始选择文件
https://bbs.tampermonkey.net.cn/data/attachment/forum/202212/15/004634sb9mp5ma0i2a939m.png
顺便来一张极限竞速





结语

有时候不得不感叹
精神小伙里我代码写的好
程序员里我又是最精神的那一批
属实赢了两拨:赢麻了
撒花~







涛之雨 发表于 2023-1-8 07:44

写的不错,问一下,![](https://bbs.tampermonkey.net.cn/data/attachment/forum/202212/14/234116ad7pbjdwpb3mr3m7.png)
这个对象怎么收到?

列明 发表于 2023-1-8 09:41

涛神问:这个对象怎么收到?
我问:你还发对象么?
我再说:下一个请务必发给我!

李恒道 发表于 2023-1-8 13:57

涛之雨 发表于 2023-1-8 07:44
写的不错,问一下,![]()
这个对象怎么收到?


JS会判断WebViewJavascriptBridge是否存在,然后尝试调用callHandler来使用app功能
我们直接实现一下
window.WebViewJavascriptBridge = {
    callHandler: (name, obj, callback) => {
       xxxxx
       防恶意利用删除代码
       balabala
 
    }
}
就可以接收到网页的各种回调事件

李恒道 发表于 2024-4-6 16:07

本帖最后由 李恒道 于 2024-4-6 16:15 编辑

rollingchair 发表于 2024-4-5 21:39
刚好在做学习通的逆向,没想到,居然已经实践出来了
哥哥加油!玩一玩的!

knight0531 发表于 2023-1-8 08:33

这个需要人脸识别才能考试的app真是够差劲的,非得强制认证一下,但是里面的题不还是度娘解决,感觉就是留痕。拜读楼主帖子,受益匪浅,还得抓紧补充知识,要不跟不上楼主步伐......

78zhanghao87 发表于 2023-1-8 14:10

厉害,这种混淆过的代码怎么看懂的?

whg118 发表于 2023-1-8 03:53

加紧学习基础知识了,不然跟不上节奏{:300_955:}

fengxu 发表于 2023-1-8 04:55

厉害厉害,请你一下

lvkeqin 发表于 2023-1-8 06:51

软件名:牢底坐穿。很刑:lol

nmkj888 发表于 2023-1-8 07:33

流弊Plus,比修改摄像头底层协议,用视频图片替换还牛{:1_921:}

Helsing9527 发表于 2023-1-8 07:39

我靠,向大佬致敬

ct268gh 发表于 2023-1-8 08:21

本帖最后由 ct268gh 于 2023-1-8 08:23 编辑

是chinaedu那个吗{:1_904:},想看看大佬的自动答题怎么做的

danding 发表于 2023-1-8 08:25

这个可不可以逆向思维干票大的

tzblue 发表于 2023-1-8 08:32

劫持人脸识别……
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 【嶺上開花】油猴实战劫持人脸识别