#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
typedef struct _THREAD_PARAM
{
FARPROC pFunc[2]; // LoadLibraryA(), GetProcAddress()
char szBuf[4][128]; // 接收传递过来的"user32.dll", "MessageBoxA", "www.xuenixiang.com", "Shin"这些字符串
} THREAD_PARAM, *PTHREAD_PARAM;
typedef HMODULE(WINAPI *PFLOADLIBRARYA)
(
LPCSTR lpLibFileName
);
typedef FARPROC(WINAPI *PFGETPROCADDRESS)//如果函数调用成功,返回值是DLL中的输出函数地址
(
HMODULE hModule,//dll模块句柄
LPCSTR lpProcName;//函数名
);
typedef int (WINAPI *PFMESSAGEBOXA)//MessageBoxA传参结构体
(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
DWORD WINAPI ThreadProc(LPVOID lParam)//线程的起始地址,线程创建成功,返回非零值,否则为0
{
PTHREAD_PARAM pParam = (PTHREAD_PARAM)lParam;//接收线程传递给函数使用的CreateThread函数lpParameter参数数据
HMODULE hMod = NULL;
FARPROC pFunc = NULL;
// LoadLibrary()
hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]); // "user32.dll"
if (!hMod)
return 1;
// GetProcAddress()
pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]); // "MessageBoxA"
if (!pFunc)
return 1;
// MessageBoxA()
((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);
return 0;
}
BOOL InjectCode(DWORD dwPID)//代码注入的核心部分
{
HMODULE hMod = NULL;
THREAD_PARAM param = { 0, };
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
LPVOID pRemoteBuf[2] = { 0, };
DWORD dwSize = 0;
hMod = GetModuleHandleA("kernel32.dll");//获取kernel32.dll动态链接库的模块句柄
// set THREAD_PARAM
param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");//返回值是DLL中LoadLibraryA函数的地址
param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
strcpy_s(param.szBuf[0], "user32.dll");
strcpy_s(param.szBuf[1], "MessageBoxA");
strcpy_s(param.szBuf[2], "www.xuenixiang.com");
strcpy_s(param.szBuf[3], "Shin");
// Open Process 打开一个已存在的进程对象,并返回进程的句柄
if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, // dwDesiredAccess
FALSE, // bInheritHandle
dwPID))) // dwProcessId
{
printf("OpenProcess() fail : err_code = %d\n", GetLastError());
return FALSE;
}
// Allocation for THREAD_PARAM
dwSize = sizeof(THREAD_PARAM);
if (!(pRemoteBuf[0] = VirtualAllocEx(hProcess, // hProcess
NULL, // lpAddress
dwSize, // dwSize
MEM_COMMIT, // flAllocationType
PAGE_READWRITE))) // flProtect
{
printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
return FALSE;
}
/*hProcess 由OpenProcess返回的进程句柄。
如参数传数据为 INVALID_HANDLE_VALUE 【即 - 1】目标进程为自身进程
lpBaseAddress要写的内存首地址
再写入之前,此函数将先检查目标地址是否可用,并能容纳待写入的数据。
lpBuffer
指向要写的数据的指针。
nSize
要写入的字节数。
返回值
非零值代表成功。
可用GetLastError获取更多的错误详细信息。*/
if (!WriteProcessMemory(hProcess, // hProcess
pRemoteBuf[0], // lpBaseAddress
(LPVOID)¶m, // lpBuffer
dwSize, // nSize
NULL)) // [out] lpNumberOfBytesWritten
{
printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
return FALSE;
}
// Allocation for ThreadProc() 为线程函数申请内存空间 执行成功就返回分配内存的首地址,不成功就是NULL
dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
if (!(pRemoteBuf[1] = VirtualAllocEx(hProcess, // hProcess
NULL, // lpAddress
dwSize, // dwSize
MEM_COMMIT, // flAllocationType
PAGE_EXECUTE_READWRITE))) // flProtect
{
printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
return FALSE;
}
if (!WriteProcessMemory(hProcess, // hProcess
pRemoteBuf[1], // lpBaseAddress
(LPVOID)ThreadProc, // lpBuffer
dwSize, // nSize
NULL)) // [out] lpNumberOfBytesWritten
{
printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
return FALSE;
}
if (!(hThread = CreateRemoteThread(hProcess, // hProcess
NULL, // lpThreadAttributes
0, // dwStackSize
(LPTHREAD_START_ROUTINE)pRemoteBuf[1], // dwStackSize
pRemoteBuf[0], // lpParameter
0, // dwCreationFlags
NULL))) // lpThreadId
{
printf("CreateRemoteThread() fail : err_code = %d\n", GetLastError());
return FALSE;
}
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;
//要对一个任意进程(包括系统安全进程和服务进程)进行指定了写相关的访问权的OpenProcess操作,
//只要当前进程具有SeDeDebug权限就可以了。要是一个用户是Administrator或是被给予了相应的权限,
//就可以具有该权限。可是,就算我们用Administrator帐号对一个系统安全进程执行
//OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID)还是会遇到“访问拒绝”的错误。什么原因呢?
//原来在默认的情况下进程的一些访问权限是没有被启用(Enabled)的,所以我们要做的首先是启用这些权限。
//与此相关的一些API函数有OpenProcessToken、LookupPrivilegevalue、AdjustTokenPrivileges。
//我们要修改一个进程的访问令牌,首先要获得进程访问令牌的句柄,这可以通过OpenProcessToken得到
if (!OpenProcessToken(GetCurrentProcess(),//用来打开与进程相关联的访问令牌
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
{
printf("OpenProcessToken error: %u\n", GetLastError());
return FALSE;
}
if (!LookupPrivilegeValue(NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if (!AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
int main(int argc, char *argv[])
{
DWORD dwPID = 0;
if (argc != 2)
{
printf("\n USAGE : %s <pid>\n", argv[0]);
return 1;
}
// change privilege
if (!SetPrivilege(SE_DEBUG_NAME, TRUE))
return 1;
// code injection
dwPID = (DWORD)atol(argv[1]);
InjectCode(dwPID);
return 0;
}