| > How do they work? A debugger is basically a very complicated exception handler that can, with the help of the kernel, intercept exceptions from other processes and access their memory. (This is for Windows, but I would guess that Linux is about the same.) When process X wants to debug process Y: 1. Process X calls into the kernel and says it wants to debug process Y. 2. The kernel verifies that process X is allowed to do that. (You wouldn't want a low privileged user to be able to debug a service, right?) 3. The kernel triggers a debug break exception in process Y, usually. 4. Process X goes into a loop where it asks the kernel for the next exception from process Y, which is a blocking call until Y has an exception. 5. The kernel's exception handler catches the exception and passes details about it back to process X. 6. While process X is in control, process Y is suspended and process X can use other kernel calls to read and write process Y's memory. 7. When process X is done doing whatever, it tells the kernel to continue the previous event and asks for the next exception. Process X will have, of course, loaded some libraries that help it navigate the structures in memory in process Y, starting with something at a well-known address like the PEB. That lets it do things like enumerate threads and loaded modules, find symbols, etc. Relevant win32 calls are: WaitForDebugEvent, ContinueDebugEvent, ReadProcessMemory, WriteProcessMemory (Standard caveat that I haven't actually written one of these things in 20 years applies. Maybe there's new stuff now.) |