Sử dụng SetWindowHoookEx cho Injection DLL trên window
Trong bài lần trước: https://viblo.asia/ninhvh/posts/57rVRqZVM4bP Mình có giới thiệu một ví dụ nhỏ về việc control một application khác từ source code của mình bằng cách sử dụng method SendMessage. Tuy nhiên với SendMessage chúng ta có thể thao tác với một application với tư cách như một user thông ...
Trong bài lần trước: https://viblo.asia/ninhvh/posts/57rVRqZVM4bP Mình có giới thiệu một ví dụ nhỏ về việc control một application khác từ source code của mình bằng cách sử dụng method SendMessage. Tuy nhiên với SendMessage chúng ta có thể thao tác với một application với tư cách như một user thông thường thôi, chúng ta khó có thể thay đổi behavior của chương trình khác được. Trong bài này mình xin giới thiệu một phương thức khác làm việc với đối tượng application khác là SetWindowHoookEx, với cách thức này chúng ta có thể thay đổi logic trên method của chương trình.
1. Cơ chế Injection:
Trong hình trên, ô màu tím là process của application chúng ta cần inject tới. Trong chương trình này sử dụng một số dll: name1.dll. name2.dll, name3.dll v.v... Việc đầu tiên chúng ta cần làm là xác định địa chỉ của function chúng ta muốn thao tác (export: efunct).
Chúng ta có thể tiêm DLL của chúng ta vào victim.exe process, từ đó chúng ta có thể làm bất cứ điều gì bên trong address space(không gian địa chỉ). Việc đầu tiên mà chúng ta cần application chứa inject dll, được viết code để thực hiện chính xác những gì chúng ta muốn các DLL thao tác khi nó được tiêm vào không gian địa chỉ của đối tượng. Để tiêm DLL vào không gian địa chỉ của application, chúng ta sẽ sử dụng function SetWindowsHookEx (program.exe là appplication chúng ta sử dụng để tiêm dll). program.exe khi hoạt động sẽ thực hiện hooking và tiêm inject.dll vào process của victim.exe.
program.exe trước hết phải handle được prcess của victim.exe và nhận được address của đối tượng function cần thao tác trong danh sách dll. Có nghĩa rằng chúng ta cần phải code inject.dll để exports ít nhất một function. Sau đó, program.exe sẽ gọi hàm SetWindowsHookEx để được nối địa chỉ của function export bên trong inject.dll đến application nạn nhân.
Hàm SetWindowsHookEx sẽ cài đặt NewProc vào hook chain của victim.exe, và sẽ được gọi bất cứ khi nào sự kiện đó được kích hoạt. Ở đây, chúng ta sẽ hook vào chức năng WH_KEYBOARD, có nghĩa là bất cứ khi nào chúng ta nhấn một phím bất kỳ trong victim.exe, newProc trong inject.dll sẽ được call. Khi sự kiện xảy ra, hệ điều hành đầu tiên kiểm tra xem liệu các DLL cần thiết đã được nạp vào address space của process hay không. Nếu không, sau đó hệ điều hành phải tải (đọc tiêm) DLL vào address space của process mà trên đó các chức năng DllMain của DLL được gọi. Sau đó, newProc method, chúng ta truyền cho SetWindowsHookEx cũng gọi để xử lý các sự kiện trong trường hợp của chúng ta.
2. SetWindowsHookEx Method:
SetWindowsHookEx sẽ cài đặt newProc vào hook chain, sau đó sẽ thực hiện mỗi khi main event được raised, ở đây là WH_KEYBOARD.
- idHook: kiểu hook được cài đặt. Nó có thể là một trong những loại sau:
WH_CALLWNDPROC WH_CALLWNDPROCRET WH_CBT WH_DEBUG WH_FOREGROUNDIDLE WH_GETMESSAGE WH_JOURNALPLAYBACK WH_JOURNALRECORD WH_KEYBOARD WH_KEYBOARD_LL WH_MOUSE WH_MOUSE_LL WH_MSGFILTER WH_SHELL WH_SYSMSGFILTER SetWindowsHookEx function, at http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx. - lpfn: a pointer của hook method. - hMod: a handle của DLL chứa hook method. - dwThreadId: nhận dạng thread, vì một method có thể được gọi trong nhiều thread. Nếu tham số là 0, hook sẽ được call bởi tất cả các thread. Nếu SetWindowsHookEx thành công, nó trả về một HHOOK handle để hook method. nếu fail trả về null. ![060313_1217_UsingSetWin3.png](/uploads/405bdb7b-0205-48c5-b9f1-50935b84a66b.png) Trong trường hợp của chúng ta, chúng ta sẽ được gắn vào sự kiện WH_KEYBOARD cho phép chúng ta theo dõi các thông điệp keystroke. ### 3. Tạo inject.dll: ### Chúng ta có thể bắt đầu một project mới trong Visual Studio và chọn DLL để tạo ra nó. Sau đó, chúng ta có thể thay đổi code trong file dllmain.c giống như sau: ```C_Cpp # include "stdafx.h" # include <stdio.h> # include <windows.h> INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) { /* open file */ FILE *file; fopen_s(&file, "C: emp.txt", "a+"); switch(Reason) { case DLL_PROCESS_ATTACH: fprintf(file, "DLL attach function called. "); break; case DLL_PROCESS_DETACH: fprintf(file, "DLL detach function called. "); break; case DLL_THREAD_ATTACH: fprintf(file, "DLL thread attach function called. "); break; case DLL_THREAD_DETACH: fprintf(file, "DLL thread detach function called. "); break; } /* close file */ fclose(file); return TRUE; } extern "C" __declspec(dllexport) int meconnect(int code, WPARAM wParam, LPARAM lParam) { FILE *file; fopen_s(&file, "C:function.txt", "a+"); fprintf(file, "Function keyboard_hook called. "); fclose(file); return(CallNextHookEx(NULL, code, wParam, lParam)); }
Chúng ta có một DLL khá đơn giản, Các DllMain () được gọi khi DLL được nạp vào không gian địa chỉ của quá trình. Khi đó, các message được ghi vào "C: temp.txt". Nhưng cũng có một chức năng có tên meconnect , chức năng lưu message "Function keyboard_hook called." vào C:function.txt. Nó khá đơn giản và không làm bất cứ điều gì khác. Nếu chúng ta muốn một chương trình keylogger, chúng ta có thể làm như vậy. Có rất nhiều khả năng chúng ta có thể khám phá, bởi vì một khi các DLL được nạp, code của chúng ta sẽ được gọi. Đây cũng là lý do mà chúng ta có thể làm được bất cứ điều gì liên quan process với method SetWindowHoookEx .
4. Tạo program.exe:
Đây là chương trình mà sẽ tiêm inject.dll của chúng ta vào không gian địa chỉ của process.
# include "stdafx.h" # include <Windows.h> int _tmain(int argc, _TCHAR* argv[]) { /* * Load library in which we'll be hooking our functions. */ HMODULE dll = LoadLibrary(L"C:driversdllinject.dll"); if(dll == NULL) { printf("The DLL could not be found. "); getchar(); return -1; } /* * Get the address of the function inside the DLL. */ HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, "meconnect"); if(addr == NULL) { printf("The function was not found. "); getchar(); return -1; } /* * Hook the function. */ HHOOK handle = SetWindowsHookEx(WH_KEYBOARD, addr, dll, 0); if(handle == NULL) { printf("The KEYBOARD could not be hooked. "); } /* * Unhook the function. */ printf("Program successfully hooked. Press enter to unhook the function and stop the program. "); getchar(); UnhookWindowsHookEx(handle); return 0; }
Đầu tiên, chúng ta gọi hàm LoadLibrary để nạp DLL của chúng ta vào address space. Nếu DLL không tìm thấy một thông điệp đơn giản, "The DLL could not be found." Được in vào cửa sổ giao diện điều khiển. Đối với các DLL được tìm thấy, chúng ta phải thay đổi đường dẫn từ C: drivers dllinject.dll đến thư mục định sẵn. Sau đó, chúng ta gọi hàm GetProcAddress để có được địa chỉ của hàm meconnect rằng chúng ta export method này trong DLL mã hóa trước đó. Tại thời điểm này, chúng ta có thể sử dụng công cụ dumpbin để kiểm tra xem chức năng đó có phải là export method hay không. Các đầu ra từ lệnh có thể được nhìn thấy dưới đây:
> dumpbin /EXPORTS C:driversdllinject.dll Microsoft (R) COFF/PE Dumper Version 10.00.30319.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file C:driversdllinject.dll File Type: DLL Section contains the following exports for dllinject.dll 00000000 characteristics 517A2D25 time date stamp Fri Apr 26 09:30:45 2013 0.00 version 1 ordinal base 1 number of functions 1 number of names ordinal hint RVA name 1 0 000110F5 meconnect = @ILT+240(_meconnect) Summary 1000 .data 1000 .idata 2000 .rdata 1000 .reloc 1000 .rsrc 4000 .text 10000 .textbss
Chú ý rằng chỉ có một chức năng được export và nó là meconnect. program.exe dụng lấy các địa chỉ của chức năng đó khi gọi GetProcAddress chức năng. Sau đó, chương trình gọi SetWindowsHookEx.
HHOOK handle = SetWindowsHookEx (WH_KEYBOARD, addr, dll, 0); if (xử lý == NULL) { printf ("The KEYBOARD có thể không được nối. n"); }
5. Chạy và View kết quả:
Bây giờ chúng ta biên dịch và bắt đầu chạy program.exe (lưu ý inject.dll cũng cần được biên soạn và được đặt trong thư mục "C: drivers "). Chương trình chạy vào show ra kết quả như sau:
Mọi thứ đã được hoàn thành và bất cứ khi nào chúng ta bắt đầu một chương trình trong Windows Desktop, DLL của chúng ta sẽ được tiêm vào không gian địa chỉ của nó.
6. Tổng kết:
Trong bài viết này, chúng ta có thể sử dụng chức năng SetWindowsHookEx để tiêm DLL vào không gian địa chỉ của process và thực thi một đoạn code nhỏ bên trong không gian địa chỉ của một application khác như thế nào.
Reference: http://www.codeproject.com/Articles/30140/API-Hooking-with-MS-Detours#Trad. http://support.microsoft.com/kb/197571. http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx. http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx. http://www.pinvoke.net/default.aspx/user32/SetWindowsHookEx.html.