HSQARKH 完整源码
这只是一个初步代码,用来实现ARK,做隐藏方面研究的.
本来打算等自己把所有自己知道的都尽量用上,再找时机发布,无奈最近平凡被各位大牛打击,实在在信心几近丧失殆尽. 暂时不想再搞这了,贻笑大方也罢,索性也把整个小工程源码给发出来, 也好让各位牛人说说我是否有再继续搞内核ROOTKIT研究的必要,是否够入门资格,代码风格是否规范(在现实世界里我从未接触过真正写程序的,我的身边都是搞医学的,真正的IT世界我丝毫不知,请勿见笑).

关于这个HSQInLineAPI.h里面的几个函数我时花了不少时间调试写出来的,如果有人不幸引用了鄙人的简陋代码,还望注明出处.

代码:
PVOID CheckFixHookedBaseAddress(PVOID);
PVOID GetNativeFunctionBaseAddress(PCWSTR);
DWORD GetFixOpcodeByLength(PVOID,LPVOID,LPVOID,DWORD);
DWORD SetHookAPIHead(LPVOID,PVOID,LPVOID,LPVOID,BYTE);
DWORD FixOpcodeForBackup(LPVOID,LPVOID,DWORD);
///////////////////////////////////////////////////////////////////////////////////// 
//*********************************************************************************** 
//模块名字:PVOID CheckFixHookedBaseAddress(PVOID lpBaseAddress)
//模块功能:对指定的基址试图寻找更合适的HOOK入口
//返回数值:返回合适的HOOK入口
//***********************************************************************************
//参数说明:参数名         |   输入/输出  |        参数说明
//          lpBaseAddress  |    IN        |  正常的需要优化的HOOK基址
//***********************************************************************************
PVOID CheckFixHookedBaseAddress(PVOID lpBaseAddress)
{
  __asm
  {  
    mov    esi, lpBaseAddress
    mov    edi, esi
    mov    ecx, 2          ; 检测前2条指令是否含直接跳转, 是则跟进之
  CheckFixHookedBaseAddress_next:    ; 支持更深层次的Inline HOOK
    push  ecx
    push  eax
    push  esp
    push  esi
    call  LDE32          ; LDE32 会修改EDX, ECX, EAX,需自己手动保护其值   
    pop    edx
    pop    ecx
    cmp    edx, 6
    je    CheckFixHookedBaseAddress_jmp_mem
    cmp    edx, 5
    je    CheckFixHookedBaseAddress_jmp_imm
  CheckFixHookedBaseAddress_jmp_continue:
    add    esi, edx
    loop  CheckFixHookedBaseAddress_next
    jmp    CheckFixHookedBaseAddress_quit
  CheckFixHookedBaseAddress_jmp_imm:
    lodsb
    dec    edx
    cmp    al, 0xe9
    jne    CheckFixHookedBaseAddress_jmp_continue
    lodsd
    add    eax, esi        ; 需修正跳转地址
    jmp    CheckFixHookedBaseAddress_new_addr
  CheckFixHookedBaseAddress_jmp_mem:
    lodsw
    cmp    ax, 0x25ff
    jne    CheckFixHookedBaseAddress_quit
    lodsd
    mov    eax, dword ptr [eax]
  CheckFixHookedBaseAddress_new_addr:
    push  eax
    pop    lpBaseAddress
  CheckFixHookedBaseAddress_quit:
  }
  return lpBaseAddress;
}

PVOID GetNativeFunctionBaseAddress(IN PCWSTR pusNativeKeJmpFunctionName)
{
  UNICODE_STRING usFunctionName;
  RtlInitUnicodeString(&usFunctionName, pusNativeKeJmpFunctionName);
  return CheckFixHookedBaseAddress(MmGetSystemRoutineAddress(&usFunctionName));
}
///////////////////////////////////////////////////////////////////////////////////// 
//*********************************************************************************** 
//模块名字:DWORD SetHookAPIHead(LPVOID lpOpcode,PVOID lpBuffer,LPVOID lpParam,
//                          LPVOID lpHookAPI,BYTE bAPICount)
//模块功能:设置被Inline HOOK的API头
//返回数值:返回实际设置Inline HOOK的API头指令串长度
//***********************************************************************************
//参数说明:参数名         |   输入/输出  |        参数说明
//          lpOpcode     |    IN        |  需要处理的操作码基址(即原API的EPO)
//          lpBuffer     |    OUT       |  接受Inline HOOK的API头指令串的本地缓冲区地址
//          lpParam       |    IN        |  远程参数缓冲区地址,(没有可以为NULL)
//          lpHookAPI     |    IN        |  HOOK API代码所存放的远程参数缓冲区地址
//          bAPICount     |    IN        |  被Inline HOOK的原API需要传入的实际参数数目
//***********************************************************************************
//更新:
//2008-05-13: 自动生成最优化HOOK头, 增加对EAX的保存,使之支持更深层次的Inline HOOK
///////////////////////////////////////////////////////////////////////////////////////
DWORD SetHookAPIHead(LPVOID lpOpcode,PVOID lpBuffer,LPVOID lpParam,LPVOID lpHookAPI,BYTE bAPICount)
{  LARGE_INTEGER dwSeed;
  #if WIN32_VERSION
  QueryPerformanceCounter(&dwSeed);
  #else
  KeQueryPerformanceCounter(&dwSeed);
  #endif
__asm
  {  
    mov    ecx, dwSeed.HighPart
    mov    eax, dwSeed.LowPart
    add    ecx, eax
    ror    ecx, cl        ; 产生随机数
    mov    eax, ecx
  ;===============================================================================  
    push  lpHookAPI      ; 开始填写可变参数
    push  lpParam
    lea    edx, SHQ_HookParam
    pop    dword ptr [edx]  
    xor    dword ptr [edx], eax
    lea    edx, SHQ_HookProc
    pop    dword ptr [edx]  
    xor    dword ptr [edx], eax ; 用随机密钥加密两个地址参数,加强检测难度
    cld
    lea    edi, SHQ_AddressKey
    stosd  
    lea    edi, SHQ_ClsESP
    mov    al, bAPICount
    shl    al, 2
    stosb          
    lea    edi, SHQ_FuckESP
    stosb            ; 填写可变参数完毕
    call  SHQ_SaveData
  ;===============================================================================
  ;###############################################################################
    mov     edi, edi    ; 8B FF  
    push    ebp        ; 55  
    mov     ebp, esp    ; 8B EC 伪扮入口标志,加强检测难度 ★★★   
    pop    ebp        ; 保存EBP (伪装时必需)
    
    xchg  eax, dword ptr [esp] ; 保存返回地址(这个很重要), 同时入栈保存EAX
                ; 在深层HOOK时,有时EAX也可能是跳转表的索引,故需保存之
                ; 2008-05-12 增加对EAX的保存
    push    ecx
    push    edx        ; 保护EBX, ECX,可以兼容fastcall api  ★★★★
  SHQ_HookParam_Fix:  
    _emit  0x68
  SHQ_HookParam:  
    DD_ADRESS        ; push    lpParam  ; 传入HOOK参数
                ; ◆注:重定位和跳转也成为RKU检测Line hook的标志◆
    _emit  0x68      ; 不使用这些, 其实这样更省空间
  SHQ_AddressKey:        ; 栈中解析地址,加强检测难度 ★★★★★
    DD_ADRESS        ; push  dword ptr [SHQ_AddressKey]      
    pop    ecx        ; 取得解码Key
  SHQ_HookParam_Fix_Sec:  
    _emit  0x31      ; 地址解码
    _emit  0x0c
    _emit  0x24      ; xor   dword ptr [esp], ecx ★★★★★  
    push  eax        ; 修正返回地址
  SHQ_BackAddress:
    _emit  0x83
    _emit  0xEC      ; 平衡堆栈  ●●●●●●●●
  SHQ_FuckESP:        ; 制造假象申请局部栈空间的同时,能保留压入的参数共HOOK使用
    _emit  0x00      ; sub     esp, x
  SHQ_FuckESP_Fix:
    _emit  0x68
  SHQ_HookProc:
    DD_ADRESS        ; push  eax, lpHookAPI  ; 设置真正的跳转地址
    _emit  0x31      ; 地址解码
    _emit  0x0c
    _emit  0x24      ; xor   dword ptr [esp], ecx ★★★★★
  SHQ_HookProc_Fix:

    push  ebp        ; 模拟原API返回前恢复原EBP (不仅实现了跳转,还恢复了EBP)
    mov    ebp, esp    ; 将HOOK代码做成正常调用退出格式,加强检测难度
    
    _emit  0x0c9      ; leave 由于无法编译通过,只好采用机器码(WIN32时却可以)
    ;leave          ; mov   esp, ebp  ; 主要目的是设置ESP指针
                ; pop   ebp      ; 在ESP指定的位置恢复EBP
    _emit  0x0c2      ; ret  x  =>  pop  eip
                ;        add  esp, x  ●●●●●●●●●  
  SHQ_ClsESP:
    DW_DATA          ; x
  ;###############################################################################
  SHQ_SaveData:        ; 保存HOOK 头数据
    pop    ecx
    ;--------------------------------------------------------------------------------
    mov    edi, lpOpcode          ; 生产最优化HOOK头,指令实时修正保存
    test  edi, edi
    je    SHQ_SaveData_Exit
    mov    esi, edi
    cld
    xor    edx, edx            ; EDX 作为属否含有PROC的标志(默认为0,表无)
    lodsw
                        ; 检测是否需要添加不必要的API入口伪装头
                        ; 尽量减小HOOK头尺寸
    cmp    ax, 0FF8Bh            ; 8BFF      mov     edi, edi
    jne    SHQ_SaveData_Nt          ; 据说NT以上MS才添加了这个,方便大家HOOK
    or    dl, 01b              ; 设置标志: -> XP
  SHQ_SaveData_Nt:
    lodsb                  ; 55    push    ebp        
    cmp    al, 55h
    je    SHQ_SaveData_Proc
    lodsw 
    jmp    SHQ_SaveData_Proc_Head
  SHQ_SaveData_Proc:
    lodsw  
    cmp    ax,  0EC8Bh            ; 8BEC    mov     ebp, esp
    jne    SHQ_SaveData_Proc_Head
    sub    esi, 3+1            ; 有PROC时,需要 POP EBP -> (+1)
    or    dl, 10b              ; 设置标志: ->标准的PROC
    and    dl, 01b              ; 检测是否为旧的OS的PROC
    je    SHQ_SaveData_Proc_Head
    sub    esi, 2
  SHQ_SaveData_Proc_Head:
    lodsb                  ; 默认不需要 POP EBP
    sub    esi, edi
    add    esi, ecx            ; 得到最优HOOK头基址
    mov    edi, lpBuffer

    lea    ecx, SHQ_HookParam_Fix
    sub    ecx, esi
    rep    movsb
    mov    eax, lpParam
    test  eax, eax            ; 如果HookParam=NULL,可以精简指令为
    jne    SHQ_SaveData_ParamExist  
    mov    ax, 6Ah              ; 6A 00         push    0
    stosw
    add    esi, 5
    lea    ecx, SHQ_HookParam_Fix_Sec
    sub    ecx, esi
    rep    movsb
    add    esi, 3              ; 0 时无需地址解码
    mov    al, 50h              ; 50            push    eax
    stosb                  ; 采用手工完成 push    eax
    jmp    SHQ_SaveData_BackMe
  SHQ_SaveData_ParamExist:
    lea    ecx, SHQ_BackAddress
    sub    ecx, esi
    rep    movsb
  SHQ_SaveData_BackMe:            ; 处理返回HOOK调用部分
    test  edx, edx
    jne    SHQ_SaveData_Proc_Back
    add    esi, 4
    lea    ecx, SHQ_HookProc_Fix
    sub    ecx, esi
    rep    movsb
    mov    al, 0c3h
    stosb                  ; 无需伪装,直接RET跳转调用HOOK
    jmp    SHQ_SaveData_Exit
  SHQ_SaveData_Proc_Back:  
    lea    ecx, SHQ_SaveData        ; 余下的指令都需要
    cmp    bAPICount, 0
    jne    SHQ_SaveData_Proc_Normal
    mov    esi, SHQ_FuckESP_Fix      ; 不用移动ESP
    sub    ecx, 2              ; 参数个数为0,又可省 2 BYTE
    mov    byte ptr [ECX-1], 0c3h
  SHQ_SaveData_Proc_Normal:
    sub    ecx, esi
    rep    movsb
  SHQ_SaveData_Exit:
    sub    edi, lpBuffer
    mov    dwSeed.LowPart, edi
  ;--------------------------------------------------------------------------------
  }
  return  dwSeed.LowPart;
}
////////////////////////////////////////////////////////////////////////////////////////
//**************************************************************************************
//模块名字:GetFixOpcodeByLength(LPVOID,LPVOID,LPVOID,DWORD)
//模块功能:备份被Inline HOOK的API头
//返回数值:返回实际备份指令串长度, 零表示失败
//**************************************************************************************
//参数说明:参数名      |   输入/输出  |        参数说明
//          lpBuffer    |    OUT       |     备份API的本地缓冲区地址
//          lpOpcode    |    IN        |     需要处理的操作码基址(即原API的EPO)
//          lpRemoteBuffer  |    IN        |     备份API的远程缓冲区地址
//          dwNumberOfBytes  |    IN        |     需要备份指令串长度
//**************************************************************************************
//更新:
//2008-05-11:
//    在内核环境下当检测到ret指令,就应该是为该指令串结束标志,不宜继续处理
//2008-05-08:
//    增加对长CALL,JMP跳转的检测功能
//2008-05-03:
//    增加对CALL跳转的修正功能
//2008-04-28:
//    如果空间不够则,不被HOOK
//2008-04-27:
//    由HSQ花12h用OD和VC9调试通过, 增加了对简单跳转指令的修正功能,及优化代码结构
////////////////////////////////////////////////////////////////////////////////////////
DWORD  GetFixOpcodeByLength(PVOID lpBuffer,LPVOID lpOpcode,LPVOID lpRemoteBuffer,DWORD dwNumberOfBytes)
{  
  __asm
  {  
    push  ebx
    xor    ebx, ebx
    mov    esi, lpOpcode
    test  esi, esi
    je    GetFixOpcodeByLength_exit    
    mov    edi, lpBuffer
    mov    ecx, ebx
    cld
  GetFixOpcodeByLength_next:
    push  ecx
    push  esp
    push  esi
    call  LDE32   
    pop    ecx
    add    ebx, ecx            ; 累计目前已扫描的指令长度
    cmp    ecx, 2              ; 检测本条指令是否需函数结束指令
    ja    GetFixOpcodeByLength_check
    lodsb
    dec    esi
    cmp    al, 0c2h            ; 若后面只存在少于5个BYTE不能继续覆盖
    je    GetFixOpcodeByLength_hook_false
    cmp    al, 0c3h            
    je    GetFixOpcodeByLength_hook_false
    jmp    GetFixOpcodeByLength_normal
  GetFixOpcodeByLength_hook_false:
    xor    ebx, ebx
    jmp    GetFixOpcodeByLength_exit    ; 无法Inline HOOK, 退出
  GetFixOpcodeByLength_check:
    cmp    ecx, 5              ; 检测本条指令是否需要修正
    jne    GetFixOpcodeByLength_check_jmp
    lodsb
    stosb
    cmp    al, 0XE8
    je    GetFixOpcodeByLength_fix_dword
    jmp    GetFixOpcodeByLength_no_call
  GetFixOpcodeByLength_check_jmp:
    cmp    ecx, 6  
    jne    GetFixOpcodeByLength_normal
    lodsw
    stosw
    xchg  ah, al
    cmp    ax, 0FF25h            ; jmp     dword ptr [80554484]
    je    GetFixOpcodeByLength_hook_false  
    cmp    ax, 0FF15h            ; call    dword ptr [80554484]
    je    GetFixOpcodeByLength_hook_false  ; 跳转地址属于系统变量, 本可以不加修正
                        ; 的直接备份,段很有可能直接跳转到已被
                        ; 修改的原入口,而非HOOK内部,如果是运行时
                        ; 全局常量,则可以修正该地址后PUSH RET之.
                        ; 暂时为简化处理,显示无法处理,返回失败  
    cmp    ax, 0F8Fh            ; 检测是否含有JXX指令
    ja    GetFixOpcodeByLength_no_jmp
    cmp    ax, 0F80h            ; 检测是否含有CALL指令
    jb    GetFixOpcodeByLength_no_jmp
  GetFixOpcodeByLength_fix_dword:  
    lodsd
    add    eax, lpOpcode 
    sub    eax, lpRemoteBuffer        ; 需修正跳转
    stosd
    jmp    GetFixOpcodeByLength_continue
  GetFixOpcodeByLength_no_jmp:
    dec    ecx
  GetFixOpcodeByLength_no_call:
    dec    ecx
  GetFixOpcodeByLength_normal:
    rep    movsb              ; 备份当前指令                 
  GetFixOpcodeByLength_continue:  
    cmp    ebx, dwNumberOfBytes
    jb    GetFixOpcodeByLength_next
    mov    al, 0e9h            ; 填加回跳指令
    stosb
    mov    eax, esi
    sub    eax, lpRemoteBuffer
    sub    eax, ebx
    sub    eax, 5
    stosd  
  GetFixOpcodeByLength_exit:
    mov    eax, ebx
    pop    ebx
    mov    dwNumberOfBytes, eax
  }
  return dwNumberOfBytes;
}
////////////////////////////////////////////////////////////////////////////////////////
//**************************************************************************************
//模块名字:FixOpcodeForBackup(LPVOID,LPVOID,DWORD)
//模块功能:修正备份Inline HOOK的API头
//返回数值:返回实际修正指令串长度, 零表示失败
//**************************************************************************************
//参数说明:参数名      |   输入/输出  |        参数说明
//          lpOpcode    |    IN        |     需要处理的操作码基址
//          lpFixBase      |    IN        |     需修正目标空间的基址
//          dwNumberOfBytes  |    IN        |     需修正的指令串长度
//**************************************************************************************
///////////////////////////////////////////////////////////////////////////////
DWORD  FixOpcodeForBackup(LPVOID lpOpcode,LPVOID lpFixBase,DWORD dwNumberOfBytes)
{  
  __asm
  {
    push  ebx
    xor    ebx, ebx
    mov    esi, lpOpcode
    test  esi, esi
    je    FixOpcodeForBackup_exit  
    mov    ecx, ebx
    cld
  FixOpcodeForBackup_next:
    push  ecx
    push  esp
    push  esi
    call  LDE32   
    pop    ecx
    add    ebx, ecx            ; 累计目前已扫描的指令长度
    cmp    ecx, 5              ; 检测本条指令是否需要修正
    jne    FixOpcodeForBackup_check_jmp
    lodsb
    cmp    al, 0XE8
    jne    FixOpcodeForBackup_no_call  
    jmp    FixOpcodeForBackup_fix_dword
  FixOpcodeForBackup_check_jmp:
    cmp    ecx, 6  
    jne    FixOpcodeForBackup_normal
    lodsw
    xchg  ah, al
    cmp    ax, 0F8Fh            ; 检测是否含有JXX指令
    ja    FixOpcodeForBackup_no_jmp
    cmp    ax, 0F80h            ; 检测是否含有CALL指令
    jb    FixOpcodeForBackup_no_jmp
  FixOpcodeForBackup_fix_dword:  
    mov    edi, esi
    lodsd
    add    eax, lpFixBase
    sub    eax, lpOpcode           ; 需修正跳转
    stosd
    jmp    FixOpcodeForBackup_continue
  FixOpcodeForBackup_no_jmp:
    dec    ecx
  FixOpcodeForBackup_no_call:
    dec    ecx
  FixOpcodeForBackup_normal:
    add    esi, ecx
  FixOpcodeForBackup_continue:
    cmp    ebx, dwNumberOfBytes
    jb    FixOpcodeForBackup_next
  FixOpcodeForBackup_exit:
    mov    eax, ebx
    pop    ebx
    mov    dwNumberOfBytes, eax
  }
  return dwNumberOfBytes;
}
                        by HSQ 22:03 2008-5-14
                                                于湖北宜昌XXX网吧
上传的附件 4.01.rar