1

我有以下 ASM 代码:

USE32
Start:
jmp Main
    struc st
        .stLong resd 1
        .stWord resw 1
        .stBuffer   resb    32
    endstruc

    mystruc:
    istruc st
        at st.stLong, dd 1
        at st.stWord, dw 1
    iend
Main:
    mov eax, 1
    mov [mystruc+st.stLong], eax

我已经使用 NASM 对其进行了编译,并尝试使用以下代码执行(逐步)在 Visual C++ 的调试模式下生成的二进制文件:

unsigned char hexData[50] = {
    0xEB, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0xA3,
    0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00 
};




__asm{
    lea eax, hexData
    call eax
}

问题是:执行第一条指令(jmp Main)总是会导致访问冲突异常。:(我不知道这里到底发生了什么。你能告诉我问题是什么吗?

4

2 回答 2

1

内存可以有不同的保护,它可以是可读的、可写的或可执行的。默认情况下,您定义的数据成员不可执行,以避免代码注入或利用代码中的攻击。您在这里有 2 个选项:

// Remember this function at least allocate a page that is usually 4096 byte
// Use GetSystemInfo to get page size.
void* pvExecutableMem = VirtualAlloc(NULL, 50, MEM_RESERVE | MEM_COMMIT,
    PAGE_EXECUTE_READWRITE);
// Resulting page is executable
memcpy( pvExecutableMem, hexData, 50 );
// Now you can execute this page
__asm {
    mov eax, pvExecutableMem
    call eax
}

另一种方法是更改​​保护类型hexData

DWORD dwOldProt;
VirtualProtect( hexData, sizeof(hexData), PAGE_EXECUTE_READWRITE, &dwOldProt );

但是因为VirtualXXX函数在页面上工作并且不能只处理 50 字节的内存,这将改变内存其他部分的内存保护,从而导致安全漏洞。

于 2012-10-21T18:46:06.427 回答
0

旁注(我无法添加评论..)

__asm{
    lea eax, hexData
    call eax
}

您不需要内联汇编程序来调用 hexData。也许 MSVC x32 没问题,但请注意 MSVC x64 没有内联汇编程序。

您可以使用以下方法调用二进制数组中的代码:

#include <iostream>
#include <ostream>
using namespace std;

namespace Namespace
{
    namespace Aux
    {
        extern "C" unsigned char hexData[]={0xC3};
    }
    extern "C" void hexData();
}

int main()
{
    Namespace::hexData();
    cout << "alive!" << endl;
    return 0;
}

为了解决访问冲突 - 遵循 BigBoss 的建议。例如,以下代码在 MSVC x64 中运行良好:

#include <iostream>
#include <windows.h>
using namespace std;

namespace Namespace
{
    namespace Aux
    {
        extern "C" unsigned char hexData[]={0xC3};
    }
    extern "C" void hexData();
}

int main()
{
    DWORD dwOldProt;
    VirtualProtect( Namespace::Aux::hexData, sizeof(Namespace::Aux::hexData), PAGE_EXECUTE_READWRITE, &dwOldProt );
    Namespace::hexData();
    cout << "alive!" << endl;
    return 0;
}
于 2012-10-21T19:09:59.327 回答