如何用AST还原某音的JSVMP

news2024/11/18 5:28:44
1. 什么是JSVMP

vmp简单来说就是将一些高级语言的代码通过自己实现的编译器进行编译得到字节码,这样就可以更有效的保护原有代码,而jsvmp自然就是对JS代码的编译保护,具体的可以看看H5应用加固防破解-JS虚拟机保护方案。

如何区分是不是jsvmp?看代码里面有没有很长的一串字符串或者是数组,并且代码里面没有具体的逻辑,还有就是有一个循环不断地在跑,里面的就是一些指令,比如x乎,x音,x讯滑块等等都是jsvmp,也都是基于堆栈的栈式虚拟机实现的。

这是某乎的:

在这里插入图片描述

这是某音的,还原了一些算术混淆、三目运算和if else控制流混淆的:

在这里插入图片描述

在这里插入图片描述

这是某讯滑块的:

在这里插入图片描述

2. 如何去还原JSVMP
  1. 调试vmp代码,分析循环代码里面每个操作数对应的代码的意义

  2. 修改源代码中的vmp解释器,添加AST的对应代码

  3. 运行代码,生成最终代码。

3. 分析具体网站

样品网站:aHR0cHM6Ly90cmVuZGluc2lnaHQub2NlYW5lbmdpbmUuY29tL2FyaXRobWV0aWMtaW5kZXgvYW5hbHlzaXM/a2V5d29yZD0lRTklODAlODYlRTUlOTAlOTEmc291cmNlPW9jZWFuZW5naW5lJmFwcE5hbWU9YXdlbWU=

这个网站要找的是X-Bogus和**_signature**这两个参数的生成,怎么定位的这里不说了,

很容易就可以看到这个函数就是在通过操作码去运行逻辑

在这里插入图片描述

所以我们要分析下这个函数,看到有算术混淆和一些逗号混淆,不方便调试,可以使用AST写个逻辑去掉 这个很简单,还原效果如下:

在这里插入图片描述

可以看到,逻辑清晰了很多,但是因为是if else混淆,里面还有一些中间变量,如果调试的话会需要点击多几次才能到目标语句,所以我们可以考虑将这个if else转换为switch语句,这样调试的时候直接一步到位。

在这里插入图片描述

上图可以看到每次都从操作码中读取两个字符,并且是十六进制的,所以**_0x1383c7**这个变量的范围就是0-255,这样switch的条件就有了,可以编写代码从0迭代到255,就可以得到每个指令对应的代码了。最后还原结果如下:

在这里插入图片描述

可以看到逻辑很清晰了,但是有个问题是0-255的case里面有些是重复的,需要删除,可以继续使用AST,在每个case的第一行插入june.push(case_num),如这样:

在这里插入图片描述

然后映射文件到网站上,运行一次,获取june数组里面的值,保存到代码里,继续编写AST代码,读取case条件值,将不在数组中存在的case值全部删除掉,最后就可以愉快地分析了!

通过调试分析出,该函数的每个参数意义如下:

参数意义
_0x307ee4字节码
_0x5b7220函数起始位置
_0x237dce函数长度
_0x3f8a47不知道干啥,不影响分析
_0x4372f0内外部变量区,存储了当前函数的参数、定义的变量和外部变量
_0x264fdc函数调用对象
_0x1f863f无意义
_0xb80186vmp分支,混淆分析的

不过我们只需要知道哪个参数是存储变量的,和栈变量即可,其他的不影响分析。

我们要想还原出逻辑,就要找到对变量的定义,赋值,然后将其转为对应的语句即可。

调试代码:

在这里插入图片描述

在这里插入图片描述

这个就是在获取变量区**$0的变量,$0代表的是本函数内定义的变量,$1就代表上一层,$2**就继续往上推等等,但是其最外面的也会是本函数内的变量,所以需要需注意(这个如果有误,望赐教)

继续跑下去,可以看到

在这里插入图片描述

在这里插入图片描述

他将刚在获取的变量区index为24的值push进了栈,是一个函数参数,继续往下看

在这里插入图片描述

通过分析可知,_0x9ac2c2为栈,此处是将字符串dfp入栈,而我们要还原语句的话,入栈就不能这个了,需要改为对应的ast语句,将字符串dfp直接放上这网站astexplorer

在这里插入图片描述

可以看到对应的ast结构,所以此处代码改为:

在这里插入图片描述

继续往下调试:

在这里插入图片描述

这里是将刚才两个入栈的数据进行属性获取,对应语句为这样: yyy[“dfp”] (这里yyy 为乱写的,方便大家看的)

所以我们需要将源代码改为对应的ast代码:

在这里插入图片描述

在这里插入图片描述

接下来继续遇到一些常量进栈的,和上面的做法一样的,就不继续说了,说下变量定义:

在这里插入图片描述

上面这个就是变量赋值,这里面获取的是变量区的值,如下:

在这里插入图片描述

在这里插入图片描述

可以看到 index 26的位置还没有,所以可以判断这是一个新变量,第一次赋值,所以语句为这个:var a = “xxx”;

在这里插入图片描述

如果当前这个“26”已经存在的话,就不需要定义变量了,而是赋值就行,语句是这样:a = “xxx”;

在这里插入图片描述

所以我们需要判断下这个语句是否存在,修改代码如下:

在这里插入图片描述

可以看到入栈的数据是一个Identifier类型的变量,这个就是变量名了,之后代码需要操作的话,就获取这个变量就行,而不是获取直接的值。

最后记得将盖语句push进body,因为赋值就是一个完整的语句了,需要还原成代码。

理解了上面的剩下的就没什么问题了,就可以边调试边改对应的case,有些case是不需要操作的,比如上面的第一步获取变量区**$0**

小技巧:在每一个case前面添加一个语句:throw Error(“未更改”);然后直接运行代码,抛出异常的就是未处理的case,然后在浏览器调试看该case的作用并修改代码即可,运行到没有异常就代表没啥问题了!

另外说下if else和for这种语句怎么还原:

在这里插入图片描述

上面这个就是进行判断的,可以看到**_0x9ac2c2[_0x47144c–]的结果不一样,_0x1383c7**就不一样,即为下一个运行的指令不一样

我的处理思路:

  1. 进入这个分支就直接生成if判断,

    1. 然后保存当前栈,当前栈指针,以及当前函数所有参数变量的值,和当前指令位置**_0x1383c7**,
      3. 将else分支的**_0x1383c7**作为if分支的结束值,因为当if分支的指令值大于或者等于else分支的指令值的时候 证明两个分支运行的语句已经一致了(不过如果遇到三目语句,这种情况又需要另外讨论了)

然后直接调用当前函数,返回语句后将if结束后返回的指令值**_0x1383c7**作为else语句的结束指令,最后用else分支保存的函数进行调用

在这里插入图片描述

最后就是判断循环了,循环的也会进入上面这个case,只需要在进入的时候判断当前的指令值和if语句的起始指令值是否相同,相同即为循环,就可以修改之前保存的if分支为循环,我这里修改为while循环,比较好改

在这里插入图片描述

最后一个就是vmp内的函数定义,调试代码分析知道这个就是定义vmp函数的:

在这里插入图片描述

我是在他定义完了之后直接调用该函数进行还原,这样可以防止他只定义没有调用到,不好的地方在于参数个数不知道,所以这个需要在代码还原之后手动优化下,问题不大,如果你有更好的方法,希望能指导下。

在这里插入图片描述

4. 开始编写AST代码

由于该网站的vmp只是部分vmp,而我们还原代码是在原有的解释器上修改的,如果直接整完整代码进行运行,需要补一定的环境,这个不行,所以我这里将这个**_$webrt_1670312749**函数扣下来修改即可

首先导入我们需要用到的库:

const escodegen = require('escodegen');  // 用于将ast转为代码的
const esprima = require('esprima');  // 将代码转为ast
const estraverse = require('estraverse');  // 遍历ast的,这里用不到,用到了下面这个常量值
const Syntax = estraverse.Syntax;
var funs = {};  // 记录vmp函数的,可以方便调用

在这里插入图片描述

然后在这个函数里面修改传过来的函数参数,将他改为ast代码的格式,而不是一个字面量,因为真正程序调用的时候,传到这里表面就是个变量了,当然也可以在**_0x207ec8**这个循环函数内修改,但是不好确定哪些是函数参数,所以我在他上一个函数这里修改了

接下的就是按照上面第三步的分析开始写代码即可,如有不懂,可以在评论区讨论。

还原jsvmp代码这个第一次需要耐心点,等你熟悉起来了,后面的就会越来越快,里面主要就是一些ast代码的定义,需要传入栈的数据和存在变量区的值,最后就是函数定义和判断分支的实现,判断分支会比较难,处理好判断分支,剩下的就不是问题了。

如果觉得这个太难,可以试试这个大佬写的编译器:给"某音"的js虚拟机写一个编译器

可以编译自己的代码或者里面例子的代码,然后试着还原也不错!

5. 分析生成后的代码
function _0x5b7a61_vmp(args_0, args_1, args_2, args_3, args_4, args_5, args_6, args_7, args_8, args_9, args_10, args_11, args_12, args_13, args_14, args_15, args_16, args_17, args_18, args_19, args_20, args_21, args_22) {
        var var_233 = 'X-Bogus';
        var var_24 = '_signature';
        var var_25 = window['XMLHttpRequest']['prototype'];
        var var_26 = var_25['open'];
        var var_27 = var_25['setRequestHeader'];
        var var_28 = var_25['send'];
        var var_29 = var_25['overrideMimeType'];
        if (var_25['_ac_intercepted']) {
            return;
        }
        var_25['_ac_intercepted'] = !0;
        var_25['setRequestHeader'] = function (args_0, args_1) {
            if (!this['_send']) {
                var var_9999 = new window['Object']();
                var_9999['func'] = 'setRequestHeader';
                var_9999['arguments'] = arguments;
                this['_byted_intercept_list']['push'](var_9999);
                if (_0xc5dbaf(window['RegExp'], _0x1a373c(['^content-type$', 'i']))['test'](args_0)) {
                    this['_byted_content'] = args_1['toString']()['toLowerCase']()['split'](';')[0];
                }
            }
            return var_27.apply(this, arguments);
        };
        var_25['overrideMimeType'] = function () {
            this['_overrideMimeTypeArgs'] = arguments;
            return var_29.apply(this, this['_overrideMimeTypeArgs']);
        };
        var_25['open'] = function (args_0, args_1, args_2) {
            this['_byted_intercept_list'] = [];
            var var_10000 = new window['Object']();
            var_10000['func'] = 'open';
            var_10000['arguments'] = arguments;
            this['_byted_intercept_list']['push'](var_10000);
            this['_byted_method'] = args_0['toUpperCase']();
            this['_byted_url'] = args_1;
            return var_26.apply(this, arguments);
        };
        var var_30 = [
            'onabort',
            'onerror',
            'onload',
            'onloadend',
            'onloadstart',
            'onprogress',
            'ontimeout'
        ];
        var var_31 = [
            'GET',
            'POST'
        ];
        var_25['send'] = function fun_4(args_0) {
            var var_6 = var_31['indexOf'](this['_byted_method']) !== 0 - 1;
            if (args_2(this['_byted_url'])) {
                if (var_6) {
                    if (this['_byted_url']['indexOf']('_signature=') > 0 - 1) {
                        return var_28(this, arguments);
                    }
                    this['_byted_body'] = args_0;
                    var var_7 = this['onreadystatechange'];
                    var var_8 = this['onabort'];
                    var var_9 = this['onerror'];
                    var var_10 = this['onload'];
                    var var_11 = this['onloadend'];
                    var var_12 = this['onloadstart'];
                    var var_13 = this['onprogress'];
                    var var_14 = this['ontimeout'];
                    var var_15 = new window['Object']();
                    var var_50 = 0;
                    while (var_50 < var_30['length']) {
                        var_15[var_30[var_50]] = this['upload'][var_30[var_50]];
                        ++var_50;
                    }
                    var var_16 = args_3['msStatus'];
                    var var_17 = args_3['__ac_testid'];
                    if (var_17 == '') {
                        var var_18 = ['msToken', args_3['msToken']];
                    } else {
                        var_18 = ['msToken', args_3['msToken'], '__ac_testid', var_17];
                    }
                    var var_19 = args_4(args_5(this['_byted_url']), var_18);
                    var var_20 = args_6(var_19);
                    var var_21 = args_7(var_20, this['_byted_body']);
                    var var_22 = args_4(var_19, [var_233, var_21]);
                    var var_23 = '';
                    if (args_8['v']) {
                        var_23 = var_22;
                    } else {
                        var var_10002 = new window['Object']();
                        var_10002['url'] = args_9(null, var_22);
                        var var_100 = var_10002;
                        if (this['_byted_method'] === 'POST') {
                            if (args_10(this['_byted_content'])) {
                                args_11(var_100, this['_byted_content'], this['_byted_body']);
                                var var_101 = args_12(var_100, args_13, 'forreal');
                                var_23 = args_4(var_22, [var_24, var_101]);
                            } else {
                                var_23 = var_22;
                            }
                        } else {
                            var var_251 = args_12(var_100, args_13, 'forreal');
                            var_23 = args_4(var_22, [var_24, var_251]);
                        }
                    }
                    if (this['_byted_intercept_list']) {
                        if (this['_byted_intercept_list'][0]['func'] !== 'open') {
                            return null;
                        }
                    }
                    var var_244 = this['_byted_intercept_list'];
                    var var_182 = 0;
                    while (var_182 < var_244['length']) {
                        if (var_182 === 0) {
                            var_244[var_182].arguments[1] = var_23;
                            this['_send'] = !0;
                            var_26.apply(this, var_244[var_182].arguments);
                        } else {
                            this[var_244[var_182]['func']].apply(this, var_244[var_182].arguments);
                        }
                        ++var_182;
                    }
                    if (this['_overrideMimeTypeArgs']) {
                        this['overrideMimeType']();
                    }
                    delete this['_byted_intercept_list'];
                    if (args_8['sdi']) {
                        this['setRequestHeader'](args_14['secInfoHeader'], args_15());

                    }
                    this['onreadystatechange'] = var_7;
                    this['onabort'] = var_8;
                    this['onerror'] = var_9;
                    this['onload'] = function () {
                        var var_6 = 0;
                        if (!this['responseURL']) {
                            if (!this['_byted_url']) {
                                var var_7 = '';
                                if (args_16(var_7)) {
                                    var_6 = 1;
                                }
                                if (var_7['indexOf'](window['location']['host']) !== 0 - 1) {
                                    var_6 = 2;
                                }
                                if (var_6 > 0) {
                                    var var_8 = this['getResponseHeader']('x-ms-token');
                                    if (var_8) {
                                        var var_9 = args_17(this['_byted_url']);
                                        if (var_9 === args_18['sec']) {
                                            args_3['msToken'] = var_8;
                                            args_3['msStatus'] = var_9;
                                            args_19('msToken', var_8);
                                            args_20(var_8);
                                            if (var_9 > var_16) {
                                                if (args_3['msNewTokenList']['length'] > 0) {
                                                    args_21(args_22, 2);
                                                }
                                            }
                                        } else if (var_16 >= args_3['msStatus']) {
                                            args_3['msToken'] = var_8;
                                        }
                                        if (var_16 === args_18['init']) {
                                            if (args_3['msNewTokenList']['length'] < 10) {
                                                args_3['msNewTokenList']['push'](var_8);
                                                if (args_3['msNewTokenList']['length'] === 1) {
                                                    args_20(var_8);
                                                    args_19('msToken', var_8);
                                                }
                                            }
                                        }
                                    }
                                }
                                if (var_10) {
                                    var_10(args_0);
                                }
                                return;
                            } else {
                                var_7 = this['_byted_url'];
                                if (args_16(var_7)) {
                                    var_6 = 1;
                                }
                                if (var_7['indexOf'](window['location']['host']) !== 0 - 1) {
                                    var_6 = 2;
                                }
                                if (var_6 > 0) {
                                    var_8 = this['getResponseHeader']('x-ms-token');
                                    if (var_8) {
                                        var_9 = args_17(this['_byted_url']);
                                        if (var_9 === args_18['sec']) {
                                            args_3['msToken'] = var_8;
                                            args_3['msStatus'] = var_9;
                                            args_19('msToken', var_8);
                                            args_20(var_8);
                                            if (var_9 > var_16) {
                                                if (args_3['msNewTokenList']['length'] > 0) {
                                                    args_21(args_22, 2);
                                                }
                                            }
                                        } else if (var_16 >= args_3['msStatus']) {
                                            args_3['msToken'] = var_8;
                                        }
                                        if (var_16 === args_18['init']) {
                                            if (args_3['msNewTokenList']['length'] < 10) {
                                                args_3['msNewTokenList']['push'](var_8);
                                                if (args_3['msNewTokenList']['length'] === 1) {
                                                    args_20(var_8);
                                                    args_19('msToken', var_8);
                                                }
                                            }
                                        }
                                    }
                                }
                                if (var_10) {
                                    var_10(args_0);
                                }
                            }
                        } else if (!this['responseURL']) {
                            var_7 = '';
                            if (args_16(var_7)) {
                                var_6 = 1;
                            }
                            if (var_7['indexOf'](window['location']['host']) !== 0 - 1) {
                                var_6 = 2;
                            }
                            if (var_6 > 0) {
                                var_8 = this['getResponseHeader']('x-ms-token');
                                if (var_8) {
                                    var_9 = args_17(this['_byted_url']);
                                    if (var_9 === args_18['sec']) {
                                        args_3['msToken'] = var_8;
                                        args_3['msStatus'] = var_9;
                                        args_19('msToken', var_8);
                                        args_20(var_8);
                                        if (var_9 > var_16) {
                                            if (args_3['msNewTokenList']['length'] > 0) {
                                                args_21(args_22, 2);
                                            }
                                        }
                                    } else if (var_16 >= args_3['msStatus']) {
                                        args_3['msToken'] = var_8;
                                    }
                                    if (var_16 === args_18['init']) {
                                        if (args_3['msNewTokenList']['length'] < 10) {
                                            args_3['msNewTokenList']['push'](var_8);
                                            if (args_3['msNewTokenList']['length'] === 1) {
                                                args_20(var_8);
                                                args_19('msToken', var_8);
                                            }
                                        }
                                    }
                                }
                            }
                            if (var_10) {
                                var_10(args_0);
                            }
                            return;
                        } else {
                            var_7 = this['responseURL'];
                            if (args_16(var_7)) {
                                var_6 = 1;
                            }
                            if (var_7['indexOf'](window['location']['host']) !== 0 - 1) {
                                var_6 = 2;
                            }
                            if (var_6 > 0) {
                                var_8 = this['getResponseHeader']('x-ms-token');
                                if (var_8) {
                                    var_9 = args_17(this['_byted_url']);
                                    if (var_9 === args_18['sec']) {
                                        args_3['msToken'] = var_8;
                                        args_3['msStatus'] = var_9;
                                        args_19('msToken', var_8);
                                        args_20(var_8);
                                        if (var_9 > var_16) {
                                            if (args_3['msNewTokenList']['length'] > 0) {
                                                args_21(args_22, 2);
                                            }
                                        }
                                    } else if (var_16 >= args_3['msStatus']) {
                                        args_3['msToken'] = var_8;
                                    }
                                    if (var_16 === args_18['init']) {
                                        if (args_3['msNewTokenList']['length'] < 10) {
                                            args_3['msNewTokenList']['push'](var_8);
                                            if (args_3['msNewTokenList']['length'] === 1) {
                                                args_20(var_8);
                                                args_19('msToken', var_8);
                                            }
                                        }
                                    }
                                }
                            }
                            if (var_10) {
                                var_10(args_0);
                            }
                        }
                    };
                    this['onloadend'] = var_11;
                    this['onloadstart'] = var_12;
                    this['onprogress'] = var_13;
                    this['ontimeout'] = var_14;
                    var var_216 = 0;
                    while (var_216 < var_30['length']) {
                        this['upload'][var_30[var_216]] = var_15[var_30[var_216]];
                        ++var_216
                    }
                }
                return var_28.apply(this, arguments);
            }
        };
    }

上面代码是在vmp还原后经过手动小优化的,因为分支处理不够好,会有重复分支,手动删除即可。

上面代码不调试,直接看,逻辑也都很清晰了,加密是在send函数里面,这一小段:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

浏览器上也是可以得到结果的,证明是没问题的

最后我也将还原的代码将算法扣出来,然后用python,去请求也没问题

在这里插入图片描述

从还原的代码来看,对环境的检测也挺多的,检测了一些dom操作,还检测了一堆异步对象,都是获取设备的一些信息的。

6. 参考文章

给"某音"的js虚拟机写一个编译器

某乎x96参数与jsvmp初体验

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/380770.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenFeign 切换HttpClient遇到的问题

背景 OpenFeign支持三种Http请求方式&#xff0c;默认情况下通过jdk中的HttpURLConnection向下游服务发起http请求&#xff08;详见下图&#xff0c;源码详见feign.Client.Default&#xff09;&#xff0c; 默认的Client 采用 HttpURLConnection&#xff0c; 这种是无法复用的…

为什么一定要做集成测试?

集成测试&#xff0c;我们都不陌生&#xff0c;几乎我们产品每天都在进行。但是我们真的有好好思考&#xff1a;为什么一定要做集成测试吗&#xff1f;只是为了简单的将“积木”搭起来就行&#xff0c;还是有什么其他的深意&#xff1f; 深意可能不一定会有&#xff0c;但是意…

qt5.15 快速安装 国内源

1 qt5.15 安装问题 最大的问题就是需要在线下载与安装。即使挂了科学上网&#xff0c;国外的服务器下载速度也还是超级慢。 在网上找了各种解决办法后&#xff0c;终于找到一个快速下载安装的办法。 2 安装器下载 阿里源、清华源都没有Windows的安装器了&#xff0c;在腾讯…

IPv4地址细讲

文章目录一、IPv4地址简介二、IPv4地址的表示方法点分十进制记法三、IP地址的分类四、特殊IPv4地址&#xff1a;全 “0” 和全 “1”五、常用的三类IP地址使用范围六、五类IP地址的范围一、IPv4地址简介 IPv4地址分5类&#xff0c;每一类地址都由固定长度的字段组成&#xff1…

软件项目管理简答题复习(1)

1.项目&#xff1a;创造唯一的产品&#xff0c;唯一的服务临时性的努力 2.项目特征&#xff1a;不可见性&#xff0c;复杂性&#xff0c;一致性&#xff0c;变更性&#xff0c;特殊性 3.项目和日常活动的区别&#xff1f; 项目具有特殊性&#xff0c;负责人是项目经理&#…

软件项目管理计算题复习(1)

软件项目管理计算题复习&#xff08;1&#xff09; 1.关键路径&#xff1a;决定项目最早完成的一系列的活动。网络图中最长的路&#xff0c;最少的时差&#xff0c;总是差为0&#xff0c;也是关键路径。 2.最短路径也是最短工期 3.总时差&#xff1a;最晚开始-最早开始最晚结…

激光共聚焦显微镜在材料生产领域中的应用

在材料生产领域中&#xff0c;如需要分析金属材料/部件粗糙度的时候&#xff0c;不管是使用原子力显微镜还是台阶仪&#xff0c;都没有办法同时兼顾分辨率、扫描区域以及扫描速度。而基于激光共聚焦显微测量技术的共聚焦激光扫描显微镜&#xff0c;配备了真彩相机并提供还原的3…

NVIDIA CUDA初级教程视频学习笔记1

周斌老师 课程链接&#xff1a; 目录第一课内容生态环境第一课 CPU体系架构的概述什么是CPU指令存储器架构CPU内部的并行性第一课 预修课程&#xff1a; Cuda c programming guide 参考内容 1,2&#xff0c;3查找一下。 内容 CPU体系架构概述 并行程序设计概述 CUDA开发环境…

二叉树——二叉搜索树的最近公共祖先

二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#…

design\project\学习 OAuth 读书笔记(一)

OAuth&#xff08;一&#xff09; 原文链接&#xff1a;OAuth 2.0 tutorial | OAuth flows 目录OAuth&#xff08;一&#xff09;应用场景分析问题1&#xff1a;代表用户授予有限访问权限OAuth 代表用户授权问题2&#xff1a;允许第三方应用程序有限的访问API&#xff08;服务…

TPS74525PQWDRVRQ1典型应用TPS62992QRYTRQ1汽车用稳压器 规格参数

TPS74525PQWDRVRQ1线性稳压器 IC 2.5V 500MA 6WSON明佳达电子【概述】TPS745/TPS745-Q1可调节500mA LDO稳压器具有极低的静态电流&#xff0c;并可提供快速的线路和负载瞬态性能。TPS745/TPS745-Q1具有130mV的超低压差&#xff08;500mA电流&#xff09;&#xff0c;这有助于提…

EEP封装?METS封装?还是ZIP封装?

档案信息化行业的老兵想必对10多年前的EEP封装包印象深刻&#xff0c;其自包含、自描述、自证明的“洋葱结构”曾经火遍大江南北&#xff0c;为电子文件的真实性和完整性保证提供了一种重要手段&#xff0c;但其过分严谨刻板的封装结构也曾让很多档案从业人员抓狂。笔者曾经主导…

Java开发 - 分页查询初体验

前言在上一篇&#xff0c;我们对es进行了深入讲解&#xff0c;相信看过的小伙伴已经能基本掌握es的使用方法&#xff0c;我们知道&#xff0c;es主要针对的是搜索条件&#xff0c;在这方面es具有无可比拟的优势&#xff0c;但我们也会注意到&#xff0c;有时候搜索条件过于宽泛…

基于JavaWeb实现的学生选课系统(源码+数据库+文档)

一、项目简介 本项目是一套基于JavaWeb实现的学生选课系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;e…

基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v6.2版已发布

关于MobileIMSDK MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架&#xff0c;超轻量级、高度提炼&#xff0c;一套API优雅支持UDP 、TCP 、WebSocket 三种协议&#xff0c;支持iOS、Android、H5、标准Java平台&#xff0c;服务端基于Netty编写。 工程开源地址是&…

Nuxt.js项目开发过程遇到的问题以及对Nuxt.js的学习与总结

文章目录&#x1f4cb;前言&#x1f4bb;Nuxtjs3快速了解&#x1f3af;nuxtjs是什么&#xff1f;官网是这样介绍它的。&#x1f3af;关于nuxtjs的SSR开发&#x1f9e9;SSR应用场景&#x1f9e9;nuxtjs的特性&#x1f4bb;nuxtjs的初始目录结构&#x1f3af;关于各个目录的解释&…

智能家居控制系统

&#x1f941;作者&#xff1a; 华丞臧. &#x1f4d5;​​​​专栏&#xff1a;【项目经验】 各位读者老爷如果觉得博主写的不错&#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方&#xff0c;欢迎在评论区指出。 推荐一款刷题网站 &#x1f449; LeetCode刷题网站…

MIGO 物料过账 创建物料凭证 BAPI_GOODSMVT_CREATE

文章目录1.前台操作2.需求分析2.1调用方式2.2分为两大概括:2.3业务逻辑细节图3.BAPI_GOODSMVT_CREATE4.RFC接口代码5.总结1.前台操作 SAP CO01(创建生产订单)/MIGO(发货投料)前台操作 这里面有migo的前台操作,首先了解前台操作后再去写RFC接口是比较容易理解的.!! 2.需求分析…

opencv读入图片注意事项

来源&#xff1a;投稿 作者&#xff1a;蓬蓬奇 编辑&#xff1a;学姐 深度学习数据预处理中常用opencv读入图片&#xff0c;一般在__getitem__函数中调用。本文主要介绍opencv读取图片的一些细节以及注意事项。本文中使用的图片见第6节“opencv测试使用的图片”。 1.如何通过o…

计算机底层:储存器的性能指标(CPU和内存等硬件的性能以及 对比标准)

计算机底层&#xff1a;储存器的性能指标(CPU和内存等硬件的性能以及 对比标准) 内存&#xff1a; MAR是存放地址的寄存器&#xff1b;MDR是存放数据的寄存器。 MAR是存放地址的寄存器&#xff0c;那么其中的二进制位一定是不能重复的&#xff0c;试想&#xff0c;如果有有两个…