已實現功能
整個窗口居中顯示,灰化最大化按鈕,空白處添加了消息回調,最後就是獲取輸入運算後判斷是否和預期相同,從而決定彈窗內容!這就是通常的 CrackMe 的套路windows
#include <windows.h> #include <string.h> LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); BOOL Check(char *Name, char *Flag); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { char *lpClassName = "FirstWin", *lpWindowName = "CrackMe0"; HWND hwnd; MSG msg; WNDCLASSEX wndclass; wndclass.cbSize = sizeof(wndclass); // 指定該結構體的大小 wndclass.style = CS_HREDRAW | CS_VREDRAW; // 寬度高度變化時重繪 wndclass.lpfnWndProc = WndProc; // 窗口回調函數 wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // NULL表示系統圖標,默認圖標 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); // 默認光標 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // 使用畫刷填充背景色,還能夠(HBRUSH)GetStockObject(BLACK_BRUSH) wndclass.lpszMenuName = NULL; wndclass.lpszClassName = lpClassName; wndclass.hIconSm = NULL; if (!RegisterClassEx(&wndclass)) { MessageBox(NULL, "Register Failed", "Tips", MB_ICONERROR); return 0; } hwnd = CreateWindow(lpClassName, lpWindowName, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, //style,WS_OVERLAPPEDWINDOW包括了最大化最小化以及關閉 0, // x 0, // y 400, // width 300, // height NULL, // hWndParent NULL, // hMenu hInstance, // hInstance NULL); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); /* 發送 WM_PAINT,保證窗口必定能夠刷新顯示 */ while (GetMessage(&msg, NULL, 0, 0)) { /* 用於Tab切換輸入框,IsDialogMessage會調用user32.dll處理某些按鍵消息,其他的交給咱們定義的窗口回調函數*/ if (!IsDialogMessage(hwnd, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; int screenWidth, screenHeight; int clientWidth, clientHeight; int id, event; PAINTSTRUCT ps; CHAR Name[32], Flag[32]; RECT rect; RECT crect; switch (message) { case WM_CREATE: /* 設置居中顯示主窗口 */ screenWidth = GetSystemMetrics(SM_CXSCREEN); screenHeight = GetSystemMetrics(SM_CYSCREEN); GetClientRect(hwnd, &crect); GetWindowRect(hwnd, &rect); // 區別於GetClientRect rect.left = (screenWidth - rect.right) / 2; rect.top = (screenHeight - rect.bottom) / 2; SetWindowPos(hwnd, HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, SWP_SHOWWINDOW); /* MoveWindow(hwnd, rect.left, rect.top, rect.right, rect.bottom, 1); 效果同上 */ CreateWindow("static", "Name:", WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE | SS_RIGHT, crect.right / 12, // 用比例保證兼容性 crect.bottom / 5, 90, 40, hwnd, (HMENU)1, (HINSTANCE)GetWindowLong(hwnd, -6), // # define GWL_HINSTANCE -6 NULL); CreateWindow("static", "Flag:", WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE | SS_RIGHT, crect.right / 12, crect.bottom * 2 / 5, 90, 40, hwnd, (HMENU)2, (HINSTANCE)GetWindowLong(hwnd, -6), NULL); CreateWindow("edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, crect.right / 3, crect.bottom / 5, 200, 35, hwnd, (HMENU)3, (HINSTANCE)GetWindowLong(hwnd, -6), NULL); CreateWindow("edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, crect.right / 3, crect.bottom * 2 / 5, 200, 35, hwnd, (HMENU)4, (HINSTANCE)GetWindowLong(hwnd, -6), NULL); CreateWindow("button", "Submit", WS_CHILD | WS_VISIBLE | WS_BORDER | BS_FLAT, crect.right * 2 / 5, crect.bottom * 16 / 25, 100, 35, hwnd, (HMENU)5, (HINSTANCE)GetWindowLong(hwnd, -6), NULL); break; case WM_CTLCOLORSTATIC: if ((HWND)lParam == GetDlgItem(hwnd, 1) || (HWND)lParam == GetDlgItem(hwnd, 2)) { SetTextColor((HDC)wParam, RGB(0, 0, 0)); SetBkMode((HDC)wParam, TRANSPARENT); } return (BOOL)(HBRUSH)GetStockObject(NULL_BRUSH); break; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); break; case WM_LBUTTONDOWN: MessageBox(hwnd, "Don't click here!", "Error", MB_OK); break; case WM_COMMAND: /* 當點擊菜單、按鈕、下拉列表框等控件時候,會觸發WM_COMMAND */ id = LOWORD(wParam); event = HIWORD(wParam); switch (id) { case 5: GetWindowText(GetDlgItem(hwnd, 3), Name, 32); GetWindowText(GetDlgItem(hwnd, 4), Flag, 32); if (*Name != 0 && *Flag != 0) // 字符判斷時要加*,還能夠用長度判斷是否爲空字符串;空字符串或者字符串結束就是內存中的00 { if (Check(Name, Flag)) // 字符串判斷要用strcmp;格式化輸出的%s是個特例須要傳地址 { MessageBox(hwnd, "Hi,admin!Your flag is right!", "Right", MB_OK); DestroyWindow(hwnd); } else { MessageBox(hwnd, "Your name or flag is wrong!", "Wrong", MB_OK); DestroyWindow(hwnd); } } else { MessageBox(hwnd, "Please input your name and flag!", "Tips", MB_OK); } break; default: return DefWindowProc(hwnd, message, wParam, lParam); } break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProc(hwnd, message, wParam, lParam); } BOOL Check(char *Name, char *Flag) { int i, len; char x; char *key = "You_are_a_pig!2333"; char flag_enc[] = {0x3f, 0x03, 0x14, 0x38, 0x1a, 0x26, 0x0d, 0x36, 0x54, 0x00, 0x41, 0x1a, 0x38, 0x47, 0x5e, 0x52, 0x0a, 0x4e}; if (!strcmp(Name, "admin") && strlen(Flag) == 18) { for (i = 0; i < len; i++) { x = Flag[i] ^ key[i]; if (x != flag_enc[i]) { return 0; } else { continue; } } } else { return 0; } return 1; }
很簡單的 CrackMe,主要是爲了學習 Windows 消息機制,程序調用gcc -m32 -mwindows
編譯的函數