关于作者

用户名:beiyu
笔名:beiyu
地区: 四川-成都
行业:其他

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言



友情连接

有用的网站

读书娱乐

我的空间

访问统计:
文章个数:186
评论个数:176
留言条数:13




Powered by BlogDriver 2.1

beiyu的博客

 

欢迎访问beiyu的博客

文章

买得起房子了

买得起房子了

看似可以,好像可以,行吗?

- 作者: beiyu 2009年05月1日, 星期五 00:10  回复(0) |  引用(0) 加入博采

我那从古至今从小到大就知道的尊老爱幼
摘要:几千年的中国文化沉淀,中国人养成了尊老爱幼的良好风范,这种美好的道德约束在日常生活种指导着国人的行为,与其说它是一种道德风范,不如就说它是中国人的习惯,这种习惯不足以用伟大来形容,因为它超出了人类原始性的范畴,它超出世界其他任何国家的道德行为规范。 查看全文

- 作者: beiyu 2009年02月24日, 星期二 16:58  回复(0) |  引用(0) 加入博采

磁盘扇区数据的读取和写入
摘要:Written by beiyu , beiyuly@gmail.com Read and Write Sectors with sdk function, v1.0 WriteSectors do the job of writing ReadSectors do the job of reading good luck! 查看全文

- 作者: beiyu 2008年08月19日, 星期二 15:58  回复(0) |  引用(0) 加入博采

封QQ的方法总结
摘要:qq登陆方式有三种,tcp登陆,udp登陆,vip登陆(在qq登陆设置可查) 应该说用任何方式登陆都要经过一定的ip和端口进行的,我发现tcp方式登陆的一般都是用以下几个地址和端口:218.18.95.153:80,218.17.209.23:80,可能还有很多ip可以登陆,但我想应该都是通过tcp的80端口登陆的,只要禁止了tcp的80端口就可以禁止tcp方式的登陆了,但大家要注意一个事实,tcp的80端口也是浏览网站的默认端口啊,屏蔽了它是不能上网浏览网页啊,所以只能封登陆的ip地址了。 查看全文

- 作者: beiyu 2008年06月30日, 星期一 21:51  回复(0) |  引用(0) 加入博采

中国朝代变迁详细表
摘要:从夏开始,至今大约四千一百多年。让我们先来宏观的看看在这漫长的四个千年中中国的统一与分裂的线条: 查看全文

- 作者: beiyu 2008年05月14日, 星期三 19:23  回复(0) |  引用(0) 加入博采

男人疼爱女人的12种方式
摘要:1、当你爱着一个女孩子,一定要记得经常对她说:我爱你。不管已经说过多少次,不管是她第几百次问你“你爱我吗?”当她对你说“我爱你”,你都要很真诚地说:我也爱你,不是用其他话或者觉得多余。    2、如果你不爱她了,放了她。不要白白享受着她的照顾和温柔,然后漫不经心地寻找着别的女孩,在找到之后才说我们分手吧,又或者干脆脚踏两只船。     查看全文

- 作者: beiyu 2008年05月6日, 星期二 15:54  回复(0) |  引用(0) 加入博采

网络热门小说《佣兵天下》《新宋》《鬼吹灯》《诛仙》等总汇下载
摘要:网络热门小说《佣兵天下》《新宋》《鬼吹灯》《诛仙》等总汇下载 查看全文

- 作者: beiyu 2008年05月6日, 星期二 15:43  回复(0) |  引用(0) 加入博采

IRP hooking and Device Chains
摘要:IRP hooking is a common rootkit technique. There are two primary ways to get involved with IRPs – hooking function pointers or registering as an attached device (sometimes called a ‘Filter Driver’). 查看全文

- 作者: beiyu 2008年04月15日, 星期二 15:15  回复(0) |  引用(0) 加入博采

经典台词--多语言版本
摘要:曾经有一份真诚的爱情摆在我的面前,我没有珍惜,等到失去的时候才后悔莫及,人世间最痛苦的事莫过于此。 如果上天能够给我一个再来一次的机会,我会对那个女孩说:“我爱你!”如果非要在这份爱加上一个期限,我希望是一万年…… 查看全文

- 作者: beiyu 2008年03月20日, 星期四 21:35  回复(0) |  引用(0) 加入博采

诫子书
摘要:夫君子之行,静以修身,俭以养德。非澹泊无以明志,非宁静无以致远。夫学须静也。才须学也,非学无以广才,非志无以成学。淫漫则不能励精,险躁则不能治性,年与时驰,意与日去。遂成枯落,多不接世,悲守穷庐,将复何及! 查看全文

- 作者: beiyu 2008年03月17日, 星期一 09:47  回复(0) |  引用(0) 加入博采

送给南朝鲜人-中国人在国外BBS上这样羞辱韩国人
摘要:我想请问韩国人,你们除了三星,现代,LG,还有什么? 查看全文

- 作者: beiyu 2008年03月9日, 星期日 22:25  回复(2) |  引用(0) 加入博采

对联精彩
摘要:鸟在笼中,恨关羽不能张飞 人在世上,要八戒更需悟空 查看全文

- 作者: beiyu 2008年02月27日, 星期三 10:55  回复(0) |  引用(0) 加入博采

Windows文件系统过滤驱动开发教程-楚狂人
摘要:第一部分:概述,钻研目的和准备 我经常在网上碰到同行请求开发文件系统驱动。Windows的PC机上以过滤驱动居多。其目的不外乎有以下几种: 查看全文

- 作者: beiyu 2007年127日, 星期五 15:53  回复(4) |  引用(0) 加入博采

诛仙词
摘要:予雪琪 暮云尽收溢清寒。影自娟娟,独羡琼楼处。漫舞夜幕散花雨,寒光尽撒凉初透。 残痕欲掩十载苦。血浸素衫,终化幽雪舞。若非情深难自禁,怎会柔转冷如霜。 天琊微怔沾泪迹。柔手纤纤,遥忆牵心时。物是人非月空映,天涯咫尺半惘然。 浅笑了然生死共。低语呢喃,寒花偎依绽。暖意柔情水亦逝,怎管明日惟迹留。 查看全文

- 作者: beiyu 2007年11月23日, 星期五 15:29  回复(0) |  引用(0) 加入博采

中国各省份名字的真正由来
摘要:  【西藏】以清正式定名得名。唐宋为吐蕃;元属宣政院;明称乌思藏,设都司等;清初称卫藏,卫即前藏,藏即后藏;后正式定名为西藏,为西藏得名的开始;清设西藏办事大臣;民国初西藏地方;建国后仍之,后改西藏自治区,区名至今未变。 查看全文

- 作者: beiyu 2007年11月8日, 星期四 14:34  回复(0) |  引用(0) 加入博采

广州!爱你!~容易么!~!!~ ——牢骚一点
摘要:转眼间,又来到了广州,如梦初醒。梦是美好的,就像大多数人以前一样,做过广州这个繁华都市的美梦。而梦有时残酷,它永远不给我们多 查看全文

- 作者: beiyu 2007年11月6日, 星期二 11:11  回复(0) |  引用(0) 加入博采

三大文化谎言弥漫中国
摘要:文化骗子有一个最大的特点:成王败寇。无可否认的是,历史上有着五千年文明史的中华民族由强转衰,如今的中国客观的说还是个穷国,卑鄙的文化骗子们穷急生疯,最好的办法是咒骂祖宗,骂死人永远无风险。且造谣不需要根据,以为把盛世中华的文化文明象抹布一样扔掉,就是近代的思想启蒙,就是完成了思想上的现代化进程,就可以跻身于现代化的强国,为了达到这一目的,不惜造谣诋毁,往传统文明上泼脏水,同样急吼吼希望一夜暴富的心理脆弱者自然而然的随声应和,造成骗子文化盛行,三大文化谎言弥漫中国 查看全文

- 作者: beiyu 2007年07月7日, 星期六 13:13  回复(1) |  引用(0) 加入博采

NTFS文件系统若干技术研究
摘要:随着以NT为内核的Windows 2000/XP的普及,很多个人用户开始用到了NTFS。因此NTFS受到了越来越多的重视。 本文主要介绍NTFS的基本概念,基于NTFS的文件基本操作,NTFS文件数据恢复,NTFS相关领域技术。 查看全文

- 作者: beiyu 2007年04月26日, 星期四 21:57  回复(2) |  引用(0) 加入博采

支持 PS/2 与 USB 的键盘过滤驱动(可卸载)

支持 PS/2 与 USB 的键盘过滤驱动(可卸载)

Author:  sinister
Email:   sinister@whitecell.org
Homepage:http://www.whitecell.org
Date:    2007-02-26


/*******************************************************************

这个键盘过滤驱动是一个定时锁定计算机程序的功能部分,以前 lgx
写过一个 linux 版,现在我们需要实现一个 windows 版。这部分的
功能要求如下:

1、强制锁定键盘/鼠标。
2、可动态加/解锁
3、兼容所有 NT 系列的操作系统。

就这个需求而言,能马上能想到的就有7,8种方案,这些方案可以说都能够实
现,但如何更合理,更稳定、更彻底的实现,如何尽量少的消耗系统资源,如
何保证其兼容性,等一系列问题不得不让我们去重新评估这几种方法。首先在
上层实现,一是怕被饶过,二是怕调用频繁影响系统性能。在底层实现,一是
怕考虑不周有兼容性问题,二是怕过多使用未公开方法导致系统不稳定。下面
就来看一下我想到的几种实现方法:

1、全局键盘/鼠标钩子
2、BlockInput() API
3、使用 setupapi 进行控制
4、全局键盘/鼠标钩子+远线程插入 WINLOGON 进程屏蔽 CTRL+AL+DEL
5、拦截 win23k!RawInputThread() 函数
6、修改 DDK 中自带的 kbfilter 的键盘(Port Driver)过滤驱动
7、拦截 kdbclass 驱动的 driver dispatch routine
8、实现一个 PS/2 与 USB 键盘过滤驱动


我们先看一下以上这些方案的实用性与通用性。第1,2套方案不在考虑
之内了,因为有办法解锁,屏蔽不了 CTRL+ALT+DEL 组合键。第3套方
案经过我的测试使用 Keyboard 的 CLASSID 不是什么环境都好使,存在
兼容性的问题。第4套方案系统效率会大大降低,而且存在很多不稳定因
素,对于全局钩子这种东西我一直很排斥。第5套方案,同样存在兼容性
问题和不稳定因素。第6套方案看似完美,但无法实现动态卸载,无法卸
载就意味着你需要一个开关来控制是否锁定,这样还要与应用层通讯,我
的目的是不让应用层与驱动有任何交互。且使用 WDM 形式这种安装起来
也很麻烦,要么 INF 要么自己 setupapi,这都不是我想看到的,还有如
果仅为实现这么一个功能,就让一个核心驱动一直存在系统中的话,我有
障碍。第7套方案看似实现起来很简单,其实有很多问题。如仅是拦截
IRP_MJ_READ 并粗暴的返回拒绝后,系统无法恢复到初始状态。且对于
USB 键盘存在兼容性问题。那么最后只有自己实现一个 PS/2 与 USB 键
盘过滤驱动了,既然要实现这么一个驱动,那么就必须能实现到第6套方
案的全部功能且不存在它所带来的问题,否则就没有什么意义了。


我们都知道实现一个可直接使用 SERVICE API 来动态装载的 KMD 键盘过
滤驱动,首先需要先 ATTACH 到 \\Device\\KeyboardClass0 设备上再进
行按键过滤。但如果仅 ATTACH 这个设备的话,会存在很多问题,那就是
只能过滤到 PS/2 键盘,而对于使用 USB 键盘的机器毫无作用。现在越
来越多的品牌机都预配的是 USB 键盘(如:DELL)。大家可能会想,从
KeyboardClass0 一直到 N 都 ATTACH 不就可以了么?总有一个是 USB
键盘设备,经过实践这是不可行的,只要是 USB 键盘设备的话,在使用
IoGetDeviceObjectPointer() 函数从设备名得到设备对象都会获取失败,
我还曾尝试使用 USB 键盘设备名来转换,还是一样失败。还有一个问题
就是 USB 键盘设备不是都有名称的,即使有它的名称也都是动态生成的
而不是固定的。那么这就带来了一个问题,既然系统提供的函数无法使
用,且我们又是为了动态安装/卸载,使用的是 KMD 类型驱动,无法通
过 AddDevice 例程来获得 USB 键盘的设备对象进行挂接。那么如何来
屏蔽 USB 键盘按键?要达到这个目的只有自己分析下 USB 协议栈,通
过使用 DriverTree 观察发现,所有 USB 外设都挂在了 \Driver\hidusb
上面,USB 键盘驱动名为 \Driver\kbdhid,而它则是 \Driver\kbdhid
的一个 FilterDriver,且这个 \Driver\kbdhid 没有设备名称,也就意
味着,我们无法 IoGetDeviceObjectPointer() 得到设备对象并 ATTACH。
经过对多个系统多台使用 USB 键盘机器的分析,可以确定让我使用它们
来作为得到 USB 键盘设备的依据。(这里仅是对 USB 键盘设备很功利
的分析,如果想了解 WINDOWS 的 USB 设备栈如何组建,请阅读 tiamo
的 《Windows 的 USB 体系结构》。在此向所有公开研究成果的人致
敬!)有了这些依据,下面就没什么好说的了,自己遍历 USB 设备栈,
根据驱动名称获得 USB 设备对象,然后 ATTACH,过滤按键。具体流程
见下面代码。

这里有必要说下动态卸载,我尝试了两种方式,一种是在 UNLOAD 例程
里直接取消 IRP,这种方法在 W2K 系统下,无论是 PS/2 还是 USB 键
盘都可以很好的实现。但在 XP/2003 系统上则无法成功,在 XP/2003
上暂时使用一个 IRP 计数器,在 UNLOAD 例程里判断如果还有一个没有
完成的 IRP 则等待,这样的话,需要在 UNLOAD 后用户按下任意键才可
继续,虽然能够安全卸载但还需要一次用户介入。考虑实现的仅是一个
锁定功能,这样也算是能够忍受了。以后考虑在驱动中直接模拟用户按
键来实现,当然这种按键要有通用性和兼容性,支持 PS/2 与 USB 键盘。


完成了上述工作后看起来好象完美了,其实不然,当你屏蔽了当前使用
的键盘时别忘了还可以再插入一个 USB 键盘,而后续插入的这个键盘是
可以被识别的。这就需要我们处理 IRP_MJ_PNP 选项,对其中我们有兴趣
的 IRP_MN_XXX 做相应处理,可以处理 IRP_MN_START_DEVICE,在这时我
们动态挂接。还可以处理其他的 IRP,索性返回错误,让识别失效。但我
们的驱动是 KMD 类型,只要加上一句对 DriverObject->DriverExtension
->AddDevice 的赋值操作则无法直接使用 SERVICE API 来动态加载了。
如何保持 KMD 又可以获得 PNP 的处理权呢?这可能要直接对 PnpManager
进行操作了。这个问题有待大家来完善了。


要问为什么把文章插在代码当中,那可能是我觉得,既然把全部代码都贴出
来了,写文章就不如直接看代码来的真切。我这里所写也仅仅是对这些天的
分析做个记录而已。我更愿意把它看做是一段注释。

最后在此代码中要

感谢:PolyMeta,他在放假前提醒我 USB 键盘的不同。

感谢:lgx,过节前给我找了些事,以至于没有让我觉得过节那么无聊。

感谢:齐佳佳,过节请我吃好吃的。

崞類浶愭蝰櫉炈棡溫滠飲钕唹徕熸唹戹樤樯殢餀膑?崞烊旡唹澾崞懽碡飲嵯
愥撫剢淦泮嵯駨耒栃撣

******************************************************************/

/*****************************************************************
 文件名        : WssLockKey.c
 描述          : 键盘过滤驱动
 作者          : sinister
 最后修改日期  : 2007-02-26
*****************************************************************/


#include "WssLockKey.h"

NTSTATUS
DriverEntry( IN PDRIVR_OBJECT KeyDriverObject,
             IN PUNICODE_STRING RegistryPath )
{
  UNICODE_STRING KeyDeviceName;
  PDRIVER_OBJECT KeyDriver;
  PDEVICE_OBJECT UsbDeviceObject;
  NTSTATUS ntStatus;
  ULONG i;

  //
  // 保存设备名,调试使用
  //
  WCHAR szDeviceName[MAXLEN + MAXLEN] =
  {
    0
  };

  KeyDriverObject->DriverUnload = KeyDriverUnload;

  //
  // 先尝试获得 USB 键盘设备对象,如果成功则挂接 USB 键盘
  //
  // 注意:因为 USB 键盘设备名不固定,且即使得到名称也无法
  // 使用 IoGetDeviceObjectPointer() 函数根据设备名称得到其
  // 设备对象,所以这里我们只能自己枚举 USB 设备栈,并得到
  // USB 键盘设备来进行挂接
  //
  ntStatus = GetUsbKeybordDevice( &UsbDeviceObject );
  if ( NT_SUCCESS( ntStatus ) && UsbDeviceObject != NULL )
  {
    //
    // 调试使用,USB 键盘设备 kbdhid 没有设备名只有驱动名
    // 所以这里打印为空
    //
    RtlInitUnicodeString( &KeyDeviceName, szDeviceName );  // USB KEYBOARD
    DbgPrint( "KeyDeviceName:%S\n", KeyDeviceName.Buffer );

    //
    // 挂接 USB 键盘设备
    //
    ntStatus = AttachUSBKeyboardDevice( UsbDeviceObject, KeyDriverObject );
    if ( !NT_SUCCESS( ntStatus ) )
    {
      DbgPrint( "Attach USB Keyboard Device to failed!\n" );
      return STATUS_INSUFFICIENT_RESOURCES;
    }
  }
  else
  {
    //
    // 如果没有 USB 键盘,则尝试挂接 PS/2 键盘设备
    //
    RtlInitUnicodeString( &KeyDeviceName, PS2KEYBOARDNAME );

    ntStatus = AttachPS2KeyboardDevice( &KeyDeviceName,
                                        KeyDriverObject,
                                        &KeyDriver );
    if ( !NT_SUCCESS( ntStatus ) || KeyDriver == NULL )
    {
      DbgPrint( "Attach PS2 Keyboard Device to failed!\n" );
      return STATUS_INSUFFICIENT_RESOURCES;
    }
  }

  //
  // 这里没有过滤其他例程,仅处理了按键操作。这样处理会禁止
  // 休眠。因在锁定时不允许休眠,所以也就无须处理其他例程
  //
  KeyDriverObject->MajorFunction[IRP_MJ_READ] = KeyReadPassThrough;

  return STATUS_SUCCESS;
}

/////////////////////////////////////////////////////////////////
// 函数类型 : 系统函数
// 函数模块 : 键盘过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 尝试取消队列里的异步 IRP,如果失败则等待用户按键,
//        卸载键盘过滤驱动
// 注意 : 取消 IRP 操作在 2000 系统上可以成功,在 XP / 2003 上
//        则需要等待用户按键,以后有待完善
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////

VOID
KeyDriverUnload( PDRIVER_OBJECT KeyDriver )
{
  PDEVICE_OBJECT KeyFilterDevice ;     
  PDEVICE_OBJECT KeyDevice ;
  PDEVICE_EXTENSION KeyExtension;
  PIRP Irp;
  NTSTATUS ntStatus;

  KeyFilterDevice = KeyDriver->DeviceObject;
  KeyExtension = ( PDEVICE_EXTENSION ) KeyFilterDevice->DeviceExtension;
  KeyDevice = KeyExtension->TargetDevice;

  IoDetachDevice( KeyDevice );

  //
  // 如果还有 IRP 未完成,且当前 IRP 有效则尝试取消这个 IRP
  //
  if ( KeyExtension->IrpsInProgress > 0 && KeyDevice->CurrentIrp != NULL )
  {
    if ( CancelKeyboardIrp( KeyDevice->CurrentIrp ) )
    {
      //
      // 成功则直接退出删除键盘过滤设备
      //
      DbgPrint( "CancelKeyboardIrp() is ok\n" );
      goto __End;
    }
  }

  //
  // 如果取消失败,则一直等待按键
  //
  while ( KeyExtension->IrpsInProgress > 0 )
  {
    DbgPrint( "Irp Count:%d\n", KeyExtension->IrpsInProgress );
  }

  __End:
  IoDeleteDevice( KeyFilterDevice );

  return ;
}

/////////////////////////////////////////////////////////////////
// 函数类型 : 自定义工具函数
// 函数模块 : 键盘过滤模块
/////////////////////////////////////////////////////////////////
// 功能 : 取消 IRP 操作
// 注意 : 这个函数仅是为配合在 UNLOAD 例程使用,其他例程中不能
//        使用此方法来取消 IRP
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2007.02.20
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
/////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////

BOOLEAN
CancelKeyboardIrp( IN PIRP Irp )
{
  if ( Irp == NULL )
  {
    DbgPrint( "CancelKeyboardIrp: Irp error\n" );
    return FALSE;
  }


  //
  // 这里有些判断应该不是必须的,比如对 CancelRoutine 字段,
  // 因为 IoCancelIrp() 函数中有判断了。但只有偏执狂才能生存 :)。
  // 小波说 低智、偏执、思想贫乏是最不可容忍的。我这一行代码就占
  // 了两条 :D,不知 xiaonvwu 看过后会作何感想?:DDD
  //

  //
  // 如果正在取消或没有取消例程则直接返回 FALSE
  //
  if ( Irp->Cancel || Irp->CancelRoutine == NULL )
  {
    DbgPrint( "Can't Cancel the irp\n" );
    return FALSE;
  }

  if ( FALSE == IoCancelIrp( Irp ) )
  {
    DbgPrint( "IoCancelIrp() to failed\n" );
    return FALSE;
  }

  //
  // 取消后重设此例程为空
  //
  IoSetCancelRoutine( Irp, NULL );

  return TRUE;
}

/////////////////////////////////////////////////////////////////
// 函数类型 : 自定义工具函数
// 函数模块 : 设备栈信息模块
////////////////////////////////////////////////////////////////
// 功能 : 遍历 DEVICE_OBJECT 中 AttachedDevice 域,找到 USB 键盘
//        设备上名为 kbdhid 的过滤驱动(Upper Filter Driver)
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.06.02
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
/////////////////////////////////////////////////////////////////
// 修改者 : sinister
// 修改日期 : 2007.2.12
// 修改内容 : 为匹配 USB 键盘驱动做了相应的修改
/////////////////////////////////////////////////////////////////

BOOLEAN
GetAttachedDeviceInfo( IN PDEVICE_OBJECT DevObj )
{
  PDEVICE_OBJECT DeviceObject;
  BOOLEAN bFound = FALSE;

  if ( DevObj == NULL )
  {
    DbgPrint( "DevObj is NULL!\n" );
    return FALSE;
  }

  DeviceObject = DevObj->AttachedDevice;

  while ( DeviceObject )
  {
    //
    // 一些 OBJECT 的名称都存在分页区,虽然大部分时候不会被交换出去,但
    // 有一次足够了。这算是经验之谈
    //
    if ( MmIsAddressValid( DeviceObject->DriverObject->DriverName.Buffer ) )
    {
      DbgPrint( "Attached Driver Name:%S,Attached Driver Address:0x%x,Attached DeviceAddress:0x%x\n",
                DeviceObject->DriverObject->DriverName.Buffer,
                DeviceObject->DriverObject,
                DeviceObject );

      //
      // 找到 USB 键盘驱动的 kbdhid 设备了么?找到了就不继续了
      //
      if ( _wcsnicmp( DeviceObject->DriverObject->DriverName.Buffer,
                      KDBDEVICENAME,
                      wcslen( KDBDEVICENAME ) ) == 0 )
      {
        DbgPrint( "Found kbdhid Device\n" );
        bFound = TRUE;
        break;
      }
    }

    DeviceObject = DeviceObject->AttachedDevice;
  }

  return bFound;
}

/////////////////////////////////////////////////////////////////
// 函数类型 : 自定义工具函数
// 函数模块 : 设备栈信息模块
/////////////////////////////////////////////////////////////////
// 功能 : 从 DEVICE_OBJECT 中得到设备与驱动名称并打印地址
// 注意 : 函数功能只是打印信息,不同环境使用中应该会做修改
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2006.05.02
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
/////////////////////////////////////////////////////////////////
// 修改者 : sinister
// 修改日期 : 2007.2.12
// 修改内容 : 打印出 USB 键盘驱动的设备名称,仅作调试使用
/////////////////////////////////////////////////////////////////

VOID
GetDeviceObjectInfo( IN PDEVICE_OBJECT DevObj )
{
  POBJECT_HEADER ObjectHeader;
  POBJECT_HEADER_NAME_INFO ObjectNameInfo;

  if ( DevObj == NULL )
  {
    DbgPrint( "DevObj is NULL!\n" );
    return;
  }

  //
  // 得到对象头
  //
  ObjectHeader = OBJECT_TO_OBJECT_HEADER( DevObj );

  if ( ObjectHeader )
  {
    //
    // 查询设备名称并打印
    //
    ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );

    if ( ObjectNameInfo && ObjectNameInfo->Name.Buffer )
    {
      DbgPrint( "Device Name:%S - Device Address:0x%x\n",
                ObjectNameInfo->Name.Buffer,
                DevObj );

      //
      // 复制 USB 键盘设备名到一个全局 BUFFER 里,为调试时显示
      // 用,没有实际的功能用途
      //
      RtlZeroMemory( szUsbDeviceName, sizeof( szUsbDeviceName ) );

      wcsncpy( szUsbDeviceName,
               ObjectNameInfo->Name.Buffer,
               ObjectNameInfo->Name.Length / sizeof( WCHAR ) );
    }

    //
    // 对于没有名称的设备,则打印 NULL
    //
    else if ( DevObj->DriverObject )
    {
      DbgPrint( "Driver Name:%S - Device Name:%S - Driver Address:0x%x - Device Address:0x%x\n",
                DevObj->DriverObject->DriverName.Buffer,
                L"NULL",
                DevObj->DriverObject,
                DevObj );
    }
  }
}

/////////////////////////////////////////////////////////////////
// 函数类型 : 自定义工具函数
// 函数模块 : 键盘过滤模块
/////////////////////////////////////////////////////////////////
// 功能 : 得到 USB 驱动 hidusb 的驱动对象,并遍历以上所有设备
//        对象,过滤出 USB 键盘设备,将其设备对象返回
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2007.02.13
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
/////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////

NTSTATUS
GetUsbKeybordDevice( OUT PDEVICE_OBJECT* UsbDeviceObject )
{
  UNICODE_STRING DriverName;
  PDRIVER_OBJECT DriverObject = NULL;
  PDEVICE_OBJECT DeviceObject = NULL;
  BOOLEAN bFound = FALSE;

  RtlInitUnicodeString( &DriverName, USBKEYBOARDNAME );

  ObReferenceObjectByName( &DriverName,
                           OBJ_CASE_INSENSITIVE,
            &bsp;              NULL,
                           0,
                           ( POBJECT_TYPE ) IoDriverObjectType,
                           KernelMode,
                           NULL,
                           &DriverObject );

  if ( DriverObject == NULL )
  {
    DbgPrint( "Not found USB Keyboard Device hidusb!\n" );
    return STATUS_UNSUCCESSFUL;
  }

  DeviceObject = DriverObject->DeviceObject;

  while ( DeviceObject )
  {
    GetDeviceObjectInfo( DeviceObject );

    if ( DeviceObject->AttachedDevice )
    {
      //
      // 查找 USB 键盘设备
      //
      if ( GetAttachedDeviceInfo( DeviceObject ) )
      {
        bFound = TRUE;
        goto __End;
      }
    }

    DeviceObject = DeviceObject->NextDevice;
  }

  __End:

  if ( bFound )
  {
    //
    // 找到则返回 USB 键盘设备对象
    //
    *UsbDeviceObject = DeviceObject;
  }
  else
  {
    *UsbDeviceObject = NULL;
  }

  return STATUS_SUCCESS;
}

/////////////////////////////////////////////////////////////////
// 函数类型 : 自定义工具函数
// 函数模块 : 键盘过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 创建过滤设备将其附加到需要跟踪的设备上,保存设备相关
//        信息,返回附加后的驱动对象
// 注意 : 此函数仅挂接 USB 键盘设备
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////

NTSTATUS
AttachUSBKeyboardDevice( IN PDEVICE_OBJECT UsbDeviceObject,
                         IN PDRIVER_OBJECT  DriverObject )
{
  PDEVICE_OBJECT DeviceObject;
  PDEVICE_OBJECT TargetDevice;
  PDEVICE_EXTENSION DevExt;
  NTSTATUS ntStatus;

  //
  // 创建过滤设备对象
  //
  ntStatus = IoCreateDevice( DriverObject,
                             sizeof( DEVICE_EXTENSION ),
                             NULL,
                             FILE_DEVICE_UNKNOWN,
                             0,
                             FALSE,
                             &DeviceObject );

  if ( !NT_SUCCESS( ntStatus ) )
  {
    DbgPrint( "IoCreateDevice() 0x%x!\n", ntStatus );
    return ntStatus;
  }

  DevExt = ( PDEVICE_EXTENSION ) DeviceObject->DeviceExtension;

  //
  // 初始化自旋锁
  //
  KeInitializeSpinLock( &DevExt->SpinLock );

  //
  // 初始化 IRP 计数器
  //
  DevExt->IrpsInProgress = 0;

  //
  // 将过滤设备对象附加在目标设备对象之上,并返回附加后的原设备对象
  //

  TargetDevice = IoAttachDeviceToDeviceStack( DeviceObject, UsbDeviceObject );
  if ( !TargetDevice )
  {
    IoDeleteDevice( DeviceObject );
    DbgPrint( "IoAttachDeviceToDeviceStack() 0x%x!\n", ntStatus );
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  //
  // 保存过滤设备信息
  //
  DevExt->DeviceObject = DeviceObject;
  DevExt->TargetDevice = TargetDevice;

  //
  // 设置过滤设备相关信息与标志
  //
  DeviceObject->Flags |= ( DO_BUFFERED_IO | DO_POWER_PAGABLE );
  DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;


  return STATUS_SUCCESS;
}

/////////////////////////////////////////////////////////////////
// 函数类型 : 自定义工具函数
// 函数模块 : 键盘过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 创建过滤设备将其附加到需要跟踪的设备上,保存设备相关
//        信息,返回附加后的驱动对象
// 注意 : 此函数仅挂接 PS/2 键盘设备
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2005.12.27
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////

NTSTATUS
AttachPS2KeyboardDevice( IN UNICODE_STRING* DeviceName, // 需要跟踪的设备名
                         IN PDRIVER_OBJECT  DriverObject, // 过滤驱动也就是本驱动的驱动对象
                         OUT PDRIVER_OBJECT* FilterDriverObject ) // 返回附加后的驱动对象
{
  PDEVICE_OBJECT DeviceObject;
  PDEVICE_OBJECT FilterDeviceObject;
  PDEVICE_OBJECT TargetDevice;
  PFILE_OBJECT FileObject;
  PDEVICE_EXTENSION DevExt;

  NTSTATUS ntStatus;

  //
  // 根据设备名称找到需要附加的设备对象
  //
  ntStatus = IoGetDeviceObjectPointer( DeviceName,
    nbsp;                                  FILE_ALL_ACCESS,
                                       &FileObject,
                                       &DeviceObject );

  if ( !NT_SUCCESS( ntStatus ) )
  {
    DbgPrint( "IoGetDeviceObjectPointer() 0x%x\n", ntStatus );
    return ntStatus;
  }

  //
  // 创建过滤设备对象
  //
  ntStatus = IoCreateDevice( DriverObject,
                             sizeof( DEVICE_EXTENSION ),
                             NULL,
                             FILE_DEVICE_KEYBOARD,
                             0,
                             FALSE,
                             &FilterDeviceObject );

  if ( !NT_SUCCESS( ntStatus ) )
  {
    ObDereferenceObject( FileObject );
    DbgPrint( "IoCreateDevice() 0x%x!\n", ntStatus );
    return ntStatus;
  }

  //
  // 得到设备扩展结构,以便下面保存过滤设备信息
  //
  DevExt = ( PDEVICE_EXTENSION ) FilterDeviceObject->DeviceExtension;


  //
  // 初始化自旋锁
  //
  KeInitializeSpinLock( &DevExt->SpinLock );

  //
  // 初始化 IRP 计数器
  //
  DevExt->IrpsInProgress = 0;

  //
  // 将过滤设备对象附加在目标设备对象之上,并返回附加后的原设备对象
  //
  TargetDevice = IoAttachDeviceToDeviceStack( FilterDeviceObject,
                                              DeviceObject );
  if ( !TargetDevice )
  {
    ObDereferenceObject( FileObject );
    IoDeleteDevice( FilterDeviceObject );
    DbgPrint( "IoAttachDeviceToDeviceStack() 0x%x!\n", ntStatus );
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  //
  // 保存过滤设备信息
  //
  DevExt->DeviceObject = FilterDeviceObject;
  DevExt->TargetDevice = TargetDevice;
  DevExt->pFilterFileObject = FileObject;

  //
  // 设置过滤设备相关信息与标志
  //
  FilterDeviceObject->DeviceType = TargetDevice->DeviceType;
  FilterDeviceObject->Characteristics = TargetDevice->Characteristics;
  FilterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  FilterDeviceObject->Flags |= ( TargetDevice->Flags & ( DO_DIRECT_IO |
                                                         DO_BUFFERED_IO ) );

  //
  // 返回附加后的驱动对象
  //
  *FilterDriverObject = TargetDevice->DriverObject;

  ObDereferenceObject( FileObject );

  return STATUS_SUCCESS;
}

/////////////////////////////////////////////////////////////////
// 函数类型 : 自定义工具函数
// 函数模块 : 键盘过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 键盘过滤驱动的 IRP_MJ_READ 派遣例程,所有按键将触发
//        这个 IRP 的完成
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2007.2.15
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历   史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////

NTSTATUS
KeyReadPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
  NTSTATUS status;
  KIRQL IrqLevel;

  PDEVICE_OBJECT pDeviceObject;
  PDEVICE_EXTENSION KeyExtension = ( PDEVICE_EXTENSION )
                                   DeviceObject->DeviceExtension;


  IoCopyCurrentIrpStackLocationToNext( Irp );

  //
  // 将 IRP 计数器加一,为支持 SMP 使用自旋锁
  //
  KeAcquireSpinLock( &KeyExtension->SpinLock, &IrqLevel );
  InterlockedIncrement( &KeyExtension->IrpsInProgress );
  KeReleaseSpinLock( &KeyExtension->SpinLock, IrqLevel );

  IoSetCompletionRoutine( Irp,
                          KeyReadCompletion,
                          DeviceObject,
                          TRUE,
                          TRUE,
                          TRUE );

  return IoCallDriver( KeyExtension->TargetDevice, Irp );
}

/////////////////////////////////////////////////////////////////
// 函数类型 :系统回调函数
// 函数模块 : 键盘过滤模块
////////////////////////////////////////////////////////////////
// 功能 : 获得键盘按键,用无效扫描码替换,以达到屏蔽键盘的目的
// 注意 :
/////////////////////////////////////////////////////////////////
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2007.2.12
/////////////////////////////////////////////////////////////////
// 重   大   修   改   历 &nbs; 史
////////////////////////////////////////////////////////////////
// 修改者 :
// 修改日期 :
// 修改内容 :
/////////////////////////////////////////////////////////////////

NTSTATUS
KeyReadCompletion( IN PDEVICE_OBJECT DeviceObject,
                   IN PIRP Irp,
                   IN PVOID Context )
{
  PIO_STACK_LOCATION IrpSp;
  PKEYBOARD_INPUT_DATA KeyData;
  PDEVICE_EXTENSION KeyExtension = ( PDEVICE_EXTENSION )
                                   DeviceObject->DeviceExtension;
  int numKeys, i;
  KIRQL IrqLevel;

  IrpSp = IoGetCurrentIrpStackLocation( Irp );


  if ( Irp->IoStatus.Status != STATUS_SUCCESS )
  {
    DbgPrint( "ntStatus:0x%x", Irp->IoStatus.Status );
    goto __RoutineEnd;
  }

  //
  // 系统在 SystemBuffer 中保存按键信息
  //
  KeyData = Irp->AssociatedIrp.SystemBuffer;
  if ( KeyData == NULL )
  {
    DbgPrint( "KeyData is NULL\n" );
    goto __RoutineEnd;
  }

  //
  // 得到按键数
  //
  numKeys = Irp->IoStatus.Information / sizeof( KEYBOARD_INPUT_DATA );
  if ( numKeys < 0 )
  {
    DbgPrint( "numKeys less zero\n" );
    goto __RoutineEnd;
  }

  //
  // 使用 0 无效扫描码替换,屏蔽所有按键
  //
  for ( i = 0; i < numKeys; i++ )
  {
    DbgPrint( "KeyDwon: 0x%x\n", KeyData[i].MakeCode );
    KeyData[i].MakeCode = 0x00;
  }


  __RoutineEnd :

  if ( Irp->PendingReturned )
  {
    IoMarkIrpPending( Irp );
  }

  //
  // 将 IRP 计数器减一,为支持 SMP 使用自旋锁
  //
  KeAcquireSpinLock( &KeyExtension->SpinLock, &IrqLevel );
  InterlockedDecrement( &KeyExtension->IrpsInProgress );
  KeReleaseSpinLock( &KeyExtension->SpinLock, IrqLevel );

  return Irp->IoStatus.Status ;
}


/*****************************************************************
 文件名        : WssLockKey.h
 描述          : 键盘过滤驱动
 作者          : sinister
 最后修改日期  : 2007-02-26
*****************************************************************/

#ifndef __WSS_LOCKKEY_H_
#define __WSS_LOCKKEY_H_

#include "ntddk.h"
#include "ntddkbd.h"
#include "string.h"
#include

#define MAXLEN 256

#define KDBDEVICENAME L"\\Driver\\kbdhid"
#define USBKEYBOARDNAME L"\\Driver\\hidusb"
#define PS2KEYBOARDNAME L"\\Device\\KeyboardClass0"

typedef struct _OBJECT_CREATE_INFORMATION
{
    ULONG Attributes;
    HANDLE RootDirectory;
    PVOID ParseContext;
    KPROCESSOR_MODE ProbeMode;
    ULONG PagedPoolCharge;
    ULONG NonPagedPoolCharge;
    ULONG SecurityDescriptorCharge;
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    PSECURITY_QUALITY_OF_SERVICE SecurityQos;
    SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
} OBJECT_CREATE_INFORMATION, * POBJECT_CREATE_INFORMATION;

typedef struct _OBJECT_HEADER
{
    LONG PointerCount;
    union
    {
        LONG HandleCount;
        PSINGLE_LIST_ENTRY SEntry;
    };
    POBJECT_TYPE Type;
    UCHAR NameInfoOffset;
    UCHAR HandleInfoOffset;
    UCHAR QuotaInfoOffset;
    UCHAR Flags;
    union
    {
        POBJECT_CREATE_INFORMATION ObjectCreateInfo;
        PVOID QuotaBlockCharged;
    };

    PSECURITY_DESCRIPTOR SecurityDescriptor;
    QUAD Body;
} OBJECT_HEADER, * POBJECT_HEADER;

#define NUMBER_HASH_BUCKETS 37

typedef struct _OBJECT_DIRECTORY
{
    struct _OBJECT_DIRECTORY_ENTRY* HashBuckets[NUMBER_HASH_BUCKETS];
    struct _OBJECT_DIRECTORY_ENTRY** LookupBucket;
    BOOLEAN LookupFound;
    USHORT SymbolicLinkUsageCount;
    struct _DEVICE_MAP* DeviceMap;
} OBJECT_DIRECTORY, * POBJECT_DIRECTORY;

typedef struct _OBJECT_HEADER_NAME_INFO
{
    POBJECT_DIRECTORY Directory;
    UNICODE_STRING Name;
    ULONG Reserved;
#if DBG
    ULONG Reserved2 ;
    LONG DbgDereferenceCount ;
#endif
} OBJECT_HEADER_NAME_INFO, * POBJECT_HEADER_NAME_INFO;

#define OBJECT_TO_OBJECT_HEADER( o ) \
    CONTAINING_RECORD( (o), OBJECT_HEADER, Body )

#define OBJECT_HEADER_TO_NAME_INFO( oh ) ((POBJECT_HEADER_NAME_INFO) \
    ((oh)->NameInfoOffset == 0 ? NULL : ((PCHAR)(oh) - (oh)->NameInfoOffset)))

