我有以下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)总是会导致访问冲突异常。 :(我不知道这里到底发生了什么。你能告诉我这是什么问题吗?
答案 0 :(得分: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个字节的内存,所以这将改变内存其他部分的内存保护,从而导致安全漏洞。
答案 1 :(得分:0)
旁注(我无法添加评论..)
__asm{
lea eax, hexData
call eax
}
您不需要内联汇编程序来调用hexData。也许它适用于MSVC x32,但注意MSVC x64没有内联汇编程序。
您可以使用following approach来调用二进制数组中的代码:
#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;
}