TASM中检测INT 1单步中断是否发生在IMUL指令执行前的实现咨询
TASM中检测INT 1单步中断是否发生在IMUL指令执行前的实现咨询
嘿,我来帮你搞定这个问题!你现在的核心需求是在INT1单步中断的处理程序里,判断当前触发中断后即将执行的指令是不是IMUL cl,然后分别输出对应的信息对吧?下面我一步步给你讲清楚怎么实现:
第一步:搞清楚IMUL cl的机器码
要判断指令类型,首先得知道它对应的机器码。你用的IMUL cl是单操作数8位寄存器版本的IMUL,它的机器码是两个字节:0xF6(第一字节,操作码前缀)和0xC1(第二字节,ModR/M字段,用来指定操作数是cl寄存器)。
第二步:修改中断处理程序,读取并判断机器码
你的中断处理程序已经拿到了返回地址(也就是下一条要执行的指令地址),现在需要读取这个地址的前两个字节,和IMUL的机器码对比。具体修改如下:
首先,在.data段添加需要输出的IMUL相关提示字符串:
.data PranNe db "Not IMUL", 13, 10, "$" ; 新增IMUL相关提示 ImulMsg db "IMUL detected!", 13, 10 AddrMsg db "Address: $" CodeMsg db 13, 10, "Machine Code: F6 C1$" MnemonicMsg db 13, 10, "Mnemonic: IMUL$" OperandMsg db 13, 10, "Operand: cl$", 13, 10, "$"
然后,修改ApdorokPertr中断处理程序里的判断逻辑:
PROC ApdorokPertr ;put register values on the stack PUSH ax PUSH bx PUSH dx PUSH bp PUSH es PUSH ds MOV ax, @data MOV ds, ax ;In the DL register, we write the operation code of the command before which the INT was called MOV bp, sp ADD bp, 12 MOV bx, [bp] ; bx = 返回地址的偏移量 MOV es, [bp+2] ; es = 返回地址的段地址 ; 读取指令的前两个字节:第一个字节存dl,第二个存dh MOV dl, [es:bx] MOV dh, [es:bx+1] ; 判断是否是IMUL cl(机器码F6 C1) CMP dl, 0F6h JNE NotImul CMP dh, 0C1h JNE NotImul ; 如果是IMUL,输出相关信息 ; 先输出检测提示 MOV ah, 9 MOV dx, offset ImulMsg INT 21h ; 输出地址(es:bx) MOV ah, 9 MOV dx, offset AddrMsg INT 21h ; 打印段地址es MOV ax, es CALL PrintHex MOV dl, ':' MOV ah, 2 INT 21h ; 打印偏移地址bx MOV ax, bx CALL PrintHex MOV dl, 13 MOV ah, 2 INT 21h MOV dl, 10 MOV ah, 2 INT 21h ; 输出机器码、助记符、操作数 MOV ah, 9 MOV dx, offset CodeMsg INT 21h MOV dx, offset MnemonicMsg INT 21h MOV dx, offset OperandMsg INT 21h JMP endd NotImul: ; 不是IMUL,输出原信息 MOV ah, 9 MOV dx, offset PranNe INT 21h endd: POP ds POP es POP bp POP dx POP bx POP ax IRET ApdorokPertr ENDP
第三步:添加十六进制打印子程序(用来输出地址)
因为要打印指令的地址(段:偏移),需要一个把16位寄存器的值转换成十六进制字符串打印的子程序,你可以在.code段里添加这个子程序:
; 十六进制打印子程序:输入ax,输出ax的十六进制值 PrintHex PROC PUSH cx PUSH dx MOV cx, 4 PrintLoop: ROL ax, 4 MOV dl, al AND dl, 0Fh ADD dl, '0' CMP dl, '9' JBE PrintChar ADD dl, 7h ; 转换为A-F PrintChar: MOV ah, 2 INT 21h LOOP PrintLoop POP dx POP cx RET PrintHex ENDP
一些关键说明
- 单步中断的触发时机:INT1单步中断是在每条指令执行前触发的,所以当中断处理程序被调用时,栈里的返回地址就是下一条要执行的指令的地址,这正是我们需要检测的目标。
- 多字节指令处理:IMUL是双字节指令,所以必须读取前两个字节才能准确判断,只读第一个字节会和其他使用
0xF6作为前缀的指令混淆。 - 寄存器保护:你的代码里已经正确保存和恢复了所有用到的寄存器,这很重要,不然会破坏主程序的执行状态。
现在把这些代码整合到你的原程序里,编译运行后,当单步中断触发在IMUL指令前时,就会输出IMUL的详细信息,其他时候输出"Not IMUL"。
备注:内容来源于stack exchange,提问作者lulzo
相关产品推荐
相关产品推荐

