本記事は、オライリージャパンから発行されている「サイバーセキュリティプログラミング ―Pythonで学ぶハッカーの思考(原題:Black Hat Python)」の学習メモとして、書籍ではPython2で書かれていますが、自分なりに解釈した上でPython3に書き直しをしています。
今回は、Pythonでシェルコードを実行する方法について学んでいきます。
シェルコードとは
シェルコード(Shellcode)とは、ソフトウェアなどの脆弱性を利用して実行されるコードを言います。
主にシェルと呼ばれるプログラムを実行する目的として作成されることから、このような名前が付きました。
実際にシェルコードを実行するには、プログラムが動作する仕組みについて理解していないといけません。
昔から使われていた方法としては、strcpy()などでのサイズチェックがきちんとされていない環境で、コピー先のバッファを溢れさせてしまう、バッファオーバーフローの脆弱性を利用した攻撃があります。
スクリプトの作成
今回は自作したlsコマンドを実行するシェルコードを使用し、WSL Ubuntu上でその動作確認をしてみます。
# shell_exec.py import ctypes #/bin/ls shellcode = b"\x48\x31\xd2\x52\x48\xb8\x2f\x62"\ b"\x69\x6e\x2f\x2f\x6c\x73\x50\x48"\ b"\x89\xe7\x52\x57\x48\x89\xe6\x48"\ b"\x8d\x42\x3b\x0f\x05" libc = ctypes.CDLL('libc.so.6') sc_ptr = ctypes.c_char_p(shellcode) size = len(shellcode) addr_aligned = ctypes.c_void_p(libc.valloc(size)) ctypes.memmove(addr_aligned, sc_ptr, size) libc.mprotect(addr_aligned, size, 1 | 2 | 4) func = ctypes.cast(addr_aligned, ctypes.CFUNCTYPE(ctypes.c_void_p)) func()
なお、書籍に記載されているコードを実行した場合、"segmentation fault"のエラーにより終了してしまいます。
これはWindowsではDEP(Data Execution Prevention)と呼ばれる仕組みで、NX bit(No eXecution bit)を有効にすることで、メモリ上にある実行する必要のないデータを実行しようとした際に、OSによって強制終了させられます。
そのため、15行目のmprotect()でメモリへのアクセスを全て許可するように、protのビットを全てonにします。
動作確認
それでは、上記で作成したスクリプトを実行します。
> python shell_exec.py shell_exec.py test.txt
問題なくlsコマンドが実行できたことが確認できました。
最後に
今回はPythonでシェルコードを実行する方法について学びました。
現在では、シェルコードを実行できないようにセキュリティ上の様々な工夫が施されているため、これらについてしっかり学んでいかねばなりません。