Skip to main content
added 35 characters in body
Source Link
PSS
  • 3.1k
  • 1
  • 22
  • 35
def thread_step_setter(dbg):
    dbg.suspend_all_threads()
    for thread_id in dbg.enumerate_threads():
        print "Single step for thread: 0x%08x" % thread_id
        h_thread = dbg.open_thread(thread_id)
        dbg.single_step(True, h_thread)
        dbg.close_handle(h_thread)

    # Resume execution, which will pass control to step handler
    dbg.resume_all_threads()
    
    return DBG_CONTINUE

def single_step_handler(dbg):
    global total_instructions
    if instructions == MAX_INSTRUCTION:
        dbg.single_step(False)
        return DBG_CONTINUE
    else:
        # Disassemble the instruction
        current_instruction = dbg.disasm(dbg.context,Eip)
        print "#%d\t0x%08x : %s" % (total_instructions, dbg.context.Eip, current_instruction)
        total_instructions += 1
        dbg.single_step(True)
    
    return DBG_CONTINUE
def thread_step_setter(dbg):
    for thread_id in dbg.enumerate_threads():
        print "Single step for thread: 0x%08x" % thread_id
        h_thread = dbg.open_thread(thread_id)
        dbg.single_step(True, h_thread)
        dbg.close_handle(h_thread)

    # Resume execution, which will pass control to step handler
    dbg.resume_all_threads()
    
    return DBG_CONTINUE

def single_step_handler(dbg):
    global total_instructions
    if instructions == MAX_INSTRUCTION:
        dbg.single_step(False)
        return DBG_CONTINUE
    else:
        # Disassemble the instruction
        current_instruction = dbg.disasm(dbg.context,Eip)
        print "#%d\t0x%08x : %s" % (total_instructions, dbg.context.Eip, current_instruction)
        total_instructions += 1
        dbg.single_step(True)
    
    return DBG_CONTINUE
def thread_step_setter(dbg):
    dbg.suspend_all_threads()
    for thread_id in dbg.enumerate_threads():
        print "Single step for thread: 0x%08x" % thread_id
        h_thread = dbg.open_thread(thread_id)
        dbg.single_step(True, h_thread)
        dbg.close_handle(h_thread)

    # Resume execution, which will pass control to step handler
    dbg.resume_all_threads()
    
    return DBG_CONTINUE

def single_step_handler(dbg):
    global total_instructions
    if instructions == MAX_INSTRUCTION:
        dbg.single_step(False)
        return DBG_CONTINUE
    else:
        # Disassemble the instruction
        current_instruction = dbg.disasm(dbg.context,Eip)
        print "#%d\t0x%08x : %s" % (total_instructions, dbg.context.Eip, current_instruction)
        total_instructions += 1
        dbg.single_step(True)
    
    return DBG_CONTINUE
Source Link
PSS
  • 3.1k
  • 1
  • 22
  • 35

One of your problems is that you try to single step through Thread2 and you only refer to Thread1 in your code:

dbg.enumerate_threads()[0] # <--- Return handle to the first thread.

In addition, the code the you posted is not reflective of the complete structure of your script, which makes it hard to judge wether you have other errors or not. You also try to set breakpoint within the sub-brach that disassembles your instructions, which does not make a lot of sense to me logically. Let me try to explain what I know, and lay it out in an organized manner. That way you might look back at your code, re-think it and correct it.

Let's start with basic framework of debugging an application with pydbg:

  1. Create debugger instance
  2. Attache to the process
  3. Set breakpoints
  4. Run it
  5. Breakpoint gets hit - handle it.

This is how it could look like:

from pydbg import *
from pydbg.defines import *

# This is maximum number of instructions we will log
MAX_INSTRUCTIONS = 20

# Address of the breakpoint
func_address = "0x7C90D21A"

# Create debugger instance
dbg = pydbg()

# PID to attach to
pid = int(raw_input("Enter PID: "))

# Attach to the process with debugger instance created earlier.
# Attaching the debugger will pause the process.
dbg.attach(pid)

# Let's set the breakpoint and handler as thread_step_setter,
# which we will define a little later...
dbg.bp_set(func_address, handler=thread_step_setter)

# Let's set our "personalized" handler for Single Step Exception
# It will get triggered if execution of a thread goes into single step mode.
dbg.set_callback(EXCEPTION_SINGLE_STEP, single_step_handler)

# Setup is done. Let's run it...
dbg.run() 

Now having the basic structure, let's define our personalized handlers for breakpoint and single stepping. The code snippet below defines our "custom" handlers. What will happen is when breakpoint hits we will iterate through threads and set them to single step mode. It will in turn trigger single step exception, which we will handle and disassemble MAX_INSTRUCTIONS amount of instructions:

def thread_step_setter(dbg):
    for thread_id in dbg.enumerate_threads():
        print "Single step for thread: 0x%08x" % thread_id
        h_thread = dbg.open_thread(thread_id)
        dbg.single_step(True, h_thread)
        dbg.close_handle(h_thread)

    # Resume execution, which will pass control to step handler
    dbg.resume_all_threads()
    
    return DBG_CONTINUE

def single_step_handler(dbg):
    global total_instructions
    if instructions == MAX_INSTRUCTION:
        dbg.single_step(False)
        return DBG_CONTINUE
    else:
        # Disassemble the instruction
        current_instruction = dbg.disasm(dbg.context,Eip)
        print "#%d\t0x%08x : %s" % (total_instructions, dbg.context.Eip, current_instruction)
        total_instructions += 1
        dbg.single_step(True)
    
    return DBG_CONTINUE

Discloser: I do not guarantee that the code above will work if copied and pasted. I typed it out and haven't tested it. However, if basic understanding is acquired, the small syntactical error could be easily fixed. I apologize in advanced if I have any. I don't currently have means or time to test it.

I really hope it helps you out.