zoukankan      html  css  js  c++  java
  • 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. ");
    }

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

  • 相关阅读:
    各位信息技术男,你们在折腾什么?
    在 C# 中使用 P/Invoke 调用 Mupdf 函数库显示 PDF 文档
    用PDF补丁丁一分钟倒排逆页序PDF文档
    简单解决“ORA27100: shared memory realm already exists”的问题
    用PDF补丁丁一分钟批量更改PDF书签的默认展开或关闭状态
    TImageList 图标更新通知方案
    常用注释
    delphi XE 下打开内存泄漏调试功能
    炎炎夏日需要一个清凉的地 自制水冷系统(十一 指尖的思绪之程序篇)
    炎炎夏日需要一个清凉的地 自制水冷系统(十 高温作业:焊接)
  • 原文地址:https://www.cnblogs.com/lsh123/p/6023302.html
Copyright © 2011-2022 走看看