32位shellcode编写demo

两个文件  make_shellcode.c 是编写同时也是生成shellcode的代码

load.c是测试加载shellcode的代码

make_shellcode.c

#include <stdio.h>
#include <stdint.h>
#include<windows.h>

void*(*GetLoadLibrary())(char*);
void* GetKernel32Base() ;
void* my_loadlib(char*libname);
int my_strcmp(char *s1, char *s2);
#define RVA_TO_VA(base, rva) ((uint8_t*)(base) + (rva))
void* GetFunctionAddress(void* module_base, char* func_name) ;


//shellcode入口  改写这个函数
int shellcode_main(){
    char user32_str[7];
    user32_str[0]='u';
    user32_str[1]='s';
    user32_str[2]='e';
    user32_str[3]='r';
    user32_str[4]='3';
    user32_str[5]='2';
    user32_str[6]=0;

    char box_str[12];
    box_str[0]='M';
    box_str[1]='e';
    box_str[2]='s';
    box_str[3]='s';
    box_str[4]='a';
    box_str[5]='g';
    box_str[6]='e';
    box_str[7]='B';
    box_str[8]='o';
    box_str[9]='x';
    box_str[10]='A';
    box_str[11]=0;

    void*user32=my_loadlib(user32_str);
    int(*box)()=GetFunctionAddress(user32,box_str);
    box(0,box_str,user32_str,1);

    return 0;
}


void* GetKernel32Base() {
    void* kernel32_base = 0;
    __asm__ volatile (
        "movl %%fs:0x30, %%eax\n"    // EAX = PEB (通过TEB偏移0x30)
        "movl 0x0C(%%eax), %%eax\n"  // EAX = PEB->Ldr (PEB_LDR_DATA)
        "movl 0x1C(%%eax), %%eax\n"  // EAX = InInitializationOrderModuleList 第一个节点 (ntdll.dll)
        "movl (%%eax), %%eax\n"      // EAX = 第二个节点 (kernel32.dll)
        "movl 0x08(%%eax), %0"      // 节点偏移0x08处为基址
        : "=r" (kernel32_base)
        :
        : "%eax"
    );
    
    return kernel32_base;
}

void* my_loadlib(char*libname){
     void*(*loaddll)(char*)=GetLoadLibrary();
     //printf("load %p\n",loaddll);
     return loaddll(libname);
}

int my_strcmp(char *s1, char *s2) {
    // 循环直到字符不同或任一字符串结束
    while (*s1 && *s2 && (*s1 == *s2)) {
        s1++;
        s2++;
    }
    // 返回第一个不同字符的差值(处理符号问题)
    return *(unsigned char*)s1 - *(unsigned char*)s2;
}

// RVA转实际地址(适用于已加载模块)
#define RVA_TO_VA(base, rva) ((uint8_t*)(base) + (rva))

void* GetFunctionAddress(void* module_base, char* func_name) {
    // 1. 获取DOS头并验证
    IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)module_base;
    if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) return NULL; // "MZ"标志检查‌:ml-citation{ref="1" data="citationList"}

    // 2. 定位NT头
    IMAGE_NT_HEADERS* nt_headers = (IMAGE_NT_HEADERS*)RVA_TO_VA(module_base, dos_header->e_lfanew);
    if (nt_headers->Signature != IMAGE_NT_SIGNATURE) return NULL; // "PE"标志检查‌:ml-citation{ref="1" data="citationList"}

    // 3. 获取导出表
    IMAGE_DATA_DIRECTORY* export_dir = &nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
    if (export_dir->VirtualAddress == 0 || export_dir->Size == 0) return NULL;

    IMAGE_EXPORT_DIRECTORY* export_table = (IMAGE_EXPORT_DIRECTORY*)RVA_TO_VA(module_base, export_dir->VirtualAddress);

    // 4. 遍历函数名数组
    DWORD* name_rvas = (DWORD*)RVA_TO_VA(module_base, export_table->AddressOfNames);
    WORD* ordinal_table = (WORD*)RVA_TO_VA(module_base, export_table->AddressOfNameOrdinals);
    DWORD* func_addresses = (DWORD*)RVA_TO_VA(module_base, export_table->AddressOfFunctions);

    for (DWORD i = 0; i < export_table->NumberOfNames; i++) {
        const char* name = (const char*)RVA_TO_VA(module_base, name_rvas[i]);
        if (my_strcmp(name, func_name) == 0) {
            // 5. 通过序号获取函数地址
            WORD ordinal = ordinal_table[i];
            return (FARPROC)RVA_TO_VA(module_base, func_addresses[ordinal]);
        }
    }
    return NULL;
}


void*(*GetLoadLibrary())(char*){
    char name[13];
    name[0]='L';
    name[1]='o';
    name[2]='a';
    name[3]='d';
    name[4]='L';
    name[5]='i';
    name[6]='b';
    name[7]='r';
    name[8]='a';
    name[9]='r';
    name[10]='y';
    name[11]='A';
    name[12]=0;
    uintptr_t base = GetKernel32Base();
    void*(*loaddll)(char*)=(void*(*)(char*))GetFunctionAddress(base,&name);
    //printf("load %p\n",loaddll);
    return loaddll;
}

void end(){
    puts("end");
}


int main() {

    FILE*f=fopen("code","wb");
    DWORD size=(DWORD)end-(DWORD)shellcode_main;
    fwrite(shellcode_main,size,1,f);
    fclose(f);
}

load.c

#include<stdio.h>
#include<windows.h>

char code[1024*1024];

int main(){
    DWORD d;
    VirtualProtect(&code,sizeof(code),PAGE_EXECUTE_READWRITE,&d);
    FILE*f=fopen("code","rb");
    fread(&code,sizeof(code),1,f);
    fclose(f);
    int r=((int(*)())&code)();
}

编译运行   运行后shellcode存入  code文件   load.exe加载运行code文件

gcc  make_shellcode.c  -m32  -o make_shellcode
gcc load.c  -m32  -o load
load

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值