12/08/2018, 12:05

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:

060313_1217_UsingSetWin1.png

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.

winspy2.gif

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:

060313_1217_UsingSetWin2.png

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:

060313_1217_UsingSetWin4.png

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.

0