一、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)

 // 代码注入.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// 代码注入,实现在任意进程注入 messagebox() 这段代码 #include "pch.h"
#include <stdio.h>
#include <Windows.h>
DWORD WINAPI ThreadProc(LPVOID lpParameter);
// 定义传入参数
typedef struct _THREAD_PARAM {
FARPROC pFunc[]; // 存放两个函数 LoadLibraryA ; GetProcess;
char szBuff[][]; // 存放四个参数
}THREAD_PARAM, *PTHREAD_PARAM; // LoadLibraryA函数
typedef HMODULE(WINAPI *PFLOADLIBARAYA)(LPCSTR lpLibFileName); // GetProcAddress()函数
typedef FARPROC(WINAPI *PGETPROCADDRESS)(HMODULE hModule, LPCSTR lpProcName); // MessageBox()函数
typedef int(WINAPI *PMESSAGEBOXA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType); // 注入目标进程的线程函数
DWORD WINAPI ThreadProc(LPVOID lpParameter) {
/*
牢记:在代码注入中
1. 不能使用系统函数。
2. 不能使用全局变量。
2. 不能使用字符串(因为这会被当成全局函数)
*/ // 先将传入的参数值取出来
PTHREAD_PARAM pParam = (PTHREAD_PARAM)lpParameter;
HMODULE hMod = NULL;
FARPROC pFunc = NULL; // messageBox这个函数 // 先调用 LoadLibarayA函数来加载user32.dll
hMod = ((PFLOADLIBARAYA)pParam->pFunc[])(pParam->szBuff[]); //LoadLibraryA(kernel32.dll) 先获取模块句柄,在获取 MessageBox这个函数。
if (!hMod) return ;
// 再来调用 GetProcess 得到 MessageBox 这个函数
pFunc = (FARPROC)((PGETPROCADDRESS)pParam->pFunc[])(hMod, pParam->szBuff[]);
if (!pFunc) return ;
// 调用函数来弹出对话框
((PMESSAGEBOXA)pFunc)(NULL, pParam->szBuff[], pParam->szBuff[], MB_OK); return ;
} BOOL InjectCode(DWORD Pid) { THREAD_PARAM param = { , };
LPVOID lpBuffer[] = { , }; // 存储两块开辟内存,一块存储参数,另一块存储代码 // 获取 kernel32.dll模块句柄,因为需要的函数全部存储在此
HMODULE hModule = GetModuleHandleA(("kernel32.dll")); // 初始化传入线程的参数
param.pFunc[] = GetProcAddress(hModule, "LoadLibraryA");
param.pFunc[] = GetProcAddress(hModule, "GetProcAddress");
strcpy_s(param.szBuff[], "user32.dll"); //加载的模块名
strcpy_s(param.szBuff[], "MessageBoxA"); //加载的函数名
strcpy_s(param.szBuff[], "abc"); //传入的第一个参数
strcpy_s(param.szBuff[], "def"); // 传入的第二个参数 //开辟内存,将线程参数传入内存中
HANDLE hProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
DWORD dwSize = sizeof(THREAD_PARAM); lpBuffer[] = VirtualAllocEx(hProcessHandle, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); if (WriteProcessMemory(hProcessHandle, lpBuffer[], (LPVOID)&param, dwSize, NULL)) {
printf("第一段代码写入成功\n");
}
else {
printf("第一段代码写入失败,错误码:%d\n", GetLastError());
return FALSE;
} // 开辟内存给线程,并将注入代码写入
dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
lpBuffer[] = VirtualAllocEx(hProcessHandle, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (WriteProcessMemory(hProcessHandle, lpBuffer[], (LPVOID)ThreadProc, dwSize, NULL)) {
printf("第二段代码写入成功\n");
}
else {
printf("第二段代码写入失败,错误码:%d\n", GetLastError());
return FALSE;
} // 开始创建远程线程
HANDLE hThread = CreateRemoteThread(hProcessHandle, NULL, , (LPTHREAD_START_ROUTINE)lpBuffer[], (LPVOID)lpBuffer[], , NULL);
if (hThread) {
printf("线程开始执行!\n");
}
else {
printf("创建远程线程失败,错误码:%d\n", GetLastError());
return FALSE;
}
// 等待线程开始执行
printf("到目前位置成功!");
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hProcessHandle);
CloseHandle(hThread); return TRUE;
} // 拒绝访问时的提权代码
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid; if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
{
wprintf(L"OpenProcessToken error: %u\n", GetLastError());
return FALSE;
} if (!LookupPrivilegeValue(NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
wprintf(L"LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
} tp.PrivilegeCount = ;
tp.Privileges[].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[].Attributes = ; // Enable the privilege or disable all privileges.
if (!AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
wprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
} if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
wprintf(L"The token does not have the specified privilege. \n");
return FALSE;
} return TRUE;
} int main(int argc,char *argv[])
{
//判断参数个数
if (argc != ) {
printf("\n USAGE : %s <pid>\n", argv[]);
return ;
}
if (!SetPrivilege(SE_DEBUG_NAME, TRUE)) {
printf("提权失败!\n");
}
else {
printf("提权成功!\n");
//atol 将字符串转换为数字
if (InjectCode(atol(argv[]))) {
printf("开启成功!\n");
}
else {
printf("开启失败!\n");
}
} getchar();
}

注入调用MessageBoxA()

 // 代码注入CreateFile函数.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// #include "pch.h"
#include <iostream>
#include <Windows.h> // 构建参数
typedef struct _thread_param {
FARPROC pFunc[]; // LoadLibrary / GetProcAddress 函数
// 这里应该存放字符
char szBuffer[][]; // 加载的模块名字 user32.dll / CreateFileA / szFilePath
}THREAD_PARAM,*PTHREAD_PARAM; // 先来构建函数指针
typedef HANDLE (WINAPI *PCREATEFILEA)(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
); // LoadLibrary
typedef HMODULE (WINAPI* PLOADLIBRARYA)(
LPCSTR lpLibFileName
); // GetProcAddress
typedef FARPROC (WINAPI* PGETPROCADDRESS)(
HMODULE hModule,
LPCSTR lpProcName
); // GetProcess
DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) { // 先取出参数,注意:传入一个指针,对应的也应该生成一个指针变量
PTHREAD_PARAM pParam = (PTHREAD_PARAM)lpParameter; // 注意:loadLibraryA与getprocaddress 在kernel32.dll,这个不用导出,因为我们直接传入其函数地址,直接根据函数指针调用即可 // 调用 LoadLibarayA来获取存放CreateFile模块
HMODULE hModule = (HMODULE)((PLOADLIBRARYA)pParam->pFunc[])(pParam->szBuffer[]);
if (!hModule) return ; // 调用GetPrcAddress来加载模块
FARPROC pFunc = (FARPROC)((PGETPROCADDRESS)pParam->pFunc[])(hModule, pParam->szBuffer[]);
if (!pFunc) return ; // 现在调用CreateFileA函数
((PCREATEFILEA)pFunc)(pParam->szBuffer[], GENERIC_READ | GENERIC_WRITE, , NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); return ;
} BOOL CodeInject(DWORD Pid) { // 我们的思路是获取目标进程句柄,分配-写入,最后再根据地址开启返回线程 // 加载LoadLibraryA和GetProcAddress 两个函数的地址并且初始化参数
THREAD_PARAM param;
HMODULE hMoudle = LoadLibraryA("kernel32.dll");
param.pFunc[] = (FARPROC)GetProcAddress(hMoudle, "LoadLibraryA");
param.pFunc[] = (FARPROC)GetProcAddress(hMoudle, "GetProcAddress");
strcpy_s(param.szBuffer[], "Kernel32.dll");
strcpy_s(param.szBuffer[], "CreateFileA");
strcpy_s(param.szBuffer[], "OneFile.txt"); LPVOID pBuffer[]; // 两个存储目标进程地址的数组。
int Res;
HANDLE hProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid); // 向目标进程分配参数内存,参数内存可读写。
DWORD dwSize = sizeof(THREAD_PARAM);
pBuffer[] = VirtualAllocEx(hProcessHandle, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
if (!WriteProcessMemory(hProcessHandle, pBuffer[], (LPVOID)&param, dwSize, NULL)) {
printf("写入参数失败,错误码:%d", GetLastError());
return FALSE;
} // 向目标进程分配代码内存,参数内存读写-可执行。
dwSize = (DWORD)CodeInject - (DWORD)ThreadProc;
pBuffer[] = VirtualAllocEx(hProcessHandle, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!WriteProcessMemory(hProcessHandle, pBuffer[], (LPVOID)ThreadProc, dwSize, NULL)) {
printf("写入代码失败,错误码:%d", GetLastError());
return FALSE;
} // 创建远程线程并执行
HANDLE hThread = CreateRemoteThread(hProcessHandle, NULL, , (LPTHREAD_START_ROUTINE)pBuffer[], (LPVOID)pBuffer[], , (LPDWORD )&Res);
if (!hThread) {
printf("创建远程线程失败,错误码:%d", GetLastError());
return FALSE;
}
printf("线程结果:%d\n", Res);
// 关闭资源句柄
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hMoudle);
CloseHandle(hThread); return TRUE;
} BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid; if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
{
wprintf(L"OpenProcessToken error: %u\n", GetLastError());
return FALSE;
} if (!LookupPrivilegeValue(NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
wprintf(L"LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
} tp.PrivilegeCount = ;
tp.Privileges[].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[].Attributes = ; // Enable the privilege or disable all privileges.
if (!AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
wprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
} if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
wprintf(L"The token does not have the specified privilege. \n");
return FALSE;
} return TRUE;
} int main(int argc,char*argv[])
{ // 在本地创建一个文件夹
// HANDLE hFile = CreateFileA("一个文件", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
//CloseHandle(hFile);
// 现在实现代码注入,要求在notepad.exe中运行上段代码。 //判断参数个数
if (argc != ) {
printf("\n USAGE : %s <pid>\n", argv[]);
return ;
} if (!SetPrivilege(SE_DEBUG_NAME, TRUE)) {
printf("提权失败!\n");
}
else {
printf("提权成功!\n");
if (CodeInject(atol(argv[]))) {
printf("开启成功1!\n");
}
else {
printf("开启失败!\n");
}
} getchar(); }

注入调用CreateFileA()

C++代码注入的更多相关文章

  1. 阿里云提示Discuz uc.key泄露导致代码注入漏洞uc.php的解决方法

    适用所有用UC整合 阿里云提示漏洞: discuz中的/api/uc.php存在代码写入漏洞,导致黑客可写入恶意代码获取uckey,.......... 漏洞名称:Discuz uc.key泄露导致代 ...

  2. 【原】iOS动态性(三) Method Swizzling以及AOP编程:在运行时进行代码注入

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  3. Java链接MySQL练习题:格式化日期、性别;避免代码注入

    一.查询人员名单,按序号 姓名 性格(男或女) 民族(某族) 生日(年月日)输出 import java.sql.*; import java.text.SimpleDateFormat; publi ...

  4. 转:EasyHook远程代码注入

    EasyHook远程代码注入 最近一段时间由于使用MinHook的API挂钩不稳定,经常因为挂钩地址错误而导致宿主进程崩溃.听同事介绍了一款智能强大的挂钩引擎EasyHook.它比微软的detours ...

  5. Android 反编译 代码注入之HelloWorld

    为了向经典的"Hello, World"致敬,我们也从一个简单的程序开始HelloWorld.apk.当你把这个APK安装到手机上运行后,在屏幕上就显示一行文字"Hell ...

  6. apk反编译(4)Smali代码注入

    转自 : http://blog.sina.com.cn/s/blog_5674d18801019i89.html 应用场景 Smali代码注入只能应对函数级别的移植,对于类级别的移植是无能为力的.具 ...

  7. 注入攻击-SQL注入和代码注入

    注入攻击 OWASP将注入攻击和跨站脚本攻击(XSS)列入网络应用程序十大常见安全风险.实际上,它们会一起出现,因为 XSS 攻击依赖于注入攻击的成功.虽然这是最明显的组合关系,但是注入攻击带来的不仅 ...

  8. Method Swizzling以及AOP编程:在运行时进行代码注入-备用

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  9. 32位汇编第三讲,RadAsm,IDE的配置和使用,以及汇编代码注入方式

    32位汇编第三讲,RadAsm,IDE的配置和使用,以及汇编代码注入方式 一丶RadAsm的配置和使用 用了怎么长时间的命令行方式,我们发现了几个问题 1.没有代码提醒功能 2.编写代码很慢,记不住各 ...

  10. CVE漏洞—PHPCMS2008 /type.php代码注入高危漏洞预警

    11月4日,阿里云安全首次捕获PHPCMS 2008版本的/type.php远程GetShell 0day利用攻击,攻击者可以利用该漏洞远程植入webshell,导致文件篡改.数据泄漏.服务器被远程控 ...

