前言
进程注入 ,简而言之就是将代码注入到另一个进程中,跨进程内存注入,即攻击者将其代码隐藏在合法进程中,长期以来一直被用作逃避检测的手段.
进程的注入方式可以分为DLL注入和shellcode注入,这两种方式本质上没有区别,在操作系统层面上,dll也就是shellcode的汇编代码。
代码框架
想法是尽量用一个通用的注入框架,有异常接收,令牌权限开启,获取进程PID的功能,只需要在main函数中调用不同的注入方式:
#include "public.h"
int main() {
DWORD pid = GetPid();
if (pid == 0) {
ShowError("Getpid");
return -1;
}
//std::cout<<"Pid:" << pid << std::endl;
if (!EnableDebugPrivilege(TRUE)) {
ShowError("EnableDebugPrivilege");
return -1;
}
BOOL bRet = Inject(DWORD dwPid, CHAR code[]);
if (bRet != TRUE)
{
ShowError("Inject");
return -1;
}
system("pause");
return 0;
}
BOOL Inject(DWORD dwPid, CHAR code[])
{
BOOL ret = TRUE;
return ret;
}
获取进程pid
主要实现通过进程名称获取进程Pid,代码很简单如下:
DWORD GetPid() {
//获取进程快照
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
//创建进程结构体
PROCESSENTRY32 process = { 0 };
process.dwSize = sizeof(process);
if (Process32First(snapshot, &process)) {
do {
if (!wcscmp(process.szExeFile, L"notepad.exe"))
break;
} while (Process32Next(snapshot, &process));
}
CloseHandle(snapshot);
return process.th32ProcessID;
}
错误处理
错误、异常处理,用来接收的返回值GetLastError():
VOID ShowError(PCHAR msg)
{
printf("%s Error %d\n", msg, GetLastError());
}
进程提权
AdjustTokenPrivileges
在进程注入中,如果要对其他进程(包括系统进程和服务进程)进行注入,需要获取当前进程的SeDeBug权限来调用OpenProcess打开要注入的进程。如果用户是管理员组下的成员是具有该权限的。
但是当我们用Administrator身份去打开一个进程时,还是会出现拒绝访问的错误:
错误代码为5表示拒绝访问:
这是因为默认情况下,某些进程的访问权限是没有开启的。所谓的"提权",其实就是将原有的权限开启,并不是真正意思上的提权,微软提供了一些可供我们修改令牌权限,比如: