⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 baohu.txt

📁 关于黑客的论坛的下载资料
💻 TXT
📖 第 1 页 / 共 5 页
字号:
 
 
--------------------------------------------------------------------------
┌———————┐
│进入 V86  模式│
└———————┘
 
        cli
        lgdt    fword ptr cs:gdtadds
        lidt    fword ptr cs:idtadds
        mov     eax,cr0
        or      al,01h
        mov     cr0,eax
        mov     bx,0018h
        ltr     bx            ;发生工作切换时 ,SS:ESP 将参考 0018 的区段表格
        jmp     0020h:0000h   ;进入工作切换 ,会跳到此表格内指定的 CS:EIP
                               (LTR.JMP 不可指向同一表格)
 
enter_v86 :                   ;假设您已将 CS:EIP 指向此处继续执行
        xor     eax,eax
        mov     ax,code
        push    eax             ;GS
        push    eax             ;FS
        push    eax             ;DS
        push    eax             ;ES
        push    eax             ;SS
        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 下产生中断後 ,电脑会自动切回保护模式 ,并从 LTR 所指定的位址取得
TSS 表格 ,然後以表格内的资料重新设定 SS.ESP ,然後把 V86 下的各暂存器值摆入
此堆叠内 ,在此需注意的是它摆放在堆叠的资料是32位元方式 ,所以对於 DS.ES....
这类16位元暂存器摆於堆叠 ,不足部份补 '0000' ,用以凑足 32Bit。
 
    简单来说 ,在真实模式下或 V86下使用一组 SS:SP ,一但透过中断进入保护模式
後 ,原先的 SS:SP 暂存器将被置换另一组数值(定义於TSS表) ,然後再将大部份的暂
存器值摆放在这个新堆叠区内(包含SS.ESP) ,直到执行 IRETD 回到 V86 後 ,SS:ESP
暂存器值才会从原先堆叠中弹出。换句话说 ,在 V86下发生中断会使用自己的堆叠 ,
而不会破坏 V86 的堆叠区 ,这也就是为什麽像 S-ICE 除错程式执行 'T' 的命令却
不会更动 User 的堆叠资料。
 
    存於保护模式堆叠内的 CS:EIP 会指向 V86下 "INT_X" 的下一行 ,而 SS:SP 值
却仍维持原来数值(不像以往产生中断会自动减6 ,然後堆叠内摆入 FLAG.CS.IP),因
此保护模式下处理中断的程式必需修改 V86 的 SP 值减6 ,并将 V86 的 CS.IP.FLAG
摆入 V86 的堆叠 ,最後再去查 0000:0000 的表格 ,将保护模式堆叠内的 CS:EIP 值
修改、指向此中断向量表 ,最後保护模式的程式执行 IRETD 返回 V86 後 ,跳到 V86
下的中断所指位址 ,这样便完成整个模拟 DOS 中断的效果。
 
PS:保护模式下堆叠会存放 EFLAG.EIP.ECS.ESP.SS...... 忘了 ,比 Real Mode 还要
   多好多喔。
 
    底下仅列出部份中断的处理方式....您必需处理 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
 
--------------------------------------------------------------------------
┌——————┐
│拦 I/O  能力│
└——————┘
 
    TSS 表格内除了可定义产生工作切换後 ,SS.ESP.DS.ES....各暂存器替换值 ,也
可以开一块记忆体做 IOMAP ,这块记忆体每个 Bit 代表一个 PORT ,一般习惯是开4K
大小 (65536埠),当某位元设定为 '1' 後 ,只要不是最高等级的人去读写此埠 ,都会
发生 GP Err #0D ,当然在最低等级的 V86 程式也不例外 ,发生此错误後 ,就形同拦
到 I/O  动作了 ,紧接著透过最高等级的处理程式去判断发生错误的原因 ,例如判断
程式码是否为 『EC  IN AL,DX』、『EE  OUT DX,AL』 ,或是其它程式码 ,就可以分
辨发生的原因是读或写产生的 ,拦到 I/O 後 ,你是否会写骗 I/O 的程式 ?
 
    以 S-ICE 的拦 I/O 能力为例 ,它先使用 IO-MAP 的方式去拦 I/O ,然後再判别
"EE.E4.EC.E6...." 等等程式码。
 
注:IOMAP 表是也是 TSS 表格的一部份。
--------------------------------------------------------------------------
┌———————┐
│相容性的处理一│      系统暂存器的相容处理法
└———————┘
 
    或许您曾经在挂入 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 系的欺骗手段。
 
    本来标准的程式是不会在 V86  下读写系统暂存器 ,可是确实也有不正常的程式
是这样搞的 ,例如倚天中文会执行 MOV EAX,CR3 ,或是一些保护程式会写入除错暂存
器 (DRx)。所以为了相容性 ,这些最好做进去。
 
注:判别发生的原因也可以利用判断 I/O 的那种方法 ,但写起来很麻烦。
--------------------------------------------------------------------------
┌———————┐
│相容性的处理二│      HIMEM.SYS
└———————┘
    HIMEM.SYS 是一个可以控制 1MB  以外记忆体的程式 ,不过之前笔者有提过 ,要
读写超过 1MB  以外的记忆体必需进入保护模式才行(据说有後门可用) ,那麽载入自
己的保护模式程式後 ,再遇到呼叫 HIMEM.SYS 去搬移 1MB 以外的记忆体 ,电脑竟然
会发生 GP Err #0D ,原来这是因为 HIMEM.SYS 在执行搬移记忆体的命令後会去呼叫
BIOS 的 AH=87h  INT_15h 去搬记忆体 ,换句话说就是因为这个 BIOS 中断会进入保
护模式去搬记忆体 ,所以才会造成当机 ,因此你的保护模式介面程式必需去模拟这个
BIOS 函式 ,就可以与 HIMEM.SYS 相容了。
 
注:BIOS AH=87h INT_15h 会重设 GDT.IDT 表 ,然後进入保护模式去搬记忆体 ,然後
   就当在 LIDT 或 LGDT 的命令上。
 
   另外如果你的程式摆在 1MB 以上的记忆体位址去执行 ,还会有另一个问题产生 ,
   不过如果你已经学会上面的这些功能 ,再尝试去写个程式去试试 ,你自然会知道
   它会发生什麽问题 ,解决的办法也很简单 ,你一定会解决。
--------------------------------------------------------------------------
    切入 V86  後 ,还有很多问题要处理 ,不过上面提到的两个问题如果你都能处理
的话 ,基本上就不会有其它大问题 ,等你会进入保护模式後 ,再来学习  VCPI、DPMI
就很简单了。
 
    如果各位会切入保护模式的话 ,接下来应该是学习 VCPI 的切入方式 ,虽然有很
多书籍有介绍 ,但是要真正了解并不容易。建议各位去买套大宇出品的激斗战士、战
国策 ,它的外加保护就是切入保护模式的最佳范例 ,包含透过 VCPI、自己切286.386
保护模式 ,虽然这是不道德的行为 ,但是却是一个最佳范本。花个五百块学新知绝对
划算。
 
    有关保护模式的部份笔者暂时介绍到此 ,下一集笔者将为您介绍虚拟记忆体 ,如
果情况允许 ,还会顺便介绍更难懂的分页机能。教各位如何写出类似 S-ICE 的 BPR
功能 ,锁定某一块记忆体的读写状态。
 
 
┌———————————————————————————————————┐
│  Soft Bugger 软体蛀虫 90:90/2                    软体新技术的实行者  │
│  BBS:02-5955461 24HR          ID:Werong Ho               -- 软蛀 --  │
└———————————————————————————————————┘

                                                    ┌┐┌┐∞
【 80386 保护模式简介五 】                     ┘└┘└┘
==========================================================================
前言:
    底下是进入保护模式、进入 V86 的精简范例 ,执行前请确定 CPU 是处在真实模
式 ,程式码因为用到 386 指令 ,请用 TASM 3.1 来编译。
--------------------------------------------------------------------------
┌——————┐
│进入保护模式│
└——————┘

    进入保护模式的程式范例 ,其目地是进入保护模式 ,并在保护模式下用绝对记忆
体读写的方式 ,直接将 'Protection Mode !' 字串写入 Video Ram (B800:0000) ,
本程式以最精简的方式撰写 ,没有任何错误处理 ,因此请确定电脑现在处在真实模式
下才可执行本程式。(禁挂 EMM 系保护模式软体)

    程式流程如下:(底下所指记忆体位址皆为 32bit 绝对位址)

        1. 设定 GDTtab 表所在的记忆体位址填入 GDTadds

        2. 设定 Selector 0008 的记忆体起始位址就是现在 CS 的记忆体位址
           设定 Selector 0010 的记忆体起始位址就是现在 CS 的记忆体位址
                Selector 0018 的记忆体起始位址就是 000B8000 = (B800:0000)

        3. 执行 LGDT FWORD PTR CS:GDTadds 告诉 CPU 一但进入保护模式 ,各
                区段的记忆体起始位址、长度

        4. 设定 CR0 的 Bit0 = '1' ,并透过 JMP 指令进入保护模式
             ※ 进入保护模式後 ,DS.ES.SS.CS.GS.FS 等等暂存器定址方式不再
                是 Segment ,而变成 Selector

        5. 秀字 将 0010:MSG_1 搬到 0018:0000
                意即将 'Protection Mode !' 字串搬到 Video Ram 去

        6. 设定 CR0 的 Bit0 = '0' ,并透过 JMP 指令回到真实模式
             ※ 回到真实模式後 ,DS.ES.SS.CS.GS.FS 等等暂存器定址方式不再
                是 Selector ,而变成 Segment

        5. 秀字 将 CS:MSG_2 搬到 B800:00A0
                意即将 'Return Real Mode !' 字串搬到 Video Ram 去

        6. 结束程式

-----------------------------  P.ASM  ------------------------------------
code    segment
        assume  cs:code,ds:code
.386p
start   proc    near
        jmp     next
gdtadds dw      001fh,0000h,0000h
gdttab  db      000h,000h,00h,00h,00h,00h,00h,00h ;00 Null
        db      0ffh,0ffh,00h,00h,00h,9bh,00h,00h ;08 PRG Seg
        db      0ffh,0ffh,00h,00h,00h,93h,00h,00h ;10 PRG Seg
        db      0ffh,0ffh,00h,80h,0bh,93h,00h,00h ;18 B8000
msg_1   db      'Protection Mode !'
msg_2   db      'Return Real Mode !'

next :
        xor     eax,eax                 ;
        xor     ebx,ebx                 ;
        mov     ax,cs                   ;设定 GDTadds
        shl     eax,04h                 ;
        mov     bx,offset gdttab        ;
        add     eax,ebx                 ;
        mov     di,offset gdtadds+02h   ;
        mov     cs:[di],eax             ;
        NOP
        xor     eax,eax                 ;
        xor     ebx,ebx                 ;
        mov     ax,cs                   ;
        shl     eax,04h                 ;
        mov     di,offset gdttab+08h    ;设定 GDTtab 内的
        mov     si,offset gdttab+10h    ;Selector 0008 及 0010
        mov     cs:[di+02h],ax          ;两个段落的记忆体起始位址
        mov     cs:[si+02h],ax          ;
        shr     eax,10h                 ;
        mov     cs:[di+04h],al          ;
        mov     cs:[si+04h],al          ;
        mov     cs:[di+07h],ah          ;
        mov     cs:[si+07h],ah          ;
        NOP
        cli
        lgdt    fword ptr cs:gdtadds    ;载入 GDT 表格
        mov     eax,cr0             ;
        or      al,01h              ;
        mov     cr0,eax             ;
        jmp     protection_mode     ;进入保护模式
protection_mode :                   ;
        mov     ax,0010h                ;
        mov     ds,ax                   ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -