欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

再和 DriverStudio 过不去之加强版:)

再和 DriverStudio 过不去之加强版:)


再和DriverStudio"过不去"之加强版 
?
 
(<<抢先DriverStudio夺取机器控制权>>系列2)
?
(测试平台 windows 2000 sp4 + masm32v9.0)
?
 
 
 
上篇仅仅说到如何抢先DriverStudio,并在结尾留给大家一
?
个遐想。现在我进一步拓展这个遐想,从而给大家更多的遐
?
想。: )
?
 
那么现在我要给这个驱动增加新的功能,不但抢
?
DriverStudio 启动,而且给用户显示几行提示,并等待用
?
户的输入,如果用户敲 B 键则发生蓝屏,如果用户按任
?
意其他键则继续往下执行,So DriverStudio 可以正常执
?
行下去。
?
 
要完成这个功能必须解决两个问题:
?
 
0 如何在系统引导时显示字符串;
?
 
1 如何捕获用户输入并延时等待。
?
 
 
那么从哪入手呢?我首先想到直接写Video Buffer和直接捕获
?
键盘寄存器,但是这个方法可行吗?我们不妨先看一下
?
DriverStudio的 bootcfg.sys 是如何做的。
?
 
照例用IDA载入bootcfg.sys,按照DriverStudio初始化
?
显示的字符串来到驱动的DriverEntry,如图0
?
 
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
?
图0
?
 
通过查找字符串的引用很快就找到对应的指令调用点,全文
?
只有一个引用,如图1所示:
?
 
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
?
图1
?
为了确认这一点,我将地址0x107dd - 0x107e6中的指令全
?
部nop掉,
?
 
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
?
图2
?
 
这时原先应该显示"Press ESC ..."这段话的地方果然没有显示,
?
而是直接跳到 Config 对话框那里去了。既然找对了地方下一
?
步就好办了,通过进一步反汇编bootcfg.sys的代码片断,
?
更加印证了我先前的想法!
?
 
下面进一步谈谈DriverStudio是如何做的:
?
a. 使用 MmMapIoSpace 完成物理地址到虚拟地址的映射,
?
因为内核已经进入保护模式,并且开了分页。要想读写物
?
理地址必须做这样的映射(我的
?
Windows 核心编程研究系列之二:读取指定物理内存地址
?
中的内容 》
?
一篇中有更为详细的说明)。
?
 
该函数原形如下:
?
PVOID 
MmMapIoSpace(
IN PHYSICAL_ADDRESS PhysicalAddress,
IN ULONG NumberOfBytes,
IN MEMORY_CACHING_TYPE CacheType
?
 
参数含义都比较明显,其中CacheType我们选择NoCache类型。
?
 
b. 使用类似于bios字符中断显示的规则,一个字符占一
?
个word(16bit),低位为字符的ascii码,高位为显示属性。
?
我这里要显示闪烁的红色字体,所以属性为 84h。与bios
?
中断不同的是,我们直接写视频缓冲,而不是调用 int 10h。
?
视频缓冲的物理地址为 0b8000h 。我写了一个显示函数,
?
包含两个参数:
?
 
第一个是字符串地址,第二个是显示的位置。
?
为了美观,我将2行字符串显示在屏幕的倒数最后两行上:
?
 
Screen_W equ 50h
?
Screen_H equ 19h ;1ch
?
Show_Pos_Line0 equ (Screen_W * (Screen_H - 2) + 5) * 2
?
Show_Pos_Line1 equ (Screen_W * (Screen_H - 1) + 5) * 2
?
 
函数内容如下:
;******************************************************
?
_DisplayString proc _lpstr,_pos
?
local pa:qword
local lpvmem:dword
?
 
mov dword ptr [pa],Video_Addr
?
mov dword ptr [pa+4],0
?
push 0 ;MmNonCached
?
push 8000h ;NumberOfBytes
?
push dword ptr [pa+4]
?
push dword ptr [pa]
?
call MmMapIoSpace
?
mov lpvmem,eax
?
mov esi,_lpstr
?
mov edi,lpvmem
?
add edi,_pos
?
mov bh,84h ;char show_attribute
?
.while TRUE
?
.if byte ptr [esi] != 0
?
mov bl,byte ptr [esi]
?
mov word ptr [edi],bx
?
inc esi
?
inc edi
?
inc edi
?
.else
?
.break
?
.endif
?
.endw
?
invoke MmUnmapIoSpace,lpvmem,8000h
?
ret
?
_DisplayString endp
?
 
 
最后不要忘了用MmUnmapIoSpace取消映射。
?
 
 
c. 为了达到延时的效果需要调用ntoskrnl.exe中的api
 
KeDelayExecutionThread,其原形如下:
 
NTSTATUS 
KeDelayExecutionThread(
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Interval
);
?
 
其中 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.
 
 
我们最好使用相对时间的延时方式,这就需要写成负数的形式,而将
参数前缀位(byte)全部置1。为了达到捕获键盘输入,需要直接访问
IO端口64h和60h,这在ring0种都不成问题 。我同样写了一个子函数方
便调用,代码如下:
 
 
;************************************************************
?
_WaitForInput proc
?
 
local al_tmp:byte
local interval:LARGE_INTEGER
local turnsNow:dword
?
mov dword ptr [interval],0ffffe000h
?
mov dword ptr [interval+4],0ffffffffh
?
mov turnsNow,0
?
.while TRUE
?
.if turnsNow == Turns
?
.break
?
.else
?
inc turnsNow
?
in al,64h
?
test al,1 ;is anykey is pressed ?
?
jz Delay
?
in al,60h
?
mov al_tmp,al
?
movzx eax,al_tmp
?
cmp eax,1
?
jz ExitWhile
?
cmp eax,1eh
?
jz ExitWhile
?
cmp eax,0b0h
?
jz ExitWhile
?
cmp eax,1ch
?
jnz Delay
?
 
ExitWhile:
?
.break
?
Delay:
?
invoke KeDelayExecutionThread,0,0,addr interval
?
.endif
?
.endw
?
xor eax,eax
?
mov al,al_tmp
?
ret
?
_WaitForInput endp
?
;**********************************************************
?
 
 
d. 剩下来做的事就是在Main中判断用户输入的键码:
?
 
invoke _DisplayString,addr szhopysay,Show_Pos_Line0
?
invoke _DisplayString,addr szchoose,Show_Pos_Line1
?
invoke _WaitForInput
?
 
.if al == 01h
?
;do nothing
?
.elseif al == 0b0h
?
invoke _TryBS
?
.else
?
;do nothing
?
.endif
?
 
 
 
运行的效果如图3所示:
?
 
 
screen.width*0.6) {this.width=screen.width*0.6;this.alt='此图已经缩小,点击察看原图。';}" border=0>
?
图3
?
 
蓝屏的代码就不给出了,因为相信每个人都能写出N种来。
?
写续篇的原因是因为正好看到驱网(www.driverdevelop.com)的
?
一篇逆向的文章,想现学现卖一番,呵呵。
?
暂时到这里吧(以前预告的第3篇文章因为要将原先结合VB的
?
界面变为C#而且又有了新的想法,所以还要等一段时间,呼呼),准
?
备去看女足啦,哇咔咔.......(无语了,这不是我...不是我....
?
不是我 ... ...)
?
 
(因为写得仓促,难免有不妥的地方,希望大家多多指出,谢谢)
?
 
(点击小图看大图)
?
 
 
 
侯佩|hopy
?
写于2007.09.18

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功