It took me a while, but this issue is that in procsupt.asm the kernel builds on the stack a return and int23h so we can properly pass the correct stack between handler and C code. Invisible Lan fredir.exe does a check to verify and find the kernel's code that invokes the int 23h when a control-break occurs. It installs its own handler then causes a control-C to invoke it, and it saves the return address. Then it cleans up some (it redirected stdout to avoid showing the ^C on the console) which overwrites the [unused] stack in the process which overwrites the data at the address previously saved. Then it checks the address returned to verify the previous instruction was int 23h, however, by now that call stack has been overwritten the int 23h instruction so the check fails and the redir aborts loading. There is secondary issues with ctrl-break handling as the ^C is printed to the CON device when it should be redirected to NUL device. The NUL device also misses checking for control-break when output since it just immediately returns success.
The relevant code in fredir.exe (note: original executable is some form of lzexe compressed)
; ... setup and invoke control-break, cleanup, and now check if we found kernel's int 23h call site
mov dx, OFFSET errormsg
cmp word [cs:0x44], 2 ; memory 0x44 & 0x46 initialized to 0x02 when exe loaded, now iret return address
jb .ctrlbreak_return
les bx, [cs:0x44]
cmp word [es:bx - 2], 0x23cd ; <-- succeeds in MSDOS, by now overwritten in FD kernel since was on stack
jne .ctrlbreak_return
xor dx, dx ; success
.ctrlbreak_return:
pop ax
pop bx
pop cx
pop si
pop di
pop bp
pop ds
pop es
ret
; transient INT 23h handler: capture DOS return CS:IP
ctrlbreak_handler:
pop word [cs:0x44]
pop word [cs:0x46]
push word [cs:0x46]
push word [cs:0x44]
iret
In kernel procsupt.asm chunk of _spawn_int23 call:
sub sp, byte 8 ;; code piece needs 7 bytes --> 4 words
push ss ;; prepare jump to INT-23 via RETF
push bp ;; will be offset / temp: saved BP
mov bp, sp
add bp, byte 4 ;; position BP onto INT-23
mov word [bp], 23cdh ;; INT 23h
mov byte [bp+2], 9ah ;; CALL FAR immediate
mov word [bp+3], ??regain_control_int23
mov word [bp+5], cs
;; complete the jump to INT-23 via RETF and restore BP
xchg word [bp-4], bp
clc ;; set default action --> resume
; invoke the int 23 handler its address has been constructed
;; on the stack
retf
??regain_control_int23:
So we need to rework this so the int 23h call is in static [patchable] location and not on stack.
It took me a while, but this issue is that in procsupt.asm the kernel builds on the stack a return and int23h so we can properly pass the correct stack between handler and C code. Invisible Lan fredir.exe does a check to verify and find the kernel's code that invokes the int 23h when a control-break occurs. It installs its own handler then causes a control-C to invoke it, and it saves the return address. Then it cleans up some (it redirected stdout to avoid showing the ^C on the console) which overwrites the [unused] stack in the process which overwrites the data at the address previously saved. Then it checks the address returned to verify the previous instruction was int 23h, however, by now that call stack has been overwritten the int 23h instruction so the check fails and the redir aborts loading. There is secondary issues with ctrl-break handling as the ^C is printed to the CON device when it should be redirected to NUL device. The NUL device also misses checking for control-break when output since it just immediately returns success.
The relevant code in fredir.exe (note: original executable is some form of lzexe compressed)
In kernel procsupt.asm chunk of _spawn_int23 call:
So we need to rework this so the int 23h call is in static [patchable] location and not on stack.