typedef struct _DEVICE_EXTENSION
{
    PDEVICE_OBJECT DeviceObject;
    PDEVICE_OBJECT TargetDevice;
    PFILE_OBJECT pFilterFileObject;
    ULONG DeviceExtensionFlags;
    LONG IrpsInProgress;
    KSPIN_LOCK SpinLock;
}DEVICE_EXTENSION, * PDEVICE_EXTENSION;


VOID
KeyDriverUnload( PDRIVER_OBJECT KeyDriver );

BOOLEAN
CancelKeyboardIrp( IN PIRP Irp );

extern POBJECT_TYPE* IoDriverObjectType;

NTSYSAPI
NTSTATUS
NTAPI ObReferenceObjectByName( IN PUNICODE_STRING ObjectName,
                               IN ULONG Attributes,
                               IN PACCESS_STATE AccessState OPTIONAL,
                               IN ACCESS_MASK DesiredAccess OPTIONAL,
                               IN POBJECT_TYPE ObjectType,
                               IN KPROCESSOR_MODE AccessMode,
            &nsp;                  IN OUT PVOID ParseContext OPTIONAL,
                               OUT PVOID* Object );

NTSTATUS
GetUsbKeybordDevice( OUT PDEVICE_OBJECT* UsbDeviceObject );

BOOLEAN
GetAttachedDeviceInfo( IN PDEVICE_OBJECT DevObj );

VOID
GetDeviceObjectInfo( IN PDEVICE_OBJECT DevObj );

NTSTATUS
AttachUSBKeyboardDevice( IN PDEVICE_OBJECT UsbDeviceObject,
                                  IN PDRIVER_OBJECT  DriverObject );

NTSTATUS
AttachPS2KeyboardDevice( IN UNICODE_STRING* DeviceName,
                                  IN PDRIVER_OBJECT  DriverObject,
                                  OUT PDRIVER_OBJECT* FilterDriverObject );

NTSTATUS
KeyReadCompletion( IN PDEVICE_OBJECT DeviceObject,
                            IN PIRP Irp,
                            IN PVOID Context );
NTSTATUS
KeyReadPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

WCHAR szUsbDeviceName[MAXLEN];

#endif


 


WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
WSS 主页:http://www.whitecell.org/
WSS 论坛:http://www.whitecell.org/forums/

- 作者: beiyu 2007年04月6日, 星期五 13:37  回复(0) |  引用(0) 加入博采

Pinczakko的AwardBIOS逆向工程指导-part5[翻译]
d.  下一步,original.tmp(post执行期间)中的POST_8S负责准备为解压缩必须的签名,如下面你所看到的:
________________________________________
E000:17B8                         POST_8S proc near
.........
E000:183F BE 00 00                  mov   si, 0
E000:1842 8E DE                     mov   ds, si
E000:1844                           assume ds:nothing
E000:1844 BE 00 70                  mov   si, 7000h
E000:1847 8B 44 04                  mov   ax, [si+4]          ; ax = FFFFh (0000:7004h filled before by Decompress_System_BIOS
E000:1847                                                     ; during bootblock_in_RAM execution)
E000:184A BF 00 00                  mov   di, 0
E000:184D 8E C7                     mov   es, di
E000:184F                           assume es:nothing
E000:184F BF 00 60                  mov   di, 6000h
E000:1852 26 89 45 04               mov   es:[di+4], ax       ; [0000:6004] = FFFFh --> signature to do LZH decompression
E000:1852                                                     ; for extension components
E000:1856 3D FF FF                  cmp   ax, 0FFFFh
E000:1859 74 10                     jz    short signature_ok
E000:185B 8B 04                     mov   ax, [si]
E000:185D 26 89 45 04               mov   es:[di+4], ax
E000:1861 8B 44 02                  mov   ax, [si+2]
E000:1864 C1 E8 0C                  shr   ax, 0Ch
E000:1867 26 89 45 06               mov   es:[di+6], ax
E000:186B                         signature_ok:               ; CODE XREF: POST_8S+A1
E000:186B E8 A2 6C         &bsp;        call  _init_Pwr_Mgmt_ctlr
E000:186E F8                        clc
E000:186F C3                        retn
E000:186F                         POST_8S endp
________________________________________
e.  下一步,例程init_nnoprom_rosupd(这只是一个例子,其他部分可能会不同)解压缩nnoprom.bin和rosupd.bin,如下面代码:
________________________________________
E000:71C1                         init_nnoprom_rosupd proc near ; CODE XREF: POST_11S
.........
E000:71CF BF A0 00                  mov   di, 0A0h ; 'a'      ; nnoprom.bin index
E000:71CF                                                     ; nnoprom.bin-->4027h; A0h = 4h*(lo_byte(4027h)+1h)
E000:71D2 E8 74 FC                  call  near ptr decompress_BIOS_component ; decompress NNOPROM.BIN
E000:71D5 0F 82 ED 00               jb    decompression_error
E000:71D9 68 00 40                  push  4000h
E000:71DC 1F                        pop   ds                  ; ds = 4000h; decompression result seg
E000:71DD                           assume ds:nothing
E000:71DD 33 F6                     xor   si, si
E000:71DF 68 00 70                  push  7000h
E000:71E2 07                        pop   es                  ; es = 7000h
E000:71E3                           assume es:nothing
E000:71E3 33 FF                     xor   di, di
E000:71E5 B9 00 40                  mov   cx, 4000h
E000:71E8 FC                        cld
E000:71E9 F3 66 A5                  rep movsd                 ; copy nnoprom decompression result from
E000:71E9                                                     ; seg 4000h to seg 7000h
E000:71EC BF 03 00                  mov   di, 3
E000:71EF 66 26 81 3D 24 4E 4E 4F   cmp   dword ptr es:[di], 'ONN$' ; match (decompressed) nnoprom.bin signature
E000:71F7 0F 85 CB 00               jnz   decompression_error
E000:71FB 68 F8 9F                  push  9FF8h
E000:71FE 07                        pop   es                  ; es = 9FF8h
E000:71FF                           assume es:nothing
E000:71FF 33 FF                     xor   di, di
E000:7201 B9 68 00                  mov   cx, 68h ; 'h'
E000:7204 32 C0                     xor   al, al
E000:7206 F3 AA                     rep stosb
E000:7208 BF A4 00                  mov   di, 0A4h ; 'a'      ; ROSUPD.bin index
E000:720B E8 3B FC                  call  near ptr decompress_BIOS_component ; decompress ROSUPD.bin
E000:720E 0F 82 B4 00               jb    decompression_error
E000:7212 1E                        push  ds
E000:7213 06                        push  es
E000:7214 0F A0                     push  fs
E000:7216 0F A8                     push  gs
E000:7218 9A DD 5F 00 F0            call  ds_es_fs_gs_flat_4GB
E000:721D 66 33 F6                  xor   esi, esi
E000:7220 8E DE                     mov   ds, si
E000:7222                           assume ds:nothing
E000:7222 8E C6                     mov   es, si
E000:722                           assume es:nothing
E000:7224 68 00 40                  push  4000h
E000:7227 5E                        pop   si
E000:7228 66 C1 E6 04               shl   esi, 4              ; esi = 4_0000h (decompressed ROSUPD.bin)
E000:722C 66 BF 00 00 10 00         mov   edi, 100000h
E000:7232 66 8B CB                  mov   ecx, ebx
E000:7235 66 C1 E9 02               shr   ecx, 2
E000:7239 FC                        cld
E000:723A F3 67 66 26 A5            rep movs dword ptr es:[edi], dword ptr es:[esi] ; copy decmprssd ROSUPD.BIN to 1MB
E000:723F 0F A9                     pop   gs
E000:7241 0F A1                     pop   fs
E000:7243 07                        pop   es
E000:7244                           assume es:nothing
E000:7244 1F                        pop   ds
E000:7245                           assume ds:nothing
E000:7245 68 F8 9F                  push  9FF8h
E000:7248 07                        pop   es
E000:7249                           assume es:nothing
E000:7249 66 26 C7 06 00 00 00 00+  mov   dword ptr es:0, 100000h
E000:7253 66 26 C7 06 04 00 00 00+  mov   dword ptr es:4, 40000h
E000:725D 66 33 C0                  xor   eax, eax
E000:7260 B8 00 E0                  mov   ax, 0E000h
E000:7263 66 C1 E0 04               shl   eax, 4
E000:7267 66 05 56 71 00 00         add   eax, 7156h
E000:726D 66 26 A3 08 00            mov   es:8, eax
E000:7272 B8 07 00                  mov   ax, 7
E000:7275 26 A3 0C 00               mov   es:0Ch, ax
E000:7279 B8 00 70                  mov   ax, 7000h
E000:727C 26 A3 0E 00               mov   es:0Eh, ax
E000:7280 66 33 C0                  xor   eax, eax
E000:7283 B8 00 E0                  mov   ax, 0E000h
E000:7286 66 C1 E0 04               shl   eax, 4
E000:728A 66 05 AA 71 00 00         add   eax, 71AAh
E000:7290 66 26 A3 10 00            mov   es:10h, eax
E000:7295 66 BE 80 FF 09 00         mov   esi, 9FF80h
E000:729B 66 81 C6 00 00 00 00      add   esi, 0
E000:72A2 B0 36                     mov   al, 36h ; '6'
E000:72A4 0E                        push  cs
E000:72A5 68 B0 72                  push  72B0h
E000:72A8 68 FD E4                  push  0E4FDh              ; read CMOS byte
E000:72AB EA 88 61 00 E0            jmp   far ptr Fseg_vector
E000:72B0                         ; ---------------------------------------------------------------------------
E000:72B0 8A D8                     mov   bl, al
E000:72B2 B8 00 00                  mov   ax, 0
E000:72B5 E8 41 FE                  call  near ptr call_nnoprom_at_7000h ; execute decompressed nnoprom.bin
E000:72B8 9C                        pushf
E000:72B9 9D                        popf
E000:72BA 72 0A                     jb    short decompression_error
E000:72BC B8 00 00                  mov   ax, 0
E000:72BF 8E D8                     mov   ds, ax
E000:72C1                           assume ds:nothing
E000:72C1 80 0E B7 04 03            or    ds:byte_0_4B7, 3
E000:72C6                 &nbs;       decompression_error:        ; CODE XREF: init_nnoprom_rosupd+14
E000:72C6                                                     ; init_nnoprom_rosupd+36 ...
E000:72C6 66 61                     popad
E000:72C8 07                        pop   es
E000:72C9                           assume es:nothing
E000:72C9 1F                        pop   ds
E000:72CA                           assume ds:nothing
E000:72CA C3                        retn
E000:72CA                         init_nnoprom_rosupd endp ; sp =  2
________________________________________
E000:6E49                         -- decompress_BIOS_component --
E000:6E49                         in: di = index to compressed component (as written at 0000:6XXXh)
E000:6E49                         ; --------------- S U B R O U T I N E ---------------------------------------
E000:6E49                         decompress_BIOS_component proc far
E000:6E49                                                     ; CODE XREF: EPA_Procedure+43
E000:6E49                                                     ; EPA_Procedure+5E ...
E000:6E49 1E                        push  ds
E000:6E4A 06                        push  es
E000:6E4B 55                        push  bp
E000:6E4C 57                        push  di
E000:6E4D 56                        push  si
E000:6E4E 81 E7 FF 3F               and   di, 3FFFh           ; clear di's MSB
E000:6E52 FA                        cli
E000:6E53 B0 FF                     mov   al, 0FFh            ; enable cache
E000:6E55 E8 14 FE                  call  F0_init_cpu_cache
E000:6E58 68 00 E0                  push  0E000h
E000:6E5B 68 69 6E                  push  6E69h
E000:6E5E 68 31 EC                  push  0EC31h
E000:6E61 68 D4 E3                  push  0E3D4h              ; mod_A20_access_mode
E000:6E64 EA 30 EC 00 F0            jmp   far ptr F000_Vector
E000:6E69                         ; ---------------------------------------------------------------------------
E000:6E69 E8 2F 7D                  call  ds_ss_Enter_Voodoo_Mode
E000:6E6C 8C D8                     mov   ax, ds
E000:6E6E 8E C0                     mov   es, ax              ; es = voodoo mode, base at 0000_0000h
E000:6E70                           assume es:nothing
E000:6E70 E8 45 7D                  call  ss_Leave_Voodoo_mode
E000:6E73 5A                        pop   dx                  ; dx = si
E000:6E74 58                        pop   ax                  ; ax = di --> compressed component index
E000:6E75 26 66 8B 9D 00 60         mov   ebx, es:[di+6000h]  ; ebx = compressed component physical addr ((seg>>0xC)+offset)
E000:6E7B 66 0B DB                  or    ebx, ebx            ; is compressd component exist?
E000:6E7E 0F 84 2E 01               jz    no_cmprssd_component
E000:6E82 83 FB FF  nbsp;               cmp   bx, 0FFFFh
E000:6E85 0F 84 27 01               jz    no_cmprssd_component
E000:6E89 F6 C4 40                  test  ah, 40h
E000:6E8C 74 04                     jz    short exec_decompress ; for nnoprom.bin, jmp taken
E000:6E8E F8                        clc
E000:6E8F E9 1F 01                  jmp   decomprss_BIOS_componnt_ret
E000:6E92                         ; ---------------------------------------------------------------------------
E000:6E92                         exec_decompress:            ; CODE XREF: decompress_BIOS_component+43
E000:6E92 26 8B 3E 00 60            mov   di, es:6000h        ; di = Decompression_Ngine offset addr
E000:6E97 67 66 8B 35 00 00 16 00   mov   esi, ds:160000h     ; mov esi,[awardext.rom 4Byte hdr]
E000:6E9F 66 F7 D6                  not   esi
E000:6EA2 67 66 89 35 00 00 08 00   mov   ds:80000h, esi      ; modify ds:80000h value; restored below
E000:6EAA 66 81 FB 00 00 10 00      cmp   ebx, 100000h        ; compressed_component_phy_addr > 1MB ?
E000:6EB1 72 57                     jb    short above_1MB     ; for nnoprom.bin, jmp _not_ taken
E000:6EB3 57                        push  di                  ; save Decompression_Ngine offset
E000:6EB4 66 BE 00 00 09 00         mov   esi, 90000h
E000:6EBA 66 BF 00 00 14 00         mov   edi, 140000h
E000:6EC0 66 B9 00 40 00 00         mov   ecx, 4000h          ; copy one segment
E000:6EC6 FC                        cld
E000:6EC7 67 F3 66 A5               rep movs dword ptr es:[edi], dword ptr [esi]
E000:6ECB 66 BE 00 00 16 00         mov   esi, 160000h
E000:6ED1 66 BF 00 00 08 00         mov   edi, 80000h
E000:6ED7 66 B9 00 80 00 00         mov   ecx, 8000h          ; 2 segment (128KB)
E000:6EDD FC                        cld
E000:6EDE 67 F3 66 A5               rep movs dword ptr es:[edi], dword ptr [esi] ; copy 2 segment (128KB) from 16_0000h to 8_0000h
E000:6EDE                                                     ; for decompression purposes
E000:6EE2 5F                        pop   di
E000:6EE3 66 C1 CB 10               ror   ebx, 10h
E000:6EE7 8E C3                     mov   es, bx              ; es = HI_WORD(phy addr of compressed component)
E000:6EE9 66 C1 CB 10               ror   ebx, 10h            ; restore ebx
E000:6EED 26 8B 4F 11               mov   cx, es:[bx+11h]     ; cx = decompression segment address.
E000:6EED                                                     ; The component will be decompressed into this segment address
E000:6EF1 51                        push  cx                  ; push decompression segment addr
E000:6EF2 26 FF 37                  push  word ptr es:[bx]    ; push (LZH hdr len and LZH hdr chksum)
E000:6EF5 F6 C4 80                  test  ah, 80h
E000:6EF8 74 36                     jz    short decompress    ; all extension BIOS component-->jmp taken
E000:6EFA 26 89 57 11               mov   es:[bx+11h], dx
E000:6EFE 02 CD                     add   cl, ch
E000:6F00 02 D6                     add   dl, dh
E000:6F02 2A CE                     sub   cl, dh
E000:6F04 26 28 4F 01               sub   es:[bx+1], cl
E000:6F08 EB 26                     jmp   short decompress
E000:6F0A                         ; --------------------------------------------------------------------------
E000:6F0A                         above_1MB:                  ; CODE XREF: decompress_BIOS_component+68
E000:6F0A 66 81 C3 00 00 0E 00      add   ebx, 0E0000h
E000:6F11 26 67 8B 4B 11            mov   cx, es:[ebx+11h]    ; cx = target segment addr (the component will be
E000:6F11                                                     ; decompressed into this segmnt)
E000:6F16 51                        push  cx
E000:6F17 26 67 FF 33               push  word ptr es:[ebx]
E000:6F1B F6 C4 80                  test  ah, 80h
E000:6F1E 74 10                     jz    short decompress
E000:6F20 26 67 89 53 11            mov   es:[ebx+11h], dx
E000:6F25 02 CD                     add   cl, ch
E000:6F27 02 D6                     add   dl, dh
E000:6F29 2A CE                     sub   cl, dh
E000:6F2B 26 67 28 4B 01            sub   es:[ebx+1], cl
E000:6F30                         decompress:                 ; CODE XREF: decompress_BIOS_component+AF
E000:6F30                                                     ; decompress_BIOS_component+BF ...
E000:6F30 66 C1 CB 10               ror   ebx, 10h
E000:6F34 8E C3                     mov   es, bx              ; es = phy_addr>>0xC (hi_word of phy addr)
E000:6F36 66 C1 CB 10               ror   ebx, 10h            ; bx = compressed component offset
E000:6F3A 0E                        push  cs
E000:6F3B 68 49 6F                  push  6F49h               ; ret addr below
E000:6F3E 68 FF DF                  push  0DFFFh
E000:6F41 BA 00 30                  mov   dx, 3000h           ; scratch_pad_seg
E000:6F44 68 00 20                  push  2000h
E000:6F47 57                        push  di                  ; call Decompression_Ngine
E000:6F48 CB                        retf                      
E000:6F49                         ; ---------------------------------------------------------------------------
E000:6F49 68 00 E0                  push  0E000h
E000:6F4C 68 5A 6F                  push  6F5Ah
E000:6F4F 68 31 EC                  push  0EC31h
E000:6F52 68 D4 E3                  push  0E3D4h              ; disable_A20...
E000:6F55 EA 30 EC 00 F0            jmp   far ptr F000_Vector
E000:6F5A                         ; ---------------------------------------------------------------------------
E000:6F5A E8 3E 7C                  call  ds_ss_Enter_Voodoo_Mode
E000:6F5D 8C D8                     mov   ax, ds
E000:6F5F 8E C0                     mov   es, ax              ; es --> voodoo mode, base at 0000_0000h
E000:6F61 E8 54 7C                  call  ss_Leave_Voodoo_mode
E000:6F64 67 66 A1 00 00 08 00      mov   eax, ds:80000h
E000:6F6B 67 66 3B 05 00 00 16 00   cmp   eax, ds:160000h
E000:6F73 75 18                     jnz   short restore_header
E000:6F75 66 C1 CB 10               ror   ebx, 10h
E000:6F79 8E C3                     mov   es, bx
E000:6F7B 66 C1 CB 10               ror   ebx, 10h
E000:6F7F 26 8F 07                  pop   wor ptr es:[bx]
E000:6F82 26 8F 47 11               pop   word ptr es:[bx+11h]
E000:6F86 26 66 8B 5F 0B            mov   ebx, es:[bx+0Bh]
E000:6F8B EB 0F                     jmp   short disable_A20
E000:6F8D                         ; ---------------------------------------------------------------------------
E000:6F8D                         restore_header:             ; CODE XREF: decompress_BIOS_component+12A
E000:6F8D 26 67 8F 03               pop   word ptr es:[ebx]
E000:6F91 26 67 8F 43 11            pop   word ptr es:[ebx+11h]
E000:6F96 26 67 66 8B 5B 0B         mov   ebx, es:[ebx+0Bh]
E000:6F9C                         disable_A20:                ; CODE XREF: decompress_BIOS_component+142
E000:6F9C 68 00 E0                  push  0E000h
E000:6F9F 68 AD 6F                  push  6FADh
E000:6FA2 68 31 EC                  push  0EC31h
E000:6FA5 68 24 E4                  push  0E424h              ; disable gate A20
E000:6FA8 EA 30 EC 00 F0            jmp   far ptr F000_Vector
E000:6FAD                         ; ---------------------------------------------------------------------------
E000:6FAD F8                        clc
E000:6FAE EB 01                     jmp   short decomprss_BIOS_componnt_ret
E000:6FB0                         ; ---------------------------------------------------------------------------
E000:6FB0                         no_cmprssd_component:       ; CODE XREF: decompress_BIOS_component+35
E000:6FB0                                                     ; decompress_BIOS_component+3C
E000:6FB0 F9                        stc
E000:6FB1                         decomprss_BIOS_componnt_ret:
E000:6FB1                                                     ; CODE XREF: decompress_BIOS_component+46
E000:6FB1                                                     ; decompress_BIOS_component+165
E000:6FB1 9C                        pushf
E000:6FB2 66 53                     push  ebx
E000:6FB4 68 00 E0                  push  0E000h
E000:6FB7 68 C5 6F                  push  6FC5h
E000:6FBA 68 31 EC                  push  0EC31h
E000:6FBD 68 D4 E3                  push  0E3D4h              ; enable gate A20
E000:6FC0 EA 30 EC 00 F0            jmp   far ptr F000_Vector
E000:6FC5                         ; ---------------------------------------------------------------------------
E000:6FC5 E8 D3 7B                  call  ds_ss_Enter_Voodoo_Mode
E000:6FC8 8C D8                     mov   ax, ds
E000:6FCA 8E C0                     mov   es, ax
E000:6FCC E8 E9 7B                  call  ss_Leave_Voodoo_mode
E000:6FCF 67 66 A1 00 00 08 00      mov   eax, ds:80000h
E000:6FD6 67 66 3B 05 00 00 16 00   cmp   eax, ds:160000h
E000:6FDE 75 2B                     jnz   short exit
E000:6FE0 66 BF 00 00 08 00         mov   edi, 80000h
E000:6FE6 66 B9 00 40 00 00         mov   ecx, 4000h
E000:6FEC 66 33 C0                  xor   eax, eax
E000:6FEF FC                        cld
E000:6FF0 67 F3 66 AB               rep stos dword ptr es:[edi]
E000:6FF4 66 BE 00 00 14 00         mov   esi, 140000h
E000:6FFA 66 BF 00 00 09 00         mov   edi, 90000h
E000:7000 66 B9 00 40 00 00         mov   ecx, 4000h
E000:7006 FC                        cld
E000:7007 67 F3 66 A5               rep movs dword ptr es:[edi], dword ptr [esi]
E000:700B                         exit:                       ; CODE XREF: decompress_BIOS_component+195
E000:700B 68 00 E0                  push  0E000h
E000:700E 68 1C 70                  push  701Ch
E000:7011 68 31 EC                  push  0EC31h
E000:7014 68 24 E4                  push  0E424h              ; turn off Gate A20
E000:7017 EA 30 EC 00 F0            jmp   far ptr F000_Vector
E000:701C                         ; ---------------------------------------------------------------------------
E000:701C 66 5B                     pop   ebx
E000:701E B0 00                     mov   al, 0               ; disable CPU cache
E000:7020 E8 49 FC                  call  F0_init_cpu_cache
E000:7023 9D                        popf
E000:7024 5D                        pop   bp
E000:7025 07                        pop   es
E000:7026 1F                        pop   ds
E000:7027 C3                        retn
E000:7027                         decompress_BIOS_component endp ; sp = -18h
其他部分的解压和处理与nnoprom.bin和rosupd.bin相似,如上。
通过上面的解释,我们只需要跟随“POST jump table execution”来知道在哪个环境下哪个“执行路径”被bios得到。做完了这个方法,我们就能够做我们喜欢做的hack award bios。不管怎样,我不准备在这里停止,下面的章节,我要给你呈现一些扩展部分的处理方法,他们很让我感兴趣。
7.2.7. Microcode Update Routine
微代码升级历程从POST_9S调用,如下所示:
________________________________________
E000:3BBE                         init_microcode proc near    ; CODE XREF: POST_9S+52
E000:3BBE E8 4E 38                  call  is_intel_CPU
E000:3BC1 75 5F                     jnz   short exit
E000:3BC3 66 B8 01 00 00 00         mov   eax, 1
E000:3BC9 0F A2                     cpuid
E000:3BCB BB 00 20                  mov   bx, 2000h
E000:3BCE 8E DB                     mov   ds, bx
E000:3BD0                           assume ds:_2000h
E000:3BD0 BB 00 90                  mov   bx, 9000h
E000:3BD3 3B 47 0C                  cmp   ax, [bx+0Ch]
E000:3BD6 75 05                     jnz   short decompress_microcode
E000:3BD8 E8 48 00                  call  get_cpu_microcode_ver
E000:3BDB 74 2C                     jz    short update_microcode
E000:3BDD                         decompress_microcode:       ; CODE XREF: init_microcode+18
E000:3BDD 66 50                     push  eax
E000:3BDF BF 08 00                  mov   di, 8               ; compressed microcode index (4*(lo_byte(4001h)+1))
E000:3BE2 E8 64 32                  call  near ptr decompress_BIOS_component
E000:3BE5 66 58                     pop   eax
E000:3BE7 72 39                     jb    short exit
E000:3BE9 66 C1 EB 0B               shr   ebx, 0Bh
E000:3BED 66 8B CB                  mov   ecx, ebx
E000:3BF0 BB 00 40                  mov   bx, 4000h
E000:3BF3 8E DB                     mov   ds, bx              ; point to seg 4000h (microcode decompression rsult)
E000:3BF5                           assum ds:nothing
E000:3BF5 33 DB                     xor   bx, bx              ; init bx
E000:3BF7                         next_microcode:             ; CODE XREF: init_microcode+47
E000:3BF7 3B 47 0C                  cmp   ax, [bx+0Ch]
E000:3BFA 75 05                     jnz   short microcode_not_match
E000:3BFC E8 24 00                  call  get_cpu_microcode_ver
E000:3BFF 74 08                     jz    short update_microcode
E000:3C01                         microcode_not_match:        ; CODE XREF: init_microcode+3C
E000:3C01 81 C3 00 08               add   bx, 800h            ; length of one microcode
E000:3C05 E2 F0                     loop  next_microcode
E000:3C07 EB 19                     jmp   short exit
E000:3C09                         ; ---------------------------------------------------------------------------
E000:3C09                         update_microcode:           ; CODE XREF: init_microcode+1D
E000:3C09                                                     ; init_microcode+41
E000:3C09 66 B9 79 00 00 00         mov   ecx, 79h ; 'y'
E000:3C0F 66 33 C0                  xor   eax, eax
E000:3C12 66 33 D2                  xor   edx, edx            ; microcode update sign
E000:3C15 8C D8                     mov   ax, ds
E000:3C17 66 C1 E0 04               shl   eax, 4
E000:3C1B 83 C3 30                  add   bx, 30h ; '0'
E000:3C1E 8B C3                     mov   ax, bx              ; eax = linear addr of the microcode
E000:3C20 0F 30                     wrmsr                     ; start microcode update
E000:3C22                         exit:                       ; CODE XREF: init_microcode+3
E000:3C22                                                     ; init_microcode+29 ...
E000:3C22 C3                        retn
E000:3C22                         init_microcode endp
8. 激昂展望
Hey, if you've read this article this far, you must be curious (^__^). Let's take a break a bit. I want to say some facts that are ridiculous. Well, at least to me. BIOS code is meant to be "twisted" so that code digger like us will find a hard time to figure it out. But, yeah here we are, understanding the big picture. Code digger rules my man! Nothing more dangerous than curiousity.
It's funny to see that the core LZH decompression routine that is used by award bioses (at least v4.51 that's dissected here) is just a complete "copy and paste" from Haruhiko Okumura's LZH code that anyone can find in the web. It's just the language that's different, Okumura's is in C while award's is in x86 assembly, the subroutines were exactly the same!
Another fact is, Phoenix code is very similar to award's code. I don't know who is "stealing" who, or perhaps there' s another source where both of them steal from (^__^). Oh no... I guess they are just doing reverse engineering like me with their tons of money. Unfortunately I don't have those tons of money he..he..he..
Well, let me stop ranting and continue my work on AMI BIOS. I guess we all waiting for it, right? It'll take sometime coz I'm very busy. If anyone of you who read this article have done it and had something to say or want to share your work with the world, I really keen to know. Why don't we join forces, right? my mail address is in the end of this article. I know some of us have done it.. we just haven't been in contact or perhaps it's better if we find our own way. Time will tell (-__-)
Greetz go to: Kris Kaspersky, Petr Soucek, Polaris, Havok, Zero, Mike Tedder a.k.a bpoint, apple_rom, Ilfak Guilfanov and many others who share their knowledge with the world.
9. 结束语
What I've explained above possibly far too premature to be ended here. But, I consider this article finished here as the Beta 5 version. If you follow this article from beginning to end, you'll be able to understand the "BIG Picture" of how the Award BIOS works. I think all of the issue dissected here is enough to do any type of modification you wish to do with award bios. If you find any mistake(s) within this article or have any suggestion, please contact me mamanzip@yahoo.com. Goodluck with your BIOS reverse engineering journey, I hope you enjoy it as much as I do (^__^) .

- 作者: beiyu 2007年04月5日, 星期四 10:53  回复(0) |  引用(0) 加入博采