• [原创]抢先DriverStudio夺取机器控制权(下篇)


    原文链接:抢先DriverStudio夺取机器控制权(下篇)

        上篇仅仅说到如何抢先DriverStudio,并在结尾留给大家一个遐想。现在我进一步拓展这个遐想,从而给大家更多的遐想。: ) 那么现在我要给这个驱动增加新的功能,不但抢先DriverStudio启动,而且给用户显示几行提示,并等待用户的输入,如果用户输入B 键则发生蓝屏,如果用户按任意其他键则继续往下执行,SoDriverStudio可以正常执行下去。

        要完成这个功能必须解决两个问题:

            0 如何在系统引导时显示字符串;

            1 如何捕获用户输入并延时等待。

    那么从哪入手呢?我首先想到直接写Video Buffer和直接捕获键盘寄存器,但是这个方法可行吗?我们不妨看一下DriverStudio的bootcfg.sys 是如何做的。

            照例用IDA载入bootcfg.sys,按照DriverStudio初始化显示的字符串来到驱动的DriverEntry,如图0

     

    图0

    通过查找字符串的引用很快就找到对应的指令点,全文只有一个引用,如图1所示:

     

    图1

    为了确认这一点,我将地址0x107dd - 0x107e6中的指令全部nop掉,

     

    图2

    这时的确原先应该显示"Press ESC ..."这段话的地方没有显示,而是直接跳到Config 对话框那里去了。既然找对了地方下一步就好办了,通过进一步反汇编bootcfg.sys的代码片断,印证了我先前的想法!下面简单说说DriverStudio是如何做的:

           

      a. 使用 MmMapIoSpace 完成物理地址到虚拟地址的映射,因为内核已经进入保护模式,并且开了分页。要想读写物理地址必须做这样的映射(本猫的《Windows 核心编程研究系列之二:读取指定物理内存地址中的内容 》一篇中有更为详细的说明)。该函数原形如下:

          

    1 PVOID 
    2     MmMapIoSpace(
    3     IN PHYSICAL_ADDRESS  PhysicalAddress,
    4     IN ULONG  NumberOfBytes,
    5     IN MEMORY_CACHING_TYPE  CacheType

     参数含义都比较明显,其中CacheType选择NoCache类型。

      b. 使用类似于bios中断字符显示的规则,一个字符占一个word,低位为字符的ascii码,高位为显示属性。我这里显示闪烁的红色字体所以属性为 84h。与bios中断不同的是,我们是直接写视频缓冲,其物理地址为 0b8000h 。我写了一个显示函数,包含两个参数:第一个是字符串地址,第二个是显示的位置。为了美观,我将2行字符串显示在屏幕的倒数最后两行上:

     1 Screen_W equ 50h
     2 Screen_H equ 19h ;1ch
     3 Show_Pos_Line0 equ (Screen_W * (Screen_H - 2) + 5) * 2
     4 Show_Pos_Line1 equ (Screen_W * (Screen_H - 1) + 5) * 2
     5 
     6            函数内容如下:
     7 
     8            ;*************************************************************************
     9 _DisplayString proc _lpstr,_pos
    10  local pa:qword
    11  local lpvmem:dword
    12 
    13  ;mov dword ptr [pa+1],Video_Addr
    14  ;mov dword ptr [pa+5],0
    15 
    16  mov dword ptr [pa],Video_Addr
    17  mov dword ptr [pa+4],0
    18 
    19  push 0 ;MmNonCached
    20  push 8000h ;NumberOfBytes
    21  ;push dword ptr [pa+5]
    22  ;push dword ptr [pa+1]
    23  push dword ptr [pa+4]
    24  push dword ptr [pa]
    25  call MmMapIoSpace
    26 
    27  mov lpvmem,eax
    28  mov esi,_lpstr
    29  mov edi,lpvmem
    30  add edi,_pos
    31  mov bh,84h  ;char show_attribute
    32 
    33  .while TRUE
    34   .if byte ptr [esi] != 0
    35    mov bl,byte ptr [esi]
    36    mov word ptr [edi],bx
    37    inc esi
    38    inc edi
    39    inc edi
    40   .else
    41    .break
    42   .endif
    43  .endw
    44 
    45  invoke MmUnmapIoSpace,lpvmem,8000h
    46 
    47  ret
    48 
    49 _DisplayString endp
    50 
    51             
    最后不要忘了用MmUnmapIoSpace取消映射。

     

      c. 为了达到延时的效果调用ntoskrnl.exe中的apiKeDelayExecutionThread,其原形如下:

    1 NTSTATUS 
    2   KeDelayExecutionThread(
    3     IN KPROCESSOR_MODE  WaitMode,
    4     IN BOOLEAN  Alertable,
    5     IN PLARGE_INTEGER  Interval
    6     );

    其中 WaitMode选择KernelMode,将可报警置为FALSE.值得注意的是第3个参数Interval,这个参数说明如下:

    Interval

    Specifies the absolute or relative time, in units of 100 nanoseconds, for which the wait is to occur. A negative value indicates relative time. Absolute expiration times track any changes in system time; relative expiration times are not affected by system time changes.

     我们最好是用相对时间的延时方式,这就需要写成负数的形式将前导位全部置1。为了达到捕获键盘输入,需要直接访问IO端口64h和60h,这在ring0种都不成问题 。我同样写了一个子函数方便使用,代码如下:

     

     1 ;*************************************************************************
     2 _WaitForInput proc
     3  local al_tmp:byte
     4  local interval:LARGE_INTEGER
     5  local turnsNow:dword
     6 
     7  mov dword ptr [interval],0ffffe000h
     8  mov dword ptr [interval+4],0ffffffffh
     9 
    10  mov turnsNow,0
    11 
    12  .while TRUE
    13   .if turnsNow == Turns
    14    .break
    15   .else
    16    inc turnsNow
    17    
    18    in al,64h
    19    test al,1
    20    jz Delay
    21 
    22    in al,60h
    23    mov al_tmp,al
    24    movzx eax,al_tmp
    25    cmp eax,1
    26    jz ExitWhile
    27 
    28    cmp eax,1eh
    29    jz ExitWhile
    30 
    31    cmp eax,0b0h
    32    jz ExitWhile
    33 
    34    cmp eax,1ch
    35    jnz Delay
    36    
    37   ExitWhile:
    38    .break
    39  
    40   Delay:
    41    invoke KeDelayExecutionThread,0,0,addr interval
    42   .endif
    43  .endw
    44 
    45  xor eax,eax
    46  mov al,al_tmp
    47  ret
    48 
    49 _WaitForInput endp
    50 
    51 ;*************************************************************************
    52 
    53         d. 剩下来做的事就是在Main中判断用户输入的键码:
    54 
    55  invoke _DisplayString,addr szhopysay,Show_Pos_Line0
    56  invoke _DisplayString,addr szchoose,Show_Pos_Line1
    57  invoke _WaitForInput
    58 
    59 
    60   .if al == 01h
    61   ;do nothing
    62  .elseif al == 0b0h
    63   invoke _TryBS
    64  .else
    65   ;do nothing
    66  .endif

    运行的效果如图3所示:

    图3

    蓝屏的代码就不给出了,因为相信每个人都能写出不同的花样来。写续篇的原因是因为正好看到驱网(www.driverdevelop.com)的一篇逆向的文章,想现学现卖一番,呵呵。暂时到这里吧(以前预告的第3篇文章因为要结合VB的界面而且又有了新的想法,所以还要等一段时间,呼呼),准备去看女足啦,哇咔咔.......(无语了,这不是我...不是我....不是我 ... ...)

     

     

                                                                                                        侯佩|hopy

                                                                                                        写于2007.09.18

  • 相关阅读:
    2016——3——16 kmp 7题
    bzoj3942——2016——3——15
    bzoj1355——2016——3——15
    poj 3641 ——2016——3——15
    KMP之我见
    转自他人——————TLE之前,没有一个节点叫失败!!!
    省选必知
    bzoj1449————2016——3——14
    bzoj1070————2016——3——14
    bzoj1562[NOI2009]变换序列——2016——3——12
  • 原文地址:https://www.cnblogs.com/hopy/p/3829057.html
Copyright © 2020-2023  润新知