📄 ioapi.cpp
字号:
// IoApi.cpp : TDI Redirector Driver I/O Interface Support.
//
#include "stdafx.h"
#include "winioctl.h"
static OVERLAPPED m_ovlp;
static HANDLE m_hFileHandle = INVALID_HANDLE_VALUE; // Open device handle
static DWORD m_BytesReturned = 0;
static BOOL m_bIsLoadSuccessfully = FALSE;
static TCHAR m_DriverName[FILE_NAME_SIZE];
BOOL TcpRedirector_InstallDriver( IN LPCTSTR DriverName )
{
SC_HANDLE schSCManager, schService;
TCHAR pszImagePath[ FILE_NAME_SIZE ];
// Format full file name
lstrcpy ( pszImagePath, _T("System32\\Drivers\\") );
lstrcat ( pszImagePath, TDIREDIR_BASE_NAME );
lstrcat ( pszImagePath, _T(".sys") );
schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if ( schSCManager == NULL )
return FALSE;
schService = CreateService(
schSCManager, // SCManager database
DriverName, // name of service
DriverName, // name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_KERNEL_DRIVER, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
pszImagePath, // service's binary
_T("PNP_TDI"), // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL // no password
);
if ( schService == NULL )
{
CloseServiceHandle( schSCManager );
return FALSE;
}
CloseServiceHandle( schService );
CloseServiceHandle( schSCManager );
return TRUE;
}
BOOL TcpRedirector_RemoveDriver( IN LPCTSTR DriverName )
{
SC_HANDLE schService, SchSCManager;
BOOL ret;
SchSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if ( SchSCManager == NULL )
return FALSE;
schService = OpenService( SchSCManager,
DriverName,
SERVICE_ALL_ACCESS
);
if ( schService == NULL )
{
CloseServiceHandle( SchSCManager );
return FALSE;
}
ret = DeleteService( schService );
CloseServiceHandle( schService );
CloseServiceHandle( SchSCManager );
return ret;
}
static BOOL TcpRedirector_StartDriver( IN SC_HANDLE SchSCManager, IN LPCTSTR DriverName )
{
SC_HANDLE schService;
BOOL ret;
schService = OpenService( SchSCManager,
DriverName,
SERVICE_ALL_ACCESS
);
if ( schService == NULL )
return FALSE;
ret = StartService( schService, 0, NULL )
|| GetLastError() == ERROR_SERVICE_ALREADY_RUNNING
|| GetLastError() == ERROR_SERVICE_DISABLED;
CloseServiceHandle( schService );
return ret;
}
static BOOL TcpRedirector_LoadDeviceDriver( const TCHAR * Name )
{
SC_HANDLE schSCManager;
BOOL okay;
schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
// Ignore success of start: it may already be started.
okay = TcpRedirector_StartDriver( schSCManager, Name );
CloseServiceHandle( schSCManager );
return TRUE;
}
static BOOL TcpRedirector_DeviceIoControl(
DWORD dwService, void *BuffIn, int SizeIn, void *BuffOut, int SizeOut, DWORD *SizeRet, LPOVERLAPPED povlp)
{
BOOL Ret = 0;
// Supports overlapped and nonoverlapped IO
if ( !SizeRet )
SizeRet = &m_BytesReturned;
if( m_hFileHandle != INVALID_HANDLE_VALUE )
{
if( povlp == NULL )
Ret = DeviceIoControl( m_hFileHandle, dwService, BuffIn, SizeIn, BuffOut, SizeOut, (unsigned long*)SizeRet, &m_ovlp);
else
Ret = DeviceIoControl( m_hFileHandle, dwService, BuffIn, SizeIn, BuffOut, SizeOut, (unsigned long*)SizeRet, povlp);
}
return Ret;
}
BOOL TcpRedirector_SetRedirectRules(
PTCP_REDIR_RULE_BUFFER pRuleBuffer,
DWORD RuleBufferSize // Total Number of Bytes at pRuleBuffer
)
{
BOOL bIOResult = FALSE;
DWORD dwBytesReturned = 0;
// Sanity Checks
if( pRuleBuffer != NULL )
{
// Check Total Buffer Size
if( RuleBufferSize != pRuleBuffer->TotalBufferSize )
{
SetLastError( ERROR_BAD_LENGTH );
return FALSE;
}
// Make Sure Buffer Contains At Least One Port Rule
if( pRuleBuffer->RuleCount == 0 )
{
SetLastError( ERROR_INVALID_DATA );
return FALSE;
}
// Make Sure Port Rule Size Is Correct
if( pRuleBuffer->RedirectRuleSize != sizeof( TCP_REDIR_RULE ) )
{
SetLastError( ERROR_INVALID_DATA );
return FALSE;
}
}
bIOResult = TcpRedirector_DeviceIoControl(
IOCTL_SET_REDIRECTION_RULES,
pRuleBuffer,
pRuleBuffer != NULL ? RuleBufferSize : 0,
NULL,
0,
&dwBytesReturned, // Bytes Returned
NULL
);
if( bIOResult == FALSE )
{
// printf( "Error: %d\n", GetLastError() );
}
return bIOResult;
}
BOOL TcpRedirector_ClearRedirectRules()
{
return TcpRedirector_SetRedirectRules ( (PTCP_REDIR_RULE_BUFFER )NULL, 0 );
}
BOOL TcpRedirector_GetRedirectRules(
PTCP_REDIR_RULE_BUFFER pRuleBuffer,
DWORD RuleBufferSize // Total Number of Bytes at pRuleBuffer
)
{
BOOL bIOResult = FALSE;
DWORD dwBytesReturned = 0;
// Sanity Checks
if( pRuleBuffer == NULL )
{
return FALSE;
}
bIOResult = TcpRedirector_DeviceIoControl(
IOCTL_GET_REDIRECTION_RULES,
NULL,
0,
pRuleBuffer,
pRuleBuffer != NULL ? RuleBufferSize : 0,
&dwBytesReturned, // Bytes Returned
NULL
);
if( bIOResult == FALSE )
{
// printf( "Error: %d\n", GetLastError() );
}
return bIOResult;
}
BOOL TcpRedirector_GetOriginalDestination(
PTCP_ORIGINAL_INFO pOriginalInfo,
DWORD BufferSize, // Total Number of Bytes at pOriginalInfo
USHORT RedirectToPort // The Proxy Local Port
)
{
BOOL bIOResult = FALSE;
DWORD dwBytesReturned = 0;
// Sanity Checks
if( pOriginalInfo == NULL )
{
return FALSE;
}
if( BufferSize != sizeof(TCP_ORIGINAL_INFO) )
{
return FALSE;
}
memset( pOriginalInfo, 0x00, BufferSize );
pOriginalInfo->OriginalInfoSize = BufferSize;
pOriginalInfo->RemotePort = RedirectToPort;
bIOResult = TcpRedirector_DeviceIoControl(
IOCTL_GET_ORIGINAL_DESTINATION,
pOriginalInfo,
BufferSize,
pOriginalInfo,
BufferSize,
&dwBytesReturned, // Bytes Returned
NULL
);
if( bIOResult == FALSE )
{
// printf( "Error: %d\n", GetLastError() );
}
return bIOResult;
}
BOOL TcpRedirector_Startup()
{
TCHAR pszFullName [ FILE_NAME_SIZE ];
// Format full file name
lstrcpy ( pszFullName, _T("\\\\.\\") );
lstrcat ( pszFullName, TDIREDIR_BASE_NAME );
// Save driver name (in our case driver name equals device symbolic link)
memset ( m_DriverName, 0, FILE_NAME_SIZE*sizeof(TCHAR) );
_tcscpy ( m_DriverName, TDIREDIR_BASE_NAME );
m_bIsLoadSuccessfully = FALSE;
m_hFileHandle = CreateFile ( pszFullName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 );
if(m_hFileHandle == INVALID_HANDLE_VALUE)
{
// Install and load driver
TcpRedirector_LoadDeviceDriver ( m_DriverName );
}
if(m_hFileHandle == INVALID_HANDLE_VALUE)
m_hFileHandle = CreateFile ( pszFullName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 );
if( m_hFileHandle == INVALID_HANDLE_VALUE )
{
DWORD err = GetLastError ();
m_ovlp.hEvent = 0;
}
else
{
m_ovlp.hEvent = 0;
m_ovlp.hEvent = CreateEvent ( 0, TRUE, FALSE, NULL );
if( m_ovlp.hEvent )
{
m_bIsLoadSuccessfully = TRUE;
}
}
m_BytesReturned = 0;
return m_bIsLoadSuccessfully;
}
void TcpRedirector_Shutdown()
{
if( m_hFileHandle != INVALID_HANDLE_VALUE )
{
CloseHandle ( m_hFileHandle );
}
if( m_ovlp.hEvent != INVALID_HANDLE_VALUE )
{
CloseHandle ( m_ovlp.hEvent );
}
}
BOOL TcpRedirector_IsDriverLoaded()
{
if( !m_bIsLoadSuccessfully )
{
TcpRedirector_Startup();
}
return m_bIsLoadSuccessfully;
}
PTCP_REDIR_RULE_BUFFER TcpRedirector_AllocateRuleBuffer()
{
PTCP_REDIR_RULE_BUFFER pRuleBuffer = NULL;
pRuleBuffer = (PTCP_REDIR_RULE_BUFFER )malloc( sizeof( TCP_REDIR_RULE_BUFFER ) );
if( pRuleBuffer != NULL )
{
pRuleBuffer->Reserved = 0;
pRuleBuffer->TotalBufferSize = sizeof( TCP_REDIR_RULE_BUFFER );
pRuleBuffer->RedirectRuleSize = sizeof( TCP_REDIR_RULE );
pRuleBuffer->RuleCount = 0;
}
return pRuleBuffer;
}
void TcpRedirector_FreeRuleBuffer( PTCP_REDIR_RULE_BUFFER pRuleBuffer )
{
free( (void * )pRuleBuffer );
}
static int TcpRedirector_PortRuleCompare( const void *arg1, const void *arg2 )
{
PTCP_REDIR_RULE pKeyRule = (PTCP_REDIR_RULE )arg1;
PTCP_REDIR_RULE pComparandRule = (PTCP_REDIR_RULE )arg2;
if( pKeyRule->RemotePort == pComparandRule->RemotePort )
{
return 0;
}
if( pKeyRule->RemotePort < pComparandRule->RemotePort )
{
return -1;
}
return 1;
}
PTCP_REDIR_RULE TcpRedirector_FindPortRule(
PTCP_REDIR_RULE_BUFFER pRuleBuffer,
USHORT RemotePort // Port Number in Host Byte Order
)
{
TCP_REDIR_RULE KeyRule;
KeyRule.RemotePort = RemotePort;
return (PTCP_REDIR_RULE )bsearch( (void * )&KeyRule, &pRuleBuffer->RuleArray[0], pRuleBuffer->RuleCount, pRuleBuffer->RedirectRuleSize,
TcpRedirector_PortRuleCompare );
}
PTCP_REDIR_RULE_BUFFER TcpRedirector_AddPortRule(
PTCP_REDIR_RULE_BUFFER pRuleBuffer, // Previously Allocated Rule Buffer
ULONG RemoteAddressRangeStart,
ULONG RemoteAddressRangeEnd,
ULONG RemoteNetMask,
USHORT RemotePort, // Port Number in Host Byte Order
PCHAR ProcessNameToRedirect,
PCHAR ProcessNameToIgnore,
HANDLE ProcessIdToIgnore,
ULONG RedirectToAddress,
USHORT RedirectToPort // Host Byte Order
)
{
PTCP_REDIR_RULE pFoundRule = NULL;
// Sanity Checks
if( pRuleBuffer == NULL )
{
pRuleBuffer = TcpRedirector_AllocateRuleBuffer();
}
if( pRuleBuffer == NULL )
{
return pRuleBuffer;
}
if( htonl( RemoteAddressRangeStart ) > htonl( RemoteAddressRangeEnd ) )
{
return pRuleBuffer;
}
// Find Existing Rule, If Any
pFoundRule = TcpRedirector_FindPortRule( pRuleBuffer, RemotePort );
if( pFoundRule == NULL )
{
// Allocate Space for New Rule
pRuleBuffer = (PTCP_REDIR_RULE_BUFFER )realloc( (void * )pRuleBuffer, pRuleBuffer->TotalBufferSize + sizeof( TCP_REDIR_RULE ) );
if( pRuleBuffer == NULL )
{
return pRuleBuffer;
}
// Initialize Rule
pRuleBuffer->TotalBufferSize = pRuleBuffer->TotalBufferSize + sizeof( TCP_REDIR_RULE );
pRuleBuffer->RedirectRuleSize = sizeof( TCP_REDIR_RULE );
++pRuleBuffer->RuleCount;
pFoundRule = &pRuleBuffer->RuleArray[ pRuleBuffer->RuleCount - 1 ];
memset( pFoundRule, 0x00, sizeof( TCP_REDIR_RULE ) );
}
pFoundRule->RemoteAddressRangeStart = RemoteAddressRangeStart;
pFoundRule->RemoteAddressRangeEnd = RemoteAddressRangeEnd;
pFoundRule->RemoteNetMask = RemoteNetMask;
pFoundRule->RemotePort = RemotePort;
memset( pFoundRule->ProcessNameToRedirect, 0x00, sizeof( pFoundRule->ProcessNameToRedirect ) );
if( ( ProcessNameToRedirect != NULL ) && ( *ProcessNameToRedirect != 0 ) )
{
strncpy( pFoundRule->ProcessNameToRedirect, ProcessNameToRedirect, sizeof( pFoundRule->ProcessNameToRedirect ) - 1 );
_strupr( pFoundRule->ProcessNameToRedirect );
}
memset( pFoundRule->ProcessNameToIgnore, 0x00, sizeof( pFoundRule->ProcessNameToIgnore ) );
if( ( ProcessNameToIgnore != NULL ) && ( *ProcessNameToIgnore != 0 ) )
{
strncpy( pFoundRule->ProcessNameToIgnore, ProcessNameToIgnore, sizeof( pFoundRule->ProcessNameToIgnore ) - 1 );
_strupr( pFoundRule->ProcessNameToIgnore );
}
pFoundRule->ProcessIdToIgnore = ProcessIdToIgnore;
pFoundRule->RedirectToAddress = RedirectToAddress;
pFoundRule->RedirectToPort = RedirectToPort;
// Quick Sort the Rule Buffer
qsort( (void * )&pRuleBuffer->RuleArray[0], pRuleBuffer->RuleCount, pRuleBuffer->RedirectRuleSize,
TcpRedirector_PortRuleCompare );
return pRuleBuffer;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -