PythonTip >> 博文 >> python

Stack Guard & Format String Blocker in Python

zihua 2014-01-20 23:01:55 点击: 809 | 收藏


Download the tool

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Stack Guard & Format String Blocker in Python

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

:author: Nam T. Nguyen

:copyright: 2010, public domain

(Shamefully admitted that this tool was used in the Capture the Flag game at HITB Kuala Lumpur 2010, and it failed)

The Big Picture

===============

Basically, we are running the application under a debugger. When an interesting event occurs, we process it accordingly.

Stack Guard

-----------

The interesting events are function entry and function exit. When we enter into a function, the value at top of stack is XOR'd with a random value. When we exit from a function, the value at TOS is again XOR'd with that same random value.

Format String

-------------

The interesting events are those ``printf`` family functions. When the function is entered, we just have to check if its format string argument contains ``%n`` or ``%hn``. For some functions (e.g. ``printf```), this argument is at TOS + 4 (leave one for saved EBP), for some others (e.g. ``fprintf``) it is at TOS + 8, yet for some (e.g. ``snprintf``) it is at TOS + 12.

The Problems

============

Breakpoints

-----------

The main issue is with multi-process (fork'd code) applications. Basically, when they fork, the soft-breakpoints (0xCC) are retained but the handler does not attach to the new process. Therefore, when a breakpoint hits, the newly forked process simply dies.

To work around this issue, the ``MultiprocessDebugger`` class is written to remember breakpoints in both original and forked processes. It also kills new image (via ``exec``) to protect against successful exploitation that launches ``/bin/sh``, for example.

Function entries/exits

----------------------

Basically, to find all function entries, and exits, we have to walk the code. A recursive iterator (flattened with a simple queue) is used to visit all functions from a starting location (usually ``main`` function). When a ``CALL`` instruction is reached, its destination is deemed a function entry. When a ``RET`` instruction is reached, this current location is deemed an exit of the the current function. This does not work with indirect calls (``CALL EAX``, for e.g.) because we do not know its destination.

Samples

=======

Please peruse ``target.py`` for a sample usage.

原文链接:http://www.wumii.com/item/7GCNC89k

作者:zihua | 分类: python | 标签: python | 阅读: 809 | 发布于: 2014-01-20 23时 |