2012-02-17 32 views
11

Tôi quan tâm đến hooking và tôi quyết định xem tôi có thể móc một số chức năng. Tôi không thích sử dụng thư viện như đường vòng vì tôi muốn có kinh nghiệm tự làm nó. Với một số nguồn tôi tìm thấy trên internet, tôi đã có thể tạo mã bên dưới. Đó là cơ bản, nhưng nó hoạt động ổn. Tuy nhiên khi hooking chức năng được gọi là bởi nhiều chủ đề nó chứng minh là cực kỳ không ổn định. Nếu hai cuộc gọi được thực hiện gần như cùng một lúc, nó sẽ sụp đổ. Sau một số nghiên cứu, tôi nghĩ rằng tôi cần phải tạo ra một chức năng trampoline. Sau khi tìm kiếm tất cả các giờ, tôi đã không thể tìm thấy bất cứ điều gì khác mà một mô tả chung về những gì một tấm bạt lò xo được. Tôi không thể tìm thấy bất cứ điều gì đặc biệt về cách viết một chức năng trampoline, hoặc làm thế nào họ thực sự làm việc. Nếu bất kỳ ai có thể giúp tôi viết một bài, đăng một số nguồn, hoặc ít nhất là chỉ cho tôi đúng hướng bằng cách giới thiệu một số bài viết, trang web, sách, v.v. Tôi rất cảm kích nó.Làm thế nào để tạo ra một chức năng trampoline cho móc

Dưới đây là mã tôi đã viết. Nó thực sự cơ bản nhưng tôi hy vọng những người khác có thể học hỏi từ nó.

test.cpp

#include "stdafx.h" 

Hook hook; 

typedef int (WINAPI *tMessageBox)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType); 

DWORD hMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) 
{ 
    hook.removeHook(); 
    tMessageBox oMessageBox = (tMessageBox)hook.funcPtr; 
    int ret =oMessageBox(hWnd, lpText, "Hooked!", uType); 
    hook.applyHook(&hMessageBox); 

    return ret; 
} 

void hookMessageBox() 
{ 
    printf("Hooking MessageBox...\n"); 
    if(hook.findFunc("User32.dll", "MessageBoxA")) 
    { 
     if(hook.applyHook(&hMessageBox)) 
     { 
      printf("hook applied! \n\n"); 
     } else printf("hook could not be applied\n"); 
    } 
} 

hook.cpp

#include "stdafx.h" 

bool Hook::findFunc(char* libName, char* funcName) 
{ 
    Hook::funcPtr = (void*)GetProcAddress(GetModuleHandleA(libName), funcName); 
    return (Hook::funcPtr != NULL); 
} 

bool Hook::removeHook() 
{ 
    DWORD dwProtect; 
    if(VirtualProtect(Hook::funcPtr, 6, PAGE_EXECUTE_READWRITE, &dwProtect)) 
     { 
     WriteProcessMemory(GetCurrentProcess(), (LPVOID)Hook::funcPtr, Hook::origData, 6, 0); 
     VirtualProtect(Hook::funcPtr, 6, dwProtect, NULL); 
     return true; 
    } else return false; 
} 

bool Hook::reapplyHook() 
{ 
    DWORD dwProtect; 
    if(VirtualProtect(funcPtr, 6, PAGE_EXECUTE_READWRITE, &dwProtect)) 
     { 
     WriteProcessMemory(GetCurrentProcess(), (LPVOID)funcPtr, Hook::hookData, 6, 0); 
     VirtualProtect(funcPtr, 6, dwProtect, NULL); 
     return true; 
    } else return false; 
} 

bool Hook::applyHook(void* hook) 
{ 
    return setHookAtAddress(Hook::funcPtr, hook); 
} 

bool Hook::setHookAtAddress(void* funcPtr, void* hook) 
{ 
    Hook::funcPtr = funcPtr; 
    BYTE jmp[6] = { 0xE9, //jmp 
        0x00, 0x00, 0x00, 0x00, //address 
        0xC3 //retn 
       }; 

    DWORD dwProtect; 

    if(VirtualProtect(funcPtr, 6, PAGE_EXECUTE_READWRITE, &dwProtect)) // make memory writable 
    { 

     ReadProcessMemory(GetCurrentProcess(), (LPVOID)funcPtr, Hook::origData, 6, 0); // save old data 
     DWORD offset = ((DWORD)hook - (DWORD)funcPtr - 5); //((to)-(from)-5) 
     memcpy(&jmp[1], &offset, 4); // write address into jmp 
     memcpy(Hook::hookData, jmp, 6); // save hook data 
     WriteProcessMemory(GetCurrentProcess(), (LPVOID)funcPtr, jmp, 6, 0); // write jmp 
     VirtualProtect(funcPtr, 6, dwProtect, NULL); // reprotect 

     return true; 
    } else return false; 
} 
+0

