Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to index page
Thread view  Board view
ecm

Homepage E-mail

Düsseldorf, Germany,
16.08.2010, 04:11
 

Confusing DEBUG (Miscellaneous)

Fact: DEBUG's G command isn't reliably able to tell whether an interrupt 03h it received really comes from one of the breakpoints it set.

On return, the G command of DEBUG just looks whether the current CS:(E)IP fits, i.e. points behind one of the breakpoints it set. By forging an interrupt 03h invocation via pushf and a faked far call to the handler you can define the return address on the stack for that interrupt, making DEBUG believe that you executed the CCh breakpoint byte it set... but you didn't! DEBUG then incorrectly decrements (E)IP. Your program could theoretically detect that.

Uses? I dunno. That's why I'm posting it here :-D

---
l

Japheth

Homepage

Germany (South),
19.08.2010, 00:52

@ ecm
 

Confusing DEBUG

> On return, the G command of DEBUG just looks whether the current CS:(E)IP
> fits, i.e. points behind one of the breakpoints it set.

I don't think this is the correct description of what - at least - FD Debug does. It's more complicated. After G returned, it does:

- read the byte at CS:E/IP-1
- restore its BPs
- if the byte it has read is 0CCh AND entry into Debug was through interrupt 3, then it again reads the byte at CS:E/IP-1. If its value is NO LONGER 0CCh, then Debug assumes one of its BPs were hit and decrements E/IP.

---
MS-DOS forever!

ecm

Homepage E-mail

Düsseldorf, Germany,
19.08.2010, 01:19

@ Japheth
 

Confusing DEBUG - EDIT

> It's more complicated.

Only a little.

> - read the byte at CS:E/IP-1
> - restore its BPs
> - if the byte it has read is 0CCh AND entry into Debug was through
> interrupt 3, then it again reads the byte at CS:E/IP-1.

Fits my description up to here.

> If its value is NO
> LONGER 0CCh, then Debug assumes one of its BPs were hit and decrements
> E/IP.

This additional check, however, doesn't avoid my exploit. Whether you include that check in DEBUG really depends on your preference: let's say there was a CCh byte anyway - which byte did cause the interrupt, the one we wrote there or the one that was there anyway? I go with the first answer.

With the second answer, you display the message about "unexpected breakpoint interrupt" and don't decrement IP. I think you should rather not display the message but point to the int3 instruction in the disassembly.

EDIT: The MS DEBUG that I just tested chose the first answer just like me ;-)

---
l

Japheth

Homepage

Germany (South),
19.08.2010, 10:17

@ ecm
 

Confusing DEBUG - EDIT

> > - read the byte at CS:E/IP-1
> > - restore its BPs
> > - if the byte it has read is 0CCh AND entry into Debug was through
> > interrupt 3, then it again reads the byte at CS:E/IP-1.
>
> Fits my description up to here.

I saw - and still see - some differences, but this is probably off-topic.

However, what's on-topic is that I'm unable to see why DEBUG is supposed to be "confused". I also don't agree that it "incorrectly decrements (E)IP". If the conditions described above are met then (E)IP has to be decremented, it doesn't matter if the INT 3 was truly executed or if it was "faked".

---
MS-DOS forever!

ecm

Homepage E-mail

Düsseldorf, Germany,
19.08.2010, 11:00

@ Japheth
 

Confusing DEBUG

> I saw - and still see - some differences, but this is probably off-topic.

Feel free to wander. (If it's about the discrepancy that your DEBUG doesn't really check CS:EIP to see if it matches one of G's breakpoint, yeah, I noticed that later.)

> However, what's on-topic is that I'm unable to see why DEBUG is supposed to
> be "confused". I also don't agree that it "incorrectly decrements (E)IP".
> If the conditions described above are met then (E)IP has to be decremented,
> it doesn't matter if the INT 3 was truly executed or if it was "faked".

r ds 0
r bx C
a 100
pushf
push cs
push word 10C
push word [bx+2]
push word [bx]
retf
db A9
jmp 110
int 3
nop
int 3

g 10B
r ip 100
g


Executing this script (in your DEBUG) with the G breakpoint set at 10B ends up at the "test ax, 02EB" instruction (db A9). With no breakpoint at 10B (or outside DEBUG assuming a simple "iret" Int03 handler) the code doesn't execute the test instruction but the contained short jump instead.

The problem with that is that the byte which was set to a breakpoint doesn't have to be a valid instruction; therefore decrementing EIP to point there is incorrect. With a non-faked breakpoint, DEBUG knows it's a valid instruction because the CCh byte was executed. Not so if the Int03 call really came from elsewhere; the breakpoint might have been inside another instruction then. (Though setting breakpoints inside instructions is always just asking for problems.)

Of course, there is no use for this exploit. It's no issue with DEBUG either because no program ever fakes interrupt 03h calls. But I told you it's useless. I just found this to be interesting.

---
l

Back to index page
Thread view  Board view
22049 Postings in 2034 Threads, 396 registered users, 308 users online (0 registered, 308 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum