代码注入技术

代码注入相对DLL注入来说更加隐蔽,但是对技术的要求要更高,个人以为代码注入最好注入稳定的Shellcode。代码注入需要用到的API有VirtualAllocEx、WriteProcessMemory、CreateRemoteThread,类似于DLL注入。通常VirtualAllocEx和WriteProcessMemory会被调用两次,分别是处理线程函数以及线程函数参数,然后通过调用CreateRemoteThread来执行代码。当如如果是注入Shellcode就只要调用一次就够了,如果是注入线程函数,需要正确的计算函数的大小,通过#pragma check_stack指令来实现(静态函数、同时关闭增量链接、Release版本)。下面的代码是一个演示弹出MessageBox的代码注入:

// CodeInjector.h
#ifndef _CODE_INJECTOR_H__
#define _CODE_INJECTOR_H__
 
#include <windows.h>
 
#define CHECK_NULL_RET(bCondition) if (!bCondition) goto Exit0
 
#define REMOTE_ALLOC_SIZE (1024 * 4)
 
#endif

// Main.cpp
// Author: 代码疯子
// Blog: http://www.programlife.net/
#include <stdio.h>
#include <string.h>
#include "CodeInjector.h"
 
typedef struct _INJECT_PARAM
{
	CHAR szMsgTitle[64];
	CHAR szMsgContent[256];
 
	DWORD dwMessageBoxA;
} INJECT_PARAM, *PINJECT_PARAM;
 
