#方法と環境
masmではない
visual studio 2013で使用言語はC++です。
マシン語を実行させます。
今回は何もしない関数を作ります。
- windows7 64bit
- core i7-2600K
#コード(失敗)
Source.cpp
unsigned char ops[] =
{
0x55, // push ebp
0x8B, 0xEC, // mov ebp,esp
0x8B, 0xE5, // mov esp,ebp
0x5D, // pop ebp
0xC3, // ret
};
int main()
{
void(*p)() = reinterpret_cast<void(*)()>(&ops[0]);
p();
return 0;
}
デバッグ実行
ハンドルされない例外が 0x00B28000 (Source.cpp_Project27.exe) で発生しました: 0xC0000005: 場所 0x00B28000 の実行中にアクセス違反が発生しました。
#なぜ失敗するのか
opsの中身が格納されているメモリに実行可能属性が無いためです。
メモリ保護というもののせいで、opsは実行されない。
#コード(成功)
Source.cpp
#include <Windows.h> //追加
unsigned char ops[] =
{
0x55, // push ebp
0x8B, 0xEC, // mov ebp,esp
0x8B, 0xE5, // mov esp,ebp
0x5D, // pop ebp
0xC3, // ret
};
int main()
{
DWORD old = 0;
VirtualProtect(ops, sizeof(ops), PAGE_EXECUTE_READWRITE, &old);
void(*p)() = reinterpret_cast<void(*)()>(&ops[0]);
p();
return 0;
}
逆アセンブルをステップ実行しopsが実行されていることを確認しました。
VirtualProtectについてはこちら(msdn)
ちなみに、oldはPAGE_READWRITEでした。
メモリの属性はページ単位で変わるので、opsの周辺のメモリも実行可能になっています。
細かいことは気にしない。
#おまけ
実行確認用にint3命令を挿入してもよいと思います。
デバッグ実行したらブレークします。
unsigned char ops[] =
{
0x55, // push ebp
0x8B, 0xEC, // mov ebp,esp
0xCC, // int3
0x8B, 0xE5, // mov esp,ebp
0x5D, // pop ebp
0xC3, // ret
};