APC注入(Ring3层)
/*
步骤:
1.提权(GrantDebugPrivileges)     
	(1)获得令牌token,OpenThreadToken(),OpenProcessToken  ()
WINADVAPI
		BOOL
		WINAPI
		OpenThreadToken(
			_In_ HANDLE ThreadHandle,
			_In_ DWORD DesiredAccess,
			_In_ BOOL OpenAsSelf,
			_Outptr_ PHANDLE TokenHandle
			);
		
		OpenAsSelf参数
[in]    true 指定应使用调用线程的进程安全上下文执行访问检查;
	            false 指定应使用调用线程本身的安全上下文执行访问检查。 
				如果线程正在模拟客户端,则此安全上下文可以是一个客户端进程的安全上下文。
WINADVAPI
		BOOL
		WINAPI
		OpenProcessToken(
			_In_ HANDLE ProcessHandle,
			_In_ DWORD DesiredAccess,
			_Outptr_ PHANDLE TokenHandle
			);
(2)将提升的权限放到TokenPrivileges结构中 
		
		WINADVAPI
		BOOL
		WINAPI
		AdjustTokenPrivileges(
		_In_ HANDLE TokenHandle,
		_In_ BOOL DisableAllPrivileges,  标志这个函数是否禁用该令牌的所有特权.如果为TRUE,这个函数禁用所有特权,NewState参数无效.
										 如果为假,以NewState参数指针的信息为基础来修改特权.
		_In_opt_ PTOKEN_PRIVILEGES NewState,
		_In_ DWORD BufferLength,
		_Out_writes_bytes_to_opt_(BufferLength, *ReturnLength) PTOKEN_PRIVILEGES PreviousState,
		_Out_opt_ PDWORD ReturnLength
		);
(3)将获取的令牌TokenHandle与TokenPrivileges结构关联
2.通过进程ImageName获取进程ID(GetProcessIDByProcessImageName)  
	(1)给系统的所有进程快照ProcessSnapshotHandle
函数原型:
	   HANDLE WINAPI CreateToolhelp32Snapshot(
		  DWORD dwFlags, //用来指定“快照”中需要返回的对象,可以是TH32CS_SNAPPROCESS等
		  DWORD th32ProcessID //一个进程ID号,用来指定要获取哪一个进程的快照,当获取系统进程列表或获取 当前进程快照时可以设为0
		  );
指定快照中包含的系统内容,dwFlags这个参数能够使用下列数值(常量)中的一个或多个。
		  TH32CS_INHERIT - 声明快照句柄是可继承的。
		  TH32CS_SNAPALL - 在快照中包含系统中所有的进程和线程。
		  TH32CS_SNAPHEAPLIST - 在快照中包含在th32ProcessID中指定的进程的所有的堆。
		  TH32CS_SNAPMODULE - 在快照中包含在th32ProcessID中指定的进程的所有的模块。
		  TH32CS_SNAPPROCESS - 在快照中包含系统中所有的进程。
		  TH32CS_SNAPTHREAD - 在快照中包含系统中所有的线程。
#define TH32CS_SNAPHEAPLIST 0x00000001
		  #define TH32CS_SNAPPROCESS  0x00000002
		  #define TH32CS_SNAPTHREAD   0x00000004
		  #define TH32CS_SNAPMODULE   0x00000008
		  #define TH32CS_SNAPMODULE32 0x00000010
		  #define TH32CS_SNAPALL      (TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE)
		  #define TH32CS_INHERIT      0x80000000
(2)通过PROCESSENTRY32结构得到ProcessID
PROCESSENTRY32,用来存放快照进程信息的一个结构体。(存放进程信息和调用成员输出进程信息)
						用来 Process32First指向第一个进程信息,并将进程信息抽取到PROCESSENTRY32中。
						用Process32Next指向下一条进程信息。
typedef struct tagPROCESSENTRY32
		{
			DWORD   dwSize;
			DWORD   cntUsage;
			DWORD   th32ProcessID;          // this process
			ULONG_PTR th32DefaultHeapID;
			DWORD   th32ModuleID;           // associated exe
			DWORD   cntThreads;
			DWORD   th32ParentProcessID;    // this process's parent process
			LONG    pcPriClassBase;         // Base priority of process's threads
			DWORD   dwFlags;
			CHAR    szExeFile[MAX_PATH];    // Path
		} PROCESSENTRY32;
process32First,Process32Next是两个个进程获取函数,当我们利用函数CreateToolhelp32Snapshot()获得当前运行进程的快照后,
									 我们可以利用process32First函数来获得第一个进程的句柄,利用Process32Next函数来获得下一个进程的句柄。
3.通过进程ID获取线程ID(GetThreadIDByProcessID)  触发异常,分配出物理内存
	
4.注入
   (1)在对方进程空间申请内存,
	
	LPVOID
	WINAPI
	VirtualAllocEx(
		_In_ HANDLE hProcess,
		_In_opt_ LPVOID lpAddress,
		_In_ SIZE_T dwSize,
		_In_ DWORD flAllocationType,
		_In_ DWORD flProtect
		);
flAllocationType参数设置:MEM_COMMIT | MEM_RESERVE
							(如果物理内存申请失败,将保留进程的虚拟地址空间,到真正执行时,会触发异常,进行物理内存分配)
MEM_COMMIT:为特定的页面区域分配内存中或磁盘的页面文件中的物理存储
							  MEM_RESERVE:保留进程的虚拟地址空间,而不分配任何物理存储。保留页面可通过继续调用VirtualAlloc()而被占用
(2)将DllFullPath写入内存当中
WriteProcessMemory()函数能写入某一进程的内存区域。入口区必须可以访问,否则操作将失败。
BOOL
		WINAPI
		WriteProcessMemory(
			_In_ HANDLE hProcess,
			_In_ LPVOID lpBaseAddress,
			_In_reads_bytes_(nSize) LPCVOID lpBuffer,
			_In_ SIZE_T nSize,
			_Out_opt_ SIZE_T * lpNumberOfBytesWritten
			);
(3)加载dll文件
LoadLibraryWAddress = (UINT_PTR)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
	//从当前进程中获得导入模块kernel32.dll的基地址,从kernel32.dll模块中的导出表中获得函数LoadLibraryW
	//目的   1.防止IAT HOOK(ImportAddressTable)   2.确保地址正确(不同虚拟地址映射到同一物理地址)
*/
#include "stdafx.h"
#include<Windows.h>
#include<ntstatus.h>
#include<iostream>
#include<vector>
#include<TlHelp32.h>
using namespace std;
BOOL GrantPriviledge(IN PWCHAR PriviledgeName);
BOOL GetProcessIDByProcessImageName(IN PWCHAR wzProcessImageName, OUT PUINT32 TargetProcessID);
BOOL GetThreadIDByProcessID(IN UINT32 ProcessID, OUT vector<UINT32>&ThreadIDVector);
BOOL InjectByAPC(IN UINT32 ProcessID,OUT UINT32 ThreadID);
WCHAR    DllFullPath[MAX_PATH] = { 0 };      //MAX_PATH 260
PVOID    DllFullPathBufferData = NULL;
UINT_PTR LoadLibraryWAddress = 0;
int main()
{
	//1.提权
	
	if (GrantPriviledge(SE_DEBUG_NAME) == false)
	{
		printf("GrantPriviledge Error.\n");
	}
//2.Dll路径
	GetCurrentDirectoryW(MAX_PATH, DllFullPath);
//#ifdef _WIN64
	wcscat(DllFullPath, L"\\Dll.dll");
//#else
//	wcscat(DllFullPath, L"\\Dll.dll");
//#endif
//	LoadLibrary(DllFullPath);
	//3.获取进程ID
	UINT32 ProcessID = -1;   //idol进程ID为0
	GetProcessIDByProcessImageName(L"explorer.exe",&ProcessID);
//4.获取线程ID_Vector
	vector<UINT32> ThreadIDVector;
	if (GetThreadIDByProcessID(ProcessID,ThreadIDVector) == false)
	{
		return 0;
	}
//5.注入
	size_t ThreadCount = ThreadIDVector.size();
	for (INT_PTR i = ThreadCount - 1; i >= 0; i--)  //INT_PTR
	{
		UINT32 ThreadID = ThreadIDVector[i];
		InjectByAPC(ProcessID,ThreadID);
	}
}
BOOL GrantPriviledge(PWCHAR PriviledgeName)
{
	TOKEN_PRIVILEGES TokenPrivileges, Oldprivileges;
	DWORD			 dwReturnLength = sizeof(Oldprivileges);
	HANDLE			 TokenHandle = INVALID_HANDLE_VALUE;
	LUID			 uID;    //LUID   64位
//打开权限令牌
	if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, false, &TokenHandle))
	{
		if (GetLastError() != ERROR_NO_TOKEN)
		{
			return false;
		}
		if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
		{
			return false;
		}
	}
	//LookupPrivilegeValue()函数查看系统权限的特权值,返回信息到一个LUID结构体里
	if (!LookupPrivilegeValue(NULL,PriviledgeName,&uID))
	{
		CloseHandle(TokenHandle);
		return false;
	}
TokenPrivileges.PrivilegeCount = 1; //要提升的权限个数
	TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	TokenPrivileges.Privileges[0].Luid = uID;
//调整权限
	if (!AdjustTokenPrivileges(TokenHandle, false, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), &Oldprivileges, &dwReturnLength))
	{
		CloseHandle(TokenHandle);
		return false;
	}
CloseHandle(TokenHandle);
	return true;
}
BOOL  GetProcessIDByProcessImageName(IN PWCHAR wzProcessImageName, OUT PUINT32 ProcessID)
{
	HANDLE		   ProcessSnapshotHandle = INVALID_HANDLE_VALUE;
	ProcessSnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  //给系统的所有进程快照
	if (ProcessSnapshotHandle == INVALID_HANDLE_VALUE)
	{
		return false;
	}
PROCESSENTRY32 ProcessEntry32 = { 0 };
	ProcessEntry32.dwSize = sizeof(PROCESSENTRY32);  //初始化PROCESSENTRY32结构
Process32First(ProcessSnapshotHandle, &ProcessEntry32);
	do
	{
		if (lstrcmpi(ProcessEntry32.szExeFile, wzProcessImageName) == 0)      //不区分大小写  双字
		{
			*ProcessID = ProcessEntry32.th32ProcessID;
			break;
		}
	} while (Process32Next(ProcessSnapshotHandle, &ProcessEntry32));  //BOOL型返回值
CloseHandle(ProcessSnapshotHandle);
	ProcessSnapshotHandle = INVALID_HANDLE_VALUE;
	return true;
}
//枚举指定进程ID的所有线程,压入模板中,返回线程模板集合
BOOL GetThreadIDByProcessID(IN UINT32 ProcessID, OUT vector<UINT32>&ThreadIDVector)
{
	HANDLE		  ThreadSnapshotHandle = INVALID_HANDLE_VALUE;
	THREADENTRY32 ThreadEntry32 = { 0 };
ThreadEntry32.dwSize = sizeof(THREADENTRY32);
	ThreadSnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (ThreadSnapshotHandle == INVALID_HANDLE_VALUE)
	{
		return false;
	}
Thread32First(ThreadSnapshotHandle, &ThreadEntry32);
	do
	{
		if (ThreadEntry32.th32OwnerProcessID == ProcessID)
		{
			ThreadIDVector.emplace_back(ThreadEntry32.th32ThreadID);   //将线程ID压入模板
		}
	} while (Thread32Next(ThreadSnapshotHandle, &ThreadEntry32));
CloseHandle(ThreadSnapshotHandle);
	ThreadSnapshotHandle = NULL;
	return true;
}
BOOL InjectByAPC(UINT32 ProcessID, UINT32 ThreadID)
{
	HANDLE ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessID);
	HANDLE ThreadHandle = INVALID_HANDLE_VALUE;
	SIZE_T DllFullPathLength = (wcslen(DllFullPath) + 1) * 2;
	//SIZE_T DllFullPathSize   = DllFullPathLength
	SIZE_T ReturnLength = 0;
	BOOL   bOK = false;
//在对方进程空间申请内存
	if (DllFullPathBufferData == NULL)
	{
		DllFullPathBufferData = VirtualAllocEx(ProcessHandle, NULL, DllFullPathLength, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
		if (DllFullPathBufferData == NULL)
		{
			CloseHandle(ProcessHandle);
			return false;
		}
		//将DllFullPath写入内存当中
		BOOL bOK = WriteProcessMemory(ProcessHandle, DllFullPathBufferData, DllFullPath, (wcslen(DllFullPath) + 1)*2, &ReturnLength);
		if (bOK == false)
		{
			VirtualFree(DllFullPathBufferData, DllFullPathLength,MEM_RELEASE);
			CloseHandle(ProcessHandle);
			return false;
		}
	}
	//从当前进程中获得导入模块kernel32.dll的基地址,从kernel32.dll模块中的导出表中获得函数LoadLibraryW
	//目的   1.防止IAT HOOK(ImportAddressTable)   2.确保地址正确(不同虚拟地址映射到同一物理地址)
    LoadLibraryWAddress = (UINT_PTR)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
	if (LoadLibraryWAddress == NULL)
	{
		VirtualFree(DllFullPathBufferData, DllFullPathLength, MEM_RELEASE);
		CloseHandle(ProcessHandle);
		return false;
	}
	__try
	{
		ThreadHandle = OpenThread(THREAD_ALL_ACCESS, false, ThreadID);
		QueueUserAPC((PAPCFUNC)LoadLibraryWAddress, ThreadHandle, (UINT_PTR)DllFullPathBufferData);
		//可执行IO?
	}
	__except(EXCEPTION_CONTINUE_EXECUTION)
	{
}
	CloseHandle(ProcessHandle);
	CloseHandle(ThreadHandle);
	return true;
}
APC注入(Ring3层)的更多相关文章
- Dll注入:Ring3 层 APC注入
		APC,即Asynchronous procedure call,异步程序调用APC注入的原理是:在一个进程中,当一个执行到SleepEx()或者WaitForSingleObjectEx()时,系统 ... 
- Windows x86/ x64 Ring3层注入Dll总结
		欢迎转载,转载请注明出处:http://www.cnblogs.com/uAreKongqi/p/6012353.html 0x00.前言 提到Dll的注入,立马能够想到的方法就有很多,比如利用远程线 ... 
- 病毒木马查杀实战第020篇:Ring3层主动防御之基本原理
		前言 假设说我们的计算机中安装有杀毒软件,那么当我们有意或无意地下载了一个恶意程序后.杀软一般都会弹出一个对话框提示我们,下载的程序非常可能是恶意程序,建议删除之类的.或者杀软就不提示.直接删除了:或 ... 
- 病毒木马查杀实战第021篇:Ring3层主动防御之编程实现
		前言 我们这次会依据上次的内容,编程实现一个Ring3层的简单的主动防御软件.整个程序使用MFC实现,程序开始监控时,会将DLL程序注入到explorer.exe进程中,这样每当有新的进程创建,程序首 ... 
- ring0 与 ring3 层之间的交互
		在进行Windows的ring0层开发时,必不可免的要与 ring3 层进行交互.进行数据间的相互传输.可用的方法有DeviceIoCntrol,ReadFile.我平常都是用的DeviceIoCon ... 
- 分析恶意驱动(进程启动apc注入dll)
		一.前言 用IDA也有好些时间了,以前就只会用F5功能玩无壳无保护的裸驱动,感觉太坑了,这两天就开始看网上大牛的逆向. 今天记录一下sudami曾经逆向过的fuck.sys.第一遍自己走的时候漏掉了 ... 
- APC注入
		0X01 注入原理 当线程被唤醒时APC中的注册函数会被执行的机制,并依此去调用我们的DLL加载代码,进而完成注入的目的 具体的流程: 1 当EXE里的某个线程执行到sleepEX(),或者waitF ... 
- Ring3层 UNICODE_STRING
		今天写驱动用到UNICODE_STRING,就在Ring3层抠了一些源代码,学习一下,不多说了上代码了 #pragma once #include <windows.h> #include ... 
- 常见注入手法第二讲,APC注入
		常见注入手法第二讲,APC注入 转载注明出处 首先,我们要了解下什么是APC APC 是一个简称,具体名字叫做异步过程调用,我们看下MSDN中的解释,异步过程调用,属于是同步对象中的函数,所以去同步对 ... 
- 注入理解之APC注入
		近期学习做了一个各种注入的MFC程序,把一些心得和体会每天分享一些 APC(Asynchronous procedure call)异步程序调用,在NT中,有两种类型的APCs:用户模式和内核模式.用 ... 
随机推荐
- PDF二次开发_iStylePDF表单域的填充
			wo讲到PDF表单,我们首先需要认识Adobe定义的PDF表单有哪些.以下是我从网上搜索到的简单介绍: PDF 表单简介 PDF 是可移植文档格式(Portable Document Format)的 ... 
- SQL Server 2012 联机丛书离线安装
			昨日根据微软官网的方式安装SQL Server 2012 联机丛书报错,无法安装: 联机丛书下载位置及安装方式: 按照给出的方式安装,无法完成,错误如下: 
- j.APR连接器整体框图(含SSL实现分析)
			APR连接器的思路和bio,nio的整体架构也是类似的,可以看到下面的整体框图: 第一个区别是,对于从Acceptor线程中的socket解析这块,无论是nio还是bio都是在Acceptor线程内直 ... 
- javascript的假查询
			1. function select(){ var text=$("#ss").val();//获得关键字 $("#show_tab tr").hide().f ... 
- 关于unity碰撞检测器的用法
			今天已经是我第三次忘记了这两种碰撞检测的用法,混淆了.特意整理一下 首先把今天要解决涉及到的东西列出来 碰撞方法: public void OnTriggerEnter(Collider other) ... 
- 雅虎(yahoo)前端优化十四条军规
			第一条.尽可能的减少 HTTP 的请求数 (Make Fewer HTTP Requests ) http请求是要开销的,想办法减少请求数自然可以提高网页速度.常用的方法,合并css,js(将一个页面 ... 
- JQUERY相关
			https://github.com/mythz/jquip/ http://zeptojs.com/ http://devework.com/jquery-builder.html http://p ... 
- hihocoder-平衡树·SBT
			http://hihocoder.com/problemset/problem/1337 #1337 : 平衡树·SBT 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 ... 
- VMware中linux配置1-安装VMware tool 共享文件夹
			linux:ubuntu 14 安装Linux,使用的ubuntu-14.04.1-desktop-amd64.iso 安装的,这个就不写了. 为了在linux中访问windows的目录,需要安装VM ... 
- git配置笔记
			windows: 1. PS>ssh-keygen -t rsa -C "your_email@youremail.com" ssh-keygen命令报错--无法将“ssh- ... 
