【发布时间】:2020-09-06 11:06:09
【问题描述】:
我正在尝试挂钩 BIOS Int 13h 以向其中添加我的自定义功能并劫持一些现有功能。 Old Int 13h 向量存储在全局变量中。 当调用中断处理程序时,DS 被设置为与调用者的原始数据段不匹配的某个值。因此访问调用者的全局变量变得很头疼。
链接中断处理程序的最佳做法是什么?
Hook 是这样安装的:
#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 钩子代码:
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
如果重要的话,我正在使用 Borland C++
【问题讨论】:
-
通常的解决方案是将变量移动到代码段中以便您可以使用
call far ptr [cs:_biosInt13h]或根据需要设置段,检索指针,将其放在堆栈上,恢复段,然后执行retf跳转到 BIOS 中断处理程序。请注意,代码将按原样崩溃,因为除了返回地址之外,中断处理程序还会弹出标志。 -
如果您使用的是微型模型,您可以在远调用中使用
cs段覆盖。但是,您要么需要将其更改为远跳,要么在远调用之前添加pushf。 -
如果您没有返回到您的处理程序并且正在尾部调用旧的处理程序,那么您可以使用
jmp far ptr [cs:_biosInt13h]。然后iret将直接由旧的中断处理程序完成。 -
只有当您在微型模型中执行此操作并最终构建 COM 程序时,CS 段覆盖才会起作用,否则您将必须显式加载 DS 寄存器,其中包含特定于您正在使用的模型的段.
-
@MichaelPetch 您只需将变量放在与访问它的中断函数相同的段中。
标签: c assembly interrupt-handling tasm real-mode