Pythonでネイティブコード(x86バイトコードなど)を実行する方法のメモ。
ctypesモジュールをインポートし、次のような関数を定義すればよい。
import ctypes def native_func(bytecode): libc = ctypes.CDLL('libc.so.6') libc.mmap.restype = ctypes.c_void_p buf = libc.mmap(None, len(bytecode), 7, 0x22, -1, 0) libc.memcpy(ctypes.c_void_p(buf), ctypes.c_char_p(bytecode), len(bytecode)) return ctypes.CFUNCTYPE(ctypes.c_void_p)(buf) rdrand = native_func('\x48\x0f\xc7\xf0\xc3') # rdrand rax; ret print hex(rdrand())
上のコードでは、例としてハードウェア乱数を生成するRDRAND命令を実行し、その結果を返す関数を定義している。
実際に実行すると、実行ごとにランダムな値が返っていることが確認できる。
$ python native_func.py 0xd8e5dd17b96e3b07L $ python native_func.py 0xdfbac12088c27055L
追記(2016-06-06)
上ではネイティブコードの例としてRDRAND命令を実行したが、単にセキュアな乱数が必要な場合はos.urandom()
を用いればよい。
# urandom.py import os import struct randvalue = struct.unpack('<Q', os.urandom(8))[0] print hex(randvalue)
$ python urandom.py 0xd67b1aeabffab050L $ python urandom.py 0x784919deb3fa692
さらに安全性を求める場合は/dev/random
を利用することになるが、このデバイスは十分なエントロピーが確保されるまでブロックされることに注意する必要がある。