Hatena::ブログ(Diary)

かーねる・う゛いえむにっき このページをアンテナに追加 RSSフィード Twitter

2013-12-25

[][]任意アセンブリコード仮想マシンで実行しちゃうRuby gem作ってみた

このブログエントリカーネル/VM Advent Calendar 2013 25日目の記事です。

前回、カーネル/VM探検隊で「バインディングさえあればスクリプト言語でもゲストOSローダを実装出来る」という話をちらっとしました(資料)。

今回の記事では、ゲストOSローダではなくてもっと実験的な、簡単なアセンブリコードRubyスクリプトからハイパーバイザへ投入する仕組みを実装したのでこれを紹介します。

ruby-virtualmachine

ruby-virtualmachineというgem作成しました。

これを用いて、任意アセンブリコードアセンブル・ロード・VM上で実行、までの一連の処理をわずかな行数のRubyスクリプトで行えます。


インストール

BHyVeが正常動作するFreeBSD 10.0以降の環境必要です。

インストールコマンドは以下の通りになります。

$ gem install virtualmachine
サンプルプログラム

以下に、引数で渡された文字を指定回数だけ仮想マシンシリアルポートポート3F8h)へ表示するプログラムの例を示します。

VMの終了には未実装IOポートへのアクセスを利用しています(ポート10h)。

require 'virtualmachine'

if ARGV.size < 2
	puts "sample1.rb [char] [repeat]"
	exit 1
end

puts "[args]"
puts "char:#{ARGV[0]}"
puts "repeat:#{ARGV[1]}"
puts

vm0 = VirtualMachine.new('vm0', 128)
vm0.rax = ARGV[0].bytes.to_a[0]
vm0.rcx = ARGV[1].to_i
vm0.load_asm(<<EOS)
	mov dx, 3F8h
loop:
	out dx, al
	dec cx
	cmp cx, 0
	jne loop
	mov al, 0ah
	out dx, al

	mov dx, 10h 
	mov al, 0h
	out dx, al
EOS

puts "[registers]"
puts "rax:#{vm0.rax}"
puts "rbx:#{vm0.rbx}"
puts "rcx:#{vm0.rcx}"
puts "rdx:#{vm0.rdx}"
puts "rip:#{vm0.rip}"
puts

puts "[run vm]"
vm0.run

puts
puts "[registers]"
puts "rax:#{vm0.rax}"
puts "rbx:#{vm0.rbx}"
puts "rcx:#{vm0.rcx}"
puts "rdx:#{vm0.rdx}"
puts "rip:#{vm0.rip}"

簡単な使い方としては、vm = VirtualMachine.new(VM名, メモリサイズ)でインスタンス作成vm.load_asm(アセンブリコード)で0x10000にアセンブリコードをロード、vm.runで実行です。

vm.raxなどとレジスタ名を指定することにより、レジスタの読み書きが可能です。

実行例

以下が実行結果です。

ここでは、表示する文字に*を、リピート回数に30回を指定しています。

$ sudo ruby sample1.rb '*' 30
[args]
char:*
repeat:30

[registers]
rax:42
rbx:0
rcx:30
rdx:0
rip:65536

[run vm]
******************************

[registers]
rax:0
rbx:0
rcx:0
rdx:16
rip:65559
制限

…というわけで、いまは制限だらけの実装ですが、もう少し機能が増えれば「今までRubyしか書いたことないけど、勉強のためにアセンブリコードを書いてみよう!」なんて用途に使えるかもしれません。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/syuu1228/20131225/1388002711