![]() To switch gdb into disassembling 16-bit code it seems you have to do this: Now I could easily put a breakpoint there and continue debugging through the code. Program received signal SIGTRAP, Trace/breakpoint trap. Single-step into the EP ( it seems that qemu gdb stub does not support single stepping though actually the problem was a known bug with breakpoints - if a breakpoint is hit, you cannot continue execution in qemu/rmode until you disable the breakpoint, or it would just re-hit this is probably because GDB doesn't care about segments, and doesn't take them into account while calculating which breakpoint to remove at given CS:IP). So, setting the breakpoints at 000F:A0D9 and 000F:A0EE (in case of my DOS version) will allow you to:Ģ. the important thing is that at the very bottom there are two retf instructions, which one can assume do the transfer (well, it would be either a jmp far, a call far, or a ret far). The function at that address (000F:9B5F) is very very long, but. Looking at 000F:3E9E+4B*2 I got the address of the "EXEC" implementation. So this code basically picks up the handler function address from the lookup table placed at 000F:3E9E ( NOTE: in case of other DOS versions this can be a totally different address). Seg000:4198 mov bl, ah AH holds the function number The interesting part start about 1-2 pages below: The code at the beginning looks like this:Īnd it's followed by what looks like an environment setup for executing more complex code. Now I needed to find the handler for the 4Bh function. ![]() I proceeded with dumping the whole 000F:* segment to a file and loading it in IDA. That basically means that the handler is at 000F:40F8. I started (after DOS was up and running) with looking up the address of the INT 21h handler in the IVT - that's basically displaying 2 16-bit words at physical address 0x21*4: a CPU-level debugger (I used qemu+gdb stub+gdb) DOS on some floppy image or hard disk image One of the ideas I had was to analyze the DOS MZ loader (or actually the INT 21h/AH=4Bh interrupt aka EXEC - LOAD AND/OR EXECUTE PROGRAM), find how it transfers the control to the program and set a breakpoint there. Unfortunately neither the bochsdbg, nor qemu+gdb stub, seemed to be able to place that kind of breakpoints (though you still could do it with bochs instrumentation of course). So "no", you can't just place the breakpoint without knowing what CS will the EP end up on.Īnd "yes", if you can set a breakpoint as "ip=e_ip & cs=whatever", then you are all set (though that might hit a few false positives at first too). The missing piece of information here is the CS segment, which is actually chosen by the DOS MZ loader. So, one could just take a look at the MZ file, determine the entry point (IMAGE_DOS_HEADER.e_ip), and place a "hardware" breakpoint on that address - right? (One exception here is DOSBox debugger, which has a "debug" command inside the emulated environment which understands programs and their EPs.) So, if there is no notion of program, then there is no notion of a program EP, and so it's hard to know where to break. On CPU-level debuggers (or actually: CPU emulators with embedded debugging features) that's a little more complicated, since there is no notion of program or an application - that's strictly OS stuff which is a layer way above the CPU emulation. The above task is obviously trivial while using standard DOS debuggers - you run the debugger with the program executable as the argument, then magic happens, and you end up looking at the debugger having already hit the breakpoint at the EP. Having a CPU-level debugger (bochsdbg, qemu+gdb stub), how to break on the Entry Point of a DOS program?
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |