I would like to understand how Turbo Debugger works. So, for example, I have a message and I moved it to the DX register.
(I show you how it looks in the debugger):
MOV DX,009E ;This is a version which debugger shows me in debugger mode;
;It takes all information from this code: MOV DX,OFFSET MSG.
In fact, the message's first element address is at 9E (this is how the debugger understands). But actually, in the debugger screen, I can see that in the DS register, MSG address is at A0. How can it be?
I know that code is more preferable, but this time a screenshot is more suitable:
As you can see, I marked 2 addresses, but they are not the same. Actually, I can see that my MSG begins in the above-marked address A0, but that the debugger understands it like 9E and moves it to DX. Can someone explain to me how this can be?
By the way, the program works and prints everything fine, the purpose is to understand how the debugger understands addresses.
MSG code is simply:
MSG db 'Hello, how do you do!!!!,'$'
I believe that if you will single step your code, instruction by instruction, you will see that
You are correct that that your message starts at DS:00A0
Turbo Debugger is also correct that it starts two bytes before that
Look carefully at what is located at DS:009E.
What do you see there ? Two bytes: 0A and 0D
That's an ascii "Line Feed" and an Ascii "Carriage Return".
Your confusion can be reduced by understanding the historical perspective...
Way back when printers used ink and paper, and telephones carried modem signals at 1200 BPS, and you paid something like ten hours of minimum wage pay for one hour of that connection to a city only three states away, there really was an economic imperative in choosing between running the little print head back to the left, or just jacking the platen down a line while the print head stayed in the same position.
I mean, you really saw it in your phone bill.
No joke, this one change, using the 0A byte without the 0D byte, could mean a 10 or 20 dollar difference in your phone bill; and remember to factor in inflation back then.
The reason that you see the message properly is because your machine is first placing a "line feed" (i.e., the cursor is probably dropping to the next line) and a "carriage return" (i.e., the cursor jumps back to the left edge) before putting your message on the screen. This happens much faster than your eye can see.
With the miracle of Turbo Debugger, you can single step this and watch it happen.
So, you are correct when you write that your message "starts" at 00A0, but Turbo Debugger is also right when it's telling you that the message starts two bytes ahead of that.
Related
I am writing some multi-thread C program. I tried to modify the few instructions at the beginning of a function's body to redirect the execution to somewhere else.
But I noticed that when debugging within Visual Studio 2015, some memory location seems to be unchangeable as displayed in the Memory window.
For example:
In below picture, a function ApSignalMceToOs() begins at 0x7FFBBEE51360. I have unprotected the memory range 0x7FFBBEE51360 to 0x7FFBBEE5136E to modify it.
Line 305 to 312 modify the address range 0x7FFBBEE51360 ~ 0x7FFBBEE5136E.
Everything is fine until 0x7FFBBEE51369. At line 311, the (uint32_t(((uintptr_t)dst) >> 32 is 0x00007ffb.
After line 311 is executed, I was expecting the memory range in 0x7FFBBEE51369 ~ 0x7FFBBEE5136C will be filled as fb 7f 00 00. But as shown below, Visual Studio says it is 48 7f 00 00, where the 48 is the old value.
Then I went to check the disassembly code of the function ApSignalMceToOs(). And not surprisingly, the instruction at 00007FFBBF171365 is mov dword ptr [rsp+4], 7F48h, which should be 7FFB. As shown below in the red box below.
So until this point, Visual Studio 2015 is telling me that my modification would fail.
But as the yellow arrow in above picture shows, after the mov dword ptr [rsp+4], 7F48h is executed, I checked the content in the stack area. Surprisingly it is indeed 7f fb got moved onto the stack (shown in the green box in above picture).
And after the ret instruction is executed, the RIP register does change to 00007FFBBEEAD940, which is no surprise. See below:
And in another function, the same location is being read. Shown as below:
The code[len] or byte ptr [rax] is the memory location holding 48 or fb. But it reads 0xcc, which is neither 0x48 nor 0xfb.
Visual Studio disassembly code is decoded from the memory content. So the memory content or how VS2015 read/refresh it is the key point.
Based on above observation, I came to 2 conclusions with VS 2015 debug mode:
Some memory content is not correctly shown (or refreshed in GUI).
Some memory read operation doesn't work correctly.
But the program runs smoothly when not debugging.
Does anyone know why this is happening?
ADD 1 - 5:08 PM 10/14/2019
Thanks to #MichaelBurr. I guess I can explain it now.
The root cause is I added a breakpoint at 0x00007FFB...369 at the disassembly code level, not the C source level.
When I did this, the VS Debugger did add a 0xCC instruction at the location 0x00007FFB...369. But it seems Visual Studio 2015 goes to great lengths to hide this fact. Below is the show of the memory content with the breakpoint at 0x00007FFB...369, we can see 0x00007FFB...369 still holds the old value 0x48.
But after I manually copied the memory from 0x00007FFB...360 to 0x00007FFB...36e to somewhere else. The 0xCC instruction at the offset 0x9 is unveiled. See below:
When I modify the content at 0x00007FFB...369, Visual Studio seemed to be alerted and it just restored the content to the old preserved one, i.e. 0x48. Not my newly written one.
But I think this very restoration doesn't make any sense. The restoration of the preserved byte content shouldn't be triggered at this moment in any way. A more reasonable action is to update the breakpoint's location a little bit and insert the 0xCC instruction to a new location. Because the newly modified code may change the "instruction boundary". This way, the debug experience of the self-modifying code can be best preserved. But this will require the Visual Studio to disassemble the new code in the nearby. And the new instruction content could be invalid if the programmer made a mistake.
I think you are essentially fighting with the debugger's breakpoint/single step handling. Breakpoints are often implemented with the int 3 instruction which has the encoding 0xCC. When the debugger sets the 0xCC for the breakpoint it has to save the original value, then replace it when the debugger has stopped program execution.
In a normal situation (code that isn't self-modified) this makes things appear as you expect when examining the code memory region. However if your program modifies the memory that is being managed by the debugger you can get confusing results since the debugger will restore the value it had saved when it set the breakpoint (overwriting your modification).
I am learning some mechanism of breakpoint and I learned that 'In x86, there exist a instruction called int3 for debugger to interrupt the CPU. And then CPU will interrupt the running program by signal'.
For example:
8048e20: 55 push %ebp
8048e21: 89 e5 mov %esp,%ebp
When the user input
b *0x8048e21
The instruction will be replaced by int3(opcode 0xcc) and become this:
8048e20: 55 push %ebp
8048e21: cc e5 mov %esp,%ebp
And it will stop at the right place.
Then comes the question:
What would happen if I set the breakpoint not at the beginning of a instruction? ie, if I input:
b *0x8048e22
will debugger still replace the e5 with cc? So I write a simple example and run it with gdb.
As you can see above, I set two break points and the second is at the middle of a break points. I Input r and stop at the first breakpoint and input c and run to the end.
So it seems that the gdb ignore the second breakpoint. (For if it really repalce it with a int3 the program would be totally wrong).
Question: What happen to the second breakpoint, more specifically, what does gdb deal with it( or what I learn is wrong?)
Edit: #dbrank already give a great example about altering the data field of a instruction, I will try to make it more comprehensive with a similar example (it seems the register).
(Any reference about mechanism of breakpoint is appreciated!)
Inserting breakpoint in the middle of instruction will alter the instruction.
See this example of a program, where inserting a breakpoint overwrites original value assigned to variable (42 (0x2a)) with breakpoint instruction (0xcc (204)).
You can find more about how breakpoints work here.
You can also look into GDB sources (breakpoint.c & infrun.c mostly).
I'm assembling the same source with two different assemblers. I expect to get two identical results (modulo memory offsets, exact value of NOPs and such). Yet I've suddenly encountered the weirdest issue: there are two possible encodings of JZ:
74 cb
and
0F 84 cw/cd
The displacement, in my case, fits into one byte, and one assembler (a flavor of GAS, I think) emits the former while another (MASM) emits the latter. Since I perform some validation by matching outputs, this throws the validation off.
I have rather little control over the options of GAS, but I have complete control over MASM. Question - is there an option, a directive, or a specific command syntax to force one encoding over the other?
If all of the code, except for this one instruction is the exact same when assembled, this looks like a bug in MASM. These instructions resolve to:
74: jz rel8
0F 84: jz rel16/32
So, MASM is improperly using more space for that opcode than it should. You may be able to remedy this by using a more explicit form of the instruction in MASM, like
jz byte my_label
However, if your machine code is different at all, this may be the proper behavior of MASM. Ensure that the signed word/dword argument to jz rel16 would fit into a signed byte
I've been getting a lot of blue screens on my XP box at work recently. So many in fact that I downloaded debugging tools for windows(x86) and have been analyzing the crash dumps. So many in fact that I've changed the dumps to mini only or else I would probably end up tanking half a work day each week just waiting for the blue screen to finish recording the detailed crash log.
Almost without exception every dump tells me that the cause of the blue screen is some kind of memory misallocation or misreference and the memory at 0x%08lx referenced 0x%08lx and could not be %s.
Out of idle curiosity I put "0x%08lx" into Google and found that quite a few crash dumps include this bizarre message. Am I to take it that 0x%08lx is a place holder for something that should be meaningful? "%s" which is part of the concluding sentence "The memory could not be %s" definitely looks like it's missing a variable or something.
Does anyone know the provenance of this message? Is it actually supposed to be useful and what is it supposed to look like?
It's not a major thing I have always worked around it. It's just strange that so many people should see this in so many crash dumps and nobody ever says: "Oh the crash dump didn't complete that message properly it's supposed to read..."
I'm just curious as to whether anyone knows the purpose of this strange error message artefact.
0x%08lx and %s are almost certainly format specifiers for the C function sprintf. But looks like the driver developers did as good a job in their error handling code as they did in the critical code, as you should never see these specifiers in the GUI -- they should be replaced with meaningful values.
0x%08lx should turn into something like "0xE001D4AB", a hexadecimal 32-bit pointer value.
%s should be replaced by another string, in this case a description. Something like
the memory at 0xE001D4AB referenced
0xE005123F and could not be read.
Note that I made up the values. Basically, a kernel mode access violation occurred. Hopefully in the mini dumps you can see which module caused it and uninstall / update / whatever it.
I believe it is just the placeholder for the memory address. 0x is a string prefix that would notify the user that it is an hexadecimal, while %08lx is the actual placeholder for a long int (l) converted to hexadecimal (x) with a padding of 8 zeroes (08).
I wrote a program about 10 years ago in Visual Basic 6 which was basically a full-screen game similar to Breakout / Arkanoid but had 'demoscene'-style backgrounds. I found the program, but not the source code. Back then I hard-coded the display mode to 800x600x24, and the program crashes whenever I try to run it as a result. No virtual machine seems to support 24-bit display when the host display mode is 16/32-bit. It uses DirectX 7 so DOSBox is no use.
I've tried all sorts of decompiler and at best they give me the form names and a bunch of assembly calls which mean nothing to me. The display mode setting was a DirectX 7 call but there's no clear reference to it in the decompilation.
In this situation, is there any pointers on how I can:
pin-point the function call in the program which is setting the display mode to 800x600x24 (ResHacker maybe?) and change the value being passed to it so it sets 800x600x32
view/intercept DirectX calls being made while it's running
or if that's not possible, at least
run the program in an environment that emulates a 24-bit display
I don't need to recover the source code (as nice as it would be) so much as just want to get it running.
One technique you could try in your disassembler is to do a search for the constants you remember, but as the actual bytes that would be contained within the executable. I guess you used the DirectDraw SetDisplayMode call, which is a COM object so can't be as easily traced to/from an entry point in a DLL. It takes parameters for width, height and bits per pixel and they are DWORDs (32-bit) so do a search for "58 02 00 00", "20 03 00 00" and "18 00 00 00". Hopefully that will narrow it down to what you need to change.
By the way which disassembler are you using?
This approach may be complicated somewhat if your VB6 program compiled to p-code rather than native code as you'll just get a huge chunk of data that represents the program rather than useful assembler instructions.
Check this:
http://www.sevenforums.com/tutorials/258-color-bit-depth-display-settings.html
If your graphics card doesn't have an entry for 24-bit display....I guess hacking your code's the only possibility. That or finding an old machine to throw windows 95 on :P.