zoukankan      html  css  js  c++  java
  • C++代码注入

    一、C++代码注入原则:

    1. 在注入代码中不允许使用API。
    2. 在注入代码中不允许使用全局变量。
    3. 在注入代码中不允许使用字符串(编译时也被当做全局变量)。
    4. 在注入代码中不允许使用函数嵌套。

    二、注入代码编写思路:

    1. 在本进程通过获取 LoadLibraryA 与 GetProcess 函数的地址。
    2. 涉及一组参数,里面包括 {函数地址、模块地址、函数名、传递参数}。
    3. 传入进去后,利用LoadLibraryA 与 GetProcess 函数,在注入代码中直接现场"加载模块-获取函数-调用",来达到调用API的目的。

    三、编写过程的几个坑:

    1. 使用typedef定义函数指针,先在msdn搜索函数原型,复制过去,将名字定义成指针并大写。
    2. 申请内存时的权限,参数的内存使用 PAGE_READWRITE权限;代码的内存使用PAGE_EXECUTE_READWRITE权限,否则代码无法被执行。
    3. 一定要预先在msdn上搜索确定函数要加载的模块以及函数名,这一步很容易出错。如果出错只能调试被注入程序获取结果,比较麻烦。

    四、olldbg调试思路:

    1. 在 "选项-调试设置-事件"中勾选“中断于新线程”。
    2. 注入后就可以在新线程上一步步进行调试。

    五、源代码(练习了两套,一套是注入MessageBoxA,另一套是注入CreateFileA)

      1 // 代码注入.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
      2 // 代码注入,实现在任意进程注入 messagebox() 这段代码
      3 
      4 #include "pch.h"
      5 #include <stdio.h>
      6 #include <Windows.h>
      7 DWORD WINAPI ThreadProc(LPVOID lpParameter);
      8     // 定义传入参数
      9     typedef struct _THREAD_PARAM {
     10         FARPROC pFunc[2]; // 存放两个函数 LoadLibraryA ; GetProcess;
     11         char szBuff[4][128]; // 存放四个参数
     12     }THREAD_PARAM, *PTHREAD_PARAM;
     13 
     14 // LoadLibraryA函数
     15 typedef HMODULE(WINAPI *PFLOADLIBARAYA)(LPCSTR lpLibFileName);
     16 
     17 // GetProcAddress()函数
     18 typedef FARPROC(WINAPI *PGETPROCADDRESS)(HMODULE hModule, LPCSTR lpProcName);
     19 
     20 // MessageBox()函数
     21 typedef int(WINAPI *PMESSAGEBOXA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
     22 
     23 // 注入目标进程的线程函数
     24 DWORD WINAPI ThreadProc(LPVOID lpParameter) {
     25     /*
     26         牢记:在代码注入中
     27         1. 不能使用系统函数。
     28         2. 不能使用全局变量。
     29         2. 不能使用字符串(因为这会被当成全局函数)
     30     */
     31 
     32 
     33     // 先将传入的参数值取出来
     34     PTHREAD_PARAM pParam = (PTHREAD_PARAM)lpParameter;
     35     HMODULE hMod = NULL;
     36     FARPROC pFunc = NULL; // messageBox这个函数
     37 
     38     // 先调用 LoadLibarayA函数来加载user32.dll
     39     hMod = ((PFLOADLIBARAYA)pParam->pFunc[0])(pParam->szBuff[0]); //LoadLibraryA(kernel32.dll) 先获取模块句柄,在获取 MessageBox这个函数。
     40     if (!hMod) return 1;
     41     // 再来调用 GetProcess 得到 MessageBox 这个函数
     42     pFunc = (FARPROC)((PGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuff[1]);
     43     if (!pFunc) return 1;
     44     // 调用函数来弹出对话框
     45     ((PMESSAGEBOXA)pFunc)(NULL, pParam->szBuff[2], pParam->szBuff[3], MB_OK);
     46 
     47     return 0;
     48 }
     49 
     50 BOOL InjectCode(DWORD Pid) {
     51 
     52 
     53 
     54     THREAD_PARAM param = { 0, };
     55     LPVOID lpBuffer[2] = { 0, }; // 存储两块开辟内存,一块存储参数,另一块存储代码
     56 
     57     // 获取 kernel32.dll模块句柄,因为需要的函数全部存储在此
     58     HMODULE hModule = GetModuleHandleA(("kernel32.dll"));
     59     
     60     // 初始化传入线程的参数
     61     param.pFunc[0] = GetProcAddress(hModule, "LoadLibraryA");
     62     param.pFunc[1] = GetProcAddress(hModule, "GetProcAddress");
     63     strcpy_s(param.szBuff[0], "user32.dll"); //加载的模块名
     64     strcpy_s(param.szBuff[1], "MessageBoxA"); //加载的函数名
     65     strcpy_s(param.szBuff[2], "abc"); //传入的第一个参数
     66     strcpy_s(param.szBuff[3], "def"); // 传入的第二个参数
     67 
     68     //开辟内存,将线程参数传入内存中
     69     HANDLE hProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
     70     DWORD dwSize = sizeof(THREAD_PARAM);
     71 
     72     lpBuffer[0] = VirtualAllocEx(hProcessHandle, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
     73 
     74     if (WriteProcessMemory(hProcessHandle, lpBuffer[0], (LPVOID)&param, dwSize, NULL)) {
     75         printf("第一段代码写入成功
    ");
     76     }
     77     else {
     78         printf("第一段代码写入失败,错误码:%d
    ", GetLastError());
     79         return FALSE;
     80     }
     81 
     82     // 开辟内存给线程,并将注入代码写入
     83     dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
     84     lpBuffer[1] = VirtualAllocEx(hProcessHandle, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
     85     if (WriteProcessMemory(hProcessHandle, lpBuffer[1], (LPVOID)ThreadProc, dwSize, NULL)) {
     86         printf("第二段代码写入成功
    ");
     87     }
     88     else {
     89         printf("第二段代码写入失败,错误码:%d
    ", GetLastError());
     90         return FALSE;
     91     }
     92 
     93     // 开始创建远程线程
     94     HANDLE hThread = CreateRemoteThread(hProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)lpBuffer[1], (LPVOID)lpBuffer[0], 0, NULL);
     95     if (hThread) {
     96         printf("线程开始执行!
    ");
     97     }
     98     else {
     99         printf("创建远程线程失败,错误码:%d
    ", GetLastError());
    100         return FALSE;
    101     }
    102     // 等待线程开始执行
    103     printf("到目前位置成功!");
    104     WaitForSingleObject(hThread, INFINITE);
    105     CloseHandle(hProcessHandle);
    106     CloseHandle(hThread);
    107 
    108 
    109     return TRUE;
    110 }
    111 
    112 // 拒绝访问时的提权代码
    113 BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
    114 {
    115     TOKEN_PRIVILEGES tp;
    116     HANDLE hToken;
    117     LUID luid;
    118 
    119     if (!OpenProcessToken(GetCurrentProcess(),
    120         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
    121         &hToken))
    122     {
    123         wprintf(L"OpenProcessToken error: %u
    ", GetLastError());
    124         return FALSE;
    125     }
    126 
    127     if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system
    128         lpszPrivilege,  // privilege to lookup 
    129         &luid))        // receives LUID of privilege
    130     {
    131         wprintf(L"LookupPrivilegeValue error: %u
    ", GetLastError());
    132         return FALSE;
    133     }
    134 
    135     tp.PrivilegeCount = 1;
    136     tp.Privileges[0].Luid = luid;
    137     if (bEnablePrivilege)
    138         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    139     else
    140         tp.Privileges[0].Attributes = 0;
    141 
    142     // Enable the privilege or disable all privileges.
    143     if (!AdjustTokenPrivileges(hToken,
    144         FALSE,
    145         &tp,
    146         sizeof(TOKEN_PRIVILEGES),
    147         (PTOKEN_PRIVILEGES)NULL,
    148         (PDWORD)NULL))
    149     {
    150         wprintf(L"AdjustTokenPrivileges error: %u
    ", GetLastError());
    151         return FALSE;
    152     }
    153 
    154     if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    155     {
    156         wprintf(L"The token does not have the specified privilege. 
    ");
    157         return FALSE;
    158     }
    159 
    160     return TRUE;
    161 }
    162 
    163 int main(int argc,char *argv[])
    164 {
    165     //判断参数个数
    166     if (argc != 2) {
    167         printf("
     USAGE  : %s <pid>
    ", argv[0]);
    168         return 1;
    169     }
    170     if (!SetPrivilege(SE_DEBUG_NAME, TRUE)) {
    171         printf("提权失败!
    ");
    172     }
    173     else {
    174         printf("提权成功!
    ");
    175         //atol 将字符串转换为数字
    176         if (InjectCode(atol(argv[1]))) {
    177             printf("开启成功!
    ");
    178         }
    179         else {
    180             printf("开启失败!
    ");
    181         }
    182     }
    183 
    184     getchar();
    185 }
    注入调用MessageBoxA()
      1 // 代码注入CreateFile函数.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
      2 //
      3 
      4 #include "pch.h"
      5 #include <iostream>
      6 #include <Windows.h>
      7 
      8 // 构建参数
      9 typedef struct _thread_param {
     10     FARPROC pFunc[2];  // LoadLibrary / GetProcAddress 函数
     11     // 这里应该存放字符
     12     char szBuffer[3][128]; // 加载的模块名字 user32.dll / CreateFileA / szFilePath
     13 }THREAD_PARAM,*PTHREAD_PARAM;
     14 
     15 // 先来构建函数指针
     16 typedef HANDLE (WINAPI *PCREATEFILEA)(
     17     LPCSTR                lpFileName,
     18     DWORD                 dwDesiredAccess,
     19     DWORD                 dwShareMode,
     20     LPSECURITY_ATTRIBUTES lpSecurityAttributes,
     21     DWORD                 dwCreationDisposition,
     22     DWORD                 dwFlagsAndAttributes,
     23     HANDLE                hTemplateFile
     24 );
     25 
     26 // LoadLibrary
     27 typedef HMODULE (WINAPI* PLOADLIBRARYA)(
     28     LPCSTR lpLibFileName
     29 );
     30 
     31 
     32 // GetProcAddress
     33 typedef FARPROC (WINAPI* PGETPROCADDRESS)(
     34     HMODULE hModule,
     35     LPCSTR  lpProcName
     36 );
     37 
     38 // GetProcess
     39 DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) {
     40 
     41     // 先取出参数,注意:传入一个指针,对应的也应该生成一个指针变量
     42     PTHREAD_PARAM pParam = (PTHREAD_PARAM)lpParameter;
     43 
     44     // 注意:loadLibraryA与getprocaddress 在kernel32.dll,这个不用导出,因为我们直接传入其函数地址,直接根据函数指针调用即可
     45     
     46     // 调用 LoadLibarayA来获取存放CreateFile模块
     47     HMODULE hModule = (HMODULE)((PLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuffer[0]);
     48     if (!hModule) return 1;
     49     
     50     
     51     // 调用GetPrcAddress来加载模块
     52     FARPROC pFunc = (FARPROC)((PGETPROCADDRESS)pParam->pFunc[1])(hModule, pParam->szBuffer[1]);
     53     if (!pFunc) return 1;
     54 
     55 
     56     // 现在调用CreateFileA函数
     57     ((PCREATEFILEA)pFunc)(pParam->szBuffer[2], GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
     58 
     59     return 0;
     60 }
     61 
     62 BOOL CodeInject(DWORD Pid) {
     63 
     64     // 我们的思路是获取目标进程句柄,分配-写入,最后再根据地址开启返回线程
     65     
     66 
     67     // 加载LoadLibraryA和GetProcAddress 两个函数的地址并且初始化参数
     68     THREAD_PARAM param;
     69     HMODULE hMoudle = LoadLibraryA("kernel32.dll");
     70     param.pFunc[0] = (FARPROC)GetProcAddress(hMoudle, "LoadLibraryA");
     71     param.pFunc[1] = (FARPROC)GetProcAddress(hMoudle, "GetProcAddress");
     72     strcpy_s(param.szBuffer[0], "Kernel32.dll");
     73     strcpy_s(param.szBuffer[1], "CreateFileA");
     74     strcpy_s(param.szBuffer[2], "OneFile.txt");
     75 
     76 
     77     LPVOID pBuffer[2]; // 两个存储目标进程地址的数组。
     78     int Res;
     79     HANDLE hProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
     80 
     81     // 向目标进程分配参数内存,参数内存可读写。
     82     DWORD dwSize = sizeof(THREAD_PARAM);
     83     pBuffer[0] = VirtualAllocEx(hProcessHandle, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
     84     if (!WriteProcessMemory(hProcessHandle, pBuffer[0], (LPVOID)&param, dwSize, NULL)) {
     85         printf("写入参数失败,错误码:%d", GetLastError());
     86         return FALSE;
     87     }
     88 
     89     // 向目标进程分配代码内存,参数内存读写-可执行。
     90     dwSize = (DWORD)CodeInject - (DWORD)ThreadProc;
     91     pBuffer[1] = VirtualAllocEx(hProcessHandle, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
     92     if (!WriteProcessMemory(hProcessHandle, pBuffer[1], (LPVOID)ThreadProc, dwSize, NULL)) {
     93         printf("写入代码失败,错误码:%d", GetLastError());
     94         return FALSE;
     95     }
     96 
     97     // 创建远程线程并执行
     98     HANDLE hThread = CreateRemoteThread(hProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)pBuffer[1], (LPVOID)pBuffer[0], 0, (LPDWORD )&Res);
     99     if (!hThread) {
    100         printf("创建远程线程失败,错误码:%d", GetLastError());
    101         return FALSE;
    102     }
    103     printf("线程结果:%d
    ", Res);
    104     // 关闭资源句柄
    105     WaitForSingleObject(hThread, INFINITE);
    106     CloseHandle(hMoudle);
    107     CloseHandle(hThread);
    108     
    109 
    110     return TRUE;
    111 }
    112 
    113 BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
    114 {
    115     TOKEN_PRIVILEGES tp;
    116     HANDLE hToken;
    117     LUID luid;
    118 
    119     if (!OpenProcessToken(GetCurrentProcess(),
    120         TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
    121         &hToken))
    122     {
    123         wprintf(L"OpenProcessToken error: %u
    ", GetLastError());
    124         return FALSE;
    125     }
    126 
    127     if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system
    128         lpszPrivilege,  // privilege to lookup 
    129         &luid))        // receives LUID of privilege
    130     {
    131         wprintf(L"LookupPrivilegeValue error: %u
    ", GetLastError());
    132         return FALSE;
    133     }
    134 
    135     tp.PrivilegeCount = 1;
    136     tp.Privileges[0].Luid = luid;
    137     if (bEnablePrivilege)
    138         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    139     else
    140         tp.Privileges[0].Attributes = 0;
    141 
    142     // Enable the privilege or disable all privileges.
    143     if (!AdjustTokenPrivileges(hToken,
    144         FALSE,
    145         &tp,
    146         sizeof(TOKEN_PRIVILEGES),
    147         (PTOKEN_PRIVILEGES)NULL,
    148         (PDWORD)NULL))
    149     {
    150         wprintf(L"AdjustTokenPrivileges error: %u
    ", GetLastError());
    151         return FALSE;
    152     }
    153 
    154     if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    155     {
    156         wprintf(L"The token does not have the specified privilege. 
    ");
    157         return FALSE;
    158     }
    159 
    160     return TRUE;
    161 }
    162 
    163 int main(int argc,char*argv[])
    164 {
    165 
    166     // 在本地创建一个文件夹
    167     // HANDLE hFile = CreateFileA("一个文件", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    168     //CloseHandle(hFile);
    169     // 现在实现代码注入,要求在notepad.exe中运行上段代码。
    170 
    171     //判断参数个数
    172     if (argc != 2) {
    173         printf("
     USAGE  : %s <pid>
    ", argv[0]);
    174         return 1;
    175     }
    176     
    177     if (!SetPrivilege(SE_DEBUG_NAME, TRUE)) {
    178         printf("提权失败!
    ");
    179     }
    180     else {
    181         printf("提权成功!
    ");
    182         if (CodeInject(atol(argv[1]))) {
    183             printf("开启成功1!
    ");
    184         }
    185         else {
    186             printf("开启失败!
    ");
    187         }
    188     }
    189 
    190 
    191     getchar();
    192     
    193 }
    注入调用CreateFileA()
  • 相关阅读:
    51 Nod 1086 多重背包问题(单调队列优化)
    51 Nod 1086 多重背包问题(二进制优化)
    51 Nod 1085 01背包问题
    poj 2559 Largest Rectangle(单调栈)
    51 Nod 1089 最长回文子串(Manacher算法)
    51 Nod N的阶乘的长度 (斯特林近似)
    51 Nod 1134 最长递增子序列(经典问题回顾)
    51 Nod 1020 逆序排列
    PCA-主成分分析(Principal components analysis)
    Python中cPickle
  • 原文地址:https://www.cnblogs.com/onetrainee/p/11648679.html
Copyright © 2011-2022 走看看