mirror of
https://github.com/sslab-gatech/winnie
synced 2026-06-08 17:35:47 +00:00
204 lines
5.2 KiB
C++
204 lines
5.2 KiB
C++
#include "pch.h"
|
|
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
#include <Windows.h>
|
|
#include <winternl.h>
|
|
#include <tlhelp32.h>
|
|
#include <conio.h>
|
|
#include <stdio.h>
|
|
#include <tchar.h>
|
|
#include <vector>
|
|
|
|
#include <forklib.h>
|
|
|
|
#define DEBUG_LOG_FILE "C:\\sslab\\temp.log"
|
|
const char* remove_cmd = "del " DEBUG_LOG_FILE;
|
|
LONGLONG pid;
|
|
|
|
void createConsole()
|
|
{
|
|
AllocConsole();
|
|
freopen_s((FILE**)stdout, "CONOUT$", "w+", stdout);
|
|
freopen_s((FILE**)stdin, "CONIN$", "r", stdin);
|
|
}
|
|
|
|
void check_fwrite(int usefork, int dryrun) {
|
|
FILE *fp;
|
|
fp = fopen(DEBUG_LOG_FILE, "a");
|
|
if (!fp) return; // sometimes the file is locked or some BS like that
|
|
fprintf(fp, "fork:%d, dry:%d\n", usefork, dryrun);
|
|
fclose(fp);
|
|
}
|
|
|
|
LARGE_INTEGER time()
|
|
{
|
|
LARGE_INTEGER now;
|
|
QueryPerformanceCounter(&now);
|
|
return now;
|
|
}
|
|
|
|
void* lol;
|
|
int forkCount = 0;
|
|
|
|
int child()
|
|
{
|
|
//Sleep(1000 * 20);
|
|
//getc(stdin);
|
|
printf("Hello!!!\n");
|
|
check_fwrite(pid, forkCount);
|
|
|
|
Sleep(5); // Simulate some work
|
|
|
|
//DebugBreak(); // give a breakpoint to debugger.
|
|
((int*)lol)[forkCount % 1000];
|
|
|
|
printf("We need to talk.\n");
|
|
BYTE message[1] = { 0x69 };
|
|
DWORD nRead;
|
|
BYTE response[1];
|
|
BOOL result = CallNamedPipeA("\\\\.\\pipe\\fuzzer", message, sizeof(message), response, sizeof(response), &nRead, NMPWAIT_WAIT_FOREVER);
|
|
printf("Okay, goodbye.\n");
|
|
TerminateProcess(GetCurrentProcess(), 0);
|
|
return 0;
|
|
}
|
|
|
|
#define NUM_ITER 80
|
|
|
|
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
system(remove_cmd);
|
|
|
|
// just initialize some data to make it more work to fork.
|
|
void* lol = HeapAlloc(GetProcessHeap(), 0, 12345);
|
|
memset(lol, 0x90, 12345);
|
|
|
|
// don't display error dialog on crash.
|
|
//SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
|
|
|
|
// needed or child will crash upon exiting when under the debugger
|
|
MarkAllHandles();
|
|
|
|
FreeConsole();
|
|
createConsole();
|
|
|
|
HANDLE hConnectEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
|
|
OVERLAPPED overlapped;
|
|
RtlZeroMemory(&overlapped, sizeof(overlapped));
|
|
overlapped.hEvent = hConnectEvent;
|
|
HANDLE hPipe = CreateNamedPipeA("\\\\.\\pipe\\fuzzer", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 4096, 4096, 0, NULL);
|
|
if (hPipe == INVALID_HANDLE_VALUE)
|
|
{
|
|
printf("CreateNamedPipe failed with %d.\n", GetLastError());
|
|
return 0;
|
|
}
|
|
|
|
if (ConnectNamedPipe(hPipe, &overlapped))
|
|
{
|
|
printf("ConnectNamedPipe failed with %d.\n", GetLastError());
|
|
return 0;
|
|
}
|
|
|
|
DWORD numChildren = 0;
|
|
std::vector<HANDLE> waitHandles;
|
|
waitHandles.push_back(overlapped.hEvent);
|
|
|
|
// forkserver
|
|
LARGE_INTEGER start = time();
|
|
do
|
|
{
|
|
// careful waitHandles.size() must never exceed MAXIMUM_WAIT_OBJECTS !!!
|
|
DWORD waitResult = WaitForMultipleObjects(waitHandles.size(), waitHandles.data(), FALSE, 0);
|
|
if (waitResult == WAIT_OBJECT_0)
|
|
{
|
|
DWORD nRead;
|
|
BYTE message[1];
|
|
BYTE response[1] = { 0x69 };
|
|
if (!GetOverlappedResult(hPipe, &overlapped, &nRead, TRUE))
|
|
{
|
|
printf("GetOverlappedResult failed = %d ?!!!!!\n", GetLastError());
|
|
}
|
|
printf("Pipe connected\n");
|
|
|
|
if (!ReadFile(hPipe, message, sizeof(message), NULL, &overlapped))
|
|
{
|
|
printf("Rx: %d!!!!!\n", GetLastError());
|
|
}
|
|
if (!GetOverlappedResult(hPipe, &overlapped, &nRead, TRUE))
|
|
{
|
|
printf("Read error %d!!!!!\n", GetLastError());
|
|
}
|
|
printf("Rx done. Got %02x\n", message[0]);
|
|
|
|
if (!WriteFile(hPipe, response, sizeof(response), NULL, &overlapped))
|
|
{
|
|
printf("Tx: %d!!!!!\n", GetLastError());
|
|
}
|
|
if (!GetOverlappedResult(hPipe, &overlapped, &nRead, TRUE))
|
|
{
|
|
printf("Write error: %d!!!!!\n", GetLastError());
|
|
}
|
|
printf("Tx done.\n");
|
|
|
|
DisconnectNamedPipe(hPipe);
|
|
|
|
if (ConnectNamedPipe(hPipe, &overlapped))
|
|
{
|
|
printf("ConnectNamedPipe failed with %d.\n", GetLastError());
|
|
return 0;
|
|
}
|
|
else if (GetLastError() == ERROR_PIPE_CONNECTED)
|
|
{
|
|
printf("Love me\n");
|
|
SetEvent(overlapped.hEvent);
|
|
}
|
|
else if (GetLastError() != ERROR_IO_PENDING)
|
|
{
|
|
printf("ConnectNamedPipe failed with %d.\n", GetLastError());
|
|
return 0;
|
|
}
|
|
}
|
|
else if (waitResult > WAIT_OBJECT_0 && waitResult < WAIT_ABANDONED_0)
|
|
{
|
|
int index = waitResult - WAIT_OBJECT_0;
|
|
HANDLE hProcess = waitHandles[index];
|
|
printf("Process %d (pid %d) finished\n", index, GetProcessId(hProcess));
|
|
waitHandles.erase(waitHandles.begin() + index);
|
|
numChildren--;
|
|
}
|
|
|
|
if (forkCount < NUM_ITER && numChildren < MAXIMUM_WAIT_OBJECTS - 1)
|
|
{
|
|
// spawn new child with fork
|
|
PROCESS_INFORMATION pi;
|
|
pid = fork(&pi);
|
|
if (pid == -1)
|
|
{
|
|
printf("fork FAILED!");
|
|
getc(stdin);
|
|
break;
|
|
}
|
|
else if (pid) // parent
|
|
{
|
|
//printf("pid: %d, count:%d\n", pid, forkCount);
|
|
forkCount++;
|
|
numChildren++;
|
|
waitHandles.push_back(pi.hProcess);
|
|
printf("%d\n", forkCount);
|
|
}
|
|
else //child (pid==0)
|
|
{
|
|
return child();
|
|
}
|
|
}
|
|
} while (forkCount < NUM_ITER || numChildren);
|
|
|
|
LARGE_INTEGER end = time();
|
|
LARGE_INTEGER freq;
|
|
QueryPerformanceFrequency(&freq);
|
|
double elapsed = (end.QuadPart - start.QuadPart) / (double)freq.QuadPart;
|
|
printf("Took %f seconds\n", elapsed);
|
|
printf("approxi. %f exec/sec , %f ms/exec\n", NUM_ITER / elapsed, elapsed * 1000 / NUM_ITER);
|
|
getc(stdin);
|
|
return 0;
|
|
}
|