I'm back, and I brought along with me my newest creation: BausButton. (Pronounced Boss Button.)

This little Windows app sits innocuously in your notification tray.  When you hit the hotkey, whatever window has focus at that moment disappears.  The window disappears and the task bar icon (if any) also disappears. Hit the hotkey again and the window reappears.  See... a boss button... for when the boss walks in and you need to quickly hide whatever you were looking at.

But there's more. It's got password protection. If you have set a password previously, then BausButton will challenge you before it un-hides the hidden window.  Passwords are salted and then hashed with SHA256. (A new random salt is generated upon each new "installation" of the app.)

By default, the "boss button" is mapped to the "Scroll Lock" key, but you may customize the hotkey by editing the BausButton registry key.


The "HideKey" value corresponds to the virtual key-codes defined by Microsoft, which you can find right here. So for instance, if you wanted to change the hotkey to the space bar, you'd change the HideKey registry value to 0x20 (decimal 32.)

If you ever just want to reset everything, just close the app, delete the whole BausButton registry key, then restart the app.

Some screenshots:

When no window is hidden, the BausButton icon is colored in.

When a window is hidden, the BausButton icon is transparent.

If you click the icon, you get a very simple menu. If you exit the app, any hidden window will automatically be unhidden before the app exits, and if a password is set, you will be challenged for that password before the app exits, and if you get the password wrong, the app just won't exit.

Here's the signed binary. Let me know what you think.

(Update 8/14/2015: v1.0.1 - Fixed password dialog focus problem.) (144 KB)

Universal Pause Button

I like to play video games.  I also have a significant other, and she often walks into the room to talk to me while I'm playing a video game.  I would like to pause the game so that I can give her my undivided attention while she's talking to me, but a lot of games (particularly single-player ones) have these "un-pausable" cut scenes or other areas of the game where the normal pause functionality doesn't work.  This annoys both me and her, because I'm supposed to be the computer expert, and it looks like I don't even know how to pause my stupid video game.  So usually what ends up happening is I skip the cut scene and miss the story, or upset my SO by not paying attention to her as well as I should.

So that is why I wrote Universal Pause Button. It's a very simple Windows desktop app that sits in the system tray. Its icon resembles a pause button.  When you hit the actual Pause key (also known as Break) on your keyboard, the program determines which window is currently in the foreground (i.e. your game's window,) and pauses it.  No matter where you are in the game. Even in the middle of one of those pesky cut scenes that would otherwise be un-pausable.  When you press the key again (as long as you haven't since re-focused to another window,) the game will un-pause.

As of v1.0.3 you can now customize the "Pause" key that you want to use. Read the settings.txt file. The program reads the custom pause key from the settings.txt file during startup.

I've currently been testing this with The Witcher 3, and it is working great.  However, your mileage may vary. "Pausing" processes is something that usually only debuggers do, and I can't predict how your game will react to it.  Pausing processes may lead to race conditions among the threads of that process, but like I said, testing has been very positive for me so far.  I've already gotten great value out of the program, as there are lots of cut scenes in The Witcher 3, that I don't want to skip. The main use case for this app is single player games, as pausing your multi-player game will undoubtedly just get you kicked from the session, as if your computer had just crashed or hung. So don't use it in multi-player games.  It also works on applications that are not games at all.

Also, it's open source!  You can find the source on Github here.

If you prefer to just download the (signed) executable, here it is:

UniversalPauseButton.exe (124.3KB)


I wrote something this weekend.

TinyWebRedirector v1.0 - Redirects HTTP Requests
Copyright (C) 2015 Joseph Ryan Ries

Install:   TinyWebRedirector -install
Uninstall: TinyWebRedirector -uninstall

I wrote this micro web server for all the sysadmins out there who have an internal Active Directory that shares the same DNS name as their public domain name. Let's say your internal AD domain name is Your public website is also In this scenario, internal employees at the office cannot reach your public website by entering into their web browsers, because internally resolves to the IP address of one of your AD domain controllers. This has lead to messy solutions, such as installing IIS on each domain controller, for the sole purpose of redirecting requests on port 80 to But installing IIS on your domain controllers is not a great idea.

TinyWebRedirector is more suited to this purpose because:

  • It is tiny. The image file is 110KB, and runs with a ~2.6MB working set. It requires no redistributable DLLs.
  • It does one thing and one thing only. This translates to a much smaller potential attack surface than a large web server such as IIS.
  • It is written in C, and so does not require .NET. Will run on any Windows machine Vista/2008 or greater.
  • The listening port (default 80) and the URL to redirect visitors to is configurable in the registry at HKLM\SYSTEM\CurrentControlSet\Services\TinyWebRedirector. Restart the service for changes to take effect.
  • The service runs as Local Service. This is a much safer configuration than services that run as Local System.

Please let me know if you find any bugs or weaknesses.

Github repository is here.

The compiled and signed x64 binary is here:

TinyWebRedirector.exe (112.8KB)

The Basics of DLL Injection Part I

Hello... sorry for not posting in a while.  I've been going through some recent career changes and haven't really come across any IT-related inspiration lately.  I thought I'd post a simple, bare-bones technique of injecting a DLL into a running process on a Windows computer.  It's really simple.

  1. Verify that the PID supplied is valid.
  2. Get a handle to the remote process.
  3. Allocate memory in the remote process.
  4. Write the DLL path into the remote process's memory.
  5. Call CreateRemoteThread to induce LoadLibrary in the remote process. 

As long as the process does not already have the DLL loaded, the remote process will automatically call DllMain (the injected DLL's entry point,) which can contain all sorts of fun code.  For instance, now that you have injected a DLL into the remote process, you are well on your way to performing something like API hooking, for example. You could modify the Import Address Table of the remote process... but I'm getting ahead of myself.  First things first.  Without further ado:

// InjectDLL.cpp
// Joseph Ryan Ries - 2015
// Injects a DLL into another process on the system.


// Returns true if the supplied file path exists and is a file.
// Returns false if the supplied path does not exist, or is a directory.
BOOL FileExists(LPCTSTR FilePath)
	DWORD FileAttributes = GetFileAttributes(FilePath);

	return (FileAttributes != INVALID_FILE_ATTRIBUTES && !(FileAttributes & FILE_ATTRIBUTE_DIRECTORY));

// Entry point. Returns 0 at the end if everything was successful.
// Returns 1 if something failed. Outputs messages to console.
int wmain(int argc, wchar_t *argv[])
	if (argc != 3)
		wprintf_s(L"\nUsage: %s C:\\Temp\\MyDLL.dll 1337\n", argv[0]);
		wprintf_s(L"\nUse the full path to the DLL you want to inject and supply the\n");
		wprintf_s(L"process ID (PID) of the process you want to inject it in to.\n");

	if (!FileExists(argv[1]))
		wprintf_s(L"\nERROR: Unable to find file %s.\n", argv[1]);

	wchar_t DLLPath[MAX_PATH] = { 0 };

	wcscpy_s(DLLPath, argv[1]);

	DWORD Pid = _wtoi(argv[2]);

	if (Pid == 0)
		wprintf_s(L"\nERROR: Unable to interpret the supplied process ID.\n");

	wprintf_s(L"Searching for PID %d.\n", Pid);

	DWORD CurrentProcesses[2048] = { 0 };
	DWORD ProcessListSize = 0;
	DWORD ProcessCount = 0;

	if (EnumProcesses(CurrentProcesses, sizeof(CurrentProcesses), &ProcessListSize) == 0)
		wprintf_s(L"\nERROR: Unable to enumerate currently running processes!\nLastError: 0x%x.\n", GetLastError());

	ProcessCount = ProcessListSize / sizeof(DWORD);

	wprintf_s(L"%d processes currently on the system.\n", ProcessCount - 1);

	BOOL ProcessFound = FALSE;

	for (unsigned int ProcessCounter = 0; ProcessCounter < ProcessCount; ProcessCounter++)
		if (CurrentProcesses[ProcessCounter] == 0)
		if (CurrentProcesses[ProcessCounter] == Pid)
			ProcessFound = TRUE;

	if (ProcessFound == FALSE)
		wprintf_s(L"\nERROR: A process with PID %d could not be found.\n", Pid);

	HANDLE ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);

	if (ProcessHandle == NULL)
		wprintf_s(L"\nERROR: Unable to open handle to process %d. LastError 0x%x.\n", Pid, GetLastError());

	wprintf_s(L"Process with PID %d successfully opened.\n", Pid);

	void* RemoteDLLPathMemory = NULL;		// The DLL entry address in the remote process

	// VirtualAlloc will probably not give us less than 4k. Whatever. We only need ~520 bytes for MAX_PATH * 2.
	RemoteDLLPathMemory = VirtualAllocEx(ProcessHandle, NULL, (MAX_PATH * sizeof(wchar_t)), MEM_COMMIT, PAGE_READWRITE);

	if (RemoteDLLPathMemory == NULL)
		wprintf_s(L"\nERROR: Unable to allocate memory in remote process %d. LastError: 0x%x.\n", Pid, GetLastError());

	wprintf_s(L"Memory allocated in process %d.\n", Pid);

	SIZE_T BytesWritten = 0;

	if (WriteProcessMemory(ProcessHandle, RemoteDLLPathMemory, (void*)DLLPath, sizeof(DLLPath), &BytesWritten) == 0)
		wprintf_s(L"\nERROR: Unable to write DLL path into remote process memory. LastError: 0x%x.\n", GetLastError());

	wprintf_s(L"%I64d bytes written into the memory of process %d.\n", BytesWritten, Pid);
	HANDLE ThreadHandle = CreateRemoteThread(
		(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"),

	if (ThreadHandle == NULL)
		wprintf_s(L"\nERROR: Unable to start remote thread in process %d. LastError: 0x%x.\n", Pid, GetLastError());

	wprintf_s(L"Successfully loaded %s into process %d.\n", DLLPath, Pid);

	wprintf_s(L"Note: DllMain will only run if the DLL has not already been loaded by the process.\n");

Ignore the very last line (</psapi.h></windows.h></stdio.h>), the code editor wigged out.