PE输入表DLL注入

news2025/1/17 13:57:07
PE输入表DLL注入

一.实现效果
启动notepad.exe时能够加载自己编写的dll.
最终效果如图所示


下面逐步讲解并附带源码
二.编写DLL
自行编写DLL,导出一个函数,弹出对话框
// MsgDLL66.cpp : Defines the entry point for the DLL application.
//
 
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
 
extern "C"
{
        __declspec(dllexport) int Msg() ;
}
 
DWORD WINAPI ThreadShow(LPVOID LpParameter)
{
        char szPath[MAX_PATH]={0};
        char szBuf[1024]={0};
        GetModuleFileName(NULL,szPath,MAX_PATH);
        sprintf(szBuf,"DLL 已注入到进程 %s [pid=%d]\n",szPath,GetCurrentProcessId());
        //以3种方式显示自己的存在
        //1.Msgbox
        MessageBox(NULL,szBuf,"DLL Inject",MB_OK);
        //2.控制台
        printf("%s",szBuf);
        //3.调试器
        OutputDebugString(szBuf);
        return 0;
}
 
__declspec(dllexport) int Msg()
{
        char szPath[MAX_PATH]={0};
        char szBuf[1024]={0};
        GetModuleFileName(NULL,szPath,MAX_PATH);
        sprintf(szBuf,"DLL 已注入到进程 %s [pid=%d]\n",szPath,GetCurrentProcessId());
        MessageBoxA(NULL, szBuf, "小星星", MB_OK);
        return 0;
}
 
BOOL APIENTRY DllMain( HANDLE hModule,
                                          DWORD  ul_reason_for_call,
                                          LPVOID lpReserved
                                          )
{
    switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
                CreateThread(NULL,0,ThreadShow,NULL,0,NULL);
                Msg();
                break;
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
                break;
    }
    return TRUE;
}

 上面的源码编译后得到dll文件
 


三.修改PE输入表实现DLL注入
新建一个工程,把上面得到的dll文件放在工程目录下
 


代码如下,关键地方都做了注释,如果PE基本结构体都不懂,那还是建议先系统学习下

// PEImportDllInject.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
#include <windows.h>
 
#define FilePath "c:\\NOTEPAD.EXE"
#define NewFilePath "c:\\NOTEPAD_new1.EXE"
 
// 把文件读到Buffer里面
LPVOID FileToBuffer()
{
        HANDLE hFile;
        DWORD lpFileSizeHigh;
        DWORD dwFileSize;
        LPVOID  FileBuffer;
        DWORD lpNumberOfBytesRead;
        BOOL bRead;
         
        hFile = CreateFile(FilePath, GENERIC_ALL,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
         
        if ( hFile == NULL)
        {
                printf("CreateFile error %d\n", GetLastError());
        }
         
    dwFileSize = GetFileSize(hFile,&lpFileSizeHigh);
         
        if ( dwFileSize == NULL)
        {
                printf("GetFileSize error %d\n", GetLastError());
        }
         
        FileBuffer = VirtualAlloc(0,dwFileSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
         
        if ( FileBuffer == NULL)
        {
                printf("VirtualAlloc error %d\n", GetLastError());
        }
         
        bRead = ReadFile(hFile,FileBuffer,dwFileSize,&lpNumberOfBytesRead,NULL);
         
        if ( bRead == FALSE)
        {
                printf("ReadFile error %d\n", GetLastError());
        }
         
        CloseHandle(hFile);
         
        return  FileBuffer;
}
 
// 从文件拷贝到内存
LPVOID FileToMemory(LPVOID FileBuffer)
{
        PIMAGE_DOS_HEADER pImageDosHeader;
        PIMAGE_NT_HEADERS  pImageNtHeaders;
        PIMAGE_FILE_HEADER  pImageFileHeader;
        PIMAGE_OPTIONAL_HEADER pImageOptionalHeader;
        PIMAGE_SECTION_HEADER  pImageSectionHeader;
         
         
        pImageDosHeader = (PIMAGE_DOS_HEADER)FileBuffer;
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
        pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageNtHeaders+0x4);
        pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pImageFileHeader+sizeof(IMAGE_FILE_HEADER));
        pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImageFileHeader->SizeOfOptionalHeader);
         
        DWORD dwSizeofImage = pImageOptionalHeader->SizeOfImage;
        DWORD dwSizeofHeader = pImageOptionalHeader->SizeOfHeaders;
        LPVOID MemoryBuffer;
        int i;
         
         
        MemoryBuffer = VirtualAlloc(0,dwSizeofImage*0x10,MEM_COMMIT,PAGE_READWRITE);
         
        if ( MemoryBuffer == NULL)
        {
                printf("VirtualAlloc error %d\n", GetLastError());
        }
         
        memcpy(MemoryBuffer,FileBuffer,dwSizeofHeader);
         
        for ( i = 0; i < pImageFileHeader->NumberOfSections; i++)
        {
                memcpy(  (BYTE*)((DWORD)MemoryBuffer+ pImageSectionHeader.VirtualAddress),
                        (BYTE*)((DWORD)FileBuffer+ pImageSectionHeader.PointerToRawData),
                        pImageSectionHeader.SizeOfRawData);
        }
         
        return MemoryBuffer;
}
 
// 从内存拷贝到新的文件
LPVOID MemoryToNewFile(LPVOID MemoryBuffer)
{
        PIMAGE_DOS_HEADER pImageDosHeader;
        PIMAGE_NT_HEADERS  pImageNtHeaders;
        PIMAGE_FILE_HEADER  pImageFileHeader;
        PIMAGE_OPTIONAL_HEADER pImageOptionalHeader;
        PIMAGE_SECTION_HEADER  pImageSectionHeader;
         
         
        pImageDosHeader = (PIMAGE_DOS_HEADER)MemoryBuffer;
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
        pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageNtHeaders+0x4);
        pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pImageFileHeader+sizeof(IMAGE_FILE_HEADER));
        pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImageFileHeader->SizeOfOptionalHeader);
         
        DWORD dwSizeofImage = pImageOptionalHeader->SizeOfImage;
        DWORD dwSizeofHeader = pImageOptionalHeader->SizeOfHeaders;
        LPVOID NewFileBuffer;
        int i;
         
         
        NewFileBuffer = VirtualAlloc(0,dwSizeofImage,MEM_COMMIT,PAGE_READWRITE);
         
        if ( NewFileBuffer == NULL)
        {
                printf("VirtualAlloc error %d\n", GetLastError());
        }
         
        memcpy(NewFileBuffer,MemoryBuffer,dwSizeofHeader);
         
        for ( i = 0; i < pImageFileHeader->NumberOfSections; i++)
        {
                
                memcpy(  (BYTE*)((DWORD)NewFileBuffer+ pImageSectionHeader.PointerToRawData),
                        (BYTE*)((DWORD)MemoryBuffer+ pImageSectionHeader.VirtualAddress),
                        pImageSectionHeader.Misc.VirtualSize);
        }
         
        return NewFileBuffer;
         
}
 
// 存盘写文件
void WriteToFile(LPVOID NewFileBuffer)
{
         
        PIMAGE_DOS_HEADER pImageDosHeader;
        PIMAGE_NT_HEADERS  pImageNtHeaders;
        PIMAGE_FILE_HEADER  pImageFileHeader;
        PIMAGE_OPTIONAL_HEADER pImageOptionalHeader;
        PIMAGE_SECTION_HEADER  pImageSectionHeader;
         
        pImageDosHeader = (PIMAGE_DOS_HEADER)NewFileBuffer;
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
        pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageNtHeaders+0x4);
        pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pImageFileHeader+sizeof(IMAGE_FILE_HEADER));
        pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImageFileHeader->SizeOfOptionalHeader);
         
        HANDLE hNewFile;
        DWORD dwFileSize;
        DWORD lpNumberOfBytesWritten;
        BOOL bWrite;
         
        hNewFile = CreateFile(NewFilePath, GENERIC_ALL,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
         
        if ( hNewFile == NULL)
        {
                printf("CreateFile error %d\n", GetLastError());
        }
         
        int k = pImageFileHeader->NumberOfSections-1;
         
        dwFileSize = pImageSectionHeader[k].PointerToRawData + pImageSectionHeader[k].SizeOfRawData;
         
         
        bWrite = WriteFile(hNewFile,NewFileBuffer, dwFileSize,&lpNumberOfBytesWritten,NULL);
         
        if ( bWrite == FALSE)
        {
                printf("WriteFile error %d\n", GetLastError());
        }
         
    CloseHandle(hNewFile);
}
 
//增加节表
DWORD  AddSection(LPVOID MemoryBuffer, char* SectionName, DWORD SectionSize)
{
         
        PIMAGE_DOS_HEADER pImageDosHeader;
        PIMAGE_NT_HEADERS  pImageNtHeaders;
        PIMAGE_FILE_HEADER  pImageFileHeader;
        PIMAGE_OPTIONAL_HEADER pImageOptionalHeader;
        PIMAGE_SECTION_HEADER  pImageSectionHeader;
         
        pImageDosHeader = (PIMAGE_DOS_HEADER)MemoryBuffer;
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
        pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageNtHeaders+0x4);
        pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pImageFileHeader+sizeof(IMAGE_FILE_HEADER));
        pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImageFileHeader->SizeOfOptionalHeader);
         
        pImageOptionalHeader->DataDirectory[0xb].Size = 0;
        pImageOptionalHeader->DataDirectory[0xb].VirtualAddress = 0;
         
        DWORD AddFileAddress;
        DWORD AddMemAddress;
         
    int i = pImageFileHeader->NumberOfSections;
         
        pImageFileHeader->NumberOfSections += 0x1;
         
        AddFileAddress = pImageSectionHeader[i-1].PointerToRawData + pImageSectionHeader[i-1].SizeOfRawData;
        AddMemAddress = pImageSectionHeader[i-1].VirtualAddress+ pImageSectionHeader[i-1].Misc.VirtualSize;
         
        if ( AddFileAddress % 0x1000 )
        {
        AddFileAddress = (AddFileAddress+0x1000)&0xFFFFF000;
        }
         
        if ( AddMemAddress % 0x1000 )
        {
        AddMemAddress = (AddMemAddress+0x1000)&0xFFFFF000;
        }
         
        strcpy( (char*)pImageSectionHeader.Name, SectionName);
        pImageSectionHeader.PointerToRawData = AddFileAddress;
        pImageSectionHeader.VirtualAddress = AddMemAddress;
        pImageSectionHeader.SizeOfRawData = SectionSize;
        pImageSectionHeader.Misc.VirtualSize = SectionSize;
        pImageSectionHeader.Characteristics = 0xFFFFFFFF;
         
        pImageOptionalHeader->SizeOfImage = pImageSectionHeader.VirtualAddress+pImageSectionHeader.Misc.VirtualSize;
         
        DWORD AddSectionBuffer;
         
        AddSectionBuffer = (DWORD)MemoryBuffer+AddMemAddress;
         
         
        return AddSectionBuffer;
}
 
//输入表dll注入
int DLLInject(LPVOID MemoryBuffer,DWORD AddSectionBuffer)
{
        PIMAGE_DOS_HEADER pImageDosHeader;
        PIMAGE_NT_HEADERS  pImageNtHeaders;
        PIMAGE_FILE_HEADER  pImageFileHeader;
        PIMAGE_OPTIONAL_HEADER pImageOptionalHeader;
        PIMAGE_SECTION_HEADER  pImageSectionHeader;
        PIMAGE_IMPORT_DESCRIPTOR pImport;
         
        pImageDosHeader = (PIMAGE_DOS_HEADER)MemoryBuffer;
        pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
        pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageNtHeaders+0x4);
        pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pImageFileHeader+sizeof(IMAGE_FILE_HEADER));
        pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImageFileHeader->SizeOfOptionalHeader);        
        pImport=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)MemoryBuffer+pImageOptionalHeader->DataDirectory[1].VirtualAddress);
        DWORD TotalSize;
        DWORD* NewAddr=(DWORD*)AddSectionBuffer;
         
         
        //1.备份原IID结构
        memcpy(NewAddr,pImport,pImageOptionalHeader->DataDirectory[1].Size);
         
        //结束标记 以0结束
        memset((void*)((DWORD)NewAddr+pImageOptionalHeader->DataDirectory[1].Size),0,sizeof(_IMAGE_IMPORT_DESCRIPTOR));
         
        //2.在原IID 区域构造新的IID的OFT Name FT结构
        DWORD DLLNameRVA=(DWORD)pImport+0x16;
        char*DLLName="MsgDLL66.dll";
        DWORD DLLNameSize=(strlen(DLLName)+1+1)&0xe;
        memcpy((void*)DLLNameRVA,DLLName,DLLNameSize);
        DWORD ByNameRVA=DLLNameRVA+DLLNameSize;
        memset((void*)ByNameRVA,0,2);//hint填充为0
        char*FunName="Msg";
        DWORD FunNameSize=(strlen(FunName)+1+1)&0xe;
        memcpy((void*)(ByNameRVA+2),FunName,FunNameSize);
        *(DWORD*)pImport=ByNameRVA-(DWORD)MemoryBuffer;
        *(DWORD*)((DWORD)pImport+0x4)=0x0;
        *(DWORD*)((DWORD)pImport+0x8)=ByNameRVA-(DWORD)MemoryBuffer;
        *(DWORD*)((DWORD)pImport+0xc)=0x0;
         
        //3.填充新输入表项的IID结构
        PIMAGE_IMPORT_DESCRIPTOR NewIID=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)NewAddr+pImageOptionalHeader->DataDirectory[1].Size-sizeof(_IMAGE_IMPORT_DESCRIPTOR));
        NewIID->OriginalFirstThunk=(DWORD)pImport-(DWORD)MemoryBuffer;
        NewIID->Name=DLLNameRVA-(DWORD)MemoryBuffer;
        NewIID->FirstThunk=(DWORD)pImport+0x8-(DWORD)MemoryBuffer;
         
        //4.修正PE文件头的信息
        //修改.txt属性
        pImageSectionHeader[0].Characteristics=0xE0000020;
        //修改新节表的属性为0xFFFFFFFF 以及数据目录第B项改为00 (新增节时已经改了)
        //更正输入表的地址以及大小
        pImageOptionalHeader->DataDirectory[1].VirtualAddress=(DWORD)NewAddr-(DWORD)MemoryBuffer;
        pImageOptionalHeader->DataDirectory[1].Size+=sizeof(_IMAGE_IMPORT_DESCRIPTOR);
         
        return 0;
}
 
int main(int argc, char* argv[])
{
        LPVOID  FileBuffer;
        LPVOID  MemoryBuffer;
        LPVOID  NewFileBuffer;
        DWORD AddSectionBuffer;
        // 把文件读到Buffer里面
        FileBuffer = FileToBuffer();
         
        // 从文件拷贝到内存
        MemoryBuffer = FileToMemory(FileBuffer);
 
        //增加节表
        AddSectionBuffer = AddSection(MemoryBuffer, ".111", 0x1000);
 
        //DLL注入
        DLLInject(MemoryBuffer,AddSectionBuffer);
         
        // 从内存拷贝到新的文件
        NewFileBuffer = MemoryToNewFile(MemoryBuffer);
 
        // 存盘写文件
         WriteToFile(NewFileBuffer);
 
 
        printf("Hello World!\n");
        return 0;
}

四.测试效果
运行后在C盘生成了如下新文件
 


双击后在打开记事本之前首先弹出了我们注入的dll弹框
 


注入成功;;;;
我们再用od加载:
 


可以看到,我们的dll也在其中
用LordPE工具加载在输入表里也看到了我们自己写的dll
 


由此可见,dll注入确实成功啦


点击下载完整源码

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

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

相关文章

Zoho CRM有哪些优势?

CRM能帮助企业管理客户信息、跟进销售机会、提高客户转化&#xff0c;显著提升企业的竞争力&#xff0c;是企业发展的重要工具。市场上有很多CRM品牌&#xff0c;企业该如何选型&#xff1f;这里给大家分享一个不错的CRM品牌 Zoho CRM有哪些优势&#xff1f; 功能全面&#x…

jQuery-使用、选择器、属性、样式、文档、循环等操作

jQuery jQuery简介 jQuery是一个快速、简洁的JavaScript框架&#xff0c;是继Prototype之后又一个优秀的JavaScript代码库&#xff08;框架&#xff09;于2006年1月由[John Resig](https://baike.baidu.com/item/John Resig/6336344?fromModulelemma_inlink)发布。jQuery设计…

Docker安装ES+kibana8.9.1

参考&#xff1a;基于Docker安装Elasticsearch【保姆级教程、内含图解】_docker elasticsearch_Acloasia的博客-CSDN博客 创建网络 docker network create es-net 基于Docker安装Elasticsearch 拉取镜像 docker pull elasticsearch:8.9.1 挂载文件 mkdir -p /usr/local/e…

vue使用vant中的popup层,在popup层中加搜索功能后,input框获取焦点 ios机型的软键盘不会将popup顶起来的问题

1.使用vant的popup弹出层做了一个piker的选择器,用户需要在此基础上增加筛选功能。也就是输入框 2.可是在ios机型中,input框在获取焦点以后,ios的软键盘弹起会遮盖住我们的popup层,导致体验不是很好 3.在大佬的解答及帮助下,采用窗口滚动的方式解决此方法 <Popupv-model&q…

NGINX的速率限制(限流)

NGINX 的速率限制&#xff08;限流&#xff09; NGINX最有用但经常被误解和配置错误的功能之一是限流。它允许您限制用户在给定时间段内可以发出的HTTP请求量。 限流可以用于安全目的&#xff0c;例如减慢暴力破解密码的攻击。它可以通过限制请求速率为真实用户的典型值来帮助…

双目色彩一致性问题定位回顾

双目色彩一致性问题定位回顾 一、事情起因&#xff1a; 客户想要用一个主控搭载两颗相同的sensor&#xff0c;使用相同的镜头进行双目拼接以扩大视场角&#xff0c;达到类似广角镜头的效果&#xff1a; 双目采集的原始图像&#xff1a;图片来源&#xff1a;宇视全彩双目广角筒…

Python“牵手”速卖通商品列表数据,关键词搜索速卖通API接口数据,速卖通API接口申请指南

速卖通平台API接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范&#xff0c;速卖通API接口是指通过编程的方式&#xff0c;让开发者能够通过HTTP协议直接访问速卖通平台的数据&#xff0c;包括商品信息、店铺信息、物流信息等&#xff0c;从而实现速…

基于NXP i.MX 6ULL核心板的物联网模块开发案例(2)

目录 2 NB-IoT模块测试 2.1 获取IMEI和IMSI 2.2 创建云端NB-IoT设备 2.3 创建通信套件实例 2.3.1 生成配置参数 2.3.2 创建实例 前言 本文主要介绍基于创龙科技TLIMX6U-EVM评估板的物联网模块开发案例&#xff0c;适用开发环境&#xff1a; Windows开发环境&#xff1a;…

Docker 安装rabbitmq:3.12-management

拉取镜像&#xff1a; docker pull rabbitmq:3.12-management mkdir -p /usr/local/rabbitmq chmod 777 /usr/local/rabbitmq docker run -id --restartalways --namerabbitmq -v /usr/local/rabbitmq:/var/lib/rabbitmq -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_U…

助力品牌形象建设,FairGuard支持企业深度定制化

2022年&#xff0c;中国游戏市场实际销售收入与游戏用户规模出现近年来的首次下降&#xff0c;标志着游戏产业发展正式迈入存量时代。 存量市场时代&#xff0c;意味着游戏产品获取用户的难度逐渐加大&#xff0c;对于游戏的内容品质、技术实力和价值拓展等有了更高的要求。如…

恒运资本:什么是股票分红和基金分红?两者有什么区别?

出资者在进行股票出资和基金出资的时分&#xff0c;能够参与股票分红或许基金分红&#xff0c;可是许多新手对分红不是很了解。那么什么是股票分红和基金分红&#xff1f;两者有什么区别&#xff1f;下面就由恒运资本为大家分析&#xff1a; 什么是股票分红和基金分红&#xff…

C语言实例_实现malloc与free函数完成内存管理

一、malloc和free函数介绍 在C语言中&#xff0c;malloc和free是用于动态内存管理的函数。 &#xff08;1&#xff09;malloc函数 malloc函数用于在堆&#xff08;heap&#xff09;中分配指定大小的内存空间&#xff0c;并返回一个指向该内存块的指针。 原型如下&#xff1a…

718. 最长重复子数组

718. 最长重复子数组 原题链接&#xff1a;完成情况&#xff1a;题解&#xff1a;方法一&#xff1a;动态规划方法二&#xff1a;滑动窗口方法三&#xff1a;二分查找 哈希 原题链接&#xff1a; 718. 最长重复子数组 https://leetcode.cn/problems/maximum-length-of-repe…

XSS盲打练习(简单认识反射型、存储型XSS和cookie欺骗)

文章目录 挖掘cms网站XSS漏洞利用XSS平台盲打CMS&#xff0c;获取后台管理cookiecookie欺骗登录管理员账户 挖掘cms网站XSS漏洞 来到cms网站主页&#xff0c;发现有一个搜索框&#xff0c;输入任意内容后搜索&#xff0c;发现内容会回显&#xff0c;这里可能存在反射型XSS漏洞…

python爬虫11:实战3

python爬虫11&#xff1a;实战3 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网站产生不好…

springboot整合modbus4J(一)

springboot整合modbus4J 1. 介绍 (1) modbus poll&#xff1a;modbus主机仿真器&#xff0c;用于测试和调试modbus从设备。该软件支持modbus rtu、ASCII、TCP/IP。用来帮助开发人员测试modbus从设备&#xff0c;或者其它modbus协议的测试和仿真。它支持多文档接口&#xff0c…

阿里云服务器和腾讯云服务器折扣对比_哪家折扣低?

阿里云服务器和腾讯云服务器根据购买时长可以享受一定的优惠折扣&#xff0c;综合对比下来腾讯云折扣更低&#xff0c;阿腾云来对比下阿里云和腾讯云的云服务器根据购买时长可以享受的常规折扣对比&#xff1a; 目录 阿里云和腾讯云折扣对比 阿里云服务器常规折扣 腾讯云服…

逃出Verifier 无限蓝屏

逃出Verifier 无限蓝屏 前情提要&#xff1a;今天由于在处理 终止代码&#xff1a;WDF_VIOLATION 的蓝屏时&#xff0c;看到网上有用Verifier 来处理这个问题&#xff0c;但是按照方法处理后导致了Verifier无限蓝屏&#xff0c;重启就蓝屏&#xff0c;最后是进入安全模式操作&a…

软件测试及数据分析处理实训室建设方案

一 、系统概述 软件测试及数据分析处理是软件开发过程中的一项重要测试活动&#xff0c;旨在验证不同软件模块或组件之间的集成与交互是否正常。综合测试确保各个模块按照设计要求正确地协同工作&#xff0c;以实现整个软件系统的功能和性能。以下是软件测试及数据分析处理的一…

数据通信——TCP(三次握手及基础特性)

引言 TCP&#xff08;传输控制协议&#xff09;&#xff0c;不像之前的UDP那样&#xff0c;因为这个协议要将很多复杂的东西&#xff0c;所以这次的特性是简单的特性&#xff0c;后续会讲一些复杂难懂的知识&#xff0c;这次先说一些TCP明显的特性 面向连接 TCP提供了对连接的管…