android frida 逆向 自吐加密算法

前言:

♛  frida  hook   android   Android  逆向神器

前几天在学习 Android 逆向的时候发现了一个神器:通过  frida hook  我们可以 “劫持”  一些函数 为我们所用, 今天就和大家上手一个  加密函数的劫持 让打印出:

  • 加密秘钥
  • 密文

效果如下:可以很直观的看出 加密算法以及秘钥

 

 

准备工作:

安装运行环境:(因为我这里都装过来 你们自己对照着来)

  1. python  环境
    C:\Users\Administrator>python --version
    Python 3.10.6
  2. frida
    C:\Users\Administrator>pip install frida
    Requirement already satisfied: frida in c:\users\administrator\appdata\local\programs\python\python310\lib\site-packages (16.1.3)
    Requirement already satisfied: typing-extensions in c:\users\administrator\appdata\local\programs\python\python310\lib\site-packages (from frida) (4.7.1)[notice] A new release of pip available: 22.2.1 -> 23.2.1
    [notice] To update, run: python.exe -m pip install --upgrade pipC:\Users\Administrator>frida
    usage: frida [options] target
    frida: error: target must be specified
  3. firda-tools
    C:\Users\Administrator>pip install frida-tools
    Requirement already satisfied: frida-tools in c:\users\administrator\appdata\local\programs\python\python310\lib\site-packages (12.2.1)
    Requirement already satisfied: prompt-toolkit<4.0.0,>=2.0.0 in c:\users\administrator\appdata\local\programs\python\python310\lib\site-packages (from frida-tools) (3.0.39)
    Requirement already satisfied: colorama<1.0.0,>=0.2.7 in c:\users\administrator\appdata\local\programs\python\python310\lib\site-packages (from frida-tools) (0.4.6)
    Requirement already satisfied: pygments<3.0.0,>=2.0.2 in c:\users\administrator\appdata\local\programs\python\python310\lib\site-packages (from frida-tools) (2.15.1)
    Requirement already satisfied: frida<17.0.0,>=16.0.9 in c:\users\administrator\appdata\local\programs\python\python310\lib\site-packages (from frida-tools) (16.1.3)
    Requirement already satisfied: typing-extensions in c:\users\administrator\appdata\local\programs\python\python310\lib\site-packages (from frida<17.0.0,>=16.0.9->frida-tools) (4.7.1)
    Requirement already satisfied: wcwidth in c:\users\administrator\appdata\local\programs\python\python310\lib\site-packages (from prompt-toolkit<4.0.0,>=2.0.0->frida-tools) (0.2.6)[notice] A new release of pip available: 22.2.1 -> 23.2.1
    [notice] To update, run: python.exe -m pip install --upgrade pip
  4.  下载一个 frida server    Releases · frida/frida · GitHub
    下载地址: https://github.com/frida/frida/releases

    因为 我用的是模拟器所有下载这个版本,可以使用 命令查看对于的类型

    C:\Users\Administrator>adb shell getprop ro.product.cpu.abi
    x86_64
  5. adb
    C:\Users\Administrator>adb devices
    List of devices attached
    emulator-5558   device

实操上手:

⒈建立注入环境:运行 frida server   (不要关闭)

把刚刚下载的 解压发送到 手机  /data/local/ 目录下, 我这里重命名为 f86(应为一些加壳软件会监测是否使用 frifa)

 

 执行 f86,   记得要给权限!chmod 777 f86

C:\Users\Administrator>adb shell
star2qltechn:/ $ su
star2qltechn:/ # cd /data/lcoal
/system/bin/sh: cd: /data/lcoal: No such file or directory
2|star2qltechn:/ # cd /data/local
star2qltechn:/data/local # ls
cfg-zeiag f86 file-cache temp-zeiag tmp traces
star2qltechn:/data/local # chmod 777 f86
star2qltechn:/data/local # su
star2qltechn:/data/local # ./f86

2 建立端口转发  一共两个端口  (不要关闭)

  • adb forward tcp:27043 tcp:27043
  • adb forward tcp:27042 tcp:27042
