Wx64ST:一款轻松可修改的C语言Shellcode模板

news2024/9/21 13:38:48

关于windows_x64_shellcode_template

windows_x64_shellcode_template简称为Wx64ST,它是一款功能强大的Shellcode模板,该模板基于C语言编写,其简单、可扩展和易于修改等特性可以帮助广大安全研究人员轻松开发适用于Windows x64的Shellcode。

值得一提的是,该模板代码可以加载LoadLibraryA和GetProcAddress,并以C语言方式暴露HMODULE给kernel32.dll。

除此之外,模板提供的函数中包含了很多注释内容,以供广大研究人员参考。

工具要求

VS 2015 / VS 2017

工具安装

广大研究人员可以直接使用下列命令将该项目源码克隆至本地:

git clone https://github.com/rainerzufalldererste/windows_x64_shellcode_template.git

cd windows_x64_shellcode_template

git submodule update --init --recursive

create_project.bat

该shellcode_template项目包括开始开发自定义Shellcode的所有内容。

如何检索 Shellcode

有很多方法可以检索生成的 shellcode。最简单的方法可能是直接进入Visual Studio调试器并切换到void shellcode_template(),然后打开反汇编视图 (Ctrl+Alt+D)。请确保打开显示代码字节并关闭显示源代码和地址以简化输出:

48 89 5C 24 08       mov         qword ptr [rsp+8],rbx  

57                   push        rdi  

48 83 EC 30          sub         rsp,30h  

65 48 8B 04 25 60 00 00 00 mov         rax,qword ptr gs:[0000000000000060h]  

33 D2                xor         edx,edx  

49 B8 47 65 74 50 72 6F 63 41 mov         r8,41636F7250746547h  

48 8B 48 18          mov         rcx,qword ptr [rax+18h]  

48 8B 41 20          mov         rax,qword ptr [rcx+20h]  

48 8B 08             mov         rcx,qword ptr [rax]  

48 8B 01             mov         rax,qword ptr [rcx]  

48 8B 78 20          mov         rdi,qword ptr [rax+20h]  

48 63 47 3C          movsxd      rax,dword ptr [rdi+3Ch]  

44 8B 8C 38 88 00 00 00 mov         r9d,dword ptr [rax+rdi+0000000000000088h]  

41 8B 44 39 20       mov         eax,dword ptr [r9+rdi+20h]  

48 03 C7             add         rax,rdi  

48 63 08             movsxd      rcx,dword ptr [rax]  

4C 39 04 39          cmp         qword ptr [rcx+rdi],r8  

 ...

现在您只需移除标签和反汇编代码即可,剩下的就是Shellcode:

48 89 5C 24 08       mov         qword ptr [rsp+8],rbx  

57                   push        rdi  

48 83 EC 30          sub         rsp,30h  

65 48 8B 04 25 60 00 00 00 mov         rax,qword ptr gs:[0000000000000060h]  

33 D2                xor         edx,edx  

49 B8 47 65 74 50 72 6F 63 41 mov         r8,41636F7250746547h  

48 8B 48 18          mov         rcx,qword ptr [rax+18h]  

48 8B 41 20          mov         rax,qword ptr [rcx+20h]  

48 8B 08             mov         rcx,qword ptr [rax]  

48 8B 01             mov         rax,qword ptr [rcx]  

48 8B 78 20          mov         rdi,qword ptr [rax+20h]  

48 63 47 3C          movsxd      rax,dword ptr [rdi+3Ch]  

44 8B 8C 38 88 00 00 00 mov         r9d,dword ptr [rax+rdi+0000000000000088h]  

41 8B 44 39 20       mov         eax,dword ptr [r9+rdi+20h]  

48 03 C7             add         rax,rdi  

48 63 08             movsxd      rcx,dword ptr [rax]  

4C 39 04 39          cmp         qword ptr [rcx+rdi],r8  

 ...
现在您只需移除标签和反汇编代码即可,剩下的就是Shellcode:

48 89 5C 24 08

57

48 83 EC 30

65 48 8B 04 25 60 00 00 00

33 D2

49 B8 47 65 74 50 72 6F 63 41

48 8B 48 18

48 8B 41 20

48 8B 08

48 8B 01

48 8B 78 20

48 63 47 3C

44 8B 8C 38 88 00 00 00

41 8B 44 39 20

48 03 C7

48 63 08

4C 39 04 39

 ...

或者,您可以将代码粘贴到像 godbolt.org 这样的在线编译器中,然后将生成的 MSVC 程序集(不调用任何内部函数,例如缓冲区安全检查或 memcpy)(即使用x64 msvc v19.latest)复制到像 https://defuse.ca/online-x86-assembler.htm/O2 /GS-这样的在线汇编程序中。然后只需复制生成的Shellcode即可。

当使用在线编译器时,你可能需要稍微清理一下汇编代码,如下所示:

x$ = 32

void shellcode_template(void) PROC               ; shellcode_template, COMDAT

$LN10:

        mov     QWORD PTR [rsp+8], rbx

        push    rdi

        sub     rsp, 48                             ; 00000030H

        mov     rax, QWORD PTR gs:96

        xor     edx, edx

        mov     r8, 4711732171926431047             ; 41636f7250746547H

        mov     rcx, QWORD PTR [rax+24]

        mov     rax, QWORD PTR [rcx+32]

        mov     rcx, QWORD PTR [rax]

        mov     rax, QWORD PTR [rcx]

        mov     rdi, QWORD PTR [rax+32]

        movsxd  rax, DWORD PTR [rdi+60]

        mov     r9d, DWORD PTR [rax+rdi+136]

        mov     eax, DWORD PTR [r9+rdi+32]

        add     rax, rdi

        movsxd  rcx, DWORD PTR [rax]

        cmp     QWORD PTR [rcx+rdi], r8

        je      SHORT $LN3@shellcode_

        npad    2

$LL2@shellcode_:

        movsxd  rcx, DWORD PTR [rax+4]

        lea     rax, QWORD PTR [rax+4]

        inc     edx

        cmp     QWORD PTR [rcx+rdi], r8

        jne     SHORT $LL2@shellcode_

$LN3@shellcode_:

        mov     ecx, DWORD PTR [r9+rdi+36]

        mov     rax, 8242266044863967052      ; 7262694c64616f4cH

        ...

可以通过一些查找和替换将代码变成这样:

shellcode_template:

        mov     qword ptr [rsp+8], rbx

        push    rdi

        sub     rsp, 48

        mov     rax, qword ptr gs:96

        xor     edx, edx

        mov     r8, 4711732171926431047

        mov     rcx, qword ptr [rax+24]

        mov     rax, qword ptr [rcx+32]

        mov     rcx, qword ptr [rax]

        mov     rax, qword ptr [rcx]

        mov     rdi, qword ptr [rax+32]

        movsxd  rax, DWORD ptr [rdi+60]

        mov     r9d, DWORD ptr [rax+rdi+136]

        mov     eax, DWORD ptr [r9+rdi+32]

        add     rax, rdi

        movsxd  rcx, DWORD ptr [rax]

        cmp     qword ptr [rcx+rdi], r8

        je      SHORT _function_found

        

        ; `npad    2` can be turned into two `nop`s.

 

        nop

        nop

 

 

_find_next_function:

        movsxd  rcx, DWORD ptr [rax+4]

        lea     rax, qword ptr [rax+4]

        inc     edx

        cmp     qword ptr [rcx+rdi], r8

        jne     SHORT _find_next_function

 

 

_function_found:

        mov     ecx, DWORD ptr [r9+rdi+36]

        mov     rax, 8242266044863967052

        ...

生成的 Shellcode

下面给出的是该项目提供的Shellcode样例,它将执行下列操作:

1、在kernel32.dll中查找GetProcAddress;

2、从kernel32.dll检索LoadLibraryA;

3、加载useR32.dll;

4、从useR32.dll检索MessageBoxA;

5、显示一个消息提示框;

6、从kernel32.dll检索ExitProcess;

7、调用ExitProcess;

