pythonでシェルコードを実行する方法
オライリー出版のサイバーセキュリティプログラミング(英題: Black Hat Python)にPythonでシェルコードを実行するスクリプトが載っていた.前から実行する方法を探していたから,喜んで試してみたが上手く行かない.
原因は簡単でPythonのバイナリ自体にNXビットが立っていることだった.という訳でNXを無効にしたPythonバイナリを作成して,実行する手順を書き残す.
Pythonって誰だ
LinuxなどにインストールされているPythonバイナリはcpythonをコンパイルしたものらしい.
これがPythonのデフォルトの実装になる.
環境
$ uname -a Linux poppycompass 4.11.9-1-ARCH #1 SMP PREEMPT Wed Jul 5 18:23:08 CEST 2017 x86_64 GNU/Linux
Arch Linux 64bitで作業した.
cpythonのコンパイル
Pythonのバージョンは2.7
を作成する.
$ git clone https://github.com/python/cpython/ $ cd cpython $ git checkout 3dbe11a # 2.7にバージョン変更 $ ./configure # コンパイルオプションに -z execstack を加えるだけ.加えた箇所はとてもいい加減. $ vim Makefile [-] CC= gcc -pthread [+] CC= gcc -fno-stack-protector -z execstack -pthread [-] CXX= g++ -pthread [+] CXX= g++ -fno-stack-protector -z execstack -pthread $ make
これでNX無効のPythonは作成完了.
以下は確認作業.やらなくてもよい.
trapkit.de - checksec.shからchecksec.sh
をダウンロード.
$ ~/Downloads/checksec.sh --file <path>/cpython/python RELRO STACK CANARY NX PIE RPATH RUNPATH FILE Partial RELRO No canary found NX disabled No PIE No RPATH No RUNPATH cpython/python
というわけで,ちゃんと無効になっていることが確認できた.
シェルコード実行用スクリプト
上記のサイバーセキュリティプログラミングの8章に載っているshell_exe.py
から不要なところを消した.
#!/usr/bin/env python # -*- coding: utf-8 -*- import ctypes # お馴染みの/bin/sh起動するだけ.64ビット向けのコード code = "\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x48\x8d\x42\x3b\x0f\x05\xc3" buf = ctypes.create_string_buffer(code, len(code)) func = ctypes.cast(buf, ctypes.CFUNCTYPE(ctypes.c_void_p)) func()
Pythonで関数ポインタの作り方がわからなかったが,ctypes
のキャストを使えばよかったらしい.勉強になった.
$ ./cpython/python ./shell_exe.py sh-4.4$
といった感じでシェルが起動する.
所感
アセンブラ関連を扱うには,Cレベルの操作を行えるライブラリを使うのが近道なようだ.
次の課題は,実行結果を受け取り,次の処理に活かす方法を調べていきたい.