• dll注入与代码注入


    学习《逆向工程核心原理》,在x64下dll注入与代码注入。

    dll注入主要用到CreateRemoteThread,

    HANDLE WINAPI CreateRemoteThread(
    __in HANDLE hProcess,
    __in LPSECURITY_ATTRIBUTES lpThreadAttributes,
    __in SIZE_T dwStackSize,
    __in LPTHREAD_START_ROUTINE lpStartAddress,
    __in LPVOID lpParameter,
    __in DWORD dwCreationFlags,
    __out LPDWORD lpThreadId
    );
    利用获取到的LoadLibraryW地址作为lpStartAddress,需注入进程中分配保存的dll名称作为lpParameter,实现动态加载dll

    代码注入类似,主要用到VirtualAllocEx,WriteProcessMemory,在需注入的进程中开辟空间,写入代码,变量。

      1 #include "pch.h"
      2 #include <windows.h>
      3 #include <tchar.h>
      4 #include <tlhelp32.h>
      5 #include <stdio.h>
      6 #include <shlobj.h>
      7 extern void checkAdmin();
      8 
      9 //遍历输出进程pid
     10 int TraversalProcess() {
     11     HANDLE hProceessnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
     12     if (hProceessnap == INVALID_HANDLE_VALUE)
     13     {
     14         printf_s("创建进行快照失败
    ");
     15         return -1;
     16     }
     17     else
     18     {
     19         PROCESSENTRY32 pe32;
     20         pe32.dwSize = sizeof(pe32);
     21         BOOL hProcess = Process32First(hProceessnap, &pe32);
     22         while (hProcess)
     23         {
     24             /*WCHAR * ProcessName =(WCHAR *)L"ProcessID.exe";
     25             if (!wcscmp(pe32.szExeFile, ProcessName))
     26             {*/
     27                 printf("进程名:%-10ls ----------------进程ID:%6d
    ", pe32.szExeFile, pe32.th32ProcessID);
     28             /*    break;
     29             }*/
     30             hProcess = Process32Next(hProceessnap, &pe32);
     31         }
     32     }
     33     CloseHandle(hProceessnap);
     34 }
     35 
     36 //设置权限
     37 BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
     38 {
     39     TOKEN_PRIVILEGES tp;
     40     HANDLE hToken;
     41     LUID luid;
     42 
     43     if (!OpenProcessToken(GetCurrentProcess(),
     44         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
     45         &hToken))
     46     {
     47         _tprintf(L"OpenProcessToken error: %u
    ", GetLastError());
     48         return FALSE;
     49     }
     50 
     51     if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system
     52         lpszPrivilege,  // privilege to lookup 
     53         &luid))        // receives LUID of privilege
     54     {
     55         _tprintf(L"LookupPrivilegeValue error: %u
    ", GetLastError());
     56         return FALSE;
     57     }
     58 
     59     tp.PrivilegeCount = 1;
     60     tp.Privileges[0].Luid = luid;
     61     if (bEnablePrivilege)
     62         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
     63     else
     64         tp.Privileges[0].Attributes = 0;
     65 
     66     // Enable the privilege or disable all privileges.
     67     if (!AdjustTokenPrivileges(hToken,
     68         FALSE,
     69         &tp,
     70         sizeof(TOKEN_PRIVILEGES),
     71         (PTOKEN_PRIVILEGES)NULL,
     72         (PDWORD)NULL))
     73     {
     74         _tprintf(L"AdjustTokenPrivileges error: %u
    ", GetLastError());
     75         return FALSE;
     76     }
     77 
     78     if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
     79     {
     80         _tprintf(L"The token does not have the specified privilege. 
    ");
     81         return FALSE;
     82     }
     83 
     84     return TRUE;
     85 }
     86 
     87 //dll注入
     88 BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
     89 {
     90     HANDLE hProcess = NULL, hThread = NULL;
     91     HMODULE hMod = NULL;
     92     LPVOID pRemoteBuf = NULL;
     93     DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);
     94     LPTHREAD_START_ROUTINE pThreadProc;
     95 
     96     // #1. 使用dwPID请求对象进程(notepad.exe)的HANDLE。
     97     if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
     98     {
     99         _tprintf(L"OpenProcess(%d) failed!!! [%d]
    ", dwPID, GetLastError());
    100         return FALSE;
    101     }
    102 
    103     // #2. 在目标进程(notepad.exe)内存中分配与szDllName大小相同的内存。
    104     pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
    105 
    106     // #3. 在分配的内存中使用dll路径
    107     WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);
    108 
    109     // #4. 请求到LoadLibraryA() API地址。
    110     hMod = GetModuleHandle(L"kernel32.dll");
    111     pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");
    112 
    113     // #5. 在notepad.exe进程中运行线程
    114     hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
    115     //通过CreateRemoteThread,调用pThreadProc,即LoadLibraryW,参数为在需注入进程中开辟的内存(存储了dll路径)
    116 
    117     WaitForSingleObject(hThread, INFINITE);
    118 
    119     CloseHandle(hThread);
    120     CloseHandle(hProcess);
    121 
    122     return TRUE;
    123 }
    124 //卸载dll
    125 BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName)
    126 {
    127     BOOL bMore = FALSE, bFound = FALSE;
    128     HANDLE hSnapshot, hProcess, hThread;
    129     HMODULE hModule = NULL;
    130     MODULEENTRY32 me = { sizeof(me) };
    131     LPTHREAD_START_ROUTINE pThreadProc;
    132     // dwPID = notepad 进程 ID
    133     // 使用TH32CS_SNAPMODULE参数获得载入notepad程序的DLL名称
    134     hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
    135 
    136     bMore = Module32First(hSnapshot, &me);
    137     for (; bMore; bMore = Module32Next(hSnapshot, &me))
    138     {
    139         if (!_tcsicmp((LPCTSTR)me.szModule, szDllName) ||
    140             !_tcsicmp((LPCTSTR)me.szExePath, szDllName))
    141         {
    142             bFound = TRUE;
    143             break;
    144         }
    145     }
    146 
    147     if (!bFound)
    148     {
    149         CloseHandle(hSnapshot);
    150         return FALSE;
    151     }
    152 
    153     if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
    154     {
    155         _tprintf(L"OpenProcess(%d) failed!!! [%d]
    ", dwPID, GetLastError());
    156         return FALSE;
    157     }
    158 
    159     hModule = GetModuleHandle(L"kernel32.dll");
    160     pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
    161     hThread = CreateRemoteThread(hProcess, NULL, 0,
    162         pThreadProc, me.modBaseAddr,
    163         0, NULL);
    164     WaitForSingleObject(hThread, INFINITE);
    165 
    166     CloseHandle(hThread);
    167     CloseHandle(hProcess);
    168     CloseHandle(hSnapshot);
    169 
    170     return TRUE;
    171 }
    172 
    173 
    174 //代码注入所需结构体
    175 typedef struct _THREAD_PARAM
    176 {
    177     FARPROC pFunc[2];               // LoadLibraryA(), GetProcAddress()
    178     char    szBuf[4][128];          // "user32.dll", "MessageBoxA", "www.reversecore.com", "ReverseCore"
    179 } THREAD_PARAM, *PTHREAD_PARAM;
    180 
    181 typedef HMODULE(WINAPI *PFLOADLIBRARYA)
    182 (
    183     LPCSTR lpLibFileName
    184     );
    185 
    186 typedef FARPROC(WINAPI *PFGETPROCADDRESS)
    187 (
    188     HMODULE hModule,
    189     LPCSTR lpProcName
    190     );
    191 
    192 typedef int (WINAPI *PFMESSAGEBOXA)
    193 (
    194     HWND hWnd,
    195     LPCSTR lpText,
    196     LPCSTR lpCaption,
    197     UINT uType
    198     );
    199 
    200 //需注入的代码
    201 DWORD WINAPI ThreadProc(LPVOID lParam)
    202 {
    203     PTHREAD_PARAM   pParam = (PTHREAD_PARAM)lParam;
    204     HMODULE         hMod = NULL;
    205     FARPROC         pFunc = NULL;
    206     //调用 LoadLibrary()  加载 "user32.dll"
    207     hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);    // "user32.dll"
    208     if (!hMod)
    209         return 1;
    210 
    211     //调用 GetProcAddress() 获取"MessageBoxA"
    212     pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]);  // "MessageBoxA"
    213     if (!pFunc)
    214         return 1;
    215 
    216     // 调用MessageBoxA()
    217     ((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);
    218     return 0;
    219 }
    220 
    221 //实现代码注入
    222 BOOL InjectCode(DWORD dwPID)
    223 {
    224     HMODULE         hMod = NULL;
    225     THREAD_PARAM    param = { 0, };
    226     HANDLE          hProcess = NULL;
    227     HANDLE          hThread = NULL;
    228     LPVOID          pRemoteBuf[2] = { 0, };
    229     DWORD           dwSize = 0;
    230 
    231     hMod = GetModuleHandleA("kernel32.dll");
    232 
    233     // set THREAD_PARAM   
    234     param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");
    235     param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
    236     strcpy_s(param.szBuf[0], "user32.dll");
    237     strcpy_s(param.szBuf[1], "MessageBoxA");
    238     strcpy_s(param.szBuf[2], "这是code inject");
    239     strcpy_s(param.szBuf[3], "好开心!");
    240 
    241     // Open Process
    242     if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS,   // dwDesiredAccess
    243         FALSE,                // bInheritHandle
    244         dwPID)))             // dwProcessId
    245     {
    246         printf("OpenProcess() fail : err_code = %d
    ", GetLastError());
    247         return FALSE;
    248     }
    249 
    250     // Allocation for THREAD_PARAM       写入代码注入所需的data
    251     dwSize = sizeof(THREAD_PARAM);
    252     if (!(pRemoteBuf[0] = VirtualAllocEx(hProcess,          // hProcess
    253         NULL,                 // lpAddress
    254         dwSize,               // dwSize
    255         MEM_COMMIT,           // flAllocationType
    256         PAGE_READWRITE)))    // flProtect
    257     {
    258         printf("VirtualAllocEx() fail : err_code = %d
    ", GetLastError());
    259         return FALSE;
    260     }
    261     SIZE_T sz = 0;
    262     if (!WriteProcessMemory(hProcess,                       // hProcess
    263         pRemoteBuf[0],                  // lpBaseAddress
    264         (LPVOID)&param,                 // lpBuffer
    265         dwSize,                         // nSize
    266         &sz))                         // [out] lpNumberOfBytesWritten
    267     {
    268         printf("写入大小:%d
    ", sz);
    269         printf("THREAD_PARAM  WriteProcessMemory() fail : err_code = %d
    ", GetLastError());
    270         return FALSE;
    271     }
    272 
    273     // Allocation for ThreadProc()     写入代码
    274     dwSize = abs((int)((DWORD)InjectCode - (DWORD)ThreadProc));
    275     
    276     printf("dwSize:%d
    ", dwSize);
    277     //dwSize = 1024;
    278     if (!(pRemoteBuf[1] = VirtualAllocEx(hProcess,          // hProcess
    279         NULL,                 // lpAddress
    280         dwSize,               // dwSize
    281         MEM_COMMIT,           // flAllocationType
    282         PAGE_EXECUTE_READWRITE)))    // flProtect
    283     {
    284         printf("VirtualAllocEx() fail : err_code = %d
    ", GetLastError());
    285         return FALSE;
    286     }
    287     sz = 0;
    288     if (!WriteProcessMemory(hProcess,                       // hProcess
    289         pRemoteBuf[1],                  // lpBaseAddress
    290         (LPVOID)ThreadProc,             // lpBuffer
    291         dwSize,                         // nSize
    292         &sz))                         // [out] lpNumberOfBytesWritten
    293     {
    294         printf("写入大小:%d
    ", sz);
    295         printf("ThreadProc() WriteProcessMemory() fail : err_code = %d
    ", GetLastError());
    296         return FALSE;
    297     }
    298     printf("ThreadProc()写入大小:%d
    ", sz);
    299     if (!(hThread = CreateRemoteThread(hProcess,            // hProcess
    300         NULL,                // lpThreadAttributes
    301         0,                   // dwStackSize
    302         (LPTHREAD_START_ROUTINE)pRemoteBuf[1],     // dwStackSize
    303         pRemoteBuf[0],       // lpParameter
    304         0,                   // dwCreationFlags
    305         NULL)))             // lpThreadId
    306     {
    307         printf("CreateRemoteThread() fail : err_code = %d
    ", GetLastError());
    308         return FALSE;
    309     }
    310 
    311     WaitForSingleObject(hThread, INFINITE);
    312     CloseHandle(hThread);
    313     CloseHandle(hProcess);
    314     printf("code inject end
    ");
    315     return TRUE;
    316 }
    317 
    318 
    319 int _tmain(int argc, TCHAR *argv[])
    320 {
    321     /*if (argc != 3)
    322     {
    323         _tprintf(L"USAGE : %s <pid> <dll_path>
    ", argv[0]);
    324         return 1;
    325     }*/
    326     // change privilege
    327       // 判断当前进程是否以管理员身份运行
    328     checkAdmin();
    329     /*if (!SetPrivilege(SE_DEBUG_NAME, TRUE))
    330         return 1;*/
    331     //TraversalProcess();
    332     TCHAR pid[10];
    333     TCHAR path[MAX_PATH];
    334     system("tasklist");
    335     printf("ok
    ");
    336     printf("输入要注入的进程pid:
    ");
    337     scanf_s("%ls", pid, 10);
    338     printf("请选择功能:1.dll注入 2.代码注入
    ");
    339     int flag = 0;
    340     scanf_s("%d", &flag, 1);
    341     if (flag == 1) {
    342     printf("输入要注入的dll路径:");
    343     scanf_s("%ls", path,MAX_PATH);
    344     // inject dll
    345     if (InjectDll((DWORD)_tstol(pid), path))
    346         _tprintf(L"InjectDll("%s") success!!!
    ", path);
    347     else
    348         _tprintf(L"InjectDll("%s") failed!!!
    ", path);
    349     printf("输入q 卸载dll
    ");
    350     while (getchar() != 'q');
    351     TCHAR *p = _tcsrchr(path, '\');
    352     if(EjectDll((DWORD)_tstol(pid), p+1))
    353         printf("卸载dll成功!
    ");
    354     else 
    355     {
    356         printf("卸载失败!
    ");
    357     }
    358 
    359     system("pause");
    360     return 0;
    361     }
    362     else if (flag == 2)
    363     {
    364         InjectCode((DWORD)_tstol(pid));
    365         system("pause");
    366         return 0;
    367     }
    368     else
    369     {
    370         system("pause");
    371         return 0;
    372     }
    373 }

    判断当前运行时的权限,以管理员身份运行。

     1 BOOL    IsAdmin(HANDLE hProcess)
     2 {
     3     HANDLE hToken = NULL;
     4     OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
     5 
     6     TOKEN_ELEVATION_TYPE tokenType = TokenElevationTypeDefault; // 用于接收令牌类型
     7 
     8     DWORD dwRetSize = 0; // 用于接收函数输出信息的字节数
     9 
    10     // 2. 查询进程令牌中的权限提升值.( 这个值会记录当前的令牌是何种类型( 细节在17_权限管理_令牌的获取.cpp ) )
    11     GetTokenInformation(hToken,
    12         TokenElevationType,// 获取令牌的当前提升等级
    13         &tokenType,
    14         sizeof(tokenType),
    15         &dwRetSize // 所需缓冲区的字节数
    16     );
    17 
    18 
    19     // 根据令牌的类型来输出相应的信息
    20     if (TokenElevationTypeFull == tokenType) {
    21         // 3. 如果令牌是TokenElevationTypeFull , 则拥有至高无上的能力,可以给令牌添加任何特权
    22         printf("管理员账户,并拥有全部的权限,可以给令牌添加任何特权
    ");
    23         return TRUE;
    24     }
    25     // 4. 如果是其他的, 则需要以管理员身份重新运行本进程. 这样就能以第三步的方法解决剩下的问题.
    26     else if (TokenElevationTypeDefault == tokenType) {
    27         printf("默认用户, 可能是一个普通用户, 可能是关闭UAC时登录的管理员用户
    ");
    28 
    29         // 调用系统函数IsUserAnAdmin, 进一步确定是普通用户还是管理员用户
    30         return IsUserAnAdmin();
    31     }
    32     else if (TokenElevationTypeLimited == tokenType) {
    33 
    34         // 判断受限制的用户是管理员
    35         // 如果是管理员, 则这个令牌中会保存有管理员的SID
    36 
    37         // 1. 获取系统内键管理员用户的SID
    38         SID adminSid;
    39         DWORD dwSize = sizeof(adminSid);
    40         CreateWellKnownSid(WinBuiltinAdministratorsSid, // 获取SID的类型,这里是系统内键管理员
    41             NULL, // 传NULL,获取本地计算机的管理员
    42             &adminSid,// 函数输出的管理员SID
    43             &dwSize // 输入结构的大小,也作为输出
    44         );
    45 
    46         // 获取本令牌的连接令牌(受限制的令牌都会有一个连接的令牌,受限制的令牌正式由主令牌所创建的. )
    47         TOKEN_LINKED_TOKEN linkToken;
    48         GetTokenInformation(hToken,
    49             TokenLinkedToken, // 获取连接的令牌句柄
    50             &linkToken,
    51             sizeof(linkToken),
    52             &dwSize
    53         );
    54 
    55         // 在连接的令牌中查找是否具有管理员的SID
    56         BOOL    bIsContain = FALSE; // 用于保存是否包含.
    57         CheckTokenMembership(linkToken.LinkedToken, // 在这个令牌中检查
    58             &adminSid,             // 检查令牌中是否包含此SID
    59             &bIsContain);           // 输出TRUE则包含,反之不包含
    60 
    61 
    62 
    63         if (bIsContain) {
    64             printf("权限被阉割的受限制管理员账户, 部分权限被移处理
    ");
    65         }
    66 
    67 
    68         return bIsContain; // 不是以管理员权限运行
    69     }
    70 
    71     return FALSE;
    72 }
    73 
    74 void checkAdmin() {
    75     if (!IsAdmin(GetCurrentProcess())) {
    76 
    77         // 以管理员身份运行本进程
    78         //  1 获取本进程的文件路径.
    79         TCHAR path[MAX_PATH] = { 0 }; // 需要初始化
    80         DWORD dwPathSize = MAX_PATH;
    81         QueryFullProcessImageName(GetCurrentProcess(), 0,
    82             path,
    83             &dwPathSize);
    84 
    85         // 2 调用创建进程的API运行本进程.
    86         ShellExecute(NULL,            // 窗口句柄,没有则填NULL
    87             _T("runas"),   // 以管理员身份运行的重要参数
    88             path,            // 所有运行的程序的路径(这里是本进程)
    89             NULL,            // 命令行参数
    90             NULL,            // 新进程的工作目录的路径
    91             SW_SHOW           // 创建后的显示标志(最小化,最大化, 显示,隐藏等)
    92         );
    93 
    94         // 退出本进程
    95         ExitProcess(0);
    96     }
    97 }
  • 相关阅读:
    机器学习的分类与主要算法对比
    关于在JSP页面中为什么一定要用${pageContext.request.contextPath}来获取项目路径,而不能用${request.contextPath}?
    Spring Boot静态资源处理
    Tomcat关闭后,重新启动,session中保存的对象为什么还存在解决方法
    Tomcat 7源码学习笔记 -9 tomcat重启后session仍然保留
    mysql-sql语句中变量的使用
    js检测对象中是否存在某个属性
    mysql :=和=的区别
    sql面试题(学生表_课程表_成绩表_教师表)
    ddd
  • 原文地址:https://www.cnblogs.com/DirWang/p/11861880.html
Copyright © 2020-2023  润新知