随机推荐

  1. 模板汇总——Tarjian

    1. 单向边  + 新图建边 int belong[N], dfn[N], low[N], now_time, scc_cnt; stack<int> s; void dfs(int u) ...

  2. PAT 天梯杯 L2-024 部落 dfs,连通块

    L2-024. 部落 时间限制 120 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不 ...

  3. 创建最简单的exe形式COM组件并在MFC程序调用

    来新公司学习接手新项目,拿到代码打开解决方案看到里面竟然有40几个工程,有点吃惊.具体看代码也有很多之前没见过的写法,上了几天火. 有件事就没太搞明白,按照文档的说法上层很多软件都要调用IO服务器,但 ...

  4. Java中String为什么是不可变的

    1.在Java中,String类是不可变类,一个不可变类是一个简单的类,并且这个的实例也不能被修改, 这个类的实例创建的时候初始化所有的信息,并且这些信息不能够被修改 2.字符串常量池 字符串常量池是 ...

  5. 零基础一年拿下BAT三家offer

    背景 1.本人本科一本双非垫底的那种,硕士211.本硕电子通信,完全0基础,转行一年. 2.研一上第一学期上课+外派到老师合作公司写MATLAB.去年4月开始学习Java. 起步 1.实话说,刚决定转 ...

  6. SpringBoot 2 快速整合 | Hibernate Validator 数据校验

    概述 在开发RESTFull API 和普通的表单提交都需要对用户提交的数据进行校验,例如:用户姓名不能为空,年龄必须大于0 等等.这里我们主要说的是后台的校验,在 SpringBoot 中我们可以通 ...

  7. .Net基础篇_学习笔记_第四天_关系运算符和逻辑运算符

    1.关系运算符 包含:>   <   <=  >=   ==  != 以及bool类型中的true和false. 2.逻辑运算符 与 && 或 || 非 ! 注 ...

  8. Python中使用pip安装库时提示:远程主机强迫关闭了一个现有的连接

    场景 在cmd中使用pip install moviepy时,需要安装一些依赖库,很长时间后提示: 远程主机中断了一个现有的连接. 原因是默认镜像源下载过慢,将其修改为国内或者设置安装时的源. 这里以 ...

  9. 基于DevExpress的SpreadsheetControl实现对Excel的打开、预览、保存、另存为、打印(附源码下载)

    场景 Winform控件-DevExpress18下载安装注册以及在VS中使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1 ...

  10. Winform中使用zxing实现二维码生成(附dll下载)

    场景 zxing.dll下载 https://download.csdn.net/download/badao_liumang_qizhi/11623214 效果 实现 新建Winform程序,将上面 ...