mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
Program from Skywing:
PipeSpy can be used to snoop traffic on a named pipe. It is intended to be used to help understand the remote kernel debugging protocol uesd by the windows kd. svn path=/trunk/; revision=8110
This commit is contained in:
parent
66f9b32741
commit
5398f1df0d
1 changed files with 251 additions and 0 deletions
251
reactos/tools/pipetools/pipespy.cpp
Normal file
251
reactos/tools/pipetools/pipespy.cpp
Normal file
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* PipeSpy
|
||||
* Copyright (c) 2004, Skywing (skywing@valhallalegends.com)
|
||||
* Released under the GNU GPL for the ReactOS project
|
||||
*
|
||||
* This program can be used to spy on a named pipe in Windows NT(+)
|
||||
* or ReactOS. It is particularly intended to be used for
|
||||
* understanding the remote kernel debugging protocol used
|
||||
* by windows kd.
|
||||
*
|
||||
* USE:
|
||||
*
|
||||
* PipeSpy \\.\pipe\debug_server \\.\pipe\debug_client > PipeSpy.log
|
||||
*
|
||||
* VMware: act as client, connect to \\.\pipe\debug_server, pipe is connected
|
||||
* to application
|
||||
*
|
||||
* WinDbg -k com:pipe,port=\\.\pipe\debug_client,resets=0
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* This program hasn't really been tested against ReactOS, and has only
|
||||
* been built with Visual Studio .NET 2003.
|
||||
*/
|
||||
#include <process.h>
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
HANDLE g_DebugServerPipe, g_DebugClientPipe;
|
||||
CRITICAL_SECTION g_OutputLock;
|
||||
|
||||
void dumphex(const char *buf, int len, int pos)
|
||||
{
|
||||
int i, j;
|
||||
for(j = 0; j < len; j += 16) {
|
||||
for(i = 0; i < 16; i++) {
|
||||
if(i + j < len)
|
||||
printf("%02x%c", (unsigned char)buf[i + j], j + i + 1 == pos ? '*' : ' ');
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
for(i = 0; i < 16; i++) {
|
||||
if(i + j < len)
|
||||
printf("%c", buf[i + j] >= ' ' ? buf[i + j] : '.');
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
PIPEBUF_INITIAL_SIZE = 4096,
|
||||
PIPEBUF_MAX_SIZE = 16384
|
||||
};
|
||||
|
||||
typedef struct _READ_OVERLAPPED {
|
||||
OVERLAPPED ReadOverlapped;
|
||||
char* Buffer;
|
||||
HANDLE Pipe, OtherPipe;
|
||||
bool Server;
|
||||
bool Connected;
|
||||
} READ_OVERLAPPED;
|
||||
|
||||
VOID WINAPI WritePipeCompletion(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
if(dwErrorCode) {
|
||||
EnterCriticalSection(&g_OutputLock);
|
||||
printf(lpOverlapped->hEvent ? "Server> Error %u writing to client pipe\n" : "Client> Error %u writing to server pipe\n", dwErrorCode);
|
||||
LeaveCriticalSection(&g_OutputLock);
|
||||
}
|
||||
|
||||
free((void*)lpOverlapped);
|
||||
}
|
||||
|
||||
VOID WINAPI ReadPipeCompletion(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
|
||||
{
|
||||
READ_OVERLAPPED* ReadOverlapped = (READ_OVERLAPPED*)lpOverlapped;
|
||||
LPOVERLAPPED WriteOverlapped;
|
||||
|
||||
EnterCriticalSection(&g_OutputLock);
|
||||
|
||||
if(dwErrorCode) {
|
||||
printf(ReadOverlapped->Server ? "Server> Error %u reading from pipe\n" : "Client> Error %u reading from pipe\n", dwErrorCode);
|
||||
ReadOverlapped->Connected = false;
|
||||
} else {
|
||||
SYSTEMTIME SystemTime;
|
||||
|
||||
GetLocalTime(&SystemTime);
|
||||
printf(ReadOverlapped->Server ? "Server> [%02u:%02u:%02u.%03u] Received %u byte message:\n" : "Client> [%02u:%02u:%02u.%03u] Received %u byte message:\n",
|
||||
SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, SystemTime.wMilliseconds, dwNumberOfBytesTransferred);
|
||||
dumphex(ReadOverlapped->Buffer, (int)dwNumberOfBytesTransferred, -1);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&g_OutputLock);
|
||||
|
||||
WriteOverlapped = (LPOVERLAPPED)malloc(sizeof(OVERLAPPED)+dwNumberOfBytesTransferred);
|
||||
|
||||
if(!WriteOverlapped)
|
||||
printf(ReadOverlapped->Server ? "Server> Out of memory\n" : "Client> Out of memory\n");
|
||||
else {
|
||||
ZeroMemory(WriteOverlapped, sizeof(OVERLAPPED));
|
||||
WriteOverlapped->hEvent = (HANDLE)ReadOverlapped->Server;
|
||||
memcpy(((char*)WriteOverlapped)+sizeof(OVERLAPPED), ReadOverlapped->Buffer, dwNumberOfBytesTransferred);
|
||||
WriteFileEx(ReadOverlapped->OtherPipe, ((char*)WriteOverlapped)+sizeof(OVERLAPPED), dwNumberOfBytesTransferred, WriteOverlapped,
|
||||
WritePipeCompletion);
|
||||
}
|
||||
|
||||
if(!dwErrorCode) {
|
||||
ZeroMemory(ReadOverlapped, sizeof(OVERLAPPED));
|
||||
ReadFileEx(ReadOverlapped->Pipe, ReadOverlapped->Buffer, PIPEBUF_INITIAL_SIZE, &ReadOverlapped->ReadOverlapped, ReadPipeCompletion);
|
||||
}
|
||||
}
|
||||
|
||||
void __cdecl pipeserver(void* param)
|
||||
{
|
||||
READ_OVERLAPPED ReadOverlapped;
|
||||
|
||||
ReadOverlapped.Pipe = (HANDLE)param, ReadOverlapped.OtherPipe = ReadOverlapped.Pipe == g_DebugServerPipe ? g_DebugClientPipe : g_DebugServerPipe;
|
||||
ReadOverlapped.Server = ReadOverlapped.Pipe == g_DebugServerPipe;
|
||||
ReadOverlapped.Buffer = (char*)malloc(PIPEBUF_INITIAL_SIZE);
|
||||
|
||||
for(;;) {
|
||||
if(!ConnectNamedPipe(ReadOverlapped.Pipe, 0) && GetLastError() != ERROR_PIPE_CONNECTED) {
|
||||
printf(ReadOverlapped.Server ? "Server> Error %u accepting pipe connection\n" : "Client> Error %u accepting pipe connection\n",
|
||||
GetLastError());
|
||||
break;
|
||||
}
|
||||
|
||||
ReadOverlapped.Connected = true;
|
||||
printf(ReadOverlapped.Server ? "Server> Connected\n" : "Client> Connected\n");
|
||||
|
||||
ZeroMemory(&ReadOverlapped.ReadOverlapped, sizeof(OVERLAPPED));
|
||||
ReadFileEx(ReadOverlapped.Pipe, ReadOverlapped.Buffer, PIPEBUF_INITIAL_SIZE, &ReadOverlapped.ReadOverlapped, ReadPipeCompletion);
|
||||
|
||||
do {
|
||||
SleepEx(INFINITE, TRUE);
|
||||
} while(ReadOverlapped.Connected) ;
|
||||
|
||||
DisconnectNamedPipe(ReadOverlapped.Pipe);
|
||||
printf(ReadOverlapped.Server ? "Server> Disconnected\n" : "Client> Disconnected\n");
|
||||
}
|
||||
|
||||
printf(ReadOverlapped.Server ? "Server> Shutting down\n" : "Client> Shutting down\n");
|
||||
|
||||
free(ReadOverlapped.Buffer);
|
||||
CloseHandle(ReadOverlapped.Pipe);
|
||||
SleepEx(0, TRUE);
|
||||
}
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
if(ac != 3) {
|
||||
printf("syntax: pipespy serverpipe clientpipe\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_DebugServerPipe = CreateNamedPipe(av[1], PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
||||
1, 4096, 4096, NMPWAIT_WAIT_FOREVER, 0);
|
||||
|
||||
if(g_DebugServerPipe == INVALID_HANDLE_VALUE) {
|
||||
printf("Error %u creating server pipe\n", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_DebugClientPipe = CreateNamedPipe(av[2], PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
||||
1, 4096, 4096, NMPWAIT_WAIT_FOREVER, 0);
|
||||
|
||||
if(g_DebugClientPipe == INVALID_HANDLE_VALUE) {
|
||||
printf("Error %u creating client pipe\n", GetLastError());
|
||||
CloseHandle(g_DebugServerPipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
InitializeCriticalSection(&g_OutputLock);
|
||||
_beginthread(pipeserver, 0, (void*)g_DebugServerPipe);
|
||||
pipeserver((void*)g_DebugClientPipe);
|
||||
DeleteCriticalSection(&g_OutputLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
while(!Error) {
|
||||
SleepEx(0, TRUE);
|
||||
BufferPos = 0;
|
||||
|
||||
if(BufferSize > PIPEBUF_MAX_SIZE) {
|
||||
char* NewBuf = (char*)realloc(Buffer, PIPEBUF_MAX_SIZE);
|
||||
|
||||
if(NewBuf) {
|
||||
Buffer = NewBuf;
|
||||
BufferSize = PIPEBUF_MAX_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
char* NewBuf;
|
||||
|
||||
if(ReadFile(Pipe, Buffer+BufferPos, BufferSize-BufferPos, &Read, 0)) {
|
||||
BufferPos += Read;
|
||||
Error = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
Error = GetLastError();
|
||||
|
||||
printf("Error=%u read=%u\n", Error, Read);
|
||||
|
||||
if(Error != ERROR_MORE_DATA) {
|
||||
printf(Server ? "Server> Error %u reading from pipe\n" : "Client> Error %u reading from pipe\n", GetLastError());
|
||||
break;
|
||||
}
|
||||
|
||||
NewBuf = (char*)realloc(Buffer, BufferSize << 1);
|
||||
|
||||
if(!NewBuf) {
|
||||
printf(Server ? "Server> Out of memory\n" : "Client> Out of memory\n");
|
||||
break;
|
||||
}
|
||||
|
||||
BufferSize <<= 1;
|
||||
BufferPos += Read;
|
||||
Error = 0;
|
||||
}
|
||||
|
||||
if(Error)
|
||||
break;
|
||||
|
||||
WriteOverlapped = (LPOVERLAPPED)malloc(sizeof(OVERLAPPED)+BufferPos);
|
||||
|
||||
if(!WriteOverlapped)
|
||||
printf(Server ? "Server> Out of memory\n" : "Client> Out of memory\n");
|
||||
else {
|
||||
ZeroMemory(WriteOverlapped, sizeof(OVERLAPPED));
|
||||
memcpy(((char*)WriteOverlapped)+sizeof(OVERLAPPED), Buffer, BufferPos);
|
||||
WriteFileEx(OtherPipe, ((char*)WriteOverlapped)+sizeof(OVERLAPPED), BufferPos, WriteOverlapped, WritePipeCompletion);
|
||||
}
|
||||
|
||||
EnterCriticalSection(&g_OutputLock);
|
||||
printf(Server ? "Server> Received %u byte message:\n" : "Client> Received %u byte message:\n", BufferPos);
|
||||
dumphex(Buffer, (int)BufferPos, -1);
|
||||
printf("\n");
|
||||
LeaveCriticalSection(&g_OutputLock);
|
||||
}
|
||||
|
||||
DisconnectNamedPipe(Pipe);
|
||||
printf(Server ? "Server> Disconnected\n" : "Client> Disconnected\n");
|
||||
|
||||
*/
|
Loading…
Reference in a new issue