Hacker News new | past | comments | ask | show | jobs | submit login

> I am a little bit freaked out by that because the pointer to the buffer is set before the IOCTL call; the code knowingly sets a pointer to a buffer into what looks like its code area. Let's hope they knew they were done with that part of the code, or it's just another interesting bug to dissect.

This is common in code without segmentation protection. CODE and DATA are convention. You can just specify a function, then a small buffer, then another function. .COM files in particular were easier to write with CS and DS pointing to the same region of memory, assuming you could fit both your code and inline buffers in 64kB.

The code explains what they are doing. Even more interesting, they're using their own stack too:

  ;  1 - This program uses its own internal stack.  The stack space provided
  ; by DOS is used as an input buffer for transfering IBMBIO and IBMDOS.
  ;
  ; SYS is linked with the CODE segment followed by the DATA segment. The
  ; last symbol in DATA is BUF. It marks the end end of data and the
  ; start of the BUFfer.  The BUFfer extends from here to SP.  The first
  ; 6.5Kb (13 sectors) in BUFfer are used for up to 12 sectors of the FAT
  ; or the directory. In Main, the remaining space is set
  ; as follows:
  ;        cdBuf = SP - ( FAT_BUF + BUF )
  ;



I looked at the call before and after to see what they had set the buffer to, and they clearly set the buffer to point into what is code. The executable is only 5KB and it's tiny; they had plenty of space in the segment to use a different part of the segment without purposefully blasting their own code.

While it's common, it was still a terrible practice. If whatever was filling in that buffer changed, they could be blasting more code than they intended. (As indicated in what I wrote, I know it was common if they wanted to reuse the space. Device drivers do something similar when they are done with their init code.)


Here's the code from DOS 3.3. I am reasonably sure they didn't intend to overwrite code -- you're probably just seeing a weird artifact where the failure case is leaving a dangling random value that happens to point into valid code.

My guess is that DS isn't being maintained across the failing call to the IOCTL and ends up pointing to the wrong segment.

  DOSOutFH    DW ?   ; fh of DOS destination


  DumpMem:
    MOV    DX,OFFSET DG:BUF+512    ; get offset of bios start
    MOV    CX,pDOS         ; beginning of next guy
    SUB    CX,DX            ; difference is length
    JZ    DumpDos         ; no bios to move
    MOV    BX,BIOSOutFH        ; where to output
    MOV    AH,Write
    INT    21h            ; wham
    retc                ; error
    CMP    AX,CX            ; Did it work?
    JNZ    WRERR            ; No
  DumpDos:
    MOV    DX,pDOS         ; beginning of dos
    MOV    CX,pDOSEnd        ; end of dos
    SUB    CX,DX            ; difference is length
    retz                ; if zero no write
    MOV    BX,DOSOutFH        ; where to output
    MOV    AH,Write
    INT    21h            ; wham
    retc                ; error
    CMP    AX,CX            ; Did it work?
    retz                ; Yes, carry clear


Where is that published? I was using Github for references on DOS 4 as 3.3 isn't there yet.

(Thanks in advance!)


https://github.com/AR1972/DOS3.3/blob/master/SRC/CMD/SYS/SYS...

Send me a note via email -- I might have some more pointers for you




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: