📄 7.txt
字号:
gt; mov ax,0f000h
> push eax ;ESP
> mov eax,00023000h ;设定VM=1 等级=3
> push eax ;Eflag
> xor eax,eax
> mov ax,code
> push eax ;CS
> mov ax,offset return_dos
> push eax ;EIP
> clts ;将 387 切换成 32 位元模式
> iretd ;回到 V86 (共弹出24h BYTE)
>
> 紧接著就程式回到 V86 下继续执行著...
> --------------------------------------------------------------------------
> ┌────────┐
> │中断向量表的处理│
> └────────┘
>
> 在保护模式下 ,产生中断後 ,会切回保护模式 ,於是您必需去呼叫原先 V86 下
> 的中断表 ,以便让程式能够正确执行。
>
> V86 下发生中断後 ,CPU 会取出 LTR 所设定 SS:ESP 值 ,然後将 V86 下的众
> 多暂存器暂存於此 ,不过因为 CPU 已变成 32 位元模式 ,所以堆叠内的 SP 值会被
> 减 12 byte (原本是6byte ,用以摆放 IP.CS.FLAG) ,且堆叠内的EIP值会指向 V86
> 下的 INT_X 的下一行 ,因此你必需先将 V86 下的 SP 值加 6 byte ,并修改 V86 下
> 的 SS:SP 里的内容为 INT_X 的下一行 ,然後将保护模式下的堆叠 CS:EIP 值指向原
> V86 下的中断位址 ,这样才可以带动 V86 下的中断表。
>
> 底下仅列出部份中断的处理方式....您必需处理 256 个中断表。
>
> new_20 :
> push 0020h
> jmp int_emu
> new_21 :
> push 0021h
> jmp int_emu
> new_22 :
> push 0022h
> jmp int_emu
> new_23 :
> push 0023h
> jmp int_emu
>
> int_emu :
> push bp
> mov bp,sp
> add bp,04h
> push eax
> push ebx
> mov ax,0010h ;
> mov ds,ax ;(Selector 0010h 的 Base=0)
> mov ax,ss:[bp+0ch] ;
> sub ax,06h ;改V86的SP-6
> mov ss:[bp+0ch],ax ;
> xor eax,eax ;
> xor ebx,ebx ;修改V86下的SS:SP ,帮它摆入
> mov ax,ss:[bp+10h] ;INT_X 後的下一行位址 ,供V86
> shl eax,04h ;下的程式IRET返回INT_X的下一行用
> mov bx,ss:[bp+0ch] ;
> add ebx,eax ;
> mov ax,ss:[bp+00h] ;
> mov ds:[ebx],ax ;
> mov ax,ss:[bp+04h] ;
> mov ds:[ebx+02h],ax ;
> mov ax,ss:[bp+08h] ;
> mov ds:[ebx+04h],ax ;
> nop
> xor ebx,ebx ;
> mov bx,ss:[bp-02h] ;
> shl ebx,02h ;
> mov ax,ds:[ebx] ;IRETD 後到V86中断表所指的位址继续执行
> mov ss:[bp+00h],ax ;(查 0000:0000 的中断表)
> mov ax,ds:[ebx+02h] ;
> mov ss:[bp+04h],ax ;
> mov eax,ss:[bp+08h]
> or eax,00032000h ;等级=3 VM=1
> and eax,0fffffeffh ;关闭'T'旗标
> mov ss:[bp+08h],eax
> pop ebx
> pop eax
> pop bp
> add sp,02h
> iretd
>
> --------------------------------------------------------------------------
> ┌──w───┐
> │相容性的处理│
> └──────┘
>
> 或许您曾经在挂入 QEMM386、EMM386 之後 ,在 V86 下执行 MOV EAX,CR0 的指
> 令 ,但是前面笔者提到读写系统暂存器必需在最高等级才可执行 ,为什麽 User 仍
> 可在最低等级下执行本命令呢 ? 底下是欺骗方式。
>
>
> (User) V86 下执行 MOV EAX,CR0
> ↓
> 发生 General Protection 0D
> CPU 自动切入保护模式 ,并执行 INT_0D 的处理程式
> (堆叠里多储存了错误代码 DWORD)
> ↓
> (EMM) 检查发生错误的原因
> 读取 EAX,CR0 (因此时已是最高等级 ,本行可以正确执行)
> ↓
> (EMM) 修改堆叠内的 EIP 值 ,指向下一行指令
> ↓
> (EMM) 修改使用者等级 3 / 设定 VM 旗标等於 1
> ↓
> (EMM) ESP 值扣掉错误代码 4byte
> ↓
> (EMM) IRETD 切回 V86
> ↓
> (User) 使用者取得 EAX 的数值
>
> 由於程式有一大半在保护模式下执行 ,所以使用者根本感觉不到 ,只知道自己真
> 的读到系统暂存器。这便是 EMM 系的欺骗手段。
>
>
> 再举例来说 ,笔者所写的 DEBUGOS ,在这个系统下您可以执行 MOV EAX,CR0 ,就
> 是因为笔者有加以处理 ,可是笔者检查保护模式错误原因里并没有处理 MOV EBX,CR0
> ,於是在这系统下 ,您就没办法执行本命令了 ,您可以试试看。
>
> 本来标准的程式是不会在 V86 下读写系统暂存器 ,可是确实也有不正常的程式
> 是这样搞的 ,例如倚天中文会 MOV EAX,CR3 ,或是一些保护程式会写入除错暂存器
> (DRx)。所以为了相容性 ,这些最好做进去。
>
> --------------------------------------------------------------------------
> ┌──────┐
> │拦 I/O 能力│
> └──────┘
>
> 在进入保护模式後 ,您可以在 IOMAP 里设定某些位元 ,用以管理 I/O 埠 ,每个
> Bit 表示一个埠 ,4K=32768埠 ,当您设定此位元後 ,等级低的人读写此埠就会发生
> General Protection Error 0D ,然後你就可以加以处理啦 ,不过 I/O MAP 只能设定
> 为读写时发生异常 ,无法单独设定为仅读取才发生或仅写入才发生 ,因此拦 I/O 的
> 人要自己去辨认原因。这点也是很麻烦的。
>
> --------------------------------------------------------------------------
> 切入 V86 後 ,还有很多问题要处理 ,包含上面提到的部份 ,和 HIMEM.SYS 相容
> 啦 ,这些问题有待您自己去寻找解决办法。
>
> 有关保护模式的部份笔者只能介绍到此 ,再下去更深的理论我不会解释 ,也掰不
> 出来 ,不过您如果会切入 V86 ,自然也能够写在保护模式下执行的程式才对。如有问
> 题再来信。
>
> DEBUGOS 这个小软体已经摆於 KPEMU300.ZIP 内了 ,这是一套模拟 KeyPro 的小
> 软体。
>
> ┌───────────────────────────────────┐
> │ Soft Bugger 软体蛀虫
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -