下面示例仅支持x64
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"
server.cpp
#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(const 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; }
client.cpp
#include "..//..//Common//Common.h" #include <stdio.h> #include <iostream> BOOL ConnectServer(const 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) { DWORD err = GetLastError(); std::cout << "NtConnectPort Status " << Status << " error " << err << "\n"; 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; }