Windows系统编程(五)静态库和动态库

在Windows中存在两种库,分别是静态库lib和动态库dll,它们都属于PE文件。这些库用于提供别人使用我们所写的功能而不会暴露源代码。

现在我们来讲解这两种库的使用方法

静态库

一.在VS中选择创建静态库,命名为Staticlib1

二.我们可以在该静态库中创建相关的头文件,以便封装函数

比如,现在我们创建一个Staticlib.h的头文件,声明了一个函数:void show();

现在在Staticlib1.cpp中包含该头文件并对其进行实现

void show()
{std::cout << “Hello Lib” << std::endl;
}

三.对该静态库进行相关属性的设置:C/C++->代码生成->Spectre缓解->已禁用,运行库->多线程调试

四.运行静态库以后,打开其所在文件夹,找到第二步创建的头文件,并进入debug找到lib文件,将两者进行复制以便接下来使用

五.创建一个新的控制台应用,项目属性修改为同静态库一致修改

六.粘贴我们第四步找到的两个文件到当前控制台应用所在文件夹下

七.在当前控制台应用中添加头文件将Staticlib.h头文件导入,并在该程序中进行包含

八.在当前控制台程序中包含该lib文件:

方法一:#pragma comment(lib,"路径")

方法二:项目属性-链接器-输入:附加依赖项:加入lib文件

九.此时便可以正常使用我们在静态库中定义的函数了

动态库

一.在VS中选择创建动态库,命名为dll1

此时便生成出来了一个动态链接库,在其dllmain.cpp文件中,其包含以下代码

BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call)
{//如果我们只是要从动态链接库中导出函数而不是在以下四个时机执行函数,那么以下四个选项没有用case DLL_PROCESS_ATTACH:    //附加到进程的时候触发事件break;case DLL_THREAD_ATTACH:     //附加到线程的时候触发事件break;case DLL_THREAD_DETACH:     //进程剥离的时候触发事件break;case DLL_PROCESS_DETACH:    //线程剥离的时候触发事件break;}return TRUE;
}

二.新建一个头文件mydll.h,用于声明函数;void show(const char* szBuffer);

三.新建一个.cpp文件用于实现该函数:

void show(const char* szBuffer)
{std::cout << szBuffer << std::endl;
}

四.对该动态链接库进行项目属性设置:C/C++->代码生成->Spectre缓解->已禁用,运行库->多线程调试

五.导出函数

注:名称粉碎机制,在我们利用PEtools等工具的时候观察动态库中导出的函数时,函数的名字是乱码

动态链接库导出函数有以下两种方法:

方法一:项目中添加模板定义文件,并在该文件写入以下代码:

LIBRARY
EXPORTS//如下书写我们的函数show(函数名)

方法二:在mydll.h中如此声明函数,具体有两种方式:

_declspec(dllexport)void show(const char* szBuffer);
//这种方式导出函数,会触发名称粉碎机制
extern"C"或EXTERN_C _declspec(dllexport)void show(const char* szBuffer);
//这种方式是以C语言的方式导出函数,不会触发名称粉碎机制

六.运行该动态链接库后,在其文件夹中找到mydll.h头文件以及在debug文件夹中找到dll文件进行复制以备后续使用

七.创建一个新的控制台应用,项目属性修改为同动态库一致修改

八.粘贴我们第六步找到的两个文件到当前控制台应用所在文件夹下

九.在当前控制台应用中添加头文件将mydll.h头文件导入,并在该程序中进行包含Windows.h头文件

十.在当前控制台应用通过以下代码方式便可以正常使用动态链接库中的函数了

接下来让我们看看,具体代码怎么书写

#include<iostream>
#include<Windows.h>
typedef void(*myshow)(const char* szBuffer)
int main()
{HMODOULE hDll = LoadLirary(L”dll1”); //在目标动态链接库中找到函数地址myshow func = (myshow)GetProcAddress(hDll, “show”); func(“sadd”);rertun 0;
}

此时运行程序便可正常使用动态链接库中的函数了

主动加载动态库事件

现在我们尝试在新项目主动加载动态链接库而非使用时,可以使其触发相关的事件
我们回到dllmain.cpp中,添加相关代码使其在加载到进程时可以发生弹窗

BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:    //附加到进程的时候触发事件MessageBox(NULL,L"加载模块","das",MB_OK);break;case DLL_THREAD_ATTACH:     //附加到线程的时候触发事件break;case DLL_THREAD_DETACH:     //进程剥离的时候触发事件break;case DLL_PROCESS_DETACH:    //线程剥离的时候触发事件break;}return TRUE;
}

此时我们回到原来的控制台项目中,开始运行程序。当动态链接库在进程加载的时候,会先弹出对话框,之后才会继续执行程序

远程注入DLL

在上述例子中我们已经见到了新项目主要加载动态链接库的情况,现在来尝试被动加载的情况  ,也就是远程注入DLL

接下来我们以上述加载了动态库的控制台项目去写一个远程注入DLL

#include<iostream>
#include<Windows.h>
void Inject(DWORD PID, const WCHAR * szBuffer)//远程注入的进程ID和DLL路径
{//获取目标进程句柄HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);//在目标进程内存中申请一段内存空间用于写入需要远程加载的dllLPVOID lpAddr = VirtualAllocEx(hProcess, NULL, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);//向内存中写入要注入的dll路径SIZE_T dwWrittenSize = 0;WriteProcessMemory(hProcess, lpAddr, szBuffer, (wcslen(szBuffer) + 1) * 2, &dwWrittenSize);//注意此处*2是因为我们此处使用的是宽字符集//创建远程线程HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryW, lpAddr, NULL, NULL);//当目标进程启动时会执行该远程线程执行LoadLibraryW函数WaitForSingleObject(hThread, -1);// 等待线程执行结束VirtualFreeEx(hProcess, lpAddr, 0, MEM_RELEASE);//内存释放CloseHandle(hProcess);CloseHandle(hThread);//关闭空闲句柄
}
int main()
{Inject(11996,L"路径")
}

此时,我们便可以将我们选中的DLL注入到目标进程了

接下来我们详解为什么CreateRemoteThread API的第四个参数为什么可以是LoadLibraryW

如下是CreateRemoteThread API原型:

CreateRemoteThread(_In_ HANDLE hProcess,_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,_In_ SIZE_T dwStackSize,_In_ LPTHREAD_START_ROUTINE lpStartAddress,_In_opt_ LPVOID lpParameter,_In_ DWORD dwCreationFlags,_Out_opt_ LPDWORD lpThreadId);

其中第四个参数是线程回调函数指针,这个参数是LPTHREAD_START_ROUTINE类型的,我们跟进去发现该类型的原型实际上是这样:

typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter);

我们再观察LoadLibraryW API:

HMODULE
WINAPI
LoadLibraryW(_In_ LPCWSTR lpLibFileName);

我们发现,它们的返回值都表示一个四字节整数,调用约定也是一样的,具体参数也是指向一段内存的指针。因此这两个函数本质是一样的。所以我们就可以把LoadLibraryW作为CreateRemoteThread的第四个参数。

注:LoadLibrary是加载线程,FreeLibrary是卸载线程

遍历模块

我们知道每个PE文件都是由多个模块组成,现在让我们去遍历获取这些模块

#include <TlHelp32.h>
#include<iostream>
#include<Windows.h>
void ShowModule(DWORD dwPid)
{//创建快照:HANDLE hSnap =CreateToolhelp32Snapshot(TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32,dwPid);MODULEENTRY32 me32 ={size0f(MODULEENTRY32)};while(MOdule32Next(hSnap,&me32)){printf(“%S\r\n”, me32.szModule); printf(“%S\r\n”, me32.szExePath);//注意打印需要格式化printf(“0x%X\r\n\n”,(DWORD)me32.modBaseAddr)//这里添加操作}
}
int main()
{ShowModule(21308);    
}

MFC动态链接库

一.在VS中选择创建MFC动态链接库,命名为MFCLibrary1,选择静态链接到MFC的常规DLL

二.MFC动态链接库只有一个入口点,并在其中添加代码

BOOL CMFCLibrary1App::InitInstance()
{CWinApp::InitInstance();MessageBox(L”qweq”, L“DHAO”, MB_OK);return TRUE;
}

三.运行该动态库以后,打开其所在文件夹进入debug找到dll文件,进行复制以便接下来使用

四.接下来就可以正常的将dll文件进行注入了

作业

1.实现远程线程注入功能,并且实现卸载功能

2.添加右键远程线程注入功能

3.添加打开模块功能,模块功能内可以右键卸载指定模块

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

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

相关文章

VGG16模型实现MNIST图像分类

MNIST图像数据集 MNIST&#xff08;Modified National Institute of Standards and Technology&#xff09;是一个经典的机器学习数据集&#xff0c;常用于训练和测试图像处理和机器学习算法&#xff0c;特别是在数字识别领域。该数据集包含了大约 7 万张手写数字图片&#xf…

喜讯 | 攸信技术入选第六批专精特新“小巨人”企业

日前&#xff0c;根据工信部评审结果&#xff0c;厦门市工业和信息化局公示了第六批专精特新“小巨人”企业和第三批专精特新“小巨人”复核通过企业名单&#xff0c;其中&#xff0c;厦门攸信信息技术有限公司进入第六批专精特新“小巨人”企业培育。 “专精特新”企业是指具有…

图像分割恢复方法

传统的图像分割方法主要依赖于图像的灰度值、纹理、颜色等特征&#xff0c;通过不同的算法将图像分割成多个区域。这些方法通常可以分为以下几类&#xff1a; 1.基于阈值的方法 2.基于边缘的方法 3.基于区域的方法 4.基于聚类的方法 下面详细介绍这些方法及其示例代码。 1. 基…

代码随想录--栈与队列--用栈实现队列

队列是先进先出&#xff0c;栈是先进后出。 如图所示&#xff1a; 题目 使用栈实现队列的下列操作&#xff1a; push(x) – 将一个元素放入队列的尾部。 pop() – 从队列首部移除元素。 peek() – 返回队列首部的元素。 empty() – 返回队列是否为空。 示例: MyQueue qu…

draw.io 设置默认字体及添加常用字体

需求描述 draw.io 是一个比较好的开源免费画图软件。但是其添加容器或者文本框时默认的字体是 Helvetica&#xff0c;一般的期刊、会议论文或者学位论文要求的英文字体是 Times New Roman&#xff0c;中文字体是 宋体&#xff0c;所以一般需要在文本字体选项里的下拉列表选择 …

分层解耦-05.IOCDI-DI详解

一.依赖注入的注解 在我们的项目中&#xff0c;EmpService的实现类有两个&#xff0c;分别是EmpServiceA和EmpServiceB。这两个实现类都加上Service注解。我们运行程序&#xff0c;就会报错。 这是因为我们依赖注入的注解Autowired默认是按照类型来寻找bean对象的进行依赖注入…

2-115 基于matlab的瞬态提取变换(TET)时频分析

基于matlab的瞬态提取变换&#xff08;TET&#xff09;时频分析&#xff0c;瞬态提取变换是一种比较新的TFA方法。该方法的分辨率较高&#xff0c;能够较好地提取出故障的瞬态特征&#xff0c;用于故障诊断领域。通过对原始振动信号设置不同信噪比噪声&#xff0c;对该方法的抗…

关于一个模仿qq通信程序

7月份的时候还在学校那个时候想要学习嵌入式Linux&#xff0c;但是还没有买开发板来玩&#xff0c;再学linux系统编程&#xff0c;网络编程&#xff0c;Linux系统的文件IO&#xff0c;于是学完之后想做一个模仿qq的通信程序于是就有了这个“ailun.exe”&#xff0c;因为暑假去打…

【数据结构与算法】线性表

文章目录 一.什么是线性表&#xff1f;二.线性表如何存储&#xff1f;三.线性表的类型 我们知道从应用中抽象出共性的逻辑结构和基本操作就是抽象数据类型&#xff0c;然后实现其存储结构和基本操作。下面我们依然按这个思路来认识线性表 一.什么是线性表&#xff1f; 定义 线性…

TryHackMe 第7天 | Web Fundamentals (二)

继续介绍一些 Web hacking 相关的漏洞。 IDOR IDOR (Insecure direct object reference)&#xff0c;不安全的对象直接引用&#xff0c;这是一种访问控制漏洞。 当 Web 服务器接收到用户提供的输入来检索对象时 (包括文件、数据、文档)&#xff0c;如果对用户输入数据过于信…

【springboot】使用代码生成器快速开发

接上一项目&#xff0c;使用mybatis-plus-generator实现简易代码文件生成 在fast-demo-web模块中的pom.xml中添加mybatis-plus-generator、freemarker和Lombok依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator&…

Python | 由高程计算坡度和坡向

写在前面 之前参加一个比赛&#xff0c;提供了中国的高程数据&#xff0c;可以基于该数据进一步计算坡度和坡向进行相关分析。 对于坡度和坡向&#xff0c;这里分享一个找到的库&#xff0c;可以方便快捷的计算。这个库为&#xff1a;RichDEM&#xff0c;官网地址如下 https…

SAP学习笔记 - 豆知识11 - 如何查询某个字段/DataElement/Domain在哪个表里使用?

大家知道SAP的表有10几万个&#xff08;也有说30多万个的&#xff0c;总之很多就是了&#xff09;&#xff0c;而且不断增多&#xff0c;那么当想知道一个字段在哪个表里使用的时候该怎么办呢&#xff1f; 思路就是SAP的表其实也是存在表里的&#xff1a;&#xff09;&#xf…

【Git】TortoiseGitPlink提示输入密码解决方法

问题 克隆仓库&#xff0c;TortoiseGitPlink提示输入密码 解法 1、打开TortoiseGit 下的puttygen工具 位置&#xff1a;C:\Program Files\TortoiseGit\bin\ 2、点击【Load】按钮&#xff0c;载入 C:\Users\Administrator\.ssh\ 文件夹下的id_rsa文件。 3、点击save private …

qt_c++_xml存这种复杂类型

demo&#xff0c;迅雷链接。或者我主页上传的资源 链接&#xff1a;https://pan.xunlei.com/s/VO8bIvYFfhmcrwF-7wmcPW1SA1?pwdnrp4# 复制这段内容后打开手机迅雷App&#xff0c;查看更方便 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>#include…

请散户股民看过来,密切关注两件大事

明天股市要开市&#xff0c;不仅散户股民期盼节后股市大涨&#xff0c;上面也同样想在节后来上一个“开门红”。 为此&#xff0c;上面没休假&#xff0c;关起门来办了两件大事&#xff0c;这两天发布消息已提前预热了。 两件大事如下&#xff1a; 一是&#xff0c;上交所10…

什么是 JavaScript 的数组空槽

JavaScript 中的数组空槽一直是一个非常有趣且颇具争议的话题。我们可能对它的实际意义、历史以及现今的新版本中对它的处理方式有所疑问。数组空槽的存在最早可以追溯到 JavaScript 的诞生之初&#xff0c;当时的设计决定让它成为了现代 JavaScript 开发中的一种特别的现象。 …

大数据新视界 --大数据大厂之数据血缘追踪与治理:确保数据可追溯性

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

计算机毕业设计hadoop+spark天气预测 天气可视化 天气大数据 空气质量检测 空气质量分析 气象大数据 气象分析 大数据毕业设计 大数据毕设

Hadoop天气预测系统开题报告 一、研究背景与意义 在信息化和大数据时代&#xff0c;天气数据已成为社会生活和经济发展中不可或缺的重要资源。天气预测系统作为现代气象学的重要组成部分&#xff0c;对于农业生产、交通管理、环境保护以及防灾减灾等方面都具有重要意义。然而…

集智书童 | 用于时态动作检测的预测反馈 DETR !

本文来源公众号“集智书童”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;用于时态动作检测的预测反馈 DETR ! 视频中的时间动作检测&#xff08;TAD&#xff09;是现实世界中的一个基本且具有挑战性的任务。得益于 Transformer …