• 动态库注入——SetThreadContext注入


    这种注入方法是主要是修改进程中的线程上下文来实现Dll注入(ShellCode)

    1. 实现步骤

       a根据进程ID的进程句柄。

       b根据进程ID得到线程句柄

       c调用SuspendThread()函数暂停线程。

       d在目标进程中申请内存,写入ShellCode

       e调用GetThreadContext()函数获得线程的上下文

       d修改Eip(rip)的值。

       f调用SetThreadContext()函数进行设置线程上下文

    2. 代码实现
        1 // SetThreadContext.cpp : 定义控制台应用程序的入口点。
        2 //
        3 
        4 #include "stdafx.h"
        5 #include <Windows.h>
        6 #include <TlHelp32.h>
        7 #include <vector>
        8 #include <iostream>
        9 
       10 using namespace std;
       11 
       12 BOOL GrantPriviledge(WCHAR* PriviledgeName);
       13 BOOL GetProcessIdByProcessImageName(IN WCHAR* wzProcessImageName, OUT UINT32* TargetProcessId);
       14 BOOL GetThreadIdByProcessId(UINT32 ProcessId, vector<UINT32>& ThreadIdVector);
       15 BOOL Inject(UINT32 ProcessId, UINT32 ThreadId);
       16 
       17 
       18 #ifdef _WIN64
       19 
       20 UINT8    ShellCode[0x100] = {
       21     0x48,0x83,0xEC,0x28,    
       22 
       23     0x48,0x8D,0x0d,            
       24     0x00,0x00,0x00,0x00,    
       25 
       26 
       27     0xff,0x15,                
       28     0x00,0x00,0x00,0x00,    
       29 
       30     0x48,0x83,0xc4,0x28,    
       31 
       32     
       33     0xff,0x25,                
       34     0x00,0x00,0x00,0x00,    
       35 
       36     
       37     0x00,0x00,0x00,0x00,    
       38     0x00,0x00,0x00,0x00,    
       39 
       40     0x00,0x00,0x00,0x00,    
       41     0x00,0x00,0x00,0x00,    
       42 
       43 };
       44 #else
       45 
       46 UINT8    ShellCode[0x100] = {
       47     0x60,                    
       48     0x9c,                    
       49     0x68,                    
       50     0x00,0x00,0x00,0x00,    
       51     0xff,0x15,                
       52     0x00,0x00,0x00,0x00,    
       53     0x9d,                    
       54     0x61,                    
       55     0xff,0x25,                
       56     0x00,0x00,0x00,0x00,    
       57 
       58 
       59     0x00,0x00,0x00,0x00,    
       60 
       61     0x00,0x00,0x00,0x00,
       62 
       63     0x00,0x00,0x00,0x00        
       64 };
       65 
       66 #endif
       67 
       68 
       69 CHAR    DllFullPath[MAX_PATH] = { 0 };
       70 
       71 int main()
       72 {
       73     // 提权
       74     if (GrantPriviledge(SE_DEBUG_NAME) == FALSE)
       75     {
       76         printf("GrantPriviledge Error\r\n");
       77     }
       78 
       79     UINT32    ProcessId = 0;
       80 
       81     GetCurrentDirectoryA(MAX_PATH, DllFullPath);
       82 
       83 #ifdef _WIN64
       84     GetProcessIdByProcessImageName(L"explorer.exe", &ProcessId);
       85 
       86     strcat_s(DllFullPath, "\\x64Dll.dll");
       87 #else
       88     GetProcessIdByProcessImageName(L"explorer.exe", &ProcessId);
       89     strcat_s(DllFullPath, "\\x86Dll.dll");
       90 #endif
       91 
       92     //枚举到线程id
       93     vector<UINT32> ThreadIdVector;
       94     GetThreadIdByProcessId(ProcessId, ThreadIdVector);
       95 
       96     for (UINT32 ThreadId : ThreadIdVector)
       97     {
       98         Inject(ProcessId, ThreadId);
       99         break;            
      100     }
      101 
      102     Sleep(3000);
      103 
      104     return 0;
      105 }
      106 
      107 UINT32    Count = 0;
      108 BOOL Inject(UINT32 ProcessId, UINT32 ThreadId)
      109 {
      110     HANDLE    ThreadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, ThreadId);
      111     HANDLE    ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
      112 
      113     // 首先挂起线程
      114     SuspendThread(ThreadHandle);
      115 
      116     CONTEXT        ThreadContext = { 0 };
      117     ThreadContext.ContextFlags = CONTEXT_ALL;
      118     if (GetThreadContext(ThreadHandle, &ThreadContext) == FALSE)
      119     {
      120         cout << GetLastError() << endl;
      121         CloseHandle(ThreadHandle);
      122         CloseHandle(ProcessHandle);
      123         return FALSE;
      124     }
      125 
      126     PVOID    BufferData = VirtualAllocEx(ProcessHandle, NULL, sizeof(ShellCode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
      127     if (BufferData != NULL)
      128     {
      129         UINT_PTR    LoadLibraryAddress = (UINT_PTR)GetProcAddress(GetModuleHandle(L"Kernel32.dll"), "LoadLibraryA");
      130         if (LoadLibraryAddress != NULL)
      131         {
      132 #ifdef _WIN64
      133 
      134             // ShellCode + 43
      135             PUINT8    v1 = ShellCode + 43;
      136             memcpy(v1, DllFullPath, strlen(DllFullPath) + 1);
      137             UINT32    DllNameOffset = (UINT32)(((PUINT8)BufferData + 43) - ((PUINT8)BufferData + 4) - 7);
      138             *(PUINT32)(ShellCode + 7) = DllNameOffset;
      139 
      140             // ShellCode + 35
      141             *(PUINT64)(ShellCode + 35) = (UINT64)LoadLibraryAddress;
      142             UINT32    LoadLibraryAddressOffset = (UINT32)(((PUINT8)BufferData + 35) - ((PUINT8)BufferData + 11) - 6);
      143             *(PUINT32)(ShellCode + 13) = LoadLibraryAddressOffset;
      144 
      145             *(PUINT64)(ShellCode + 27) = ThreadContext.Rip;
      146             
      147             if (!WriteProcessMemory(ProcessHandle, BufferData, ShellCode, sizeof(ShellCode), NULL))
      148             {
      149                 return FALSE;
      150             }
      151             ThreadContext.Rip = (UINT64)BufferData;
      152 
      153 #else
      154             PUINT8    v1 = ShellCode + 29;
      155 
      156             memcpy((char*)v1, DllFullPath, strlen(DllFullPath) + 1);    
      157             *(PUINT32)(ShellCode + 3) = (UINT32)BufferData + 29;
      158 
      159             *(PUINT32)(ShellCode + 25) = LoadLibraryAddress;  
      160             *(PUINT32)(ShellCode + 9) = (UINT32)BufferData + 25;
      161                                                              
      162             *(PUINT32)(ShellCode + 21) = ThreadContext.Eip;
      163             *(PUINT32)(ShellCode + 17) = (UINT32)BufferData + 21;
      164             if (!WriteProcessMemory(ProcessHandle, BufferData, ShellCode, sizeof(ShellCode), NULL))
      165             {
      166                 printf("write Process Error\n");
      167                 return FALSE;
      168             }
      169             ThreadContext.Eip = (UINT32)BufferData;
      170 
      171 #endif            
      172             if (!SetThreadContext(ThreadHandle, &ThreadContext))
      173             {
      174                 printf("set thread context error\n");
      175                 return FALSE;
      176             }
      177             ResumeThread(ThreadHandle);
      178 
      179             printf("ShellCode 注入完成: %d\r\n", ++Count);
      180         }
      181     }
      182 
      183     CloseHandle(ThreadHandle);
      184     CloseHandle(ProcessHandle);
      185     return TRUE;
      186 }
      187 
      188 //获得线程ID
      189 BOOL GetThreadIdByProcessId(UINT32 ProcessId, vector<UINT32>& ThreadIdVector)
      190 {
      191     HANDLE            ThreadSnapshotHandle = NULL;
      192     THREADENTRY32    ThreadEntry32 = { 0 };
      193 
      194     ThreadEntry32.dwSize = sizeof(THREADENTRY32);
      195 
      196     ThreadSnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
      197     if (ThreadSnapshotHandle == INVALID_HANDLE_VALUE)
      198     {
      199         return FALSE;
      200     }
      201 
      202     Thread32First(ThreadSnapshotHandle, &ThreadEntry32);
      203     do
      204     {
      205         if (ThreadEntry32.th32OwnerProcessID == ProcessId)
      206         {
      207             ThreadIdVector.emplace_back(ThreadEntry32.th32ThreadID);        // 把该进程的所有线程id压入模板
      208         }
      209     } while (Thread32Next(ThreadSnapshotHandle, &ThreadEntry32));
      210 
      211     CloseHandle(ThreadSnapshotHandle);
      212     ThreadSnapshotHandle = NULL;
      213     return TRUE;
      214 }
      215 
      216 
      217 BOOL GetProcessIdByProcessImageName(IN WCHAR* wzProcessImageName, OUT UINT32* TargetProcessId)
      218 {
      219     HANDLE            ProcessSnapshotHandle = NULL;
      220     PROCESSENTRY32    ProcessEntry32 = { 0 };
      221 
      222     ProcessEntry32.dwSize = sizeof(PROCESSENTRY32);        
      223 
      224     ProcessSnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    
      225 
      226     if (ProcessSnapshotHandle == INVALID_HANDLE_VALUE)
      227     {
      228         return FALSE;
      229     }
      230 
      231     Process32First(ProcessSnapshotHandle, &ProcessEntry32);        
      232     do
      233     {
      234         if (lstrcmpi(ProcessEntry32.szExeFile, wzProcessImageName) == 0)        
      235         {
      236             *TargetProcessId = ProcessEntry32.th32ProcessID;
      237             break;
      238         }
      239     } while (Process32Next(ProcessSnapshotHandle, &ProcessEntry32));
      240 
      241     CloseHandle(ProcessSnapshotHandle);
      242     ProcessSnapshotHandle = NULL;
      243     return TRUE;
      244 }
      245 
      246 
      247 
      248 // 提限
      249 BOOL GrantPriviledge(WCHAR* PriviledgeName)
      250 {
      251     TOKEN_PRIVILEGES TokenPrivileges, OldPrivileges;
      252     DWORD             dwReturnLength = sizeof(OldPrivileges);
      253     HANDLE             TokenHandle = NULL;
      254     LUID             uID;
      255 
      256     // 打开权限令牌
      257     if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &TokenHandle))
      258     {
      259         if (GetLastError() != ERROR_NO_TOKEN)
      260         {
      261             return FALSE;
      262         }
      263         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
      264         {
      265             return FALSE;
      266         }
      267     }
      268 
      269     //查看权限令牌
      270     if (!LookupPrivilegeValue(NULL, PriviledgeName, &uID))        
      271     {
      272         CloseHandle(TokenHandle);
      273         return FALSE;
      274     }
      275 
      276     TokenPrivileges.PrivilegeCount = 1;        
      277     TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    
      278     TokenPrivileges.Privileges[0].Luid = uID;
      279 
      280     // 调整权限
      281     if (!AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), &OldPrivileges, &dwReturnLength))
      282     {
      283         CloseHandle(TokenHandle);
      284         return FALSE;
      285     }
      286 
      287     CloseHandle(TokenHandle);
      288     return TRUE;
      289 }
  • 相关阅读:
    noi.ac NOI挑战营模拟赛1-5
    TJOI2015 弦论
    CQOI2018 破解D-H协议
    NOI2013 矩阵游戏
    NOI2015 荷马史诗
    NOI2015 寿司晚宴
    SDOI2014 重建
    NOI1999 生日蛋糕
    NOI2015 程序自动分析
    ZJOI2008 泡泡堂
  • 原文地址:https://www.cnblogs.com/banchen/p/6682777.html
Copyright © 2020-2023  润新知