windows黑客编程系列(一)
由于课题需要,不得不转行windows PE文件的研究,需要接触windows黑客编程。
本文为《windows黑客编程技术详解》读书笔记。
新建windows编程系列笔记,待课题结束,回归ELF。
使用codeblocks新建一个win32 GUI程序
打开codeblocks -> create a new project -> 选择win32 GUI project -> Go -> 选择frame based -> 输入工程名字即可
新建win32 GUI工程的主程序
- 红框圈出部分为该程序的入口函数
运行单一实例
大多数的病毒木马在成功植入用户计算机之后,在执行核心恶意代码之前,都会先进行初始化操作。在初始化操作中有一个很重要的点,运行单一实例。
如果病毒木马被多次运行,系统中会存在多份病毒木马的进程,那么,这就有可能增加暴露的风险。所以要想解决上述问题,就要确保系统中只运行一个病毒木马的进程。
要确保只运行一个进程实例的实现方法有很多,它可以通过扫描进程列表来实现,可以通过枚举程序窗口来实现,也可以通过共享全局变量来实现。
下面介绍一种使用广泛且应用简单的方法,即通过创建系统命名互斥对象的方式来实现。
函数介绍
CreateMutex函数
创建或打开一个已命名或未命名的互斥对象
HANDLE WINAPI CreateMutex
(
LPSECURITY_ATTRIBUTES ipMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
)
- 第一个参数:指向SECURITY_ATTRIBUTES结构的指针,如果此参数为NULL,则该举兵不能由子进程继承
- 第二个参数:如果此值为TRUE并且调用者创建了互斥锁,否则线程不会获得互斥锁的所有权
- 第三个参数:互斥对象的名称,该名称仅限于MAX_PATH字符,名称区分大小写。如果为NULL,则会创建不带名称的互斥对象
返回值
- 如果函数成功,则返回值为新创建的互斥对象的句柄
- 如果函数失败,则返回值为NULL。要获得扩展的错误信息,需要调用GetLastError函数
- 如果互斥锁是一个已命名的互斥锁,并且该对象在此函数调用之前就存在,则返回值是现有对象的句柄,GetLastError哈桑农户返回ERROE_ALREADY_EISTS。
实现原理
通常情况下,系统中的进程是相互独立的,每个进程都拥有自己的独立资源和地址空间,进程间互不影响。所以,同一个进程可以重复运行,但系统上的进程互不影响。但是在一些特殊情况下,程序在系统上需要只保存一份进程实例,这就引起了进程互斥的问题。
CreateMutex函数一共三个参数:
- 第一个参数表示互斥对象的安全设置,直接设置为NULL即可。
- 第二个参数表示线程是否获得互斥锁对象的初始所有权,在本程序中无论为TRUE还是FALSE,均不影响程序的正常运行。
- 第三个参数表示互斥对象的名称,对于通过互斥对象来判断进程实例是否重复运行的程序来说,该参数一定要设置,而且要保证设置名称的唯一性。
如何判断是否重复运行
判断原理十通过该函数创建一个命名的互斥对象,如果对象创建成功,而且通过GetLastError函数获取的返回码为ERROE_ALREADY_EISTS,则表示该命名互斥对象存在,即程序重复运行。否则认为程序是首次运行。
函数实现
BOOL IsAlreadyRun()
{
HANDLE hmutex = NULL;
hmutex = ::CreateMutex(NULL, FALSE, "TEST");
if (hmutex)
{
if (ERROR_ALREADY_EXISTS == ::GetLastError())
return TRUE;
}
return FALSE;
}
函数效果
- 转到存放源程序的目录
- 在该目录下的bin\Debug目录下
- 双击运行编译生成的exe文件
第一次运行效果图:
第一次运行的窗口不关闭,进行第二次运行
可以发现程序按照我们想要的逻辑往下走,给出了已经重复运行的提示
完整源代码
#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#include <tchar.h>
#include <windows.h>
#include <stdio.h>
BOOL IsAlreadyRun()
{
HANDLE hmutex = NULL;
hmutex = ::CreateMutex(NULL, FALSE, "TEST");
if (hmutex)
{
if (ERROR_ALREADY_EXISTS == ::GetLastError())
return TRUE;
}
return FALSE;
}
int WINAPI WinMain (HINSTANCE hThisInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nCmdShow)
{
BOOL flag = IsAlreadyRun();
if (flag == TRUE)
printf("Already Run\n");
else
printf("Not Already Run\n");
system("pause");
return 0;
}
安全提示
- 使用该函数进行创建的互斥对象,可以通过调用CloseHandle函数来关闭互斥对象的句柄,从属于他的所有句柄都关闭后,就会删除该对象。
- 在本程序中不要使用CloseHandle函数来关闭CreateMutex函数创建的互斥对象的句柄,关闭句柄的同时会释放资源,系统上也就不会存在对应的命名互斥对象了,我们的程序逻辑也会出现问题,因为已经没办法判断了该互斥对象是否在内存中运行了。
- 在线程同步操作中,ReleaseMutex函数可以释放线程对互斥对象的控制权。