断消息服务端
#include "..//..//Common/Common.h"
#include <stdio.h>
BOOL g_Stop = FALSE;
volatile LONG g_dwCurrentClient = 0;
DWORD WINAPI CommunicationThread(LPVOID lParam)
{
NTSTATUS NtStatus = 0;
TRANSFERED_MESSAGE RecvMessage = { 0 };
TRANSFERED_MESSAGE SendMsg = { 0 };
InitializeMessageHeader(&SendMsg.Header, sizeof(TRANSFERED_MESSAGE), 0);
HANDLE ServerCommunicationPortHandle = (HANDLE)lParam;
InterlockedAdd(&g_dwCurrentClient, 1);
while (!g_Stop)
{
printf("\r\n");
ZeroMemory(&RecvMessage, sizeof(TRANSFERED_MESSAGE));
NtStatus = NtRequestWaitReplyPort(ServerCommunicationPortHandle, &SendMsg.Header, &RecvMessage.Header);
if (NtStatus != 0)
{
printf("NtRequestWaitReplyPort:%d\r\n", GetLastError());
NtClose(ServerCommunicationPortHandle);
break;
}
switch (RecvMessage.Command)
{
case LPC_COMMAND_REQUEST_NOREPLY:
{
printf("MessageType:%d\r\nClientID<%d,%d>\r\nToTalLength:%d\r\nMessage:%ws\r\n",
RecvMessage.Header.u2.s2.Type,
RecvMessage.Header.ClientId.UniqueProcess,
RecvMessage.Header.ClientId.UniqueThread,
RecvMessage.Header.u1.s1.TotalLength,
RecvMessage.MessageText);
break;
}
}
}
InterlockedExchange(&g_dwCurrentClient, g_dwCurrentClient - 1);
return 0;
}
void StartServer(WCHAR* szServerPortName)
{
SECURITY_DESCRIPTOR SecurityDesc = { 0 };
UNICODE_STRING uniPortName;
LSA_OBJECT_ATTRIBUTES ObjectAttribute = { 0 };
NTSTATUS NtStatus = 0;
HANDLE hConnectionPort;
CHAR RequestBuffer[sizeof(PORT_MESSAGE) + MAX_LPC_DATA] = { 0 };
PTRANSFERED_MESSAGE LPCRequertMessage = PTRANSFERED_MESSAGE(RequestBuffer);
while(!g_Stop)
{
if (!InitializeSecurityDescriptor(&SecurityDesc, SECURITY_DESCRIPTOR_REVISION))
{
printf("InitializeSecurityDescriptor:%d\r\n", GetLastError());
break;
}
if (!SetSecurityDescriptorDacl(&SecurityDesc, TRUE, NULL, FALSE))
{
printf("SetSecurityDescriptorDacl:%d\r\n", GetLastError());
break;
}
RtlInitUnicodeString(&uniPortName, szServerPortName);
InitializeObjectAttributes(&ObjectAttribute, &uniPortName, 0, NULL, &SecurityDesc);
NtStatus = NtCreatePort(&hConnectionPort, &ObjectAttribute, NULL, sizeof(PORT_MESSAGE) + MAX_LPC_DATA, 0);
if (NtStatus != 0)
{
printf("NtCreatePort:%d\r\n", GetLastError());
break;
}
BOOL bOk = TRUE;
HANDLE ServerCommunicationPortHandle = NULL;
HANDLE AcceptPortHandle = NULL;
NTSTATUS NtStatus = 0;
TRANSFERED_MESSAGE LPCRequertMessage = { 0 };
while (!g_Stop)
{
// 清空RecvMsg 监听等待连接
RtlZeroMemory(&LPCRequertMessage, sizeof(TRANSFERED_MESSAGE));
NtStatus = NtListenPort(hConnectionPort, &LPCRequertMessage.Header);
if (NtStatus != 0)
{
printf("NtListenPort:%d\r\n", GetLastError());
g_Stop = TRUE;
NtClose(hConnectionPort);
break;
}
// 打印客户进程的一些信息
printf("MessageType:%d\r\nClientID<%d,%d>\r\nToTalLength:%d\r\n",
LPCRequertMessage.Header.u2.s2.Type,
LPCRequertMessage.Header.ClientId.UniqueProcess,
LPCRequertMessage.Header.ClientId.UniqueThread,
LPCRequertMessage.Header.u1.s1.TotalLength);
// 判断是否允许连接
if (g_dwCurrentClient < MAX_COMMUN_NUMBER)
{
bOk = TRUE;
}
else
{
bOk = FALSE;
}
// 处理连接请求 - 根据bOk决定是否接受连接
NtStatus = NtAcceptConnectPort(&ServerCommunicationPortHandle, 0, &LPCRequertMessage.Header, bOk, NULL, NULL);
if (NtStatus != 0)
{
printf("SetSecurityDescriptorDacl:%d\r\n", GetLastError());
g_Stop = TRUE;
NtClose(hConnectionPort);
break;
}
// 完成Connect
NtStatus = NtCompleteConnectPort(ServerCommunicationPortHandle);
if (NtStatus != 0)
{
printf("SetSecurityDescriptorDacl:%d\r\n", GetLastError());
g_Stop = TRUE;
NtClose(hConnectionPort);
break;
}
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CommunicationThread, ServerCommunicationPortHandle, 0, NULL);
}
}
Sleep(1000);
}
int main()
{
InitLpc();
StartServer(SERVER_PORT_NAME);
return 0;
}
短消息客户端
#include "..//..//Common/Common.h"
#include <stdio.h>
BOOL ConnectServer(WCHAR* szServerPortName,HANDLE & ClientCommunicationPortHandle)
{
SECURITY_QUALITY_OF_SERVICE SecurityQos = { 0 };
NTSTATUS NtStatus = 0;
UNICODE_STRING uniServerName = { 0 };
DWORD MaxMessageLength;
__try
{
RtlInitUnicodeString(&uniServerName, szServerPortName);
SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
SecurityQos.ImpersonationLevel = SecurityImpersonation;
SecurityQos.EffectiveOnly = FALSE;
SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
NtStatus = NtConnectPort(&ClientCommunicationPortHandle, &uniServerName, &SecurityQos, NULL, NULL, (PULONG)&MaxMessageLength, NULL, NULL);
if (NtStatus != 0)
{
printf("NtConnectPort:%d\r\n", GetLastError());
}
}
__finally
{
if (NtStatus != 0)
{
return FALSE;
}
}
printf("NtConnectPort Success\r\n");
return TRUE;
}
void CommunicateWithServer(HANDLE hClientCommunicate)
{
USHORT MsgType = LPC_COMMAND_REQUEST_NOREPLY;
TRANSFERED_MESSAGE LPCRecvMessage = { 0 };
TRANSFERED_MESSAGE LPCSendMsg = { 0 };
NTSTATUS NtStatus = 0;
InitializeMessageHeader(&LPCRecvMessage.Header, sizeof(TRANSFERED_MESSAGE), 0);
InitializeMessageHeader(&LPCSendMsg.Header, sizeof(TRANSFERED_MESSAGE), 0);
NtReplyWaitReceivePort(hClientCommunicate, NULL, NULL, &LPCRecvMessage.Header);
while (TRUE)
{
LPCSendMsg = LPCRecvMessage;
switch (MsgType)
{
case LPC_COMMAND_REQUEST_NOREPLY:
scanf_s("%ws", LPCSendMsg.MessageText, 48);
LPCSendMsg.Command = MsgType;
NtReplyWaitReceivePort(hClientCommunicate, NULL, &LPCSendMsg.Header, &LPCRecvMessage.Header);
break;
}
if (NtStatus != 0)
{
printf("GetLastError:%d\r\n", GetLastError());
break;
}
}
}
int main()
{
InitLpc();
HANDLE hClientCommunicate;
if (ConnectServer(SERVER_PORT_NAME, hClientCommunicate) == TRUE)
{
CommunicateWithServer(hClientCommunicate);
}
return 0;
}
公共头文件Common.h
#include <windows.h>
#include <NTSecAPI.h>
using namespace std;
#define MAX_LPC_DATA 0x148
#define LPC_MESSAGE_LENGTH 48
#define MAX_COMMUN_NUMBER 10
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct _PORT_MESSAGE
{
union
{
struct
{
USHORT DataLength; // Length of data following the header (bytes)
USHORT TotalLength; // Length of data + sizeof(PORT_MESSAGE)
} s1;
ULONG Length;
} u1;
union
{
struct
{
USHORT Type;
USHORT DataInfoOffset;
} s2;
ULONG ZeroInit;
} u2;
union
{
CLIENT_ID ClientId;
double DoNotUseThisField; // Force quadword alignment
};
ULONG MessageId; // Identifier of the particular message instance
union
{
ULONG_PTR ClientViewSize; // Size of section created by the sender (in bytes)
ULONG CallbackId; //
};
} PORT_MESSAGE, *PPORT_MESSAGE;
typedef struct _TRANSFERED_MESSAGE
{
PORT_MESSAGE Header;
ULONG Command;
WCHAR MessageText[48];
} TRANSFERED_MESSAGE, *PTRANSFERED_MESSAGE;
#define InitializeMessageHeader(ph, l, t) \
{ \
(ph)->u1.s1.TotalLength = (USHORT)(l); \
(ph)->u1.s1.DataLength = (USHORT)(l - sizeof(PORT_MESSAGE)); \
(ph)->u2.s2.Type = (USHORT)(t); \
(ph)->u2.s2.DataInfoOffset = 0; \
(ph)->ClientId.UniqueProcess = NULL; \
(ph)->ClientId.UniqueThread = NULL; \
(ph)->MessageId = 0; \
(ph)->ClientViewSize = 0; \
}
#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof( LSA_OBJECT_ATTRIBUTES ); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
enum LPC_MSG_TYPE
{
LPC_COMMAND_REQUEST_NOREPLY,
LPC_COMMAND_REQUEST_REPLY,
LPC_COMMAND_STOP
};
NTSTATUS(NTAPI* NtCreatePort)(PHANDLE PortHandle, PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ULONG MaxConnectionInfoLength, ULONG MaxMessageLength, PULONG MaxPoolUsage);
NTSTATUS(NTAPI* NtAcceptConnectPort)(PHANDLE PortHandle, PVOID PortContext, PPORT_MESSAGE ConnectionRequest, BOOL AcceptConnection, PVOID ServerView, PVOID ClientView);
NTSTATUS(NTAPI* NtCompleteConnectPort)(HANDLE PortHandle);
NTSTATUS(NTAPI* NtReplyWaitReceivePort)(HANDLE PortHandle, PVOID* PortContext, PPORT_MESSAGE ReplyMessage, PPORT_MESSAGE ReceiveMessage);
NTSTATUS(NTAPI* NtRequestWaitReplyPort)(HANDLE PortHandle, PPORT_MESSAGE RequestMessage, PPORT_MESSAGE ReplyMessage);
NTSTATUS(NTAPI* RtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString);
NTSTATUS(NTAPI* NtListenPort)(HANDLE PortHandle, PPORT_MESSAGE ConnectionRequest);
NTSTATUS(NTAPI* NtReplyPort)(HANDLE PortHandle, PPORT_MESSAGE ReplyMessage);
NTSTATUS(NTAPI* NtClose)(HANDLE Handle);
NTSTATUS(NTAPI* NtConnectPort)(PHANDLE PortHandle, PUNICODE_STRING PortName, PSECURITY_QUALITY_OF_SERVICE SecurityQos, PVOID ClientView, PVOID ServerView, PULONG MaxMessageLength, PVOID ConnectionInformation, PULONG ConnectionInformationLength);
NTSTATUS(NTAPI* NtRequestPort)(HANDLE PortHandle, PPORT_MESSAGE RequestMessage);
void InitLpc()
{
HMODULE NtdllModule = GetModuleHandleW(L"ntdll.dll");
if (NtdllModule == NULL)
{
return;
}
(FARPROC&)NtCreatePort = GetProcAddress(NtdllModule, "NtCreatePort");
(FARPROC&)NtAcceptConnectPort = GetProcAddress(NtdllModule, "NtAcceptConnectPort");
(FARPROC&)NtCompleteConnectPort = GetProcAddress(NtdllModule, "NtCompleteConnectPort");
(FARPROC&)NtReplyWaitReceivePort = GetProcAddress(NtdllModule, "NtReplyWaitReceivePort");
(FARPROC&)NtRequestWaitReplyPort = GetProcAddress(NtdllModule, "NtRequestWaitReplyPort");
(FARPROC&)RtlInitUnicodeString = GetProcAddress(NtdllModule, "RtlInitUnicodeString");
(FARPROC&)NtListenPort = GetProcAddress(NtdllModule, "NtListenPort");
(FARPROC&)NtReplyPort = GetProcAddress(NtdllModule, "NtReplyPort");
(FARPROC&)NtClose = GetProcAddress(NtdllModule, "NtClose");
(FARPROC&)NtConnectPort = GetProcAddress(NtdllModule, "NtConnectPort");
(FARPROC&)NtRequestPort = GetProcAddress(NtdllModule, "NtRequestPort");
}
#define SERVER_PORT_NAME L”\\ServerPortName”
注意:需要UAC,不支持Wow64