📄 cping.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
//
// Module: cping.exe - COM Ping
// File: cping.cpp
// Author: Galen C. Hunt
// Copyright: 1996-1999, Microsoft Corporation
//
// http://www.research.microsoft.com/sn/detours
//
#define INITGUID
#include <objbase.h>
#include <objidl.h>
#include <ocidl.h>
#include <olectl.h>
#include <shellapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <rpc.h>
#include <rpcdcep.h>
#include <detours.h>
#include "iping.h"
////////////////////////////////////////////////////////// Assertion Handling.
//
#ifndef _DEFINED_ASMBREAK_
#define _DEFINED_ASMBREAK_
#define ASMBREAK() __asm { int 3 }
//#define ASMBREAK() DebugBreak()
#endif // _DEFINED_ASMBREAK_
#ifndef NODEBUG
#undef ASSERT
VOID PingAssertMessage(CONST PCHAR szMsg, CONST PCHAR szFile, ULONG nLine);
#define ASSERT(x) \
do { if (!(x)) { PingAssertMessage(#x, __FILE__, __LINE__); ASMBREAK(); }} while (0)
;
#else // NODEBUG
#undef ASSERT
#define ASSERT(x)
#endif // NODEBUG
//////////////////////////////////////////////////////////////////////////////
#define PingLoadCycleCount(x) \
_asm { \
__asm lea ecx, x \
__asm _emit 0x0f \
__asm _emit 0x31 \
__asm mov [ecx], eax \
__asm mov [ecx+4], edx \
}
#define arrayof(x) (sizeof(x)/sizeof(x[0]))
#define wcssize(x) ((wcslen(x) + 1) * sizeof(WCHAR))
#define strsize(x) ((strlen(x) + 1) * sizeof(CHAR))
extern "C" {
ULONG WINAPI iping_DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
HRESULT STDAPICALLTYPE iping_DllRegisterServer(void);
HRESULT STDAPICALLTYPE iping_DllUnregisterServer(void);
HRESULT STDAPICALLTYPE iping_DllGetClassObject(REFCLSID rclsid,
REFIID riid, PVOID *ppv);
HRESULT STDAPICALLTYPE iping_DllCanUnloadNow(void);
}
STDAPI PingMessage(PCSTR msg, ...);
///////////////////////////////////////////////////////////////////// Globals.
FILE * g_fpLog = NULL;
void * g_pBuffer = NULL;
WCHAR g_wzServerName[128];
WCHAR g_wzClientName[128];
ULONG g_cbBufferMax = 262144;
double g_dCyclesPerSecond = 0.0;
double g_dMsPerCycle = 0.0;
double g_dLatency = 0.0;
BOOL g_fSummarize = TRUE;
ULONG g_nFixedToClient = 0;
ULONG g_nFixedToServer = 0;
//////////////////////////////////////////////////////////////////////////////
//
static CHAR s_szMessageBuf[2048];
STDAPI PingMessage(PCSTR msg, ...)
{
double d = 0.0; // Required for FP support
va_list args;
va_start(args, msg);
vsprintf(s_szMessageBuf, msg, args);
// OutputDebugStringA(s_szMessageBuf);
fwrite(s_szMessageBuf, 1, strlen(s_szMessageBuf), stdout);
fflush(stdout);
return S_FALSE;
}
VOID PingAssertMessage(CONST PCHAR szMsg, CONST PCHAR szFile, ULONG nLine)
{
PingMessage("%08lx ASSERT(%s) failed in %s, line %d.\n",
GetCurrentThreadId(), szMsg, szFile, nLine);
printf("ASSERT(%s) failed in %s, line %d.\n", szMsg, szFile, nLine);
}
BOOLEAN CheckResult(HRESULT hr, PCSTR pszMsg, ...)
{
if (FAILED(hr)) {
va_list args;
va_start(args, pszMsg);
vsprintf(s_szMessageBuf, pszMsg, args);
printf(" %-57.57s -> %08lx\n", s_szMessageBuf, hr);
return FALSE;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
#define NTSYSAPI DECLSPEC_IMPORT
#define NTAPI __stdcall
#define NTSTATUS LONG
#define PIO_APC_ROUTINE PVOID
typedef struct
{
NTSTATUS Status;
LONG Information;
} *PIO_STATUS_BLOCK;
NTSTATUS (NTAPI *s_pNtWaitForSingleObject)(HANDLE Handle,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout) = NULL;
NTSTATUS (NTAPI *s_pNtDeviceIoControlFile)(HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength) = NULL;
NTSTATUS (NTAPI *s_pTrampoline_NtWaitForSingleObject)(HANDLE Handle,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout) = NULL;
NTSTATUS (NTAPI *s_pTrampoline_NtDeviceIoControlFile)(HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength) = NULL;
//////////////////////////////////////////////////////////////////////////////
//
static LONG s_nInCall = 0;
static LONG s_nInIRpc = 0;
static ULONG s_nThread = 0;
enum {
E_MinValue = 0,
E_Sleep = 1,
E_Proxy,
E_I_RpcGetBuffer,
E_I_RpcSendReceive,
E_I_RpcFreeBuffer,
E_I_RpcSend,
E_I_RpcReceive,
E_I_RpcFreePipeBuffer,
E_I_RpcReallocPipeBuffer,
E_I_RpcRequestMutex,
E_I_RpcClearMutex,
E_I_RpcAllocate,
E_I_RpcFree,
E_I_RpcPauseExecution,
E_I_RpcMonitorAssociation,
E_I_RpcStopMonitorAssociation,
E_Recv,
E_RecvFrom,
E_NtWaitForSingleObject,
E_NtDeviceIoControlFileRecv,
E_NtDeviceIoControlFile,
E_Send,
E_SendTo,
E_NtDeviceIoControlFileSend,
E_DCOM,
E_RPC,
E_UDP,
E_NET,
E_MaxValue,
E_DcomBeg = E_Proxy,
E_DcomEnd = E_Proxy,
E_RpcBeg = E_I_RpcGetBuffer,
E_RpcEnd = E_I_RpcStopMonitorAssociation,
E_UdpBeg = E_Send,
E_UdpEnd = E_NtDeviceIoControlFileSend,
E_NetBeg = E_Recv,
E_NetEnd = E_NtDeviceIoControlFile,
};
PCHAR s_rgRouteNames[E_MaxValue] =
{
"<NULL>",
"Sleep",
"Proxy",
"I_RpcGetBuffer",
"I_RpcSendReceive",
"I_RpcFreeBuffer",
"I_RpcSend",
"I_RpcReceive",
"I_RpcFreePipeBuffer",
"I_RpcReallocPipeBuffer",
"I_RpcRequestMutex",
"I_RpcClearMutex",
"I_RpcAllocate",
"I_RpcFree",
"I_RpcPauseExecution",
"I_RpcMonitorAssociation",
"I_RpcStopMonitorAssociation",
"Recv",
"RecvFrom",
"NtWaitForSingleObject",
"NtDeviceIoControlRecv",
"NtDeviceIoControlFile",
"Send",
"SendTo",
"NtDeviceIoControlSend",
"DCOM",
"RPC",
"UDP/TCP (Send Only)",
"NET",
};
LONGLONG s_rgCycles[E_MaxValue];
LONGLONG s_rgTotals[E_MaxValue];
LONG s_rgCounts[E_MaxValue];
class CRouteTime
{
public:
inline CRouteTime(LONG nRoute)
{
if (s_nInCall && GetCurrentThreadId() == s_nThread) {
LONGLONG llBeg;
m_nOldRoute = s_nRoute;
m_llOldMinus = s_llMinus;
s_nRoute = m_nRoute = nRoute;
s_rgCounts[m_nRoute]++;
s_llMinus = 0;
ASSERT(m_nRoute != m_nOldRoute);
PingLoadCycleCount(llBeg);
m_llBeg = llBeg;
}
else {
m_nRoute = 0;
}
}
inline ~CRouteTime()
{
if (m_nRoute) {
LONGLONG llEnd;
PingLoadCycleCount(llEnd);
llEnd -= m_llBeg;
s_rgTotals[m_nRoute] += llEnd;
s_rgCycles[m_nRoute] += llEnd - s_llMinus;
s_nRoute = m_nOldRoute;
s_llMinus = m_llOldMinus + llEnd;
}
}
inline BOOL Routed()
{
return m_nRoute;
}
public:
ULONG m_nRoute;
ULONG m_nOldRoute;
LONGLONG m_llBeg;
LONGLONG m_llOldMinus;
static ULONG s_nRoute;
static LONGLONG s_llMinus;
};
ULONG CRouteTime::s_nRoute = 0;
LONGLONG CRouteTime::s_llMinus = 0;
VOID ZeroCycles(VOID)
{
for (ULONG n = 0; n < E_MaxValue; n++) {
s_rgCycles[n] = 0;
s_rgTotals[n] = 0;
s_rgCounts[n] = 0;
}
}
VOID DumpCycles(LONG nRoute)
{
if (s_rgCycles[nRoute] != 0 || s_rgTotals[nRoute] != 0) {
printf(";; %-21.21s %10I64d %8.3fms %10I64d %8.3fms :%6d\n",
s_rgRouteNames[nRoute],
s_rgCycles[nRoute], (double)s_rgCycles[nRoute] * g_dMsPerCycle,
s_rgTotals[nRoute], (double)s_rgTotals[nRoute] * g_dMsPerCycle,
s_rgCounts[nRoute]);
}
}
VOID SummarizeCycles(VOID)
{
for (ULONG n = E_DCOM; n <= E_NET; n++) {
s_rgCycles[n] = 0;
s_rgTotals[n] = 0;
s_rgCounts[n] = 0;
}
for (n = E_DcomBeg; n <= E_DcomEnd; n++) {
s_rgCycles[E_DCOM] += s_rgCycles[n];
s_rgTotals[E_DCOM] += s_rgTotals[n];
}
for (n = E_RpcBeg; n <= E_RpcEnd; n++) {
s_rgCycles[E_RPC] += s_rgCycles[n];
s_rgTotals[E_RPC] += s_rgTotals[n];
}
for (n = E_UdpBeg; n <= E_UdpEnd; n++) {
s_rgCycles[E_UDP] += s_rgCycles[n];
s_rgTotals[E_UDP] += s_rgTotals[n];
}
for (n = E_NetBeg; n <= E_NetEnd; n++) {
s_rgCycles[E_NET] += s_rgCycles[n];
s_rgTotals[E_NET] += s_rgTotals[n];
}
#ifdef BE_VERBOSE
printf("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
"::::::::::::::::::\n");
printf(":: Protocol Cycles:\n");
DumpCycles(E_DCOM);
DumpCycles(E_RPC);
DumpCycles(E_UDP);
DumpCycles(E_NET);
#endif
s_rgCycles[E_DCOM] /= s_rgCounts[E_DCOM];
s_rgCycles[E_RPC] /= s_rgCounts[E_DCOM];
s_rgCycles[E_UDP] /= s_rgCounts[E_DCOM];
s_rgCycles[E_NET] /= s_rgCounts[E_DCOM];
s_rgTotals[E_DCOM] /= s_rgCounts[E_DCOM];
s_rgTotals[E_RPC] /= s_rgCounts[E_DCOM];
s_rgTotals[E_UDP] /= s_rgCounts[E_DCOM];
s_rgTotals[E_NET] /= s_rgCounts[E_DCOM];
#ifdef BE_VERBOSE
printf("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
"::::::::::::::::::\n");
printf(":: Protocol Cycles Per DCOM Call:\n");
DumpCycles(E_DCOM);
DumpCycles(E_RPC);
s DumpCycles(E_UDP);
DumpCycles(E_NET);
#endif
for (n = 0; n < E_DCOM; n++) {
s_rgCycles[n] = 0;
s_rgTotals[n] = 0;
s_rgCounts[n] = 0;
}
}
//////////////////////////////////////////////////////////////////////////////
//
// To re-route you need three things:
// 1) DETOUR_TRAMPOLINE:
// Name of function to be re-routed
// Prototype of original function (the base) trampoline function (Trampoline_*).
// 2) Instrumentation function. (Catch_*)
// 3) Insert instrumentation in the function (modify the binary):
// DetourFunctionWithTrampoline((PBYTE)Trampoline_Sleep, (PBYTE)Detour_Sleep);
//
DETOUR_TRAMPOLINE(VOID WINAPI Trampoline_Sleep(DWORD dwMilliseconds),
Sleep);
DETOUR_TRAMPOLINE(int WSAAPI Trampoline_send(SOCKET s,
const char * buf, int len, int flags),
send);
DETOUR_TRAMPOLINE(int WSAAPI Trampoline_sendto(SOCKET s,
const char * buf, int len, int flags,
const struct sockaddr * to, int tolen),
sendto);
DETOUR_TRAMPOLINE(int WSAAPI Trampoline_recv(SOCKET s, char * buf, int len, int flags),
recv);
DETOUR_TRAMPOLINE(int WSAAPI Trampoline_recvfrom(SOCKET s,char * buf, int len, int flags,
struct sockaddr * from, int * fromlen),
recvfrom);
DETOUR_TRAMPOLINE(RPC_STATUS RPC_ENTRY
Trampoline_I_RpcGetBuffer(RPC_MESSAGE * Message),
I_RpcGetBuffer);
DETOUR_TRAMPOLINE(RPC_STATUS RPC_ENTRY
Trampoline_I_RpcSendReceive(RPC_MESSAGE * Message),
I_RpcSendReceive);
DETOUR_TRAMPOLINE(RPC_STATUS RPC_ENTRY
Trampoline_I_RpcFreeBuffer(RPC_MESSAGE * Message),
I_RpcFreeBuffer);
DETOUR_TRAMPOLINE(RPC_STATUS RPC_ENTRY
Trampoline_I_RpcSend(PRPC_MESSAGE Message),
I_RpcSend);
DETOUR_TRAMPOLINE(RPC_STATUS RPC_ENTRY
Trampoline_I_RpcReceive(PRPC_MESSAGE Message,
unsigned int Size),
I_RpcReceive);
DETOUR_TRAMPOLINE(RPC_STATUS RPC_ENTRY
Trampoline_I_RpcFreePipeBuffer(RPC_MESSAGE * Message),
I_RpcFreePipeBuffer);
DETOUR_TRAMPOLINE(RPC_STATUS RPC_ENTRY
Trampoline_I_RpcReallocPipeBuffer(PRPC_MESSAGE Msg,
unsigned int Size),
I_RpcReallocPipeBuffer);
DETOUR_TRAMPOLINE(void RPC_ENTRY
Trampoline_I_RpcRequestMutex(I_RPC_MUTEX * Mutex),
I_RpcRequestMutex);
DETOUR_TRAMPOLINE(void RPC_ENTRY
Trampoline_I_RpcClearMutex(I_RPC_MUTEX Mutex),
I_RpcClearMutex);
DETOUR_TRAMPOLINE(void * RPC_ENTRY
Trampoline_I_RpcAllocate(unsigned int Size),
I_RpcAllocate);
DETOUR_TRAMPOLINE(void RPC_ENTRY
Trampoline_I_RpcFree(void * Object),
I_RpcFree);
DETOUR_TRAMPOLINE(void RPC_ENTRY
Trampoline_I_RpcPauseExecution(unsigned long Milliseconds),
I_RpcPauseExecution);
DETOUR_TRAMPOLINE(RPC_STATUS RPC_ENTRY
Trampoline_I_RpcMonitorAssociation(RPC_BINDING_HANDLE Handle,
PRPC_RUNDOWN RundownRoutine,
void * Context),
I_RpcMonitorAssociation);
DETOUR_TRAMPOLINE(RPC_STATUS RPC_ENTRY
Trampoline_I_RpcStopMonitorAssociation(RPC_BINDING_HANDLE Handle),
I_RpcStopMonitorAssociation);
//////////////////////////////////////////////////////////////////////////////
//
static VOID WINAPI Detour_Sleep(DWORD dwMilliseconds)
{
CRouteTime rt(E_Sleep);
Trampoline_Sleep(dwMilliseconds);
}
static int WSAAPI Detour_send(SOCKET s, const char * buf, int len, int flags)
{
CRouteTime rt(E_Send);
return Trampoline_send(s, buf, len, flags);
}
static int WSAAPI Detour_sendto(SOCKET s, const char * buf, int len, int flags,
const struct sockaddr * to, int tolen)
{
CRouteTime rt(E_SendTo);
return Trampoline_sendto(s, buf, len, flags, to, tolen);
}
static int WSAAPI Detour_recv(SOCKET s, char * buf, int len, int flags)
{
CRouteTime rt(E_Recv);
return recv(s, buf, len, flags);
}
static int WSAAPI Detour_recvfrom(SOCKET s,char * buf, int len, int flags,
struct sockaddr * from, int * fromlen)
{
CRouteTime rt(E_RecvFrom);
return recvfrom(s, buf, len, flags, from, fromlen);
}
static VOID DumpStack(PCHAR pszDesc, PULONG pStack)
{
printf("%-15.15s:", pszDesc);
for (ULONG n = 0; n < 6; n++) {
__try {
printf(" %08x", pStack[1]);
pStack = (PULONG)pStack[0];
} __except(EXCEPTION_EXECUTE_HANDLER) {
n = 8;
}
}
printf("\n");
}
static NTSTATUS NTAPI Detour_NtWaitForSingleObject(HANDLE Handle,
BOOLEAN Alertable,
PLARGE_INTEGER Timeout)
{
CRouteTime rt(E_NtWaitForSingleObject);
if (rt.Routed()) {
//printf("WaitForSingle(%d, %I64d)\n", Alertable, Timeout->QuadPart);
}
#ifdef INCLUDE_THIS
if (rt.Routed()) {
PULONG pStack = NULL;
__asm mov pStack, ebp;
DumpStack("NtWaitForSingle", pStack);
}
#endif
return s_pTrampoline_NtWaitForSingleObject(Handle, Alertable, Timeout);
}
#define IO_CONTROL_AFD_SEND_DATAGRAM 0x12023
#define IO_CONTROL_AFD_SEND 0x1201f
#define IO_CONTROL_AFD_RECV_DATAGRAM 0x1201b
#define IO_CONTROL_AFD_RECV 0x12017
static NTSTATUS NTAPI Detour_NtDeviceIoControlFile(HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength)
{
if (IoControlCode == IO_CONTROL_AFD_SEND_DATAGRAM ||
IoControlCode == IO_CONTROL_AFD_SEND) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -