拾い物のコンパス

まともに書いたメモ

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レベルの操作を行えるライブラリを使うのが近道なようだ.
次の課題は,実行結果を受け取り,次の処理に活かす方法を調べていきたい.

参考

サイバーセキュリティプログラミング―Pythonで学ぶハッカーの思考