公共头文件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
#define LARGE_MESSAGE_SIZE 0x10000
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 structure for initializing shared memory on the caller's side of the port
//
typedef struct _PORT_VIEW {
ULONG Length; // Size of this structure
HANDLE SectionHandle; // Handle to section object with
// SECTION_MAP_WRITE and SECTION_MAP_READ
ULONG SectionOffset; // The offset in the section to map a view for
// the port data area. The offset must be aligned
// with the allocation granularity of the system.
SIZE_T ViewSize; // The size of the view (in bytes)
PVOID ViewBase; // The base address of the view in the creator
//
PVOID ViewRemoteBase; // The base address of the view in the process
// connected to the port.
} PORT_VIEW, *PPORT_VIEW;
//
// 定义来自远程端口的共享内存
//
typedef struct _REMOTE_PORT_VIEW {
ULONG Length; // 结构体大小
SIZE_T ViewSize; // view大小
PVOID ViewBase; // view 基地址
} REMOTE_PORT_VIEW, *PREMOTE_PORT_VIEW;
typedef struct _COMMUNICATE_
{
PORT_VIEW ServerView;
REMOTE_PORT_VIEW ClientView;
HANDLE hCommunicateHandle;
HANDLE hSectionHandle;
}COMMUNICATE, *PCOMMUNICATE;
#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);
NTSTATUS(NTAPI* NtCreateSection)(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN PLSA_OBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN PLARGE_INTEGER MaximumSize OPTIONAL,
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle OPTIONAL
);
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");
(FARPROC&)NtCreateSection = GetProcAddress(NtdllModule, "NtCreateSection");
}
#define SERVER_PORT_NAME L"\\ServerPortName"
服务器
#include "..//..//Common//Common.h"
#include <stdio.h>
BOOL g_Stop = FALSE;
volatile LONG g_dwCurrentClient = 0;
DWORD WINAPI CommunicationThread(LPVOID lParam)
{
NTSTATUS NtStatus = 0;
PCOMMUNICATE pCommunicate = (PCOMMUNICATE)lParam;
PORT_MESSAGE RecvMsg;
PORT_MESSAGE SendMsg;
InterlockedAdd(&g_dwCurrentClient, 1);
while (!g_Stop)
{
InitializeMessageHeader(&SendMsg, sizeof(PORT_MESSAGE), 0);
ZeroMemory(&RecvMsg, sizeof(PORT_MESSAGE));
NtStatus = NtRequestWaitReplyPort(pCommunicate->hCommunicateHandle,
&SendMsg,
&RecvMsg);
if (NtStatus != 0)
{
CloseHandle(pCommunicate->hSectionHandle);
NtClose(pCommunicate->hCommunicateHandle);
printf("NtReplyWaitReceivePort:%d\r\n", GetLastError());
break;
}
printf("MessageType:%d\r\nClientID<%d,%d>\r\nToTalLength:%d\r\nMessage:%ws\r\n",
RecvMsg.u2.s2.Type,
RecvMsg.ClientId.UniqueProcess,
RecvMsg.ClientId.UniqueThread,
RecvMsg.u1.s1.TotalLength,
pCommunicate->ClientView.ViewBase);
}
InterlockedExchange(&g_dwCurrentClient, g_dwCurrentClient - 1);
return 0;
}
void StartServer(WCHAR* szServerPortName)
{
NTSTATUS Status = 0;
PORT_MESSAGE LpcMessage;
LSA_OBJECT_ATTRIBUTES ObjAttr;
UNICODE_STRING PortName;
HANDLE hSectionHandle;
HANDLE hServerConnectionHandle;
SECURITY_DESCRIPTOR SecurityDesc = { 0 };
LARGE_INTEGER SectionSize = { LARGE_MESSAGE_SIZE };
g_Stop = FALSE;
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(&PortName, SERVER_PORT_NAME);
InitializeObjectAttributes(&ObjAttr, &PortName, 0, NULL, &SecurityDesc);
Status = NtCreatePort(&hServerConnectionHandle,
&ObjAttr,
NULL,
sizeof(PORT_MESSAGE),
0
);
if (Status != 0)
{
printf("NtCreatePort:%d\r\n", GetLastError());
break;
}
while (!g_Stop)
{
HANDLE hServerCommunicateHandle;
Status = NtListenPort(hServerConnectionHandle, &LpcMessage);
if (Status != 0)
{
printf("NtListenPort:%d\r\n", GetLastError());
g_Stop = TRUE;
break;
}
if (g_dwCurrentClient < MAX_COMMUN_NUMBER)
{
PCOMMUNICATE pThreadPara = new COMMUNICATE;
Status = NtCreateSection(&pThreadPara->hSectionHandle,
SECTION_MAP_READ | SECTION_MAP_WRITE,
NULL,// 使用页文件,而不是文件映射
&SectionSize,
PAGE_READWRITE,
SEC_COMMIT,
NULL);
if (Status != 0)
{
printf("NtCreateSection:%d\r\n", GetLastError());
break;
}
//
// 接受端口的连接
//
pThreadPara->ServerView.Length = sizeof(PORT_VIEW);
pThreadPara->ServerView.SectionHandle = pThreadPara->hSectionHandle;
pThreadPara->ServerView.SectionOffset = 0;
pThreadPara->ServerView.ViewSize = LARGE_MESSAGE_SIZE;
pThreadPara->ClientView.Length = sizeof(REMOTE_PORT_VIEW);
Status = NtAcceptConnectPort(&pThreadPara->hCommunicateHandle,
NULL,
&LpcMessage,
TRUE,
&pThreadPara->ServerView,
&pThreadPara->ClientView);
if (Status != 0)
{
printf("NtAcceptConnectPort:%d\r\n", GetLastError());
g_Stop = TRUE;
CloseHandle(pThreadPara->hSectionHandle);
break;
}
//
// 完成连接请求Complete the connection
//
Status = NtCompleteConnectPort(pThreadPara->hCommunicateHandle);
if (Status != 0)
{
printf("NtCompleteConnectPort:%d\r\n", GetLastError());
g_Stop = TRUE;
CloseHandle(pThreadPara->hSectionHandle);
break;
}
printf("MessageType:%d\r\nClientID<%d,%d>\r\nToTalLength:%d\r\nServerBase:%p\tServerSize:%x\r\nClientBase:%p\tClientSize:%x\r\n",
LpcMessage.u2.s2.Type,
LpcMessage.ClientId.UniqueProcess,
LpcMessage.ClientId.UniqueThread,
LpcMessage.u1.s1.TotalLength,
pThreadPara->ServerView.ViewBase, pThreadPara->ServerView.ViewSize,
pThreadPara->ClientView.ViewBase, pThreadPara->ClientView.ViewSize);
CreateThread(NULL, 0, CommunicationThread, pThreadPara, 0, NULL);
}
else
{
NtAcceptConnectPort(&hServerCommunicateHandle,NULL,
&LpcMessage,
FALSE,
NULL, NULL);
}
}
}
}
int main()
{
InitLpc();
StartServer(SERVER_PORT_NAME);
return 0;
}
客户端
#include "..//..//Common//Common.h"
#include <stdio.h>
BOOL ConnectServer(WCHAR* szServerPortName, COMMUNICATE & ClientCommunicate)
{
SECURITY_QUALITY_OF_SERVICE SecurityQos;
UNICODE_STRING PortName;
PORT_MESSAGE LpcMessage;
PORT_MESSAGE LpcReply;
NTSTATUS Status = 0;
LARGE_INTEGER SectionSize = { LARGE_MESSAGE_SIZE };
__try
{
Status = NtCreateSection(&ClientCommunicate.hSectionHandle,
SECTION_MAP_READ | SECTION_MAP_WRITE,
NULL,
&SectionSize,
PAGE_READWRITE,
SEC_COMMIT,
NULL);
if (Status != 0)
{
printf("NtReplyWaitReceivePort:%d\r\n", GetLastError());
__leave;
}
RtlInitUnicodeString(&PortName, szServerPortName);
SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
SecurityQos.ImpersonationLevel = SecurityImpersonation;
SecurityQos.EffectiveOnly = FALSE;
SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
ClientCommunicate.ServerView.Length = sizeof(PORT_VIEW);
ClientCommunicate.ServerView.SectionHandle = ClientCommunicate.hSectionHandle;
ClientCommunicate.ServerView.SectionOffset = 0;
ClientCommunicate.ServerView.ViewSize = LARGE_MESSAGE_SIZE;
ClientCommunicate.ClientView.Length = sizeof(REMOTE_PORT_VIEW);
Status = NtConnectPort(&ClientCommunicate.hCommunicateHandle,
&PortName,
&SecurityQos,
&ClientCommunicate.ServerView,
&ClientCommunicate.ClientView,
0,
NULL,
NULL);
if (Status != 0)
{
CloseHandle(ClientCommunicate.hSectionHandle);
printf("NtConnectPort:%d\r\n", GetLastError());
__leave;
}
}
__finally
{
if (Status != 0)
{
return FALSE;
}
}
printf("NtConnectPort Success\r\n");
return TRUE;
}
void CommunicateWithServer(COMMUNICATE& ClientCommunicate)
{
PORT_MESSAGE LpcSndMsg = { 0 };
PORT_MESSAGE LpcRecvMsg = { 0 };
InitializeMessageHeader(&LpcRecvMsg, sizeof(TRANSFERED_MESSAGE), 0);
NTSTATUS NtStatus = 0;
NtStatus = NtReplyWaitReceivePort(ClientCommunicate.hCommunicateHandle, NULL, NULL, &LpcRecvMsg);
while (NtStatus == 0)
{
LpcSndMsg = LpcRecvMsg;
scanf_s("%ws", ClientCommunicate.ServerView.ViewBase, 0x1000);
NtStatus = NtReplyWaitReceivePort(ClientCommunicate.hCommunicateHandle, NULL, &LpcSndMsg, &LpcRecvMsg);
if (NtStatus != 0)
{
NtClose(ClientCommunicate.hCommunicateHandle);
CloseHandle(ClientCommunicate.hSectionHandle);
printf("GetLastError:%d\r\n", GetLastError());
break;
}
}
}
int main()
{
InitLpc();
COMMUNICATE ClientCommunicate = { 0 };
if (ConnectServer(SERVER_PORT_NAME, ClientCommunicate) == TRUE)
{
CommunicateWithServer(ClientCommunicate);
}
return 0;
}