Tôi sẽ đăng liên kết tới GD, nhưng tôi vừa nhận thấy bạn cũng là thành viên ở đó. Bạn đã thử sử dụng chức năng tìm kiếm của họ chưa? Nó đi kèm với tấn ví dụ :) –

+0

Bạn có thể kiểm tra mã của EasyHook, tôi tin rằng đó là mã nguồn mở. Ngoài ra còn có rất nhiều ví dụ khác xung quanh. Nếu bạn dự định sử dụng ứng dụng này trong một ứng dụng được triển khai, tôi khuyên bạn nên sử dụng thư viện (như EasyHook) có thể xử lý đệ quy trên móc/tấm bạt lò xo, luồng và một số nội dung thú vị. – ssube

+0

@Tom Knapen Tôi đã tìm kiếm GD, MPGH và một vài trang web khác trước khi đăng. Tìm kiếm 'tấm bạt lò xo' trên GD trả lại một số bài đăng có liên quan đến một chút nhưng không phải những gì tôi đang tìm kiếm. – Stratus

Trả lời

7

Nếu bạn muốn móc của bạn được an toàn khi được gọi bởi nhiều chủ đề, bạn không muốn được liên tục unhooking và rehooking sự API ban đầu.

Một tấm bạt lò xo chỉ đơn giản là một đoạn mã bạn tạo ra sao chép chức năng của vài byte đầu tiên của API ban đầu (mà bạn ghi đè bằng bước nhảy), sau đó nhảy vào API sau khi các byte bạn ghi đè.

Thay vì không tìm kiếm API, hãy gọi nó và phục hồi lại, bạn chỉ cần gọi tấm bạt lò xo.

Điều này khá phức tạp để thực hiện trên x86 vì bạn cần bộ tách rời (khá tối thiểu) để tìm ra các ranh giới hướng dẫn. Bạn cũng cần phải kiểm tra xem mã bạn sao chép vào tấm bạt lò xo của bạn không làm bất cứ điều gì liên quan đến con trỏ chỉ dẫn (như một jmp, chi nhánh hay cuộc gọi).

Điều này là đủ để thực hiện cuộc gọi đến móc chỉ an toàn, nhưng bạn không thể tạo móc nếu nhiều chủ đề đang sử dụng API. Đối với điều này, bạn cần phải móc các chức năng với một hai byte gần nhảy (có thể được viết nguyên tử). Các API Windows thường được bắt đầu bởi một vài NOP (có thể được ghi đè bằng một bước nhảy xa) để cung cấp mục tiêu cho bước nhảy gần này.

Làm điều này trên x64 là nhiều hơn phức tạp hơn. Bạn không thể chỉ đơn giản là vá các chức năng với một bước nhảy xa 64-bit (vì không có một, và hướng dẫn để mô phỏng nó thường là quá dài). Và, tùy thuộc vào những gì trampoline của bạn làm, bạn có thể cần phải thêm nó vào ngăn xếp của hệ điều hành thư giãn thông tin.

Tôi hy vọng điều này không quá chung chung.

+0

Cảm ơn, nhưng điều này là khá nhiều những gì tôi đã tìm thấy và không giúp tôi viết một. – Stratus

+0

@Stratus: Bạn đang thiếu gì? Phân bổ một số bộ nhớ thực thi. Sao chép n byte từ hàm prolog đến bộ nhớ được cấp phát và theo nó với một bước nhảy để thực hiện hàm prolog + n. n là kích thước của các lệnh bạn cần sao chép để giải phóng ít nhất 5 byte trong hàm prolog. Đó là tấm bạt lò xo. Có một số nếp nhăn khác (như không sao chép hướng dẫn sửa đổi IP) nhưng đó là cơ bản nó. – arx

Các vấn đề liên quan