zoukankan      html  css  js  c++  java
  • 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
    ");
        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;
    }
  • 相关阅读:
    DEBIAN下中文显示
    SpringMVC整合Quartz实现定时任务以及Tomcat服务执行初始化定时任务
    SpringMVC 配置定时执行任务
    Mybatis update In
    mybatis在xml文件中处理大于号小于号的方法
    解决Cannot change version of project facet Dynamic web module to 2.5
    android 圆角边框及图片
    Android MotionEvent事件响应机制
    android:configChanges属性
    Android之ScrollView嵌套ListView
  • 原文地址:https://www.cnblogs.com/arsense/p/6427472.html
Copyright © 2011-2022 走看看