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): 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 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.