#pragma check_stack(off)
static DWORD WINAPI RemoteThreadProc(LPVOID lpParameter)
{
	typedef int (WINAPI *PFN_MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
	PINJECT_PARAM lpParam = (PINJECT_PARAM)lpParameter;
	PFN_MessageBoxA pfnMessageBoxA = (PFN_MessageBoxA)lpParam->dwMessageBoxA;
 
	pfnMessageBoxA(NULL, lpParam->szMsgContent, lpParam->szMsgTitle, MB_ICONWARNING);
 
	return TRUE;
}
 
static void AfterRemoteThreadProc(void){ return ;}
#pragma check_stack
 
BOOL EnableDebugPrivilege(void)
{
	HANDLE hToken; 
	TOKEN_PRIVILEGES tkp;
	BOOL bRet = FALSE;
 
	bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
	CHECK_NULL_RET(bRet);
 
	bRet = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
	CHECK_NULL_RET(bRet);
	tkp.PrivilegeCount = 1;  
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
 
	bRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
	CHECK_NULL_RET(bRet);
	bRet = TRUE;
 
Exit0:
	CloseHandle(hToken);
	return bRet;
}
 
BOOL InjectCode(DWORD dwPid)
{
	BOOL bRet = FALSE;
	HANDLE hProcess = NULL;
	LPVOID lpThreadProc = NULL;
	DWORD dwResult = 0;
	HANDLE hThread = NULL;
	DWORD dwThreadProcSize = 0;
	INJECT_PARAM stParam = {0};
	LPVOID lpParam = NULL;
 
	bRet = EnableDebugPrivilege();
	CHECK_NULL_RET(bRet);
 
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
	CHECK_NULL_RET(bRet);
 
	// Allocate memory for ThreadProc
	lpThreadProc = VirtualAllocEx(hProcess, NULL, REMOTE_ALLOC_SIZE, 
		MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	CHECK_NULL_RET(lpThreadProc);
 
	dwThreadProcSize = (BYTE *)AfterRemoteThreadProc - (BYTE *)RemoteThreadProc;
	bRet = WriteProcessMemory(hProcess, lpThreadProc, (LPVOID)RemoteThreadProc, 
				dwThreadProcSize, &dwResult);
	CHECK_NULL_RET(bRet);
 
	HMODULE hUser32 = LoadLibrary(TEXT("user32.dll"));
	stParam.dwMessageBoxA = (DWORD)GetProcAddress(hUser32, "MessageBoxA");
 
	strcpy(stParam.szMsgTitle, "Just a Test");
	strcpy(stParam.szMsgContent, "Http://Www.ProgramLife.Net/");
 
	// Allocate memory for parameter
	lpParam = VirtualAllocEx(hProcess, NULL, sizeof(INJECT_PARAM), 
		MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	CHECK_NULL_RET(lpParam);
 
	bRet = WriteProcessMemory(hProcess, lpParam, (LPVOID)&stParam, 
		sizeof(stParam), &dwResult);
	CHECK_NULL_RET(bRet);
 
	hThread = CreateRemoteThread(
				hProcess,
				NULL,
				0,
				(LPTHREAD_START_ROUTINE)lpThreadProc,
				lpParam,
				0,
				NULL);
	CHECK_NULL_RET(hThread);
 
	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hThread);
 
Exit0:
	if (NULL != lpThreadProc)
	{
		VirtualFreeEx(hProcess, lpThreadProc, 0, MEM_RELEASE);
	}
	if (NULL != lpParam)
	{
		VirtualFreeEx(hProcess, lpParam, 0, MEM_RELEASE);
	}
	CloseHandle(hProcess);
	return bRet;
}
 
int main(int argc, char **argv)
{
	if (argc != 2)
	{
		printf("Usage: %s PID\n",
		return 1;
	}
 
	DWORD dwPid = atoi(argv[1]);
	InjectCode(dwPid);
 
	return 0;
}
恶意软件跨进程代码注入技术


如果是直接注入Shellcode,只需要为Shellcode分配空间,然后调用CreateRemoteThread执行即可。

DWORD ReadShellcode(BYTE *pShellcode, CHAR *szShellcode)
{
	HANDLE hFile = CreateFileA(
						szShellcode,
						GENERIC_READ,
						FILE_SHARE_READ,
						NULL,
						OPEN_EXISTING,
						FILE_ATTRIBUTE_NORMAL,
						NULL);
 
	DWORD dwSize = GetFileSize(hFile, NULL);
	DWORD dwRead = 0;
 
	ReadFile(hFile, (LPVOID)pShellcode, dwSize, &dwRead, NULL);
	CloseHandle(hFile);
 
	return dwRead;
}
 
// szShellcode为Shellcode文件Path
BOOL InjectCode(DWORD dwPid, CHAR *szShellcode)
{
	BOOL bRet = FALSE;
	HANDLE hProcess = NULL;
	LPVOID lpThreadProc = NULL;
	BYTE pShellcode[SHELL_CODE_SIZE] = {0};
	DWORD dwShellcodeSize = 0;
	DWORD dwResult = 0;
	HANDLE hThread = NULL;
 
	bRet = EnableDebugPrivilege();
	CHECK_NULL_RET(bRet);
 
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
	CHECK_NULL_RET(bRet);
 
	lpThreadProc = VirtualAllocEx(hProcess, NULL, REMOTE_ALLOC_SIZE, 
		MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	CHECK_NULL_RET(lpThreadProc);
 
	dwShellcodeSize = ReadShellcode(pShellcode, szShellcode);
	bRet = WriteProcessMemory(hProcess, lpThreadProc, (LPVOID)pShellcode, 
				dwShellcodeSize, &dwResult);
	CHECK_NULL_RET(bRet);
 
	hThread = CreateRemoteThread(
				hProcess,
				NULL,
				0,
				(LPTHREAD_START_ROUTINE)lpThreadProc,
				NULL,
				0,
				NULL);
	CHECK_NULL_RET(hThread);
 
	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hThread);
 
Exit0:
	if (NULL != lpThreadProc)
	{
		VirtualFreeEx(hProcess, lpThreadProc, 0, MEM_RELEASE);
	}
	CloseHandle(hProcess);
	return bRet;
}

一篇说明一些细节的文章: http://hi.baidu.com/lufa2014/blog/item/f5a249cbee31e71ebe09e685.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值