2013-12-21 20 views
0

我已经编写了代码来修补例如Kernel32.dll中的“睡眠”函数。修补作品完美无瑕。修补程序的去除效果非常好。但是,调用原始函数根本不起作用。它崩溃严重。如何在hotpatch之后调用原始函数

#include <windows.h> 
#include <iostream> 

std::uint8_t* Patch(std::uint8_t* OrigFunc, std::uint8_t* HookFunc) 
{ 
    DWORD dwProtect = 0; 
    const static std::uint8_t jmp[] = {0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0}; 
    const static std::int8_t jmp_size = sizeof(jmp)/sizeof(std::uint8_t); 
    static std::uint8_t HookJump[jmp_size + 1] = {jmp_size}; 
    VirtualProtect(OrigFunc, jmp_size, PAGE_EXECUTE_READWRITE, &dwProtect); 
    memcpy(&HookJump[1], OrigFunc, jmp_size); 
    memcpy(OrigFunc, jmp, jmp_size); 
    memcpy(OrigFunc + 1, &HookFunc, sizeof(void*)); 
    VirtualProtect(OrigFunc, jmp_size, dwProtect, &dwProtect); 
    return HookJump; 
} 

void RemovePatch(std::uint8_t* OrigFunc, std::uint8_t* HookJump) 
{ 
    DWORD dwProtect = 0; 
    VirtualProtect(OrigFunc, HookJump[0], PAGE_EXECUTE_READWRITE, &dwProtect); 
    memcpy(OrigFunc, &HookJump[1], HookJump[0]); 
    VirtualProtect(OrigFunc, HookJump[0], dwProtect, &dwProtect); 
} 

typedef void (__stdcall *pSleep)(DWORD); 
pSleep oSleep; 

void __stdcall hSleep(DWORD MS) 
{ 
    std::cout<<"HERE"; 
    oSleep(MS); //Crashes Here. 
} 

int main() 
{ 
    std::uint8_t* OrigFunc = (std::uint8_t*)GetProcAddress(GetModuleHandle("kernel32.dll"), "Sleep"); 
    std::uint8_t* HookFunc = (std::uint8_t*)hSleep; 
    std::uint8_t* HookJump = Patch(OrigFunc, HookFunc); //Works fine. 

    oSleep = (pSleep)&HookJump[1]; 
    Sleep(1000); //Prints Here then crashes immediately. 

    RemovePatch(OrigFunc, HookJump); //Works fine. 
    Sleep(1000); //Works fine. 
} 

任何想法我的代码丢失了什么?

+1

你为什么不使用MS走弯路,正如我前面建议? –

+0

因为MSDetours仅适用于Visual Studio。我确实早些时候使用过它,它工作得很好,但我想学习写我自己的,所以我不必每次都依赖它。我已经得到了,我现在不能回去:( – Brandon

+0

“MSDetours只适用于Visual Studio”没有意义。 –

回答

0

在给定的代码中,似乎将原始字节存储在名为HookJump的静态数组中,返回一个指向该数组的指针,然后跳转到它的开始位置,就像它是有效的机器代码一样。它没有跟随原始功能的其余部分。


在Windows中挂钩函数的更好方法是使用Microsoft Detours。

这是我(的工作草图)Hook类,使用绕行:

[Hook.h]

#pragma once 
// Copyright (c) 2013 Alf P. Steinbach 

#include <rfc/cppx/core/Non_copyable.h>  // cppx::Non_copyable 
#include <rfc/cppx/core/macros/ASSERT.h> // CPPX_ASSERT 
#include <rfc/detours/Transaction.h>  // detours::Transaction 

namespace detours { 
    using cppx::Non_copyable; 

    template< class Func > 
    class Hook_ 
     : public Non_copyable 
    { 
    private: 
     Func* original_; 
     Func* replacement_; 

    public: 
     auto original_func() const 
      -> Func* 
     { return original_; } 

     ~Hook_() 
     { 
      if(original_ != nullptr) 
      { 
       Transaction().detach(original_, replacement_).commit(); 
      } 
     } 

     Hook_(Func* const original, Func* const replacement) 
      : original_(original) 
      , replacement_(replacement) 
     { 
      CPPX_ASSERT(original_ != nullptr); 
      CPPX_ASSERT(replacement_ != nullptr); 
      Transaction().attach(original_, replacement_).commit(); 
     } 

     Hook_(Hook_&& other) 
      : original_(other.original_) 
      , replacement_(other.replacement_) 
     { other.original_ = nullptr; other.replacement_ = nullptr; } 
    }; 

    template< class Func > 
    inline auto hook(Func* const original, Func* const replacement) 
     -> Hook_<Func> 
    { return Hook_<Func>(original, replacement); } 

} // namespace detours 

而这里的Transaction类它使用,这又调用Detours API:

[Transaction.h]

#pragma once 
// Copyright (c) 2013 Alf P. Steinbach 

#include <rfc/cppx/core/utility/If_.h>  // cppx::If 
#include <rfc/cppx/core/Non_copyable.h>  // cppx::Non_copyable 
#include <rfc/cppx/core/Type_.h>   // cppx::Type_ 

#include <thread>   // std::thread 
#include <type_traits>  // std::is_function, std::enable_if 

namespace detours { 
    using cppx::If_; 
    using cppx::Non_copyable; 
    using cppx::Type_; 
    using std::is_function; 
    using std::thread; 

    typedef thread::native_handle_type Thread_handle; 

    class Basic_transaction 
     : public Non_copyable 
    { 
    private: 
     typedef Type_<void(*)()> Proc; 

     bool is_committed_; 

     void raw_attach(Proc& original, Proc const replacement); 
     void raw_detach(Proc& original, Proc const replacement); 

    public: 
     auto is_committed() const 
      -> bool; 
     void commit(); 

     auto update_thread(Thread_handle const h) 
      -> Basic_transaction&; 

     auto update_this_thread() 
      -> Basic_transaction&; 

     template< class Func, class Enabled = If_<is_function<Func>> > 
     auto attach(Func*& original, Func* const replacement) 
      -> Basic_transaction& 
     { 
      raw_attach(
       reinterpret_cast<Proc&>(original), 
       reinterpret_cast<Proc>(replacement) 
       ); 
      return *this; 
     } 

     template< class Func, class Enabled = If_<is_function<Func>> > 
     auto detach(Func*& original, Func* const replacement) 
      -> Basic_transaction& 
     { 
      raw_detach(
       reinterpret_cast<Proc&>(original), 
       reinterpret_cast<Proc>(replacement) 
       ); 
      return *this; 
     } 

     ~Basic_transaction(); 
     Basic_transaction(); 
    }; 

    class Transaction 
     : public Basic_transaction 
    { 
    public: 
     Transaction() 
     { update_this_thread(); } 
    }; 

} // namespace detours 

[Transaction.cpp]

#include "Transaction.h" 

#include <rfc/cppx/core/throwing.h> 
#include <rfc/cppx/core/macros/ASSERT.h>     // CPPX_ASSERT 
#include <rfc/detours_wrappers/detours_h.h> 

using cppx::hopefully; 
using cppx::fail; 

typedef long Error_code; 

namespace detours{ 

    auto Basic_transaction::is_committed() const 
     -> bool 
    { return is_committed_; } 

    void Basic_transaction::commit() 
    { 
     CPPX_ASSERT(!is_committed_); 
     Error_code const code = ::DetourTransactionCommit(); 
     hopefully(code == 0) 
      || fail("Basic_transaction::commit: DetourTransactionCommit failed", code); 
     is_committed_ = true; 
    } 

    auto Basic_transaction::update_thread(Thread_handle const h) 
     -> Basic_transaction& 
    { 
     Error_code const code = ::DetourUpdateThread(reinterpret_cast<HANDLE>(h)); 
     hopefully(code == 0) 
      || fail("Transaction::update_thread: DetourUpdateThread failed", code); 
     return *this; 
    } 

    auto Basic_transaction::update_this_thread() 
     -> Basic_transaction& 
    { 
     return update_thread(Thread_handle(::GetCurrentThread())); 
    } 

    void Basic_transaction::raw_attach(Proc& original, Proc const replacement) 
    { 
     Error_code const code = ::DetourAttach(
      reinterpret_cast<void**>(&original), 
      reinterpret_cast<void*>(replacement) 
      ); 
     hopefully(code == 0) 
      || fail("Transaction::attach: DetourAttach failed", code); 
    } 

    void Basic_transaction::raw_detach(Proc& original, Proc const replacement) 
    { 
     Error_code const code = ::DetourDetach(
      reinterpret_cast<void**>(&original), 
      reinterpret_cast<void*>(replacement) 
      ); 
     hopefully(code == 0) 
      || fail("Transaction::attach: DetourAttach failed", code); 
    } 

    Basic_transaction::~Basic_transaction() 
    { 
     if (!is_committed_) 
     { 
      Error_code const code = ::DetourTransactionAbort(); 
      hopefully(code == 0) 
       || fail("Basic_transaction::<destroy>: DetourTransactionAbort failed", code); 
     } 
    } 

    Basic_transaction::Basic_transaction() 
     : is_committed_(false) 
    { 
     Error_code const code = ::DetourTransactionBegin(); 
     hopefully(code == 0) 
      || fail("Basic_transaction::<init>: DetourTransactionBegin failed", code); 
    } 

} // namespace detours 

弯路包装HEA DER:

[detours.h]

#pragma once 
#include <rfc/winapi_wrappers/windows_h.h> 
#include <microsoft_detours/detours.h> 

我然后使用CPP文件中的特定的Detours实施方式中,例如,使适用于x86:

[detours_cpp.x86-32.cpp]

// Copyright (c) 2013 Alf P. Steinbach 

#define DETOURS_INTERNAL     // Necessary for DETOUR_TRACE 
#include <rfc/detours_wrappers/detours_h.h> 
#define DETOURS_X86 
#define DETOURS_32BIT 
#include <microsoft_detours/detours.cpp> // Source 
#include <microsoft_detours/disasm.cpp>  // More source, e.g. DetourCopyInstruction 
相关问题