Pythonでネイティブコードを実行する

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を利用することになるが、このデバイスは十分なエントロピーが確保されるまでブロックされることに注意する必要がある。

関連リンク