4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Win32アプリでx86命令を直接実行させる

Posted at

#方法と環境
masmではない
visual studio 2013で使用言語はC++です。
マシン語を実行させます。
今回は何もしない関数を作ります。

  • windows7 64bit
  • core i7-2600K

#コード(失敗) :trollface:

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は実行されない。

#コード(成功):feelsgood:

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
};
4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?