C:\Users\Administrator>adb forward tcp:27043 tcp:27043
27043C:\Users\Administrator>adb forward tcp:27042 tcp:27042
27042

3  运行我们的 hook.js 代码  (不要关闭)

frida -U -F -l C:\Users\Administrator\Desktop\py\hook.js
  • -U 指的的我们的 USB设备
  • -F 指的是我们最手机 最上层运行的APP
  • -l 指定我们脚本路径

 运行这App的时候 跑起来我们的脚本

 

 

4  奇迹就发生了

 

 

hook.js 脚本

var N_ENCRYPT_MODE = 1
var N_DECRYPT_MODE = 2function showStacks() {var Exception = Java.use("java.lang.Exception");var ins = Exception.$new("Exception");var straces = ins.getStackTrace();if (undefined == straces || null == straces) {return;}console.log("============================= Stack strat=======================");console.log("");for (var i = 0; i < straces.length; i++) {var str = "   " + straces[i].toString();console.log(str);}console.log("");console.log("============================= Stack end=======================\r\n");Exception.$dispose();
}//工具相关函数
var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',base64DecodeChars = new Array((-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), 62, (-1), (-1), (-1), 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, (-1), (-1), (-1), (-1), (-1), (-1), (-1), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, (-1), (-1), (-1), (-1), (-1), (-1), 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, (-1), (-1), (-1), (-1), (-1));function stringToBase64(e) {var r, a, c, h, o, t;for (c = e.length, a = 0, r = ''; a < c;) {if (h = 255 & e.charCodeAt(a++), a == c) {r += base64EncodeChars.charAt(h >> 2),r += base64EncodeChars.charAt((3 & h) << 4),r += '==';break}if (o = e.charCodeAt(a++), a == c) {r += base64EncodeChars.charAt(h >> 2),r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4),r += base64EncodeChars.charAt((15 & o) << 2),r += '=';break}t = e.charCodeAt(a++),r += base64EncodeChars.charAt(h >> 2),r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4),r += base64EncodeChars.charAt((15 & o) << 2 | (192 & t) >> 6),r += base64EncodeChars.charAt(63 & t)}return r
}
function base64ToString(e) {var r, a, c, h, o, t, d;for (t = e.length, o = 0, d = ''; o < t;) {dor = base64DecodeChars[255 & e.charCodeAt(o++)];while (o < t && r == -1);if (r == -1)break;doa = base64DecodeChars[255 & e.charCodeAt(o++)];while (o < t && a == -1);if (a == -1)break;d += String.fromCharCode(r << 2 | (48 & a) >> 4);do {if (c = 255 & e.charCodeAt(o++), 61 == c)return d;c = base64DecodeChars[c]} while (o < t && c == -1);if (c == -1)break;d += String.fromCharCode((15 & a) << 4 | (60 & c) >> 2);do {if (h = 255 & e.charCodeAt(o++), 61 == h)return d;h = base64DecodeChars[h]} while (o < t && h == -1);if (h == -1)break;d += String.fromCharCode((3 & c) << 6 | h)}return d
}
function hexToBase64(str) {return base64Encode(String.fromCharCode.apply(null, str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" ")));
}
function base64ToHex(str) {for (var i = 0, bin = base64Decode(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) {var tmp = bin.charCodeAt(i).toString(16);if (tmp.length === 1)tmp = "0" + tmp;hex[hex.length] = tmp;}return hex.join("");
}
function hexToBytes(str) {var pos = 0;var len = str.length;if (len % 2 != 0) {return null;}len /= 2;var hexA = new Array();for (var i = 0; i < len; i++) {var s = str.substr(pos, 2);var v = parseInt(s, 16);hexA.push(v);pos += 2;}return hexA;
}
function bytesToHex(arr) {var str = '';var k, j;for (var i = 0; i < arr.length; i++) {k = arr[i];j = k;if (k < 0) {j = k + 256;}if (j < 16) {str += "0";}str += j.toString(16);}return str;
}
function stringToHex(str) {var val = "";for (var i = 0; i < str.length; i++) {if (val == "")val = str.charCodeAt(i).toString(16);elseval += str.charCodeAt(i).toString(16);}return val
}
function stringToBytes(str) {var ch, st, re = [];for (var i = 0; i < str.length; i++) {ch = str.charCodeAt(i);st = [];do {st.push(ch & 0xFF);ch = ch >> 8;}while (ch);re = re.concat(st.reverse());}return re;
}
//将byte[]转成String的方法
function bytesToString(arr) {var str = '';arr = new Uint8Array(arr);for (var i in arr) {str += String.fromCharCode(arr[i]);}return str;
}
function bytesToBase64(e) {var r, a, c, h, o, t;for (c = e.length, a = 0, r = ''; a < c;) {if (h = 255 & e[a++], a == c) {r += base64EncodeChars.charAt(h >> 2),r += base64EncodeChars.charAt((3 & h) << 4),r += '==';break}if (o = e[a++], a == c) {r += base64EncodeChars.charAt(h >> 2),r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4),r += base64EncodeChars.charAt((15 & o) << 2),r += '=';break}t = e[a++],r += base64EncodeChars.charAt(h >> 2),r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4),r += base64EncodeChars.charAt((15 & o) << 2 | (192 & t) >> 6),r += base64EncodeChars.charAt(63 & t)}return r
}
function base64ToBytes(e) {var r, a, c, h, o, t, d;for (t = e.length, o = 0, d = []; o < t;) {dor = base64DecodeChars[255 & e.charCodeAt(o++)];while (o < t && r == -1);if (r == -1)break;doa = base64DecodeChars[255 & e.charCodeAt(o++)];while (o < t && a == -1);if (a == -1)break;d.push(r << 2 | (48 & a) >> 4);do {if (c = 255 & e.charCodeAt(o++), 61 == c)return d;c = base64DecodeChars[c]} while (o < t && c == -1);if (c == -1)break;d.push((15 & a) << 4 | (60 & c) >> 2);do {if (h = 255 & e.charCodeAt(o++), 61 == h)return d;h = base64DecodeChars[h]} while (o < t && h == -1);if (h == -1)break;d.push((3 & c) << 6 | h)}return d
}
//stringToBase64 stringToHex stringToBytes
//base64ToString base64ToHex base64ToBytes
//               hexToBase64  hexToBytes    
// bytesToBase64 bytesToHex bytesToStringJava.perform(function () {var secretKeySpec = Java.use('javax.crypto.spec.SecretKeySpec');secretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function (a, b) {showStacks();var result = this.$init(a, b);console.log("======================================");console.log("算法名:" + b + "|str密钥:" + bytesToString(a));console.log("算法名:" + b + "|Hex密钥:" + bytesToHex(a));return result;}var DESKeySpec = Java.use('javax.crypto.spec.DESKeySpec');DESKeySpec.$init.overload('[B').implementation = function (a) {showStacks();var result = this.$init(a);console.log("======================================");var bytes_key_des = this.getKey();console.log("des密钥  |str " + bytesToString(bytes_key_des));console.log("des密钥  |hex " + bytesToHex(bytes_key_des));return result;}DESKeySpec.$init.overload('[B', 'int').implementation = function (a, b) {showStacks();var result = this.$init(a, b);console.log("======================================");var bytes_key_des = this.getKey();console.log("des密钥  |str " + bytesToString(bytes_key_des));console.log("des密钥  |hex " + bytesToHex(bytes_key_des));return result;}var mac = Java.use('javax.crypto.Mac');mac.getInstance.overload('java.lang.String').implementation = function (a) {showStacks();var result = this.getInstance(a);console.log("======================================");console.log("算法名:" + a);return result;}mac.update.overload('[B').implementation = function (a) {//showStacks();this.update(a);console.log("======================================");console.log("update:" + bytesToString(a))}mac.update.overload('[B', 'int', 'int').implementation = function (a, b, c) {//showStacks();this.update(a, b, c)console.log("======================================");console.log("update:" + bytesToString(a) + "|" + b + "|" + c);}mac.doFinal.overload().implementation = function () {//showStacks();var result = this.doFinal();console.log("======================================");console.log("doFinal结果: |str  :"     + bytesToString(result));console.log("doFinal结果: |hex  :"     + bytesToHex(result));console.log("doFinal结果: |base64  :"  + bytesToBase64(result));return result;}mac.doFinal.overload('[B').implementation = function (a) {//showStacks();var result = this.doFinal(a);console.log("======================================");console.log("doFinal参数: |str  :"     + bytesToString(a));console.log("doFinal结果: |str  :"     + bytesToString(result));console.log("doFinal结果: |hex  :"     + bytesToHex(result));console.log("doFinal结果: |base64  :"  + bytesToBase64(result));return result;}var md = Java.use('java.security.MessageDigest');md.getInstance.overload('java.lang.String', 'java.lang.String').implementation = function (a, b) {//showStacks();console.log("======================================");console.log("算法名:" + a);return this.getInstance(a, b);}md.getInstance.overload('java.lang.String').implementation = function (a) {//showStacks();console.log("======================================");console.log("算法名:" + a);return this.getInstance(a);}md.update.overload('[B').implementation = function (a) {//showStacks();console.log("======================================");console.log("update:" + bytesToString(a))return this.update(a);}md.update.overload('[B', 'int', 'int').implementation = function (a, b, c) {//showStacks();console.log("======================================");console.log("update:" + bytesToString(a) + "|" + b + "|" + c);return this.update(a, b, c);}md.digest.overload().implementation = function () {//showStacks();console.log("======================================");var result = this.digest();console.log("digest结果:" + bytesToHex(result));console.log("digest结果:" + bytesToBase64(result));return result;}md.digest.overload('[B').implementation = function (a) {//showStacks();console.log("======================================");console.log("digest参数:" + bytesToString(a));var result = this.digest(a);console.log("digest结果:" + bytesToHex(result));console.log("digest结果:" + bytesToBase64(result));return result;}var ivParameterSpec = Java.use('javax.crypto.spec.IvParameterSpec');ivParameterSpec.$init.overload('[B').implementation = function (a) {//showStacks();var result = this.$init(a);console.log("======================================");console.log("iv向量: |str:" + bytesToString(a));console.log("iv向量: |hex:" + bytesToHex(a));return result;}var cipher = Java.use('javax.crypto.Cipher');cipher.getInstance.overload('java.lang.String').implementation = function (a) {//showStacks();var result = this.getInstance(a);console.log("======================================");console.log("模式填充:" + a);return result;}cipher.init.overload('int', 'java.security.Key').implementation = function (a, b) {//showStacks();var result = this.init(a, b);console.log("======================================");if (N_ENCRYPT_MODE == a){console.log("init  | 加密模式");    }else if(N_DECRYPT_MODE == a){console.log("init  | 解密模式");    }var bytes_key = b.getEncoded();console.log("init key:" + "|str密钥:" + bytesToString(bytes_key));console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key));return result;}cipher.init.overload('int', 'java.security.cert.Certificate').implementation = function (a, b) {//showStacks();var result = this.init(a, b);console.log("======================================");if (N_ENCRYPT_MODE == a){console.log("init  | 加密模式");    }else if(N_DECRYPT_MODE == a){console.log("init  | 解密模式");    }return result;}cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec').implementation = function (a, b, c) {//showStacks();var result = this.init(a, b, c);console.log("======================================");if (N_ENCRYPT_MODE == a){console.log("init  | 加密模式");    }else if(N_DECRYPT_MODE == a){console.log("init  | 解密模式");    }var bytes_key = b.getEncoded();console.log("init key:" + "|str密钥:" + bytesToString(bytes_key));console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key));return result;}cipher.init.overload('int', 'java.security.cert.Certificate', 'java.security.SecureRandom').implementation = function (a, b, c) {//showStacks();var result = this.init(a, b, c);if (N_ENCRYPT_MODE == a){console.log("init  | 加密模式");    }else if(N_DECRYPT_MODE == a){console.log("init  | 解密模式");    }return result;}cipher.init.overload('int', 'java.security.Key', 'java.security.SecureRandom').implementation = function (a, b, c) {//showStacks();var result = this.init(a, b, c);if (N_ENCRYPT_MODE == a){console.log("init  | 加密模式");    }else if(N_DECRYPT_MODE == a){console.log("init  | 解密模式");    }var bytes_key = b.getEncoded();console.log("init key:" + "|str密钥:" + bytesToString(bytes_key));console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key));return result;}cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters').implementation = function (a, b, c) {//showStacks();var result = this.init(a, b, c);if (N_ENCRYPT_MODE == a){console.log("init  | 加密模式");    }else if(N_DECRYPT_MODE == a){console.log("init  | 解密模式");    }var bytes_key = b.getEncoded();console.log("init key:" + "|str密钥:" + bytesToString(bytes_key));console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key));return result;}cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters', 'java.security.SecureRandom').implementation = function (a, b, c, d) {//showStacks();var result = this.init(a, b, c, d);if (N_ENCRYPT_MODE == a){console.log("init  | 加密模式");    }else if(N_DECRYPT_MODE == a){console.log("init  | 解密模式");    }var bytes_key = b.getEncoded();console.log("init key:" + "|str密钥:" + bytesToString(bytes_key));console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key));return result;}cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec', 'java.security.SecureRandom').implementation = function (a, b, c, d) {//showStacks();var result = this.update(a, b, c, d);if (N_ENCRYPT_MODE == a){console.log("init  | 加密模式");    }else if(N_DECRYPT_MODE == a){console.log("init  | 解密模式");    }var bytes_key = b.getEncoded();console.log("init key:" + "|str密钥:" + bytesToString(bytes_key));console.log("init key:" + "|Hex密钥:" + bytesToHex(bytes_key));return result;}cipher.update.overload('[B').implementation = function (a) {//showStacks();var result = this.update(a);console.log("======================================");console.log("update:" + bytesToString(a));return result;}cipher.update.overload('[B', 'int', 'int').implementation = function (a, b, c) {//showStacks();var result = this.update(a, b, c);console.log("======================================");console.log("update:" + bytesToString(a) + "|" + b + "|" + c);return result;}cipher.doFinal.overload().implementation = function () {//showStacks();var result = this.doFinal();console.log("======================================");console.log("doFinal结果: |str  :"     + bytesToString(result));console.log("doFinal结果: |hex  :"     + bytesToHex(result));console.log("doFinal结果: |base64  :"  + bytesToBase64(result));return result;}cipher.doFinal.overload('[B').implementation = function (a) {//showStacks();var result = this.doFinal(a);console.log("======================================");console.log("doFinal参数: |str  :"     + bytesToString(a));console.log("doFinal结果: |str  :"     + bytesToString(result));console.log("doFinal结果: |hex  :"     + bytesToHex(result));console.log("doFinal结果: |base64  :"  + bytesToBase64(result));return result;}var x509EncodedKeySpec = Java.use('java.security.spec.X509EncodedKeySpec');x509EncodedKeySpec.$init.overload('[B').implementation = function (a) {//showStacks();var result = this.$init(a);console.log("======================================");console.log("RSA密钥:" + bytesToBase64(a));return result;}var rSAPublicKeySpec = Java.use('java.security.spec.RSAPublicKeySpec');rSAPublicKeySpec.$init.overload('java.math.BigInteger', 'java.math.BigInteger').implementation = function (a, b) {//showStacks();var result = this.$init(a, b);console.log("======================================");//console.log("RSA密钥:" + bytesToBase64(a));console.log("RSA密钥N:" + a.toString(16));console.log("RSA密钥E:" + b.toString(16));return result;}var KeyPairGenerator = Java.use('java.security.KeyPairGenerator');KeyPairGenerator.generateKeyPair.implementation = function (){//showStacks();var result = this.generateKeyPair();console.log("======================================");var str_private = result.getPrivate().getEncoded();var str_public = result.getPublic().getEncoded();console.log("公钥  |hex" + bytesToHex(str_public));console.log("私钥  |hex" + bytesToHex(str_private));return result;}KeyPairGenerator.genKeyPair.implementation = function (){//showStacks();var result = this.genKeyPair();console.log("======================================");var str_private = result.getPrivate().getEncoded();var str_public = result.getPublic().getEncoded();console.log("公钥  |hex" + bytesToHex(str_public));console.log("私钥  |hex" + bytesToHex(str_private));return result;}
});

总结:

使用 frida hook 的原理, 是直接劫持java加密函数, 不需要去逆向代码直接, 效率很高!

对于使用 java 原生开发的应用 效率很高! 但是相对于 flutter 开发的应用效果就比较差了

 

后面抽空研究研究  fiida 在 flutter 身上的新姿势

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Window11-Ubuntu双系统安装

一、制作Ubuntu系统盘 1.下载Ubuntu镜像源 阿里云开源镜像站&#xff1a;https://mirrors.aliyun.com/ubuntu-releases/ 清华大学开源软件镜像网站&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/ 选择想要的版本下载&#xff0c;我用的是20.04版本。 2…

【广州华锐互动】AR昆虫认知学习系统实现对昆虫形态的捕捉和还原

随着科技的不断发展&#xff0c;人们对自然界的认识也在不断加深。在这个过程中&#xff0c;AR&#xff08;增强现实&#xff09;技术的出现为人们带来了全新的体验方式。为此&#xff0c;广州华锐互动开发了AR昆虫认知学习系统&#xff0c;本文将为大家详细介绍这款系统的特点…

无涯教程-Android - Style Demo Example函数

下面的示例演示如何将样式用于单个元素。让我们开始按照以下步骤创建一个简单的Android应用程序- 步骤说明 1 您将使用Android Studio IDE创建一个Android应用程序,并在 com.example.saira_000.myapplication 包下将其命名为 myapplication ,如中所述您好世界Example一章。 2 …

【方案】基于视频与AI智能分析技术的城市轨道交通视频监控建设方案

一、背景分析 地铁作为重要的公共场所交通枢纽&#xff0c;流动性非常高、人员大量聚集&#xff0c;轨道交通需要利用视频监控系统来实现全程、全方位的安全防范&#xff0c;这也是保证地铁行车组织和安全的重要手段。调度员和车站值班员通过系统监管列车运行、客流情况、变电…

vue小测试之拖拽、自定义事件

在开始之前我去复习了一下&#xff0c;clientX、clientY、pageX、pageY的区别&#xff0c;对于不熟悉offsetLeft和offsetTop的也可以在这里去复习一下。 vue拖拽指令之offsetX、clientX、pageX、screenX_wade3po的博客-CSDN博客_vue offset 客户区坐标位置&#xff08;clientX&…

讲讲几道关于 TCP/UDP 通信的面试题

TCP &#xff08;1&#xff09;TCP 的 accept 发生在三次握手的哪个阶段&#xff1f; 如下图connect和accept的关系&#xff1a; accept过程发生在三次握手之后&#xff0c;三次握手完成后&#xff0c;客户端和服务器就建立了tcp连接并可以进行数据交互了。这时可以调用accep…

像linux 一样清理Windows C盘

像 linux 有命令 du -sh 查看文件夹大小 但是windows 可就没有这个命令了&#xff0c;就算有命令&#xff0c;也不能扫描子目录里面的文件 但是windows 可以借助 软件来清理&#xff0c;和linux 一样 文件上面是目录&#xff0c;下面是文件所占用空间大小的图&#xff0c;咋…

通过参数化可变形曲线直接从 X 射线投影数据计算分割研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

虚拟机Ubuntu20.04 网络连接器图标开机不显示怎么办

执行以下指令&#xff1a; sudo service network-manager stop sudo rm /var/lib/NetworkManager/NetworkManager.state sudo service network-manager start

MySQL 特殊语法时间格式以及Greadb连接

一、时间语法 DATE_FORMAT和to_char() select to_char(now(),%Y-%m-%d %H:%i:%s) from dual; select DATE_FORMAT(now(),%Y-%m-%d %H:%i:%s) from dual; 2.to_date() 和STR_TO_DATE(#{date},%Y-%m-%d ) select to_date(now(),yyyy-mm-dd hh24:mi:ss) from dual;

LeetCode——栈的压入、弹出序列

这里我用下面的例子子来讲解一下模拟栈的实现。 例子1&#xff1a;pushed [1,2,3,4,5] popped [4,5,3,2,1] 思路&#xff1a;第一步&#xff1a;我们先创建一个栈&#xff0c;然后将pushed的数据压进去 第二步&#xff1a;判断&#xff01; 当压入栈的数据和popped第一个数据…

本地启动若依微服务版本

前置工作&#xff1a; 1.导入sql文件 2.安装完nacos 3.安装完redis 启动步骤&#xff1a; 1.开启nacos&#xff0c;在bin目录下 startup.cmd -m standalone 注意&#xff1a;在这之前要配置nacos持久化&#xff0c;修改conf/application.properties文件&#xff0c;增加支持…

MR混合现实石油化工课堂情景实训教学演示

MR&#xff08;混合现实&#xff09;技术是一种结合了虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;优势的新型技术&#xff0c;在教育领域具有广阔的应用前景。在石油化工课堂中&#xff0c;MR混合现实情景实训教学的应用可以大大提高学生的学习效…

抖音短视频账号矩阵seo分发系统--开发源代

1.抖音矩阵号/抖音短视频SEO矩阵系统开发及开发者思路分享: 短视频获客系统开发原型支持短视频智能批量剪辑、短视频多账号管理定时发布&#xff0c;短视频排名查询及优化&#xff0c;智能客服私信回复等&#xff0c;那么短视频seo系统开发时需要开发哪些功能呢&#xff1f;今天…

实现基于栈的表达式求值计算器(难度4/10)

本作业主要考察&#xff1a;解释器模式的实现思想/栈结构在表达式求值方面的绝对优势 C数据结构与算法夯实基础作业列表 通过栈的应用&#xff0c;理解特定领域设计的关键作用&#xff0c;给大家眼前一亮的感觉。深刻理解计算机语言和人类语言完美结合的杰作。是作业中的上等…

winform嵌入浏览器 webView2

1、项目引用nuget 2、winform窗体中初始化 var webView new WebView2();webView.Source new Uri(url);webView.Dock DockStyle.Fill;//接收js调用c#函数的消息webView.WebMessageReceived CoreWebView2_WebMessageReceivedAsync; this.panel1.Controls.Add(…

成集云 | 飞书审批同步金蝶云星空 | 解决方案

源系统成集云目标系统 方案介绍 飞书员工报销审批通过后&#xff0c;审批单据内容和审批状态实时同步金蝶云星空 飞书是字节跳动于2016年自研的新一代一站式协作平台&#xff0c;将即时沟通、日历、云文档、云盘和工作台深度整合&#xff0c;通过开放兼容的平台&#xff0c;…

2023年创新药行业研究报告

第一章 行业概况 1.1 定义 根据《英国医学杂志》的定义&#xff0c;创新药物被定义为”完全或部分新的活性物质或生物实体&#xff0c;或者这些实体的组合&#xff0c;通过药理或分子机制对抗疾病&#xff0c;缓解症状&#xff0c;或预防疾病&#xff0c;以及作为可以改善病人…

Graylog 更改显示的时区(Display timezone)

每个 Graylog 用户都可以配置他们的显示时区。 这会更改用于查看日志消息的时区&#xff0c;但不会更改日志消息的原始时区。 默认情况下&#xff0c;Graylog 显示 UTC 格式的所有时间戳&#xff08;也就是 0:00&#xff09;。就像是下面这样 非Admin账户要更改时区&#xff1…

Elasticsearch 7.6 - Springboot应用基础操作篇

ES 7.6 - JAVA应用基础操作篇 环境准备依赖配置 实体类准备使用说明索引/映射操作创建索引和映射索引和映射相关查询删除索引 文档操作插入数据更新数据删除数据批量操作 文档查询根据ID查询根据字段精准查询根据字段分词查询控制返回字段范围查询组合查询排序分页高亮搜索聚合…