- Its start and stop events, along with any errors, are automatically logged as system events.
- It is trivial to make the process run under the local system account.
- Failure recovery policies can be defined and managed by the operating system itself.
In this project, I have decided to use unmanaged memory IPC. This is a form of IPC in which blocks of memory in the service and GUI frontend application are allocated and then used to communicate between the two programs. The initial setup of this method requires a handshake in which the address of a memory block can be passed to the other process. To do so we can send a custom command to the service using the service control manager.
The following is a simple example of how unmanaged memory IPC can be set up:
- Client program uses VirtualAlloc to allocate two blocks of memory - one for parameters, one for return values. It fills the memory blocks with the pattern 0x1337D00D. The memory pages for the return value block are marked as PAGE_READWRITE. The memory pages for the parameters block are marked as PAGE_READONLY. Giving execute permissions would be bad for security.
- Client program sends an AETHER_CLIENT_PID message to the service.
- Service begins waiting for the process ID of the client program.
- Client program sends its process ID to the service as a message.
- Service stores the process ID.
- Client program sends an AETHER_ADDR_PARAM message to the service.
- Service begins waiting for parameter memory address.
- Client program encodes the address of the parameter memory block as an integer and sends it to the service as a message.
- Service stores the memory address.
- Client program sends an AETHER_ADDR_RETN message to the service.
- Service begins waiting for return value memory address.
- Client program encodes the address of the return value memory block as an integer and sends it to the service as a message.
- Service stores the memory address.
- Client program sends an AETHER_IPC_TEST message to the service.
- Service uses OpenProcess to get a handle to the client program's process, then uses ReadProcessMemory to check that all buffers read 0x1337D00D. It then uses WriteProcessMemory to fill the memory blocks with 0x00000000.
- Client program waits 100ms and checks the memory blocks to make sure the pattern was written correctly.
- If either test (15 or 16) failed, throw an error message.
To prevent problems such as overlap (e.g. a return value for one operation being sent when a return value for another is expected) each operation is designated a unique identification number. Furthermore, the code that manages IPC is designed such that only one operation can be communicated about at one point in time. To do this, I will use the Mutex class.
Parameters and return values will be encoded as binary serialized structures (using the BinaryFormatter class) with a prepended length value. In order to provide a literally identical structure for both client and service code, the shared structures will be placed in a separate library.
No comments:
Post a Comment
Note: only a member of this blog may post a comment.