diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 1c42daf..7ec7287 --- a/README.md +++ b/README.md @@ -1,4 +1,44 @@ -# StopShutdown -A small proof of concept that temporarily prevents a shutdown +# WinAPI-Fun +> A collection of (relatively) harmless prank / virus examples using the Windows API -This really small program is handy if you have pesky friends / coworkers that think its funny to shutoff your computer while you are working. I had a problem with this in one of my classes, so I created an easy solution. +
+ +Pre-built binaries can be found in the [Releases](../../releases) section + +To reset most examples, re-launch and kill the program again + +
+ +| File | Description | +| -------------------------------------------------- | --------------------------------------------------------------------- | +| [avoid.nim](src/avoid.nim) | The start button avoids mouse clicks by jumping around on the taskbar | +| [bsod.nim](src/bsod.nim) | Triggers Blue Screen of Death | +| [dripper.nim](src/dripper.nim) | Moves the current window down slightly every 10 seconds | +| [highcontrast.nim](src/highcontrast.nim) | Enable high contrast mode system-wide | +| [intercept_space.nim](src/intercept_space.nim) | Replaces space bar keypress with the word "space" | +| [mouse_button_swap.nim](src/mouse_button_swap.nim) | Swap the left and right mouse buttons | +| [mouse_trails.nim](src/mouse_trails.nim) | Creates a trail of mouse icons behind the cursor as it moves | +| [mouse_trap.nim](src/mouse_trap.nim) | Traps the mouse cursor in the top right corner for 60 seconds | +| [random_capslock.nim](src/random_capslock.nim) | Randomly toggle the Caps Lock every 0-30 seconds | +| [random_close.nim](src/random_close.nim) | Randomly closes the current focussed window every 0-30 seconds | +| [rotate.nim](src/rotate.nim) | Rotates the display 180 degrees | +| [shake.nim](src/shake.nim) | Rapidly shakes the current focussed window | +| [start_disable.nim](src/start_disable.nim) | Disables clicking the start button or taskbar | +| [start_popup.nim](src/start_popup.nim) | Opens the start menu popup randomly every 0-60 seconds | +| [stop_shutdown.nim](src/stop_shutdown.nim) | Temporarily prevents a shutdown with a custom message | +| [time_local.nim](src/time_local.nim) | Adds the message "HI" to the AM/PM localization string system-wide | + +
+ +## Requirements +[Install Nim](https://nim-lang.org/install_unix.html) and the [Winim](https://github.com/khchen/winim) library, then compile with the `--app:gui` flag + +Note: if cross-compiling from Linux or macOS, also install the [mingw](https://www.mingw-w64.org/) toolchain and use the `-d:mingw` flag + +```sh +nim c -d:mingw --app:gui src/avoid.nim +``` + +

+ +### USE AT YOUR OWN RISK \ No newline at end of file diff --git a/src/avoid.nim b/src/avoid.nim new file mode 100755 index 0000000..f85f575 --- /dev/null +++ b/src/avoid.nim @@ -0,0 +1,45 @@ +import std/random +import winim + + +let hWndTaskBar = FindWindow("Shell_TrayWnd", NULL); +let hWndStart = FindWindowEx(hWndTaskBar, 0x0, "Start", "Start"); + +var cursor: POINT +GetCursorPos(&cursor) + +var rectTaskBar: RECT +GetWindowRect(hWndTaskBar, &rectTaskBar) + +var rectStart: RECT +GetWindowRect(hWndStart, &rectStart) + +# Reset Start Button Position +SetWindowPos(hWndStart, 0x0, 0, 0, 0, 0, (SWP_NOSIZE or SWP_NOZORDER)) + +var upperBound = rectTaskBar.right - rectStart.right; + + +# Run callback everytime mouse is moved +proc HookCallback(nCode: int32, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} = + GetCursorPos(&cursor) + + if cursor.x >= rectStart.left and cursor.x <= rectStart.right and cursor.y >= rectStart.top: + var newX = rand(upperBound) + SetWindowPos(hWndStart, 0x0, (int32)newX, 0, 0, 0, (SWP_NOSIZE or SWP_NOZORDER)) + GetWindowRect(hWndStart, &rectStart) + + return CallNextHookEx(0, nCode, wParam, lParam) + + +# Hook LowLevelMouseProc +var hook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC) HookCallback, 0, 0) +if bool(hook): + try: + PostMessage(0, 0, 0, 0) + var msg: MSG + while GetMessage(msg.addr, 0, 0, 0): + discard + + finally: + UnhookWindowsHookEx(hook) diff --git a/src/bsod.nim b/src/bsod.nim new file mode 100755 index 0000000..68a7e13 --- /dev/null +++ b/src/bsod.nim @@ -0,0 +1,17 @@ +import winim + + +proc RtlAdjustPrivilege*(privilege: ULONG, bEnablePrivilege: BOOLEAN, isThreadPrivilege: BOOLEAN, previousValue: PBOOLEAN): NTSTATUS + {.discardable, stdcall, dynlib: "ntdll", importc: "RtlAdjustPrivilege".} + +proc NtRaiseHardError*(errorStatus: NTSTATUS, numberOfParameters: ULONG, unicodeStringParameterMask: ULONG, parameters: PULONG_PTR, validResponseOption: ULONG, response: PULONG): NTSTATUS + {.discardable, stdcall, dynlib: "ntdll", importc: "NtRaiseHardError".} + +var + prev: BOOLEAN + response: ULONG + +# SE_SHUTDOWN_PRIVILEGE = 19 +discard RtlAdjustPrivilege(19, TRUE, FALSE, &prev) + +discard NtRaiseHardError(STATUS_ASSERTION_FAILURE, 0, 0, NULL, 6, &response); \ No newline at end of file diff --git a/src/dripper.nim b/src/dripper.nim new file mode 100755 index 0000000..80b2dfc --- /dev/null +++ b/src/dripper.nim @@ -0,0 +1,12 @@ +import os +import winim + + +var windowCoords: RECT + +while true: + var hWnd = GetForegroundWindow() + GetWindowRect(hWnd, &windowCoords) + + SetWindowPos(hWnd, 0x0, windowCoords.left, windowCoords.top + 2, 0, 0, (SWP_NOSIZE or SWP_NOZORDER)) + sleep(10000) \ No newline at end of file diff --git a/src/highcontrast.nim b/src/highcontrast.nim new file mode 100755 index 0000000..673311c --- /dev/null +++ b/src/highcontrast.nim @@ -0,0 +1,11 @@ +import winim + + +var contrast: HIGHCONTRASTA +contrast.cbSize = (int32)sizeof(HIGHCONTRASTA) + +SystemParametersInfoA(SPI_GETHIGHCONTRAST, (int32)sizeof(HIGHCONTRASTA), &contrast, 0) + +contrast.dwFlags = contrast.dwFlags xor HCF_HIGHCONTRASTON + +SystemParametersInfoA(SPI_SETHIGHCONTRAST, (int32)sizeof(HIGHCONTRASTA), &contrast, 0) \ No newline at end of file diff --git a/src/intercept_space.nim b/src/intercept_space.nim new file mode 100755 index 0000000..9210d98 --- /dev/null +++ b/src/intercept_space.nim @@ -0,0 +1,83 @@ +import winim + + +type + SendKeys = array[12, INPUT] + +proc SendSpace() = + var inputs: SendKeys + + # Hold shift for caps + inputs[0].type = INPUT_KEYBOARD + inputs[0].ki.wVk = VK_SHIFT + + # S key + inputs[1].type = INPUT_KEYBOARD + inputs[1].ki.wVk = 0x53 + inputs[2].type = INPUT_KEYBOARD + inputs[2].ki.wVk = 0x53 + inputs[2].ki.dwFlags = KEYEVENTF_KEYUP + + # P key + inputs[3].type = INPUT_KEYBOARD + inputs[3].ki.wVk = 0x50 + inputs[4].type = INPUT_KEYBOARD + inputs[4].ki.wVk = 0x50 + inputs[4].ki.dwFlags = KEYEVENTF_KEYUP + + # A key + inputs[5].type = INPUT_KEYBOARD + inputs[5].ki.wVk = 0x41 + inputs[6].type = INPUT_KEYBOARD + inputs[6].ki.wVk = 0x41 + inputs[6].ki.dwFlags = KEYEVENTF_KEYUP + + # C key + inputs[7].type = INPUT_KEYBOARD + inputs[7].ki.wVk = 0x43 + inputs[8].type = INPUT_KEYBOARD + inputs[8].ki.wVk = 0x43 + inputs[8].ki.dwFlags = KEYEVENTF_KEYUP + + # E key + inputs[9].type = INPUT_KEYBOARD + inputs[9].ki.wVk = 0x45 + inputs[10].type = INPUT_KEYBOARD + inputs[10].ki.wVk = 0x43 + inputs[10].ki.dwFlags = KEYEVENTF_KEYUP + + # Release shift key + inputs[11].type = INPUT_KEYBOARD + inputs[11].ki.wVk = VK_SHIFT + inputs[11].ki.dwFlags = KEYEVENTF_KEYUP + + SendInput((UINT)len(inputs), &inputs[0], (int32)sizeof(INPUT)); + + +# Run callback everytime key is pressed +proc HookCallback(nCode: int32, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} = + + if (bool(lParam)): + var kbd: PKBDLLHOOKSTRUCT = cast[ptr KBDLLHOOKSTRUCT](lparam) + + if (kbd.vkCode == VK_SPACE): + if (wParam == WM_KEYDOWN): + SendSpace() + return 1 + elif (wParam == WM_KEYUP): + return 1 + + return CallNextHookEx(0, nCode, wParam, lParam) + + +# Hook LowLevelKeyboardProc +var hook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC) HookCallback, 0, 0) +if bool(hook): + try: + PostMessage(0, 0, 0, 0) + var msg: MSG + while GetMessage(msg.addr, 0, 0, 0): + discard + + finally: + UnhookWindowsHookEx(hook) diff --git a/src/mouse_button_swap.nim b/src/mouse_button_swap.nim new file mode 100755 index 0000000..589c7f4 --- /dev/null +++ b/src/mouse_button_swap.nim @@ -0,0 +1,5 @@ +import winim + +# If buttons were already swapped, return back to normal +if (SwapMouseButton(TRUE)): + SwapMouseButton(FALSE) diff --git a/src/mouse_trails.nim b/src/mouse_trails.nim new file mode 100755 index 0000000..1456118 --- /dev/null +++ b/src/mouse_trails.nim @@ -0,0 +1,13 @@ +import std/random +import winim + + +var trails: int32 +SystemParametersInfoA(SPI_GETMOUSETRAILS, 0, &trails, 0) + +if (trails < 2): + trails = (int32)rand(2..9) +else: + trails = 0 + +SystemParametersInfoA(SPI_SETMOUSETRAILS, trails, NULL, 0) \ No newline at end of file diff --git a/src/mouse_trap.nim b/src/mouse_trap.nim new file mode 100755 index 0000000..013bb09 --- /dev/null +++ b/src/mouse_trap.nim @@ -0,0 +1,10 @@ +import std/os +import winim + + +var rect: RECT +SetRect(&rect, 0, 0, 100, 100); + +ClipCursor(&rect); +sleep(60000) +ClipCursor(NULL); \ No newline at end of file diff --git a/src/random_capslock.nim b/src/random_capslock.nim new file mode 100755 index 0000000..aa4ace4 --- /dev/null +++ b/src/random_capslock.nim @@ -0,0 +1,23 @@ +import std/os +import std/random +import winim + + +type + SendKeys = array[2, INPUT] + +var inputs: SendKeys + +# Key Down event +inputs[0].type = INPUT_KEYBOARD +inputs[0].ki.wVk = VK_CAPITAL + +# Key Up event +inputs[1].type = INPUT_KEYBOARD +inputs[1].ki.wVk = VK_CAPITAL +inputs[1].ki.dwFlags = KEYEVENTF_KEYUP + +# Send keypress randomly +while true: + SendInput((UINT)len(inputs), &inputs[0], (int32)sizeof(INPUT)); + sleep(rand(30000)) \ No newline at end of file diff --git a/src/random_close.nim b/src/random_close.nim new file mode 100755 index 0000000..c22ad97 --- /dev/null +++ b/src/random_close.nim @@ -0,0 +1,28 @@ +import std/os +import std/random +import winim + + +type + SendKeys = array[4, INPUT] + +var inputs: SendKeys + +inputs[0].type = INPUT_KEYBOARD +inputs[0].ki.wVk = VK_MENU + +inputs[1].type = INPUT_KEYBOARD +inputs[1].ki.wVk = VK_F4 + +inputs[2].type = INPUT_KEYBOARD +inputs[2].ki.wVk = VK_F4 +inputs[2].ki.dwFlags = KEYEVENTF_KEYUP + +inputs[3].type = INPUT_KEYBOARD +inputs[3].ki.wVk = VK_MENU +inputs[3].ki.dwFlags = KEYEVENTF_KEYUP + +# Send keypress randomly +while true: + SendInput((UINT)len(inputs), &inputs[0], (int32)sizeof(INPUT)); + sleep(rand(30000)) \ No newline at end of file diff --git a/src/rotate.nim b/src/rotate.nim new file mode 100755 index 0000000..9f4d39d --- /dev/null +++ b/src/rotate.nim @@ -0,0 +1,12 @@ +import winim + + +var dm: DEVMODE +EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm) + +if (dm.dmDisplayOrientation == DMDO_DEFAULT): + dm.dmDisplayOrientation = DMDO_180 +else: + dm.dmDisplayOrientation = DMDO_DEFAULT + +ChangeDisplaySettings(&dm, 0) \ No newline at end of file diff --git a/src/shake.nim b/src/shake.nim new file mode 100755 index 0000000..5338ff3 --- /dev/null +++ b/src/shake.nim @@ -0,0 +1,22 @@ +import os +import std/random +import winim + + +var hWndOrig = GetForegroundWindow() +var windowCoords: RECT +GetWindowRect(hWndOrig, &windowCoords) + +while true: + var hWndNew = GetForegroundWindow() + + if (hWndNew != hWndOrig): + hWndOrig = hWndNew + GetWindowRect(hWndOrig, &windowCoords) + + var + newX = rand(windowCoords.left - 3 .. windowCoords.left + 3) + newY = rand(windowCoords.top - 3 .. windowCoords.top + 3) + + SetWindowPos(hWndOrig, 0x0, (int32)newX, (int32)newY, 0, 0, (SWP_NOSIZE or SWP_NOZORDER)) + sleep(10) \ No newline at end of file diff --git a/src/start_disable.nim b/src/start_disable.nim new file mode 100755 index 0000000..c9bbccf --- /dev/null +++ b/src/start_disable.nim @@ -0,0 +1,10 @@ +import winim + + +let hWndTaskBar = FindWindow("Shell_TrayWnd", NULL); +let hWndStart = FindWindowEx(hWndTaskBar, 0x0, "Start", "Start"); + +# If the windows are already disabled, re-enable them +if (EnableWindow(hWndStart, FALSE) or EnableWindow(hWndTaskBar, FALSE)): + EnableWindow(hWndStart, TRUE) + EnableWindow(hWndTaskBar, TRUE) \ No newline at end of file diff --git a/src/start_popup.nim b/src/start_popup.nim new file mode 100755 index 0000000..803be99 --- /dev/null +++ b/src/start_popup.nim @@ -0,0 +1,22 @@ +import std/os +import winim + + +type + SendKeys = array[2, INPUT] + +var inputs: SendKeys + +# Key Down event +inputs[0].type = INPUT_KEYBOARD +inputs[0].ki.wVk = VK_LWIN + +# Key Up event +inputs[1].type = INPUT_KEYBOARD +inputs[1].ki.wVk = VK_LWIN +inputs[1].ki.dwFlags = KEYEVENTF_KEYUP + +# Send input every 60 seconds +while true: + SendInput((UINT)len(inputs), &inputs[0], (int32)sizeof(INPUT)); + sleep(60000) \ No newline at end of file diff --git a/src/stop_shutdown.nim b/src/stop_shutdown.nim new file mode 100755 index 0000000..1a3e263 --- /dev/null +++ b/src/stop_shutdown.nim @@ -0,0 +1,44 @@ +import winim + + +var + hInstance = GetModuleHandle(nil) + hwnd: HWND + msg: MSG + wndclass: WNDCLASS + + +# Handle Message Pump +proc WindowProc(hwnd: HWND, message: UINT, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} = + case message + of WM_DESTROY: + PostQuitMessage(0) + return 0 + + of WM_CLOSE, WM_QUERYENDSESSION: + return 0 + + else: + return DefWindowProc(hwnd, message, wParam, lParam) + + +# Boilerplate to create window +wndclass.style = CS_HREDRAW or CS_VREDRAW +wndclass.lpfnWndProc = WindowProc +wndclass.cbClsExtra = 0 +wndclass.cbWndExtra = 0 +wndclass.hInstance = hInstance +wndclass.hIcon = LoadIcon(0, IDI_APPLICATION) +wndclass.hCursor = LoadCursor(0, IDC_ARROW) +wndclass.hbrBackground = GetStockObject(WHITE_BRUSH) +wndclass.lpszMenuName = nil +wndclass.lpszClassName = "StopShutdown" +RegisterClass(wndclass) + +hwnd = CreateWindow("StopShutdown", "Stop Shutdown", WS_MINIMIZE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, nil) + +ShutdownBlockReasonCreate(hwnd, "Nice Try") + +while GetMessage(msg, 0, 0, 0) != 0: + TranslateMessage(msg) + DispatchMessage(msg) \ No newline at end of file diff --git a/src/time_local.nim b/src/time_local.nim new file mode 100755 index 0000000..0fc9803 --- /dev/null +++ b/src/time_local.nim @@ -0,0 +1,15 @@ +import std/registry + + +var + hkcuHandle = registry.HKEY_CURRENT_USER + amLocal = getUnicodeValue("Control Panel\\International", "s1159", hkcuHandle) + pmLocal = getUnicodeValue("Control Panel\\International", "s2359", hkcuHandle) + + +if (amLocal == "AM" and pmLocal == "PM"): + setUnicodeValue("Control Panel\\International", "s1159", "AM HI", hkcuHandle) + setUnicodeValue("Control Panel\\International", "s2359", "PM HI", hkcuHandle) +else: + setUnicodeValue("Control Panel\\International", "s1159", "AM", hkcuHandle) + setUnicodeValue("Control Panel\\International", "s2359", "PM", hkcuHandle) \ No newline at end of file