0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60,

  0x00, 0x00, 0x00, 0x33, 0xD2, 0x49, 0xB8, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x41, 0x48,

  0x8B, 0x48, 0x18, 0x48, 0x8B, 0x41, 0x20, 0x48, 0x8B, 0x08, 0x48, 0x8B, 0x01, 0x48, 0x8B, 0x78,

  0x20, 0x48, 0x63, 0x47, 0x3C, 0x44, 0x8B, 0x8C, 0x38, 0x88, 0x00, 0x00, 0x00, 0x41, 0x8B, 0x44,

  0x39, 0x20, 0x48, 0x03, 0xC7, 0x48, 0x63, 0x08, 0x4C, 0x39, 0x04, 0x39, 0x74, 0x12, 0x66, 0x90,

  0x48, 0x63, 0x48, 0x04, 0x48, 0x8D, 0x40, 0x04, 0xFF, 0xC2, 0x4C, 0x39, 0x04, 0x39, 0x75, 0xF0,

  0x41, 0x8B, 0x4C, 0x39, 0x24, 0x48, 0xB8, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x48,

  0x03, 0xCF, 0x48, 0x63, 0xD2, 0x4C, 0x0F, 0xBF, 0x04, 0x51, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x41,

  0x8B, 0x4C, 0x39, 0x1C, 0x48, 0x03, 0xCF, 0x4A, 0x63, 0x1C, 0x81, 0x48, 0x8B, 0xCF, 0x48, 0x03,

  0xDF, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0xC7, 0x44, 0x24, 0x28, 0x61, 0x72, 0x79, 0x41, 0xFF,

  0xD3, 0x48, 0xB9, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x48, 0xC7, 0x44, 0x24, 0x28,

  0x6C, 0x6C, 0x00, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, 0xD0,

  0x48, 0xB9, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x48, 0xC7, 0x44, 0x24, 0x28, 0x6F,

  0x78, 0x41, 0x00, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x8B, 0xC8,

  0xFF, 0xD3, 0x48, 0xB9, 0x48, 0x61, 0x73, 0x74, 0x61, 0x20, 0x6C, 0x61, 0x4C, 0x8D, 0x44, 0x24,

  0x2F, 0x48, 0x89, 0x4C, 0x24, 0x20, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0xB9, 0x20, 0x76, 0x69,

  0x73, 0x74, 0x61, 0x21, 0x00, 0x45, 0x33, 0xC9, 0x48, 0x89, 0x4C, 0x24, 0x28, 0x33, 0xC9, 0xFF,

  0xD0, 0x48, 0xB8, 0x45, 0x78, 0x69, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x48, 0xC7, 0x44, 0x24, 0x28,

  0x65, 0x73, 0x73, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x20, 0x48, 0x89, 0x44, 0x24, 0x20, 0x48, 0x8B,

  0xCF, 0xFF, 0xD3, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x48, 0x8B, 0x5C, 0x24, 0x40, 0x48,

  0x83, 0xC4, 0x30, 0x5F, 0xC3

工具使用演示

下面给出的是一个示例应用程序,演示了如何使用Wx64ST在子进程内执行生成的Shellcode:

// Load Process Environment Block.

  PEB *pProcessEnvironmentBlock = (PEB *)__readgsqword(0x60);

 

  // `pProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList` contains a double linked list.

  // `Flink` and `Blink` are pointers to the next and previous element.

  //

  // All Windows executables should have the following module order.

  //  1. The module of the current executable.

  //  2. `ntdll.dll` (`%windir%\System32\ntdll.dll`)

  //  3. `kernel32.dll` (`%windir%\System32\kernel32.dll`)

  //

  //  ... followed by other modules.

  //

  // In order to get the `GetProcAddress` function we need to therefore get the third item (`Flink->Flink->Flink`).

  // We use the `CONTAINING_RECORD` macro to retrieve the associated table entry.

  LDR_DATA_TABLE_ENTRY *pKernel32TableEntry = CONTAINING_RECORD(pProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList.Flink->Flink->Flink, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

 

  // We've ended up at the base address of `kernel32.dll`.

  IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER *)pKernel32TableEntry->DllBase;

 

  // In order to get the exported functions we need to go to the NT PE header.

  IMAGE_NT_HEADERS *pNtHeader = (IMAGE_NT_HEADERS *)((size_t)pDosHeader + pDosHeader->e_lfanew);

 

  // From the NtHeader we can extract the virtual address of the export directory of this module.

  IMAGE_EXPORT_DIRECTORY *pExports = (IMAGE_EXPORT_DIRECTORY *)((size_t)pDosHeader + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

 

  // The exports directory contains both a list of function _names_ of this module and the associated _addresses_ of the functions.

  const int32_t *pNameOffsets = (const int32_t *)((size_t)pDosHeader + pExports->AddressOfNames);

  

  // We will use this struct to store strings.

  // We are using a struct to make sure strings don't end up in another section of the executable where we wouldn't be able to address them in a different process.

  struct

  {

    uint64_t text0, text1;

  } x;

 

  // We're now looking for the `GetProcAddress` function. Since there's no other function starting with `GetProcA` we'll just find that instead.

  x.text0 = 0x41636F7250746547; // `GetProcA`

 

  int32_t i = 0;

 

  // We're just extracting the first 8 bytes of the strings and compare them to `GetProcA`. We'll find it eventually.

  while (*(uint64_t *)((size_t)pDosHeader + pNameOffsets[i]) != x.text0)

    ++i;

 

  // We have found the index of `GetProcAddress`.

 

  // The entry at an index in `AddressOfNames` corresponds to an entry at the same index in `AddressOfNameOrdinals`, which resolves the index of a given name to it's corresponding entry in `AddressOfFunctions`. (DLLs can export unnamed functions, which will not be listed in `AddressOfNames`.)

  // Let's get the function name ordinal offsets and function offsets in order to retrieve the location of `GetProcAddress` in memory.

  const int16_t *pFunctionNameOrdinalOffsets = (const int16_t *)((size_t)pDosHeader + pExports->AddressOfNameOrdinals);

  const int32_t *pFunctionOffsets = (const int32_t *)((size_t)pDosHeader + pExports->AddressOfFunctions);

 

  // Now resolve the index in `pFunctionOffsets` from `pFunctionNameOrdinalOffsets` to get the address of the desired function in memory.

  typedef FARPROC(*GetProcAddressFunc)(HMODULE, const char *);

  GetProcAddressFunc pGetProcAddress = (GetProcAddressFunc)(const void *)((size_t)pDosHeader + pFunctionOffsets[pFunctionNameOrdinalOffsets[i]]);

 

  // Now that we've got `GetProcAddress`, let's use it to get `LoadLibraryA`.

 

  // A HMODULE is just a pointer to the base address of a module.

  HMODULE kernel32Dll = (HMODULE)pDosHeader;

 

  // Get `LoadLibraryA`.

  x.text0 = 0x7262694C64616F4C; // `LoadLibr`

  x.text1 = 0x0000000041797261; // `aryA\0\0\0\0`

 

  typedef HMODULE(*LoadLibraryAFunc)(const char *);

  LoadLibraryAFunc pLoadLibraryA = (LoadLibraryAFunc)pGetProcAddress(kernel32Dll, (const char *)&x.text0);

项目地址

windows_x64_shellcode_template:【GitHub传送门】

参考资料

Compiler Explorer

Online x86 and x64 Intel Instruction Assembler

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

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

相关文章

kali (linux) 安装配置 共享文件夹 samba

一、samba 安装 sudo apt-get install samba 二、启动samba 服务 systemctl enable nmb systemctl enable smb systemctl start nmb systemctl start smb 三、查看 samba状态 systemctl status nmb systemctl status smb 四、创建共享文件夹 ,并修改权限 …

技术指南:5分钟零成本实现本地AI知识库搭建

你一定经历过各种通用大模型一本正经胡说八道的时候吧,AI一通丝滑输出让人真假难辨,防不胜防。这种情况被称为AI幻觉。 大模型产生幻觉不幸“翻车”的原因很大程度上是“先天不足”,例如训练时来自特定领域的训练数据就比较缺失或存在偏差等…

20-22 - 打造专业的编译环境

---- 整理自狄泰软件唐佐林老师课程 文章目录 1. 大型项目的编译(无第三方库)1.1 大型项目的目录结构(无第三方库)1.2 项目结构设计分析1.3 需要打造的编译环境1.4 解决方案设计 2. 第 1 阶段任务2.1 关键的实现要点2.2 模块 make…

MES管理系统如何提升产品质量与可追溯性

在智能制造的新纪元里,MES管理系统正逐步崭露头角,成为驱动制造业转型升级的幕后英雄。MES管理系统不仅重新定义了生产过程的管理与控制方式,还以数据为驱动,引领着制造业迈向更高效、更智能、更可持续的未来。 智能制造的赋能者&…

U-Mail垃圾邮件过滤网关‍是如何过滤垃圾邮件的?

随着互联网的普及,垃圾邮件已经成为计算机网络安全的又一个公害。因此,反垃圾邮件已经成为互联网应用研究中一个重要课题。为了防止垃圾邮件首先要学会保护自己的邮件地址,避免在网上随意登记和使用邮件地址,预防垃圾邮件骚扰。其…

ALV Tree Control树控件

ALV Tree Control CL_GUI_ALV_TREE 效果: 自定义函数调用,在函数里画屏幕定义树控件显示 FUNCTION ZFI_YSYWLX_HELP_NEW . *"---------------------------------------------------------------------- *"*"本地接口: *&qu…

zset使用lua实现取最高分数中的随机成员

zset使用lua实现取最高分数中的随机成员 这种场景适用队列中不想要先入先出、先入后出因为zset的命令都是带有排序功能的,所以取值时要不从大到小要不从小到大所以我使用lua实现随机取成员使用lua是因为可以保持原子性在执行过程中Lua脚本是不会被其他命令或请求打…

C语言典型例题59

《C程序设计教程(第四版)——谭浩强》 题目: 例题4.11 译密码。为使电文保密,往往按一定规律将其转换为密码,收报人再按约定的规律将其译回原文。 例如,可以按以下规律将电文变为密码: 将字母A…

我不是非酋之-天空概率

最近入坑了dnf手游,染上了合天空,大黑蛋子一个,突发奇想,模拟下合天空概率,看看是否真的有20%。 梳理代码逻辑如下: 不考虑礼包和其他东西 条件: 合成概率20%,每次需要2个装扮和一个…

格式化的磁盘数据能恢复吗?五个看完即可掌握的恢复方法

磁盘是大多数电子设备都必须具有的一个存储介质,在平时使用的过程中,很多用户为了途一时的方便,经常会需要一键将磁盘里面的数据执行格式化,以实现清空或者删除的情况。然而,在执行完具体的操作后,过了一段…

Vue(十三) 路由、路由嵌套、query、param传参、propos、replace属性。编程式路由导航,特有的生命周期函数,路由守卫

文章目录 路由1. 基本使用2. 多级(嵌套)路由3. 路由query传参4. 命名路由5. 路由param传参6. propos属性7. replace属性8. 编程式路由导航9. 缓存路由组件10. actived,deactived生命周期函数11. 路由守卫1、全局路由2、独享路由3、组件内路由守卫 12. 路由器工作的两…

干货含源码!如何用Java后端操作Docker(命令行篇)

目录 干货含源码!如何用Java后端操作Docker(命令行篇) 一、为什么要用后端程序操作Docker 二、安装Docker 1、安装Docker 2、启动Docker 三、使用Java后端操作docker 1、构建docker镜像并生成容器 2、执行完毕后删除容器和镜像 3、在…

怎么删除谷歌浏览器的下载记录

定期删除谷歌浏览器的下载记录,对于保护个人隐私和提升浏览器性能都非常的重要。为了帮助大家安全的进行谷歌浏览器下载记录的清除,本文为大家分享了实用的操作方法,一起来看看吧。 删除谷歌浏览器下载记录的原因说明 1、保护隐私&#xff1…

【算法 动态规划 简单多状态 dp 问题】打家劫舍题型

打家劫舍题型 按摩师 (easy)解题思路代码 打家劫舍II (medium)解题思路代码 删除并获得点数(medium)解题思路代码 按摩师 (easy) 题目链接 该题是打家劫舍的变形 解题思路 状态表示 分析: 注意题目, 对于当天的预约, 可以接受…

车辆远控功能自动化测试方案:打造高效可靠的测试流程

随着汽车逐步走向智能化、网联化,整车的功能已经不再局限于驾驶员在车内进行本地操作。在远离车辆时,驾驶员也可以通过手机APP下发控制指令来实现对车辆的远程控制。 近几年,伴随远控功能项不断增多,其功能逻辑也越来越复杂&…

python开发--信息的增删改

部门信息的增删改 1. 增加 点击新建部门 跳转到新建部门页面:http://127.0.0.1:8000/depart/add/ 在views.py里面增加如下代码,可以将用户输入的信息添加到数据库中 def depart_add(request):if request.method GET:return render(request, depart…

STL之my_list容器

前言:各位老铁好久不见了,今天分享的知识是自己实现一个简单的list容器,为什么我先跳过vector容器的自我实现呢?我个人觉得vector相对于list的自我实现简单一点,所以今天先分享实现my_list的知识 我们要实现my_list&a…

machine learning - 2

泛化误差 也可以认为是预测时的误差。 训练误差 并不是越小越好,太小会过拟合。 获得测试集合的方法: 1): 2):例如:k-折交叉验证法, 就的每k个数据取一个座位测试集 3&#xff0…

nginx容器映射配置文件后,启动一直报错提示:failed (13: Permission denied)的排查

问题现象: 使用harbor 的install.sh 创建docker-compose之后,出现nginx容器一直重启。 查看日志发现是:配置文件无权限。报错信息如下: Sep 2 16:43:13 172.28.0.1 nginx[1344]: 2024/09/02 08:43:13 [emerg] 1#0: open() “/e…

网站网站建设公司用什么

随着互联网的飞速发展,网站已经成为企业的重要门面和宣传工具。为了在网上展示自己的品牌形象和吸引更多的客户,越来越多的企业选择找专业的网站建设公司进行网站建设。那么,网站建设公司主要使用什么技术和方法呢? 首先&#xff…