Skip to content

Commit 0874686

Browse files
committed
Added minidump support (ticket #71). Untested.
1 parent 5eac922 commit 0874686

File tree

8 files changed

+1187
-2
lines changed

8 files changed

+1187
-2
lines changed

docs/source/Debugging.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,3 +501,19 @@ Example #16: resolving a label back into a memory address
501501
.. literalinclude:: ../../examples/debugging/16_resolve_label.py
502502
:start-after: # POSSIBILITY OF SUCH DAMAGE.
503503
:end-before: # When invoked from the command line,
504+
505+
Generating minidump files
506+
--------------------------
507+
508+
In addition to WinAppDbg's native crash dumps, you can also generate standard Windows minidump files (.dmp) that can be analyzed with tools like WinDbg, Visual Studio, or other debuggers. Minidumps are the industry-standard format for crash reporting on Windows.
509+
510+
The minidump functionality is available through the :meth:`Process.generate_minidump` method for any process, and through :meth:`Event.generate_minidump` method on debug events for convenient crash dump generation. Exception events automatically include exception context and exception records.
511+
512+
Example #17: saving crash minidumps
513+
++++++++++++++++++++++++++++++++++++
514+
515+
:download:`Download <../../examples/debugging/17_crash_minidump.py>`
516+
517+
.. literalinclude:: ../../examples/debugging/17_crash_minidump.py
518+
:start-after: # POSSIBILITY OF SUCH DAMAGE.
519+
:end-before: # When invoked from the command line,

docs/source/Instrumentation.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,3 +288,16 @@ Example #26: stopping and starting a system service
288288
.. literalinclude:: ../../examples/instrumentation/26_service_restart.py
289289
:start-after: # POSSIBILITY OF SUCH DAMAGE.
290290
:end-before: # When invoked from the command line,
291+
292+
Generating minidump files
293+
--------------------------
294+
295+
**Minidump files** are the standard Windows format for crash dumps and process snapshots. The *Process* class provides a convenient method to generate minidump files for any running process, which can then be analyzed with tools like WinDbg, Visual Studio, or other debuggers.
296+
297+
Example #27: generating a minidump of a running process
298+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
299+
300+
:download:`Download <../../examples/instrumentation/27_generate_minidump.py>`
301+
302+
.. literalinclude:: ../../examples/instrumentation/27_generate_minidump.py
303+
:start-after: # POSSIBILITY OF SUCH DAMAGE.
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#!/usr/bin/python3
2+
# -*- coding: utf-8 -*-
3+
4+
# Copyright (c) 2009-2025, Mario Vilas
5+
# All rights reserved.
6+
#
7+
# Redistribution and use in source and binary forms, with or without
8+
# modification, are permitted provided that the following conditions are met:
9+
#
10+
# * Redistributions of source code must retain the above copyright notice,
11+
# this list of conditions and the following disclaimer.
12+
# * Redistributions in binary form must reproduce the above copyright
13+
# notice,this list of conditions and the following disclaimer in the
14+
# documentation and/or other materials provided with the distribution.
15+
# * Neither the name of the copyright holder nor the names of its
16+
# contributors may be used to endorse or promote products derived from
17+
# this software without specific prior written permission.
18+
#
19+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29+
# POSSIBILITY OF SUCH DAMAGE.
30+
31+
import os
32+
33+
from winappdbg import win32
34+
from winappdbg.debug import Debug
35+
from winappdbg.textio import HexDump
36+
37+
38+
def my_event_handler(event):
39+
# Get the event name.
40+
name = event.get_event_name()
41+
42+
# Get the event code.
43+
code = event.get_event_code()
44+
45+
# Get the process ID where the event occured.
46+
pid = event.get_pid()
47+
48+
# Get the thread ID where the event occured.
49+
tid = event.get_tid()
50+
51+
# Get the value of EIP/RIP at the thread.
52+
pc = event.get_thread().get_pc()
53+
54+
# Show something to the user.
55+
bits = event.get_process().get_bits()
56+
format_string = "%s (%s) at address %s, process %d, thread %d"
57+
message = format_string % (
58+
name,
59+
HexDump.integer(code, bits),
60+
HexDump.address(pc, bits),
61+
pid,
62+
tid,
63+
)
64+
print(message)
65+
66+
# If the event is a crash...
67+
if code == win32.EXCEPTION_DEBUG_EVENT and event.is_last_chance():
68+
print("Crash detected, generating minidump...")
69+
70+
# Generate a filename based on the process name and exception code.
71+
process = event.get_process()
72+
filename = process.get_filename()
73+
if filename:
74+
basename = os.path.basename(filename)
75+
basename = os.path.splitext(basename)[0]
76+
else:
77+
basename = "process_%d" % pid
78+
79+
exception_code = event.get_exception_code()
80+
minidump_filename = "%s_crash_%08X.dmp" % (basename, exception_code)
81+
82+
try:
83+
# Generate a minidump with full memory and exception information.
84+
# The event.generate_minidump() method automatically includes
85+
# the exception context and exception record.
86+
event.generate_minidump(
87+
minidump_filename,
88+
DumpType=win32.MiniDumpWithFullMemory
89+
| win32.MiniDumpWithHandleData
90+
| win32.MiniDumpWithThreadInfo,
91+
)
92+
print("Minidump saved to: %s" % minidump_filename)
93+
94+
except Exception as e:
95+
print("Error generating minidump: %s" % e)
96+
import traceback
97+
98+
traceback.print_exc()
99+
100+
# You can also launch the interactive debugger from here. Try it! :)
101+
# event.debug.interactive()
102+
103+
# Kill the process.
104+
event.get_process().kill()
105+
106+
107+
def simple_debugger(argv):
108+
# Instance a Debug object, passing it the event handler callback.
109+
debug = Debug(my_event_handler, bKillOnExit=True)
110+
try:
111+
# Start a new process for debugging.
112+
debug.execv(argv)
113+
114+
# Wait for the debugee to finish.
115+
debug.loop()
116+
117+
# Stop the debugger.
118+
finally:
119+
debug.stop()
120+
121+
122+
# When invoked from the command line,
123+
# the first argument is an executable file,
124+
# and the remaining arguments are passed to the newly created process.
125+
if __name__ == "__main__":
126+
import sys
127+
128+
simple_debugger(sys.argv[1:])
129+
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/usr/bin/python3
2+
# -*- coding: utf-8 -*-
3+
4+
# Copyright (c) 2009-2025, Mario Vilas
5+
# All rights reserved.
6+
#
7+
# Redistribution and use in source and binary forms, with or without
8+
# modification, are permitted provided that the following conditions are met:
9+
#
10+
# * Redistributions of source code must retain the above copyright notice,
11+
# this list of conditions and the following disclaimer.
12+
# * Redistributions in binary form must reproduce the above copyright
13+
# notice,this list of conditions and the following disclaimer in the
14+
# documentation and/or other materials provided with the distribution.
15+
# * Neither the name of the copyright holder nor the names of its
16+
# contributors may be used to endorse or promote products derived from
17+
# this software without specific prior written permission.
18+
#
19+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29+
# POSSIBILITY OF SUCH DAMAGE.
30+
31+
import sys
32+
33+
from winappdbg import win32
34+
from winappdbg.process import Process
35+
36+
# Get the process ID and output filename from the command line.
37+
if len(sys.argv) < 2:
38+
print("Usage: %s <process_id> [output_file] [dump_type]" % sys.argv[0])
39+
print()
40+
print(" process_id : Process ID to dump")
41+
print(" output_file : Output minidump file (default: minidump.dmp)")
42+
print(" dump_type : Dump type flags (default: MiniDumpNormal)")
43+
print()
44+
print("Example dump types:")
45+
print(" MiniDumpNormal - Basic information only")
46+
print(" MiniDumpWithFullMemory - Include all accessible memory")
47+
print(" MiniDumpWithHandleData - Include handle information")
48+
print(" MiniDumpWithThreadInfo - Include thread information")
49+
print(" MiniDumpWithDataSegs - Include data segments")
50+
print()
51+
print("Multiple flags can be combined with | (OR operator).")
52+
print("Example: MiniDumpWithFullMemory | MiniDumpWithHandleData")
53+
sys.exit(1)
54+
55+
pid = int(sys.argv[1])
56+
output_file = sys.argv[2] if len(sys.argv) > 2 else "minidump.dmp"
57+
58+
# Parse dump type if provided
59+
if len(sys.argv) > 3:
60+
# Allow user to specify flags like: MiniDumpWithFullMemory | MiniDumpWithHandleData
61+
dump_type_str = sys.argv[3]
62+
# Evaluate in a namespace with win32 constants
63+
dump_type = eval(dump_type_str, {"__builtins__": {}}, vars(win32))
64+
else:
65+
dump_type = win32.MiniDumpNormal
66+
67+
try:
68+
# Create a Process object for the target process.
69+
process = Process(pid)
70+
71+
# Generate the minidump file.
72+
print("Generating minidump for process %d..." % pid)
73+
print("Output file: %s" % output_file)
74+
print("Dump type: 0x%08X" % dump_type)
75+
76+
process.generate_minidump(output_file, DumpType=dump_type)
77+
78+
print("Minidump generated successfully!")
79+
80+
except WindowsError as e:
81+
print("Error: %s" % e)
82+
sys.exit(1)
83+
except Exception as e:
84+
print("Unexpected error: %s" % e)
85+
import traceback
86+
87+
traceback.print_exc()
88+
sys.exit(1)
89+

tests/test_strings_integration.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,6 @@ def test_strings_on_notepad():
121121
notepad_process = Process(pid)
122122
else:
123123
print("Starting notepad.exe...")
124-
# Start notepad
125-
import subprocess
126124

127125
_ = subprocess.Popen(["notepad.exe"])
128126
time.sleep(2) # Give it time to start

0 commit comments

Comments
 (0)