-
12-05-2014, 08:44 AM #1Banned
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Customize hộp thoại MessageBox với kỹ thuật Hooking
Source code:
CustomizeMessageBox.rar
Image:
IDE: Visual C++ 2005
0. Mở đầu
Những bài học chập chững printf(“Hello World”) thửa đầu với màn hình console, hay ứng dụng cơ bản MessageBox(NULL, “Hello World”, “Caption”, 0) khi làm quen với lập trình WinAPI. Tất cả những thứ đó đã đưa chúng ta đi những bước đi đầu tiên đến với vùng đất it này.
Hôm nay, một ngày không đẹp trời lắm, chúng ta hãy cùng quay trở về nơi những bước đi chập chững thửa đầu đó để ôn lại những kỷ niệm và thử xem chúng ta có thể làm gì “nếu thời gian có quay trở lại”?
Như chúng ta đã biết, hàm MessageBox có 4 tham số với ý nghĩa như sau:
1. HWND: handle cửa sổ cha của hộp thoại
2. LPCTSTR: chuỗi ký tự chứa nội dung cần thông báo
3. LPCTSTR: chuỗi ký tự chứa nội dung của thanh tiêu đề
4. UINT: style của hộp thoại, có một số kiểu style có sẵn để chúng ta chọn lựa (số nút bấm, kiểu thộp thoại, kiểu hiển thị text trái – phải…)
Windows cung cấp cho chúng ta khá nhiều style (tham số 4) để thực hiện việc tùy chỉnh hộp thoại MessageBox cho phù hợp với từng mục đích sử dụng. Nhưng không có một style nào giành cho việc thay đổi text, kích thước của các nút bấm, hay màu của các đoạn text trong hộp thoại MessageBox. Vậy làm như nào để chúng ta có thể thay đổi đoạn text trong các nút bấm của hộp thoại MessageBox, hay một số tùy chỉnh khác?
Bài học đầu tiên trong ký ức xưa chợt ùa về, với những điều mới mẻ được mở ra…
I. Thay đổi nút bấm của hộp thoại MessageBox
I.a Giới thiệu
Trước tiên, chúng ta cần biết hàm MessageBox làm những gì “trong đó”?
Sử dụng một vài công cụ debug, chúng ta có thể dễ dàng nhận ra những việc hàm MessageBox làm như sau:
MessageBox -> MessageBoxTimeout -> SoftModalMessageBox
Như vậy hàm xử lý chính để tạo ra hộp thoại MessageBox nằm ở hàm SoftModalMessageBox
Muốn customize các nút bấm, chúng ta cần phải “xử lý” hàm SoftModalMessageBox.
Một số đặc điểm của hàm SoftModalMessageBox như sau:
- Được export bởi thư viện user32.dllMicrosoft không cung cấp tài liệu về hàm này
Tham số đầu vào hàm SoftModalMessageBox là 1 pointer trỏ tới cấu trúc như sau:
- MSGBOXPARAMS: cái này có giới thiệu ở msdnDWORD: unknowDWORD: unknowDWORD: unknow (từ win 8 trở đi, microsoft thêm tham số này vô, mình cũng không biết để làm gì @@)DWORD*: mảng chứa id các nút bấmWCHAR**: mảng chứa các đoạn text của các nút bấmDWORD: số lượng buttonDWORD: id nút bấm mặc địnhDWORD: id nút bấn CancelDWORD: timeout của hộp thoại
Nhìn vào đây chắc các bạn cũng đã hiểu cũng ta phải làm gì tiếp theo rồi phải không?
<font size="3">I.b Việt hóa đoạn text trong các nút bấm trong hộp thoại MessageBox
- Khai báo cấu trúc của tham số đầu vào hàm SoftModalMessageBox. Do từ win8, cấu trúc này được bổ sung thêm 1 tham số nên ta sẽ khai báo 2 cấu trúc tương ứng với win 8 và các win trước
Mã:- //Struct for win 7 and xptypedef struct _MSGBOXINFO{ MSGBOXPARAMS params; DWORD dwUnk1; DWORD dwUnk2; DWORD lpdwListButtonId; DWORD lppszListButtonText; DWORD dwButtonsCount; DWORD dwDefaultButtonId; DWORD dwCancelButtonId; DWORD dwTimeout;} MSGBOXINFO; //Struct for win 8 and latertypedef struct _MSGBOXINFO_W8{ MSGBOXPARAMS params; DWORD dwUnk1; DWORD dwUnk2; DWORD dwUnk3; DWORD* lpdwListButtonId; WCHAR** lppszListButtonText; DWORD dwButtonCount; DWORD dwDefButtonId; DWORD dwCancelButtonId; DWORD dwTimeout;} MSGBOXINFO_W8;
Mã:- void StartHookInline(BYTE *src, BYTE *des, int len, void *org){ BYTE *jmp; DWORD oldProtect; jmp=(BYTE*)VirtualAlloc(NULL, 5+len, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); CopyMemory(jmp, src, len); jmp[len]=0xe9; *(DWORD*)&jmp[len+1]=(DWORD)src-(DWORD)jmp-5; *(DWORD*)org=(DWORD)jmp; VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &oldProtect); src[0]=0xe9; *(DWORD*)(src+1)=(DWORD)des-(DWORD)src-5; VirtualProtect(src, len, oldProtect, &oldProtect);}
Mã:- typedef DWORD (WINAPI *_SoftModalMessageBox)(void*);_SoftModalMessageBox cmbSoftModalMessageBox_org=NULL; //Function overwrite for win 7 and xpDWORD WINAPI cmMySoftModelMessageBox(MSGBOXINFO *info){ const WCHAR *text[]={L"Em đồng ý", L"Em từ chối", L"Hủy bỏ"}; const DWORD id[]={IDYES, IDNO, IDCANCEL}; info->lppszListButtonText=(WCHAR**)text; info->lpdwListButtonId=(DWORD*)id; info->dwButtonCount=3; return cmSoftModalMessageBox_org(info);}//Function overwrite for win 8 and laterDWORD WINAPI cmSoftModalMessageBoxW8(MSGBOXINFO_W8 *info){ const WCHAR *text[]={L"Em đồng ý", L"Em từ chối", L"Hủy bỏ"}; const DWORD id[]={IDYES, IDNO, IDCANCEL}; info->lppszListButtonText=(WCHAR**)text; info->lpdwListButtonId=(DWORD*)id; info->dwButtonCount=3; return cmSoftModalMessageBox_org(info);}
Mã:- DWORD hUser32;DWORD fnc;DWORD dwMajorVersion, dwMinorVersion, dwVersion; dwVersion=GetVersion();dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); hUser32=(DWORD)GetModuleHandle(L"User32.dll");if (hUser32){ fnc=(DWORD)GetProcAddress((HMODULE)hUser32, "SoftModalMessageBox"); if (fnc) { if (dwMajorVersion>=6 && dwMinorVersion>=2)//Check win8 or later StartHookInline((BYTE*)fnc, (BYTE*)cmSoftModalMessageBoxW8, 5, (void*)&cmSoftModalMessageBox_org); else //Win7 and xp StartHookInline((BYTE*)fnc, (BYTE*)cmSoftModalMessageBox, 5, (void**)&cmSoftModalMessageBox_org); }}
<font size="3">I.c Thêm nút bấm “Yes to all” vào hộp thoại MessageBox
- Viết lại hook SoftModalMessageBox để thêm nút bấm YesToAll
Mã:- //Function overwrite for win 7 and xpDWORD WINAPI cmSoftModalMessageBox(MSGBOXINFO *info){ const WCHAR *text[]={L"Yes to &All", L"Em đồng ý", L"Em từ chối", L"Hủy bỏ"}; const DWORD id[]={IDOK, IDYES, IDNO, IDCANCEL}; info->lppszListButtonText=(WCHAR**)text; info->lpdwListButtonId=(DWORD*)id; info->dwButtonCount=4; return cmSoftModalMessageBox_org(info);} //Function overwrite for win 8 and laterDWORD WINAPI cmSoftModalMessageBoxW8(MSGBOXINFO_W8 *info){ const WCHAR *text[]={L"Yes to &All", L"Em đồng ý", L"Em từ chối", L"Hủy bỏ"}; const DWORD id[]={IDOK, IDYES, IDNO, IDCANCEL}; info->lppszListButtonText=(WCHAR**)text; info->lpdwListButtonId=(DWORD*)id; info->dwButtonCount=4; return cmSoftModalMessageBox_org(info);}
II. Thay đổi màu text</font>
II.a Giới thiệu
Màu của các đoạn text của hộp thoại MessageBox được đặt thông qua hàm winapi SetTextColor. Vì vậy chúng ta sẽ hook hàm này để thay đổi màu các đoạn text trong hộp thoại. Vấn đề chính ở đây là hàm SetTextColor được gọi khá nhiều để thay đổi các đoạn text khác trong chương trình, còn chúng ta chỉ muốn đổi màu các đoạn text trong hộp thoại chúng ta muốn.
Một suy nghĩ đến khá tự nhiên, chúng ta sẽ làm cách nào đó để phân biệt hàm SetTextColor này sẽ thay đổi màu của đoạn text nào, từ đó quyết định có thay đổi thành màu chúng ta muốn hay giữ nguyên màu mặc định của chương trình.
Phương pháp kiểm tra hàm SetTextColor thay đổi text của hộp thoại MessageBox
- Sử dụng hàm WindowFromDC để lấy về hwndSử dụng hàm GetParent để lầy về hwnd của cửa sổ cha (vì các đoạn text đều nằm trong các childwindow của hộp thoại MessageBox)Kiểm tra cửa sổ cha có phải là hộp thoại MessageBox không? Có một điểm đặc biệt khá thú vị, cửa sổ được tạo ra bởi MessageBox có chứa một dữ liệu "userdata" 4 bytes chính là con trỏ tới cấu trúc MSGBOXINFO. Do đó chúng ta có thể sử dụng dữ liệu này để kiểm tra xem cửa sổ này có phải là hộp thoại MessageBox hay không?
II.b Thay đổi màu đoạn text nội dung của MessageBox
- Đoạn text nội dung hộp thoại MessageBox là một child window với classname là “static”, vì vậy đơn giản chúng ta sẽ kiểm tra classname nào trùng với static thì sẽ đổi màu.Viết hàm hook SetTextColor để thay đổi màu cho đoạn text nội dung. Chú ý do trường đầu tiên trong cấu trúc MSGBOXINFO cả 2 version luôn là MSGBOXPARAMS, do đó chỉ cần viết 1 hàm SetTextColor cho cả 2 version
Mã:- COLORREF WINAPI cmSetTextColor(HDC hdc, COLORREF crColor){ HWND hWnd, hParent; BYTE *data; hWnd=WindowFromDC(hdc); hParent=GetParent(hWnd); if (hParent) { data=(BYTE*)GetWindowLong(hParent, GWL_USERDATA); if (data && ((MSGBOXPARAMS*)data)->cbSize==sizeof(MSGBOXPARAMS))//Valid for MessageBox { TCHAR szName[50]; GetClassName(hWnd, szName, 50); if (wcsicmp(szName, TEXT("static"))==0) crColor=RGB(0xff, 0x00, 0x00);//Set red color for text content } } return cmSetTextColor_org(hdc, crColor);}
Mã:- hGdi32=(DWORD)GetModuleHandle(L"Gdi32.dll"); if (hGdi32) { fnc=(DWORD)GetProcAddress((HMODULE)hGdi32, "SetTextColor"); if (fnc) { StartHookInline((BYTE*)fnc, (BYTE*)cmSetTextColor, 5, (void**)&cmSetTextColor_org); } }
<font size="3">II.c Thay đổi màu đoạn text trong các nút bấm
- Cũng giống phương pháp đổi màu đoạn text nội dung, các nút bấm trong hộp thoại MessageBox những child window với classname là “button”.Viết hàm hook SetTextColor
Mã:- COLORREF WINAPI cmSetTextColor(HDC hdc, COLORREF crColor){ HWND hWnd, hParent; BYTE *data; hWnd=WindowFromDC(hdc); hParent=GetParent(hWnd); if (hParent) { data=(BYTE*)GetWindowLong(hParent, GWL_USERDATA); if (data && ((MSGBOXPARAMS*)data)->cbSize==sizeof(MSGBOXPARAMS))//Valid for MessageBox { TCHAR szName[50]; GetClassName(hWnd, szName, 50); if (wcsicmp(szName, TEXT("static"))==0) crColor=RGB(0xff, 0x00, 0x00);//Set red color for text content else if (wcsicmp(szName, TEXT("button"))==0) crColor=RGB(0x00, 0x00, 0xff);//Set blue color for text button } } return cmSetTextColor_org(hdc, crColor);}
View more random threads:
- chỉ dẫn phương pháp Hook APi bằng inline hook
- Lỗi messagebox chỉ hiện lên khi người dùng nhấn ALT
- [Kernel Driver] ShaDow SSDT Hook Có Phải là Hook đồ Họa
- Mã : Liệt kê tất cả các tập tin theo 1 đuôi mở rộng trong 1 ổ đĩa
- Thắc mắc Theo Dõi Process. Bắt một process mới hoạt động.
- Cần 1 source đơn giản về Hook. Ai giúp em?
- Antivirus lấy các hàm API trong PE File bằng cách nào
- SetWinEventHook AccessibleObjectFromEvent ?
- Detect User Hook by user mode code?
- cần tìm lỗi của dialog box WIN32 API
Pallet nhựa Long An đã trở thành một trong những lựa chọn phổ biến cho nhu cầu vận chuyển và lưu trữ hàng hóa trong nhiều ngành công nghiệp. Với đặc tính nhẹ nhàng, chắc chắn và dễ vận chuyển, các...
Thanh lý pallet nhựa Long An giá rẻ