Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
villor committed Mar 4, 2020
0 parents commit 67a5dc7
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
19 changes: 19 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) Launch",
"type": "cppvsdbg",
"request": "launch",
"program": "build/squeeze-injector.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false
}
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"C_Cpp.default.configurationProvider": "vector-of-bool.cmake-tools"
}
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.10)

project(squeeze)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_library(squeeze SHARED src/squeeze.cc)
add_executable(squeeze-injector WIN32 src/injector.cc)
12 changes: 12 additions & 0 deletions build.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@echo off

mkdir build
cd build

if not defined DevEnvDir (
call "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
)
cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug
cmake --build .

cd ..
69 changes: 69 additions & 0 deletions src/injector.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <Windows.h>
#include "shared.h"

static bool gShouldExit = 0;

// TODO: Add explorer.exe restart detection

int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
// Find shell window
HWND hWnd = FindWindow(TEXT("Shell_TrayWnd"), nullptr);
int t = 0;
while (hWnd == nullptr) {
Sleep(500);
hWnd = FindWindow(TEXT("Shell_TrayWnd"), nullptr);
t++;
if (t > 30 && hWnd == nullptr) {
MessageBox(0, TEXT("Could not find Shell_TrayWnd (is eplorer.exe running?)"), TEXT("Squeeze: Injection error"), MB_ICONERROR);
return -1;
}
}

// Get thread and process id for shell window
DWORD processId;
DWORD threadId = GetWindowThreadProcessId(hWnd, &processId);

HANDLE hProcess = OpenProcess(0xFFF, FALSE, processId);
if (hProcess == NULL) {
MessageBox(0, TEXT("Unable to obtain the explorer handle"), TEXT("Squeeze: Injection error"), MB_ICONERROR);
return -1;
}

// Allocate memory in explorer.exe and write squeeze DLL path to it
LPCSTR dllPath = "D:\\Dev\\squeeze\\build\\squeeze.dll";
SIZE_T dllPathSize = strlen(dllPath) + 1;
SIZE_T dllPathNumBytesWritten;
LPVOID lpRemoteBuf = VirtualAllocEx(hProcess, NULL, dllPathSize, MEM_COMMIT, PAGE_READWRITE);
if (WriteProcessMemory(hProcess, lpRemoteBuf, dllPath, dllPathSize, &dllPathNumBytesWritten)) {
if (dllPathNumBytesWritten != dllPathSize) {
VirtualFreeEx(hProcess, lpRemoteBuf, dllPathSize, MEM_COMMIT);
MessageBox(0, TEXT("Written memory length does not match DLL path length."), TEXT("Squeeze: Injection error"), MB_ICONERROR);
CloseHandle(hProcess);
return -1;
}
} else {
MessageBox(0, TEXT("Failed to write DLL path to explorer memory"), TEXT("Squeeze: Injection error"), MB_ICONERROR);
CloseHandle(hProcess);
return -1;
}
VirtualFreeEx(hProcess, lpRemoteBuf, dllPathSize, MEM_COMMIT);

// Inject squeeze DLL
DWORD dwNewThreadId;
LPVOID lpLoadDll = LoadLibraryA;
HANDLE hNewRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpLoadDll, lpRemoteBuf, 0, &dwNewThreadId);
if (hNewRemoteThread == NULL) {
MessageBox(0, TEXT("Failed to start remote thread (LoadLibraryA)."), TEXT("Squeeze: Injection error"), MB_ICONERROR);
CloseHandle(hProcess);
return -1;
}
WaitForSingleObject(hNewRemoteThread, INFINITE);
CloseHandle(hNewRemoteThread);
CloseHandle(hProcess);

// Send injector PID to the DLL so it knows when to exit
SendMessage(hWnd, WM_SQUEEZE, SQUEEZE_INJECTOR_PID, GetCurrentProcessId());

Sleep(INFINITE);
}
2 changes: 2 additions & 0 deletions src/shared.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define WM_SQUEEZE 0x0409
#define SQUEEZE_INJECTOR_PID 0x90
102 changes: 102 additions & 0 deletions src/squeeze.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#include <Windows.h>
#include "shared.h"

const int DESIRED_WIDTH = 2560;

static DWORD gInjectorPid = 0;
static HMODULE gModule = 0;
static HANDLE gThreadHandle = 0;
static HWND gTaskbarHWnd = 0;

static WNDPROC gOriginalWndProc = 0;

void UpdateTaskbar()
{
HWND desktopHWnd = GetDesktopWindow();
RECT desktopRect;
GetWindowRect(desktopHWnd, &desktopRect);

RECT taskbarRect;
GetWindowRect(gTaskbarHWnd, &taskbarRect);

int desiredLeft = (desktopRect.right / 2) - (DESIRED_WIDTH / 2);
int desiredRight = (desktopRect.right / 2) + (DESIRED_WIDTH / 2);

if (taskbarRect.left != desiredLeft || taskbarRect.right != desiredRight) {
// Resize taskbar and make sure everything is updated
SetWindowPos(gTaskbarHWnd, NULL, desiredLeft, taskbarRect.top, DESIRED_WIDTH, taskbarRect.bottom - taskbarRect.top, SWP_NOSENDCHANGING);
ShowWindow(gTaskbarHWnd, SW_SHOW);
UpdateWindow(gTaskbarHWnd);
RedrawWindow(desktopHWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
SystemParametersInfo(SPI_SETWORKAREA, 0, NULL, SPIF_SENDCHANGE);
}
}

void SqueezeExit()
{
if (gOriginalWndProc != NULL)
SetWindowLongPtr(gTaskbarHWnd, GWLP_WNDPROC, (LONG_PTR)gOriginalWndProc);

CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)FreeLibraryAndExitThread, gModule, 0, nullptr));
}

bool InjectorStillRunning()
{
if (gInjectorPid == 0)
return true; // Injector has not notified us so we assume we should keep running

HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, gInjectorPid);
DWORD lpExitCode;
GetExitCodeProcess(handle, &lpExitCode);
if (lpExitCode != STILL_ACTIVE)
return false;

return true;
}

LRESULT CALLBACK WndProcTaskBar(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (!InjectorStillRunning()) {
SqueezeExit();
return CallWindowProcA(gOriginalWndProc, hwnd, uMsg, wParam, lParam);
}

switch (uMsg) {
case WM_WINDOWPOSCHANGING:
UpdateTaskbar();
return 0;
case WM_SQUEEZE:
if (wParam == SQUEEZE_INJECTOR_PID) {
gInjectorPid = (DWORD)lParam;
}
default:
break;
}
return CallWindowProcA(gOriginalWndProc, hwnd, uMsg, wParam, lParam);
}

void SqueezeInit()
{
gTaskbarHWnd = FindWindow(TEXT("Shell_TrayWnd"), nullptr);
if (IsWindow(gTaskbarHWnd)) {
gOriginalWndProc = (WNDPROC)SetWindowLongPtr(gTaskbarHWnd, GWLP_WNDPROC, (LONG_PTR)&WndProcTaskBar);
}
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
gModule = hModule;
SqueezeInit(); // CreateThread?
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}

0 comments on commit 67a5dc7

Please sign in to comment.