I'm trying to hook BIOS Int 13h to add my custom functionality to it and hijack some of existing one. Old Int 13h vector is stored in global variable. When interrupt handler is called the DS is set to some value that doesn't match the original data segment of caller. Therefore accessing global variables of caller turns into a headache.
What is best practice to chain interrupt handlers?
Hook is installed this way:
#ifdef __cplusplus
# define INTARGS ...
#else
# define INTARGS unsigned bp, unsigned di, unsigned si,\
unsigned ds, unsigned es, unsigned dx,\
unsigned cx, unsigned bx, unsigned ax
#endif
void interrupt (far *hackInt13h)(INTARGS) = NULL;
void interrupt (far *biosInt13h)(INTARGS) = (void interrupt (far *)(INTARGS))0xDEADBEEF;
void main(void)
{
struct REGPACK reg;
biosInt13h = getvect(0x13);
hackInt13h = int13h;
setvect(0x13, hackInt13h);
// Calling CAFE
reg.r_ax = 0xCAFE;
intr(0x13, ®);
printf("Cafe returned: 0x%04x\n", reg.r_ax);
// Resetting FDD just to check interrupt handler chaining
reg.r_ax = 0;
reg.r_dx = 0;
intr(0x13, ®);
printf("CF=%i\n", reg.r_flags & 0x01);
setvect(0x13, biosInt13h);
}
Int 13h hook code:
P286
.MODEL TINY
_Data SEGMENT PUBLIC 'DATA'
EXTRN _biosInt13h:FAR
_Data ENDS
_Text SEGMENT PUBLIC 'CODE'
PUBLIC _int13h
_int13h PROC FAR
pusha
cmp AX,0CAFEh
jnz chain
popa
mov AX, 0BEEFh
iret
chain:
popa
call far ptr [_biosInt13h] ; <-- at this moment DS points to outer space
; and _biosInt13h is not valid
_int13h ENDP
_Text ENDS
END
I'm using Borland C++ if it matters
Thanks guys, I've found solution!
First thing I've missed is moving variable to code segment and explicitly specifying it.
Second one is using hacked (pushed on stack) return address and retf
instead of call
that adds real return address on stack.
No need to pushf
explicitly 'cause flags are already on stack after int
. And flags will be popped on iret
no matter in my handler or in chained one.
P286
.MODEL TINY
_Text SEGMENT PUBLIC 'CODE'
EXTRN _biosInt13h:FAR ; This should be in CODE 'cause CS is only segreg reliable
PUBLIC _int13h
_int13h PROC FAR
pusha
cmp AX, 0CAFEh
jnz chain
popa
mov AX, 0BEEFh
iret
chain:
popa
push word ptr cs:[_biosInt13h + 2] ; Pushing chained handler SEG on stack
push word ptr cs:[_biosInt13h] ; Pushing chained handler OFFSET on stack
retf ; ...actually this is JMP FAR to address on stack
_int13h ENDP
_Text ENDS
END
User contributions licensed under CC BY-SA 3.0