热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

第二章基础技术

一、运行单一实例通过创建系统命名互斥对象的方式来实现1、实现原理通过CreateMutex函数创建一个命名的互斥对象,如果对象创建成功,而且通过调用GetLastError函数获取

一、运行单一实例

通过创建系统命名互斥对象的方式来实现


1、实现原理

通过CreateMutex函数创建一个命名的互斥对象,如果对象创建成功,而且通过调用GetLastError函数获取的返回码为ERROR_ALREADY_EXISTS,则表示该命名互斥对象存在,即程序重复运行。否则,认为程序首次运行。


2、API

CreateMutex

https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa


3、实现代码如下

#include
#include
#include
BOOL IsAlreadyRun()
{
HANDLE hMutex = NULL;
hMutex = ::CreateMutex(NULL, FALSE, _T("TEST"));
if (hMutex)
{
if (ERROR_ALREADY_EXISTS == ::GetLastError())
{
return true;
}
}
return false;
}
int main()
{
if (IsAlreadyRun())
{
printf("Already RUN");
system("pause");
}
else
{
printf("NOT Already Run");
system("pause");
}
}


4、小结

这个程序实现起来并不难,关键是熟悉CreateMutex函数的调用。在调用CreateMutex函数来创建命名的互斥对象时,注意互斥对象的名称不要与现有事件、信号量或者文件映射对象等名称相同,否则创建互斥对象会失败。

在实现过程中,特别要注意,程序一定不要调用CloseHandle函数来关闭由CreateMutex函数创建出来的互斥对象的句柄,否则会导致互斥对象判断失败。因为CloseHandle函数会关闭互斥对象的句柄,释放资源。这样,系统上便不会存在对应的命名互斥对象了,通过CreateMutex创建的命名互斥对象都是不会重复的。


5、安全小贴士

使用CreateMutex函数创建的互斥对象,可以通过调用CloseHandle函数来关闭互斥对象的句柄,从属于它的所有句柄都关闭后,就会删除该对象。

在线程同步操作中, ReleaseMutex函数可以释放线程对互斥对象的控制权。


二、DLL延迟加载

使用延迟加载方式编译链接可执行文件


1、实现原理

本程序以加载第三方库——skin++库为例进行讲解演示。首先导入skin++库文件,然后编码,最后对程序编译链接生成exe可执行文件。使用PE查看器PEview.exe查看可执行文件的导入表,便可知道可执行文件必需的DLL文件了。

这样做的好处是可以把必需的DLL文件以资源形式插入到程序中,并使用DLL延迟加载技术延迟加载。在正式调用必需的DLL之前,程序都是可以正常执行的。程序可以在这段时间内,把资源中的DLL释放到本地,等到正式调用DLL的时候释放的文件就会正确地加载执行。这样当使用程序的时候,只需把exe文件发送给用户,而不需要附加DLL文件了,也不需要担心程序会丢失DLL文件。

DLL延迟加载的具体设置步骤为:

属性-->链接器-->输入-->延迟加载的DLL-->输入:SkinPPWTL.dll


2、小结

DLL延迟加载技术不需要编码来实现,只需对VS开发环境设置链接器即可完成。DLL延迟加载技术,配合资源释放技术,可以使程序变得更加方便易用。


3、安全小贴士

在PE结构中, DLL延迟加载的信息存储在ImgDelayDescr延迟导入表中,可以通过数据目录DataDirectory中的IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT项获取延迟导入表RVA相对的偏移地址和数据大小。


三、资源释放

病毒木马之所以会广泛使用资源释放技术,是因为它可以使程序变得更简洁。如果程序额外需要加载一些DLL文件、文本文件、图片文件,或者其他的音/视频文件等,则可以把它们作为资源插入到程序里,等到程序运行后,再把它们释放到本地上。这样做的好处是编译出来的程序只有一个exe文件,而不需要附带其他文件,因而程序变得很简洁。只需把exe植入到用户计算机上,而不需要连同其他文件一起植入,这降低了被发现的风险。


1、资源插入步骤

首先新建一个资源520.txt



再自定义添加对话框



最后,导入该对话框


2、API

FindResource 确定模块中指定类型和名称的资源所在位置

https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-findresourcea

sizeofResource 获取指定资源的字节数

https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-sizeofresource

LoadResource 装载指定资源到全局存储器

https://docs.microsoft.com/en-us/previous-versions/ms915421(v=msdn.10)

LockResource 锁定资源并得到资源在内存中第一个字节的指针

https://docs.microsoft.com/en-us/previous-versions/aa932898(v=msdn.10)


3、实现原理

首先,通过FindResource定位程序里的资源,主要是根据"资源类型"和"资源名称"进行定位,从而获取资源信息块的句柄.

其次,根据上面获取的资源信息块的句柄,利用sizeofResource获取资源的大小之后,再通过LoadResource把资源加载程序内存中.

接着,通过LockResource锁定加载到内存中的资源,防止程序中的其他操作影响这块内存。其中,返回值就是资源在进程内存中的起始地址。

最后,根据资源大小以及进程内存的起始地址,可将资源数据读取出来并保存为本地文件。

注意:要必须明确资源所在的模块,要指明所在模块句柄并且统一。


4、实现代码如下

#include
#include
#include "resource.h"
void FreeRes_ShowError(char* pszText)
{
char szErr[MAX_PATH] = { 0 };
wsprintf(szErr, "%s Error[%d]\n", pszText, ::GetLastError());
}
BOOL FreeMyResource(UINT uiResourceName, char* lpszResourceType, char *lpszSaveFileName)
{
//获取指定模块里的资源
HRSRC hRsrc = ::FindResource(NULL, MAKEINTRESOURCE(uiResourceName), lpszResourceType);
if (NULL == hRsrc)
{
FreeRes_ShowError("FindResource");
return FALSE;
}
// 获取资源的大小
DWORD dwSize = ::SizeofResource(NULL, hRsrc);
if (0 >= dwSize)
{
FreeRes_ShowError("SizeofResource");
return FALSE;
}
// 将资源加载到内存里
HGLOBAL hGlobal = ::LoadResource(NULL, hRsrc);
if (NULL == hGlobal)
{
FreeRes_ShowError("LoadResource");
return FALSE;
}
// 锁定资源
LPVOID lpVoid = ::LockResource(hGlobal);
if (NULL == lpVoid)
{
FreeRes_ShowError("LockResource");
return FALSE;
}
// 保存资源为文件
FILE* fp = NULL;
fopen_s(&fp, lpszSaveFileName, "wb+");
if (NULL == fp)
{
FreeRes_ShowError("LockResource");
return FALSE;
}
fwrite(lpVoid, sizeof(char), dwSize, fp);
fclose(fp);
return TRUE;
}
int main(){
char szSaveName[MAX_PATH] = "520.txt";
// 释放资源
BOOL bRet = FreeMyResource(IDR_MYRES2, "MYRES", szSaveName);
if (FALSE == bRet)
{
MessageBox(NULL, "Free Resource Error!", "ERROR", MB_OK);
}
else
{
MessageBox(NULL, "Free Resource OK!", "OK", MB_OK);
}
return 0;

}



推荐阅读
  • 深入分析 Linux 内核链表转
    引用地址:http:www.ibm.comdeveloperworkscnlinuxkernell-chainindex.html一、链表数据结构简介链表是一种常用的 ... [详细]
  • 文章目录1.注释2.定义变量3.条件语句4.循环标签5.Velocity中的宏6.debug语法标签7.不存在的变量显示为空白8.本地文件引入9.调用类方法1.注释单行注释:# ... [详细]
  • 实验目的:统计文章单词数实验内容:*程序头部注释开始*程序的版权和版本声明部分*Copyright(c)2011,烟台大学计算机学院学生*Copyri ... [详细]
  • codeproject 调试技巧 学习笔记
    http:www.codeproject.comKBtracemytracer.aspxAsimplesolutiontoseetheinsideofyourcodeKEYWORD ... [详细]
  • 我有一个用C#编写的服务器,需要从Java1.6与之对话.我需要连接到服务器,保持连接,并双向发送消息.消息是一个int(消息的长度),然后是一个XML文件.做这个的最好方式是什么 ... [详细]
  • 1http:blog.csdn.netlfdfhlarticledetails8220729代码如下:imageView.startAnimation(welcomeAnimation) ... [详细]
  • MPI的全称是MessagePassingInterface即标准消息传递界面,可以用于并行计算。MPI的具体实现一般采用MPICH。下面介绍如何在WindowsXP系统下VC6中搭建MPI环境 ... [详细]
  • 打开文件是由参数-filename指定标识文件,将其与流对象相关联,以便对文件内容执行输入/输出操作。参数-mode指定打开模式。 ... [详细]
  • 我正在使用getusermedia()将网络摄像头用于在线应用程序。我正在使用LogitechC ... [详细]
  • 深入探索String、StringBuffer和StringBuilder区别(源码 + 代码验证)
    String、StringBuffer和StringBuilder都是Java中用来表示字符串的。在Java中,String类是一个不可变类,任何对St ... [详细]
  • 开发笔记:LA2995  Image is everything
    本文由编程笔记#小编为大家整理,主要介绍了LA2995Imageiseverything相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 视频鉴黄提供视频内容检测,识别视频中是否存在色情内容。支持存储在七牛云bucket(支持华东、华北和华南bucket)或非七牛云bucket中的视频进行视频鉴黄。支持 ... [详细]
  • vs中检测内存泄漏的方法分类:MFC2013-03-0821:442764人阅读评论(0)收藏举报使用vs的内存检测有以下几种方法。在debug模式下以F5运行:方法一:[html ... [详细]
  • 实验十:指针
    #includevoidsplitfloat(floatx,int*intpart,float*fracpart);intmain(void){intintpa ... [详细]
  • <selectnameBigClassName><optionvalue>请选择一级分类& ... [详细]
author-avatar
single
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有