Created
April 10, 2017 00:39
-
-
Save jmahmood/d7feb32d902e266609dbc7ec22575a8d to your computer and use it in GitHub Desktop.
Python; learning debugging for the mac
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Creating a debugger on Mac OS using Python and Python CTypes | |
# ------------------------------------------------------------ | |
# If you are like me, you are following along the Grey Hat Python book that was on the "Humble Bundle" sale and are | |
# a bit frustrated that everything is about Windows. Also that it requires Python 2.5. | |
# | |
# (I haven't used a Windows machine for years and doubt I will be doing dev for it in my career.) | |
# | |
# I am trying to implement the Chapter 3 debugger stuff in this file, using Python 3.5. | |
# This is not necessarily something pythonic or using best practices, I just want to get it working, after which | |
# I may clean it up. | |
# | |
# I am not too familiar with the Windows API, so I could be using the wrong system calls here. I am making no attempt | |
# to make this cross-platform, as I am only interested in having this work on the Mac for now. | |
# | |
# A lot of useful information about necessary C is here: | |
# http://system.joekain.com/2015/06/08/debugger.html | |
# | |
# Basically, it seems that you can create a process in Windows using CreateProcessA that is in "debug mode" based on | |
# the data you pass in as dwCreationFlags. There is no single flag you can pass to execv that does the same, but you | |
# can set ptrace on the forked process before running execv with a similar outcome. | |
# | |
# Goals: | |
# Create a process that is paused by the debugger: COMPLETE | |
# Create a process that is paused and resumed by the bugger: COMPLETE | |
# Create a class called "Debugger" that lets you load a program | |
# Examine the dwDesiredAccess settings in Windows and determine if something similar exists w/ Ptrace | |
# Get a list of the current active thread in the debugging program when it is blocked | |
# Grab value of all registers wrt the active thread | |
import ctypes | |
import os | |
import signal | |
from ctypes import * | |
libc = CDLL("libc.dylib") # we use dylib on mac instead of .so | |
PT_TRACE_ME = 0 # Taken from the mac ptrace header file: https://opensource.apple.com/source/xnu/xnu-344/bsd/sys/ptrace.h | |
PT_CONTINUE = 7 # Taken from the mac ptrace header file: https://opensource.apple.com/source/xnu/xnu-344/bsd/sys/ptrace.h | |
EAGAIN = 35 | |
result = libc.fork() | |
first = True | |
while first or (result == -1 and libc.errno == EAGAIN): | |
first = False | |
if result == 0: | |
# setup_inferior | |
print("Inferior process being activated / Ptraced") | |
libc.ptrace(PT_TRACE_ME, None, None, None) | |
os.execv('/Users/jawaad/PycharmProjects/DebuggerTutorial/basic_program/hw', ['']) | |
elif result == -1: | |
# error | |
print("Error") | |
else: | |
# debugger | |
print("Debugger") | |
while True: | |
status_ptr_type = ctypes.POINTER(ctypes.c_int) | |
status_ptr = status_ptr_type(ctypes.c_int(25)) | |
# print("Waiting for pid") | |
# print("Result: " + str(result)) | |
print("Debugger waiting for next step is run in inferior process.") | |
print("Process ID: " + str(libc.waitpid(result, status_ptr, 0))) | |
# print("Status pointer: " + str(status_ptr[0])) | |
# print(repr(status_ptr.contents)) | |
# print(repr(os.WIFSTOPPED(status_ptr[0]))) | |
# print(repr(os.WSTOPSIG(status_ptr[0]))) | |
# print(repr(os.WIFEXITED(status_ptr[0]))) | |
if os.WIFSTOPPED(status_ptr[0]) and os.WSTOPSIG(status_ptr[0]) == signal.SIGTRAP: | |
print("Inferior stopped on SIGTRAP - continuing...\n") | |
libc.ptrace(PT_CONTINUE, result, 1, 0) # caddr_t addr == 1 to indicate "continue". | |
if os.WIFEXITED(status_ptr[0]): | |
print("Inferior exited - debugger terminating...\n") | |
exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi.
I'm really glad that I found this code because I'm exactly in the same case as you. I also got the Gray Hat book on Humble Bundle, and wanted to use it on a Mac with Python 3.
The link given is a nice start too. I also picked some ideas from your code. I was so focused on ctypes that I even forgot to use the o module... for instance for exec (which makes the code much cleaner).
There are a few things I don't understand well in your code, like for instance why you do a while loop with the EAGAIN condition and the 'first' boolean variable. The blog post uses waitpid which seems much simpler and way cleaner code...
Here's my current file (that does mostly what the blog post does).
Note: The first function load_defines is an automatic way to get constant definitions from the .h files. It's very rough as it is, but works on the constants I wanted to get and will hopefully be reusable later instead of reading and copying values by hand (will probably have to patch it as I go to account for new syntax from time to time).