2013-12-21 19 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 
相關問題