代码注入

// CodeInjection.cpp
// reversecore@gmail.com
// http://www.reversecore.com

#include "windows.h"
#include "stdio.h"

typedef struct _THREAD_PARAM
{
	FARPROC pFunc[2];               // LoadLibraryA(), GetProcAddress()
	char    szBuf[4][128];          // "user32.dll", "MessageBoxA", "www.reversecore.com", "ReverseCore"
} THREAD_PARAM, * PTHREAD_PARAM;

typedef HMODULE(WINAPI* PFLOADLIBRARYA)
(
	LPCSTR lpLibFileName
	);

typedef FARPROC(WINAPI* PFGETPROCADDRESS)
(
	HMODULE hModule,
	LPCSTR lpProcName
	);

typedef int (WINAPI* PFMESSAGEBOXA)
(
	HWND hWnd,
	LPCSTR lpText,
	LPCSTR lpCaption,
	UINT uType
	);

DWORD WINAPI ThreadProc(LPVOID lParam)
{
	PTHREAD_PARAM   pParam = (PTHREAD_PARAM)lParam;
	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");

	// set THREAD_PARAM
	param.pFunc[0] = GetProcAddress(hMod, "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.reversecore.com");
	strcpy_s(param.szBuf[3], "ReverseCore");

	// 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;
	}

	if (!WriteProcessMemory(hProcess,                       // hProcess
		pRemoteBuf[0],                  // lpBaseAddress
		(LPVOID)& param,                 // lpBuffer
		dwSize,                         // nSize
		NULL))                         // [out] lpNumberOfBytesWritten
	{
		printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
		return FALSE;
	}

	// Allocation for ThreadProc()
	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;

	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;
}

  一堆typedef是针对C语言语法的,定义了函数和结构体。

  先看main函数,argc,argv上一篇DLL注入说明过。

  SetPrivilege函数,是权限问题。

  然后获取进程号(PID),atol是把字符串转换为长整型。

  然后调用InjectCode函数,注入代码。

 

 接下来我们看看SetPrivilege函数。  

typedef struct _TOKEN_PRIVILEGES
{
ULONG PrivilegeCount; //数组元素的个数
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; //数组.类型为LUID_AND_ATTRIBUTES
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
先定义了一个结构体,此结构体原型如上。
 
OpenProcessToken函数就是要让进程可以更改权限。
BOOL OpenProcessToken(
HANDLE ProcessHandle,
DWORD DesiredAccess,
PHANDLE TokenHandle
);
第一參数是要改动访问权限的进程句柄。(GetCurrentProcess函数可以获得当前进程的访问令牌的句柄)
第三个參数就是返回的访问令牌指针,返回一个句柄;
第二个參数指定你要进行的操作类型。如要改动令牌我们要指定第二个參数为TOKEN_ADJUST_PRIVILEGES。


LookupPrivilegeValue 函数查看系统权限的特权值,返回信息到一个LUID结构体里。
  BOOL LookupPrivilegeValue(LPCTSTR lpSystemName,LPCTSTR lpName,PLUID lpLuid);
  第一个参数表示所要查看的系统,本地系统直接用NULL
  第二个参数表示所要查看的特权信息的名称,定义在winnt.h中。(此处在main中传进来权限参数)
  第三个参数用来接收所返回的制定特权名称的信息。
  函数调用成功后,信息存入第三个类型为LUID的结构体中,并且函数返回非0。

 

然后给tp结构体赋值。使用AdjustTokenPrivileges函数调整权限。

BOOL AdjustTokenPrivileges(
HANDLE TokenHandle, // handle to token
BOOL DisableAllPrivileges, // disabling option
PTOKEN_PRIVILEGES NewState, // privilege information
DWORD BufferLength, // size of buffer
PTOKEN_PRIVILEGES PreviousState, // original state buffer
PDWORD ReturnLength // required buffer size
);
第一个參数是訪问令牌的句柄。第二个參数决定是进行权限改动还是除能(Disable)全部权限;第三个參数指明要改动的权限,是一个指向TOKEN_PRIVILEGES结构的指针,该结构包括一个数组。数据组的每一个项指明了权限的类型和
要进行的操作;

第四个參数是结构PreviousState的长度。假设PreviousState为空,该參数应为NULL;第五个參数也是一个指向TOKEN_PRIVILEGES结构的指针,存放改动前的訪问权限的信息,可空。最后一个參数为实际PreviousState结构返回的大小。

然后我们分析InjectCode函数。
这个函数中大部分都分析过,所以主要分析一下注入过程吧。

1.设置线程参数(THREAD_PARAM)
2.获取进程句柄。
3.分配内存0。
4.在内存0中写入ThreadProc的参数。
5.分配内存1。(此处计算函数大小是用InjectCode函数起始地址减去ThreadProc函数起始地址,因为两函数紧挨,所以相减即为ThreadProc函数的大小。)
6.在内存1中写入ThreadProc函数。
7.调用CreateRemoteThread函数创建线程。
到此注入就完成了。
 
posted @ 2019-07-09 20:40  s1lenc3  阅读(378)  评论(0编辑  收藏  举报