diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c2dfbfd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "PipeServer/PipeStream"] + path = PipeServer/PipeStream + url = https://github.com/KN4CK3R/PipeStream diff --git a/MemoryPipePlugin.sln b/MemoryPipePlugin.sln index cd56963..57df1fb 100644 --- a/MemoryPipePlugin.sln +++ b/MemoryPipePlugin.sln @@ -1,14 +1,19 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2002 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemoryPipePlugin", "Plugin\MemoryPipePlugin.csproj", "{CA79BA0B-0D80-476A-B793-FC7EF6DCEAD8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReClass.NET", "..\ReClass.NET\ReClass.NET.csproj", "{BFB8917D-E9B4-463F-A6E8-612C35728C78}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReClass.NET", "..\ReClass.NET\ReClass.NET\ReClass.NET.csproj", "{BFB8917D-E9B4-463F-A6E8-612C35728C78}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PipeServer", "PipeServer\PipeServer.vcxproj", "{75CAA2A9-D512-40E0-8918-B7F87806805E}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{01140249-48EF-45C1-B14E-9CC1B835F8AC}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -45,4 +50,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {002EFECF-F8EE-4634-878A-C0DE1E00EE03} + EndGlobalSection EndGlobal diff --git a/PipeServer/BinaryReader.cpp b/PipeServer/BinaryReader.cpp deleted file mode 100644 index 57bf89b..0000000 --- a/PipeServer/BinaryReader.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#include "BinaryReader.hpp" - -BinaryReader::BinaryReader(Stream& _input) - : input(_input), - buffer{ 0 } -{ - -} -//--------------------------------------------------------------------------- -bool BinaryReader::ReadBoolean() -{ - FillBuffer(1); - return buffer[0] != 0; -} -//--------------------------------------------------------------------------- -uint8_t BinaryReader::ReadByte() -{ - int b = input.ReadByte(); - if (b == -1) - { - throw IOException(); - } - return (uint8_t)b; -} -//--------------------------------------------------------------------------- -std::vector BinaryReader::ReadBytes(int count) -{ - std::vector result(count); - result.resize(count); - - int numRead = 0; - do - { - int n = input.Read(result.data(), numRead, count); - if (n == 0) - { - break; - } - numRead += n; - count -= n; - } while (count > 0); - - if (numRead != count) - { - result = std::vector(std::begin(result), std::begin(result) + numRead); - } - - return result; -} -//--------------------------------------------------------------------------- -short BinaryReader::ReadInt16() -{ - FillBuffer(2); - return (short)(buffer[0] | buffer[1] << 8); -} -//--------------------------------------------------------------------------- -unsigned short BinaryReader::ReadUInt16() -{ - FillBuffer(2); - return (unsigned short)(buffer[0] | buffer[1] << 8); -} -//--------------------------------------------------------------------------- -int BinaryReader::ReadInt32() -{ - FillBuffer(4); - return (int)(buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24); -} -//--------------------------------------------------------------------------- -unsigned int BinaryReader::ReadUInt32() -{ - FillBuffer(4); - return (unsigned int)(buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24); -} -//--------------------------------------------------------------------------- -long long BinaryReader::ReadInt64() -{ - FillBuffer(8); - unsigned int lo = (unsigned int)(buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24); - unsigned int hi = (unsigned int)(buffer[4] | buffer[5] << 8 | buffer[6] << 16 | buffer[7] << 24); - return (long long)((unsigned long long)hi) << 32 | lo; -} -//--------------------------------------------------------------------------- -unsigned long long BinaryReader::ReadUInt64() -{ - FillBuffer(8); - unsigned int lo = (unsigned int)(buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24); - unsigned int hi = (unsigned int)(buffer[4] | buffer[5] << 8 | buffer[6] << 16 | buffer[7] << 24); - return ((unsigned long long)hi) << 32 | lo; -} -//--------------------------------------------------------------------------- -void* BinaryReader::ReadIntPtr() -{ -#ifdef _WIN64 - return reinterpret_cast(ReadUInt64()); -#else - return reinterpret_cast(ReadUInt32()); -#endif -} -//--------------------------------------------------------------------------- -float BinaryReader::ReadSingle() -{ - auto tmp = ReadUInt32(); - return *(float*)&tmp; -} -//--------------------------------------------------------------------------- -double BinaryReader::ReadDouble() -{ - auto tmp = ReadUInt64(); - return *(double*)&tmp; -} -//--------------------------------------------------------------------------- -std::wstring BinaryReader::ReadString() -{ - const int MaxCharBytesSize = 128; - - auto byteLength = Read7BitEncodedInt(); - if (byteLength < 0) - { - throw IOException(); - } - - if (byteLength == 0) - { - return std::wstring(); - } - - std::wstring tmp; - - int currPos = 0; - uint8_t charBytes[MaxCharBytesSize]; - do - { - auto readLength = (byteLength - currPos) > MaxCharBytesSize ? MaxCharBytesSize : byteLength - currPos; - - auto n = input.Read(charBytes, 0, readLength); - if (n == 0) - { - throw IOException(); - } - - tmp.append(reinterpret_cast(charBytes), readLength / sizeof(std::wstring::value_type)); - - currPos += n; - } while (currPos < byteLength); - - return tmp; -} -//--------------------------------------------------------------------------- -void BinaryReader::FillBuffer(int numBytes) -{ - int bytesRead = 0; - int n = 0; - - if (numBytes == 1) - { - n = input.ReadByte(); - if (n == -1) - { - throw IOException(); - } - buffer[0] = (uint8_t)n; - return; - } - - do - { - n = input.Read(buffer, bytesRead, numBytes - bytesRead); - if (n == 0) - { - throw IOException(); - } - bytesRead += n; - } while (bytesRead < numBytes); -} -//--------------------------------------------------------------------------- -int BinaryReader::Read7BitEncodedInt() -{ - // Read out an int32 7 bits at a time. The high bit of the - // byte when on means to continue reading more bytes. - int count = 0; - int shift = 0; - uint8_t b; - do - { - if (shift == 5 * 7) - { - throw IOException(); - } - - b = ReadByte(); - count |= (b & 0x7F) << shift; - shift += 7; - } while ((b & 0x80) != 0); - - return count; -} -//--------------------------------------------------------------------------- diff --git a/PipeServer/BinaryReader.hpp b/PipeServer/BinaryReader.hpp deleted file mode 100644 index e511546..0000000 --- a/PipeServer/BinaryReader.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include - -#include "Stream.hpp" -#include "Exceptions.hpp" - -class BinaryReader -{ -public: - BinaryReader(Stream& input); - - bool ReadBoolean(); - - uint8_t ReadByte(); - - std::vector ReadBytes(int count); - - short ReadInt16(); - - unsigned short ReadUInt16(); - - int ReadInt32(); - - unsigned int ReadUInt32(); - - long long ReadInt64(); - - unsigned long long ReadUInt64(); - - void* ReadIntPtr(); - - float ReadSingle(); - - double ReadDouble(); - - std::wstring ReadString(); - -private: - void FillBuffer(int numBytes); - - int Read7BitEncodedInt(); - - Stream& input; - uint8_t buffer[8]; -}; diff --git a/PipeServer/BinaryWriter.cpp b/PipeServer/BinaryWriter.cpp deleted file mode 100644 index 55459d2..0000000 --- a/PipeServer/BinaryWriter.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#include "BinaryWriter.hpp" - -BinaryWriter::BinaryWriter(Stream& _output) - : output(_output), - buffer{ 0 } -{ - -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(bool value) -{ - buffer[0] = (uint8_t)(value ? 1 : 0); - output.Write(buffer, 0, 1); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(uint8_t value) -{ - output.WriteByte(value); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(const uint8_t* buffer, int offset, int length) -{ - output.Write(buffer, 0, length); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(short value) -{ - buffer[0] = (uint8_t)value; - buffer[1] = (uint8_t)(value >> 8); - output.Write(buffer, 0, 2); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(unsigned short value) -{ - buffer[0] = (uint8_t)value; - buffer[1] = (uint8_t)(value >> 8); - output.Write(buffer, 0, 2); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(int value) -{ - buffer[0] = (uint8_t)value; - buffer[1] = (uint8_t)(value >> 8); - buffer[2] = (uint8_t)(value >> 16); - buffer[3] = (uint8_t)(value >> 24); - output.Write(buffer, 0, 4); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(unsigned int value) -{ - buffer[0] = (uint8_t)value; - buffer[1] = (uint8_t)(value >> 8); - buffer[2] = (uint8_t)(value >> 16); - buffer[3] = (uint8_t)(value >> 24); - output.Write(buffer, 0, 4); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(long long value) -{ - buffer[0] = (uint8_t)value; - buffer[1] = (uint8_t)(value >> 8); - buffer[2] = (uint8_t)(value >> 16); - buffer[3] = (uint8_t)(value >> 24); - buffer[4] = (uint8_t)(value >> 32); - buffer[5] = (uint8_t)(value >> 40); - buffer[6] = (uint8_t)(value >> 48); - buffer[7] = (uint8_t)(value >> 56); - output.Write(buffer, 0, 8); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(unsigned long long value) -{ - buffer[0] = (uint8_t)value; - buffer[1] = (uint8_t)(value >> 8); - buffer[2] = (uint8_t)(value >> 16); - buffer[3] = (uint8_t)(value >> 24); - buffer[4] = (uint8_t)(value >> 32); - buffer[5] = (uint8_t)(value >> 40); - buffer[6] = (uint8_t)(value >> 48); - buffer[7] = (uint8_t)(value >> 56); - output.Write(buffer, 0, 8); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(const void* value) -{ -#ifdef _WIN64 - Write(reinterpret_cast(value)); -#else - Write(reinterpret_cast(value)); -#endif -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(float value) -{ - auto tmp = *(unsigned int*)&value; - buffer[0] = (uint8_t)tmp; - buffer[1] = (uint8_t)(tmp >> 8); - buffer[2] = (uint8_t)(tmp >> 16); - buffer[3] = (uint8_t)(tmp >> 24); - output.Write(buffer, 0, 4); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(double value) -{ - auto tmp = *(unsigned long long*)&value; - buffer[0] = (uint8_t)tmp; - buffer[1] = (uint8_t)(tmp >> 8); - buffer[2] = (uint8_t)(tmp >> 16); - buffer[3] = (uint8_t)(tmp >> 24); - buffer[4] = (uint8_t)(tmp >> 32); - buffer[5] = (uint8_t)(tmp >> 40); - buffer[6] = (uint8_t)(tmp >> 48); - buffer[7] = (uint8_t)(tmp >> 56); - output.Write(buffer, 0, 8); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write(const std::wstring& value) -{ - int byteLength = (int)value.length() * sizeof(std::wstring::value_type); - Write7BitEncodedInt(byteLength); - - output.Write(reinterpret_cast(value.data()), 0, byteLength); -} -//--------------------------------------------------------------------------- -void BinaryWriter::Write7BitEncodedInt(int value) -{ - // Write out an int32 7 bits at a time. The high bit of the byte, - // when on, tells reader to continue reading more byte. - auto v = (unsigned int)value; - while (v >= 0x80) - { - Write((uint8_t)(v | 0x80)); - v >>= 7; - } - Write((uint8_t)v); -} -//--------------------------------------------------------------------------- diff --git a/PipeServer/BinaryWriter.hpp b/PipeServer/BinaryWriter.hpp deleted file mode 100644 index e0a424c..0000000 --- a/PipeServer/BinaryWriter.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include - -#include "Stream.hpp" - -class BinaryWriter -{ -public: - BinaryWriter(Stream& output); - - void Write(bool value); - - void Write(uint8_t value); - - void Write(const uint8_t* buffer, int offset, int length); - - void Write(short value); - - void Write(unsigned short value); - - void Write(int value); - - void Write(unsigned int value); - - void Write(long long value); - - void Write(unsigned long long value); - - void Write(const void* value); - - void Write(float value); - - void Write(double value); - - void Write(const std::wstring& value); - -private: - void Write7BitEncodedInt(int value); - - Stream& output; - uint8_t buffer[8]; -}; diff --git a/PipeServer/Exceptions.hpp b/PipeServer/Exceptions.hpp deleted file mode 100644 index 475d6e3..0000000 --- a/PipeServer/Exceptions.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include - -class IOException : std::exception -{ -public: - IOException() = default; - IOException(int) - { - - } -}; - -class InvalidOperationException : std::exception -{ - -}; diff --git a/PipeServer/MemoryHelper.cpp b/PipeServer/MemoryHelper.cpp index 1a4e93a..d249868 100644 --- a/PipeServer/MemoryHelper.cpp +++ b/PipeServer/MemoryHelper.cpp @@ -3,10 +3,13 @@ #include #include #include +#include + +#include "ReClassNET_Plugin.hpp" bool IsValidMemoryRange(LPCVOID address, int length) { - auto endAddress = static_cast(address) + length; + const auto endAddress = static_cast(address) + length; do { @@ -34,7 +37,7 @@ bool IsValidMemoryRange(LPCVOID address, int length) return false; } - address = (uint8_t*)info.BaseAddress + info.RegionSize; + address = static_cast(info.BaseAddress) + info.RegionSize; } while (endAddress > address); return true; @@ -42,7 +45,7 @@ bool IsValidMemoryRange(LPCVOID address, int length) //--------------------------------------------------------------------------- bool ReadMemory(LPCVOID address, std::vector& buffer) { - if (!IsValidMemoryRange(address, (int)buffer.size())) + if (!IsValidMemoryRange(address, static_cast(buffer.size()))) { return false; } @@ -54,7 +57,7 @@ bool ReadMemory(LPCVOID address, std::vector& buffer) //--------------------------------------------------------------------------- bool WriteMemory(LPVOID address, const std::vector& buffer) { - if (!IsValidMemoryRange(address, (int)buffer.size())) + if (!IsValidMemoryRange(address, static_cast(buffer.size()))) { return false; } @@ -72,38 +75,68 @@ bool WriteMemory(LPVOID address, const std::vector& buffer) return false; } //--------------------------------------------------------------------------- -void EnumerateRemoteSectionsAndModules(const std::function& moduleCallback, const std::function& sectionCallback) +void EnumerateRemoteSectionsAndModules(const std::function& moduleCallback, const std::function& sectionCallback) { - struct SectionInfo - { - LPVOID BaseAddress; - SIZE_T RegionSize; - WCHAR Name[IMAGE_SIZEOF_SHORT_NAME + 1]; - DWORD State; - DWORD Protection; - DWORD Type; - WCHAR ModulePath[260]; - }; - std::vector sections; + std::vector sections; // First enumerate all memory sections. - MEMORY_BASIC_INFORMATION memInfo = { 0 }; + MEMORY_BASIC_INFORMATION memInfo = { }; memInfo.RegionSize = 0x1000; size_t address = 0; - while (VirtualQuery((LPCVOID)address, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) != 0 && address + memInfo.RegionSize > address) + while (VirtualQuery(reinterpret_cast(address), &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) != 0 && address + memInfo.RegionSize > address) { if (memInfo.State == MEM_COMMIT) { - SectionInfo section = {}; + EnumerateRemoteSectionData section = {}; section.BaseAddress = memInfo.BaseAddress; - section.RegionSize = memInfo.RegionSize; - section.State = memInfo.State; - section.Protection = memInfo.Protect; - section.Type = memInfo.Type; + section.Size = memInfo.RegionSize; + + switch (memInfo.Protect & 0xFF) + { + case PAGE_EXECUTE: + section.Protection = SectionProtection::Execute; + break; + case PAGE_EXECUTE_READ: + section.Protection = SectionProtection::Execute | SectionProtection::Read; + break; + case PAGE_EXECUTE_READWRITE: + case PAGE_EXECUTE_WRITECOPY: + section.Protection = SectionProtection::Execute | SectionProtection::Read | SectionProtection::Write; + break; + case PAGE_NOACCESS: + section.Protection = SectionProtection::NoAccess; + break; + case PAGE_READONLY: + section.Protection = SectionProtection::Read; + break; + case PAGE_READWRITE: + case PAGE_WRITECOPY: + section.Protection = SectionProtection::Read | SectionProtection::Write; + break; + } + if ((memInfo.Protect & PAGE_GUARD) == PAGE_GUARD) + { + section.Protection |= SectionProtection::Guard; + } + + switch (memInfo.Type) + { + case MEM_IMAGE: + section.Type = SectionType::Image; + break; + case MEM_MAPPED: + section.Type = SectionType::Mapped; + break; + case MEM_PRIVATE: + section.Type = SectionType::Private; + break; + } + + section.Category = section.Type == SectionType::Private ? SectionCategory::HEAP : SectionCategory::Unknown; sections.push_back(std::move(section)); } - address = (size_t)memInfo.BaseAddress + memInfo.RegionSize; + address = reinterpret_cast(memInfo.BaseAddress) + memInfo.RegionSize; } struct UNICODE_STRING @@ -153,38 +186,47 @@ void EnumerateRemoteSectionsAndModules(const std::function(__readgsqword(0x60)); + const auto peb = reinterpret_cast(__readgsqword(0x60)); #else - auto peb = reinterpret_cast(__readfsdword(0x30)); + const auto peb = reinterpret_cast(__readfsdword(0x30)); #endif auto ldr = reinterpret_cast(peb->LoaderData->InLoadOrderModuleList.Flink); while (ldr->BaseAddress != nullptr) { - moduleCallback(ldr->BaseAddress, (const void*)(intptr_t)ldr->SizeOfImage, ldr->FullDllName.Buffer); + moduleCallback(static_cast(ldr->BaseAddress), reinterpret_cast(static_cast(ldr->SizeOfImage)), ldr->FullDllName.Buffer); - auto it = std::lower_bound(std::begin(sections), std::end(sections), ldr->BaseAddress, [§ions](const SectionInfo& lhs, const LPVOID& rhs) + const auto it = std::lower_bound(std::begin(sections), std::end(sections), ldr->BaseAddress, [§ions](const auto& lhs, const LPVOID& rhs) { return lhs.BaseAddress < rhs; }); - auto dosHeader = reinterpret_cast(ldr->BaseAddress); - auto ntHeader = reinterpret_cast((intptr_t)ldr->BaseAddress + dosHeader->e_lfanew); + const auto dosHeader = reinterpret_cast(ldr->BaseAddress); + const auto ntHeader = reinterpret_cast(reinterpret_cast(ldr->BaseAddress) + dosHeader->e_lfanew); int i = 0; for (auto sectionHeader = IMAGE_FIRST_SECTION(ntHeader); i < ntHeader->FileHeader.NumberOfSections; i++, sectionHeader++) { - auto sectionAddress = (intptr_t)ldr->BaseAddress + (intptr_t)sectionHeader->VirtualAddress; + const auto sectionAddress = reinterpret_cast(ldr->BaseAddress) + static_cast(sectionHeader->VirtualAddress); for (auto j = it; j != std::end(sections); ++j) { - if (sectionAddress >= (intptr_t)j->BaseAddress && sectionAddress < (intptr_t)j->BaseAddress + (intptr_t)j->RegionSize) + if (sectionAddress >= reinterpret_cast(j->BaseAddress) && sectionAddress < reinterpret_cast(j->BaseAddress) + static_cast(j->Size)) { // Copy the name because it is not null padded. char buffer[IMAGE_SIZEOF_SHORT_NAME + 1] = { 0 }; std::memcpy(buffer, sectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME); + if (std::strcmp(buffer, ".text") == 0 || std::strcmp(buffer, "code") == 0) + { + j->Category = SectionCategory::CODE; + } + else if (std::strcmp(buffer, ".data") == 0 || std::strcmp(buffer, "data") == 0 || std::strcmp(buffer, ".rdata") == 0 || std::strcmp(buffer, ".idata") == 0) + { + j->Category = SectionCategory::DATA; + } + size_t convertedChars = 0; mbstowcs_s(&convertedChars, j->Name, IMAGE_SIZEOF_SHORT_NAME, buffer, _TRUNCATE); - std::memcpy(j->ModulePath, ldr->FullDllName.Buffer, sizeof(SectionInfo::ModulePath)); + std::memcpy(j->ModulePath, ldr->FullDllName.Buffer, sizeof(EnumerateRemoteSectionData::ModulePath)); break; } } @@ -195,7 +237,7 @@ void EnumerateRemoteSectionsAndModules(const std::function(section.Size), section.Type, section.Category, section.Protection, section.Name, section.ModulePath); } } //--------------------------------------------------------------------------- diff --git a/PipeServer/MemoryStream.cpp b/PipeServer/MemoryStream.cpp deleted file mode 100644 index 959f533..0000000 --- a/PipeServer/MemoryStream.cpp +++ /dev/null @@ -1,192 +0,0 @@ -#include "MemoryStream.hpp" -#include "Exceptions.hpp" - -MemoryStream::MemoryStream() - : MemoryStream(0) -{ - -} -//--------------------------------------------------------------------------- -MemoryStream::MemoryStream(int _capacity) - : buffer(_capacity), - length(0), - capacity(_capacity), - position(0), - isOpen(true), - isExpandable(true) -{ - -} -//--------------------------------------------------------------------------- -MemoryStream::MemoryStream(const std::vector& _buffer) - : buffer(_buffer), - length((int)_buffer.size()), - capacity((int)_buffer.size()), - position(0), - isOpen(true), - isExpandable(false) -{ - -} -//--------------------------------------------------------------------------- -MemoryStream::~MemoryStream() -{ - isOpen = false; -} -//--------------------------------------------------------------------------- -int MemoryStream::GetCapacity() const -{ - if (!isOpen) - { - throw IOException(); - } - return capacity; -} -//--------------------------------------------------------------------------- -void MemoryStream::SetCapacity(int value) -{ - if (!isOpen) - { - throw IOException(); - } - if (!isExpandable && (value != capacity)) - { - throw IOException(); - } - - if (isExpandable && value != capacity) - { - if (value > 0) - { - buffer.resize(value); - } - else - { - buffer.clear(); - } - - capacity = value; - } -} -//--------------------------------------------------------------------------- -int MemoryStream::GetLength() const -{ - if (!isOpen) - { - throw IOException(); - } - return (int)buffer.size(); -} -//--------------------------------------------------------------------------- -int MemoryStream::GetPosition() const -{ - if (!isOpen) - { - throw IOException(); - } - return position; -} -//--------------------------------------------------------------------------- -void MemoryStream::SetPosition(int value) -{ - if (!isOpen) - { - throw IOException(); - } - position = value; -} -//--------------------------------------------------------------------------- -int MemoryStream::Read(uint8_t* _buffer, int offset, int count) -{ - if (!isOpen) - { - throw IOException(); - } - - int n = length - position; - if (n > count) - { - n = count; - } - if (n <= 0) - { - return 0; - } - - int byteCount = n; - while (--byteCount >= 0) - { - _buffer[offset + byteCount] = buffer[position + byteCount]; - } - - position += n; - - return n; -} -//--------------------------------------------------------------------------- -void MemoryStream::Write(const uint8_t* _buffer, int offset, int count) -{ - if (!isOpen) - { - throw IOException(); - } - - int i = position + count; - if (i < 0) - { - throw IOException(); - } - - if (i > length) - { - if (i > capacity) - { - EnsureCapacity(i); - } - length = i; - } - - while (--count >= 0) - { - buffer[position + count] = _buffer[offset + count]; - } - - position = i; -} -//--------------------------------------------------------------------------- -std::vector MemoryStream::ToArray() const -{ - return std::vector(std::begin(buffer), std::begin(buffer) + length); -} -//--------------------------------------------------------------------------- -bool MemoryStream::EnsureCapacity(int value) -{ - if (value < 0) - { - throw IOException(); - } - if (value > capacity) - { - int newCapacity = value; - if (newCapacity < 256) - { - newCapacity = 256; - } - - if (newCapacity < capacity * 2) - { - newCapacity = capacity * 2; - } - - if ((unsigned int)(capacity * 2) > MaxByteArrayLength) - { - newCapacity = (unsigned int)value > MaxByteArrayLength ? value : MaxByteArrayLength; - } - - SetCapacity(newCapacity); - - return true; - } - return false; -} -//--------------------------------------------------------------------------- diff --git a/PipeServer/MemoryStream.hpp b/PipeServer/MemoryStream.hpp deleted file mode 100644 index 71a40a5..0000000 --- a/PipeServer/MemoryStream.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include - -#include "Stream.hpp" - -class MemoryStream : public Stream -{ -public: - MemoryStream(); - - MemoryStream(int capacity); - - MemoryStream(const std::vector& buffer); - - virtual ~MemoryStream() override; - - int GetCapacity() const; - - void SetCapacity(int value); - - int GetLength() const; - - int GetPosition() const; - - void SetPosition(int value); - - virtual int Read(uint8_t* buffer, int offset, int count) override; - - virtual void Write(const uint8_t* buffer, int offset, int count) override; - - std::vector ToArray() const; - -private: - bool EnsureCapacity(int value); - -private: - const unsigned int MaxByteArrayLength = 0x7FFFFFC7; - - std::vector buffer; - int length; - int capacity; - int position; - bool isOpen; - bool isExpandable; -}; \ No newline at end of file diff --git a/PipeServer/MessageClient.cpp b/PipeServer/MessageClient.cpp index e44884e..cb317a6 100644 --- a/PipeServer/MessageClient.cpp +++ b/PipeServer/MessageClient.cpp @@ -1,14 +1,10 @@ #include "MessageClient.hpp" +#include "PipeStream/MemoryStream.hpp" MessageClient::MessageClient(PipeStream& _pipe) : pipe(_pipe) { -} -//--------------------------------------------------------------------------- -void MessageClient::RegisterMessage(int type, const std::function()>& creator) -{ - registeredMessages[type] = creator; } //--------------------------------------------------------------------------- std::unique_ptr MessageClient::Receive() @@ -17,16 +13,16 @@ std::unique_ptr MessageClient::Receive() std::vector buffer(256); do { - auto length = pipe.Read(buffer.data(), 0, (int)buffer.size()); + const auto length = pipe.Read(buffer.data(), 0, static_cast(buffer.size())); ms.Write(buffer.data(), 0, length); } while (!pipe.IsMessageComplete()); ms.SetPosition(0); BinaryReader br(ms); - auto type = br.ReadInt32(); + const auto type = static_cast(br.ReadInt32()); - auto it = registeredMessages.find(type); + const auto it = registeredMessages.find(type); if (it != std::end(registeredMessages)) { auto message = it->second(); @@ -38,15 +34,15 @@ std::unique_ptr MessageClient::Receive() return nullptr; } //--------------------------------------------------------------------------- -void MessageClient::Send(const IMessage& message) +void MessageClient::Send(const IMessage& message) const { MemoryStream ms; BinaryWriter bw(ms); - bw.Write(message.GetType()); + bw.Write(static_cast(message.GetMessageType())); message.WriteTo(bw); auto data = ms.ToArray(); - pipe.Write(data.data(), 0, (int)data.size()); + pipe.Write(data.data(), 0, static_cast(data.size())); } //--------------------------------------------------------------------------- diff --git a/PipeServer/MessageClient.hpp b/PipeServer/MessageClient.hpp index 0383cd9..c0b4580 100644 --- a/PipeServer/MessageClient.hpp +++ b/PipeServer/MessageClient.hpp @@ -4,23 +4,28 @@ #include #include -#include "PipeStream.hpp" +#include "PipeStream/PipeStream.hpp" #include "Messages.hpp" -#include "MemoryStream.hpp" class MessageClient { public: - MessageClient(PipeStream& pipe); + explicit MessageClient(PipeStream& pipe); - void RegisterMessage(int type, const std::function()>& creator); + template + void RegisterMessage() + { + const auto messageCreator = []() { return std::make_unique(); }; + + registeredMessages[messageCreator()->GetMessageType()] = messageCreator; + } std::unique_ptr Receive(); - void Send(const IMessage& message); + void Send(const IMessage& message) const; private: PipeStream& pipe; - std::unordered_map()>> registeredMessages; + std::unordered_map()>> registeredMessages; }; diff --git a/PipeServer/Messages.cpp b/PipeServer/Messages.cpp index 7d76a08..73ec445 100644 --- a/PipeServer/Messages.cpp +++ b/PipeServer/Messages.cpp @@ -3,64 +3,64 @@ extern bool ReadMemory(LPCVOID, std::vector&); extern bool WriteMemory(LPVOID, const std::vector&); -extern void EnumerateRemoteSectionsAndModules(const std::function&, const std::function&); +extern void EnumerateRemoteSectionsAndModules(const std::function&, const std::function&); -bool OpenProcessMessage::Handle(MessageClient& client) +bool OpenProcessRequest::Handle(MessageClient& client) { - client.Send(StatusMessage(true)); + client.Send(StatusResponse(true)); return true; } //--------------------------------------------------------------------------- -bool CloseProcessMessage::Handle(MessageClient& client) +bool CloseProcessRequest::Handle(MessageClient& client) { - client.Send(StatusMessage(true)); + client.Send(StatusResponse(true)); return false; } //--------------------------------------------------------------------------- -bool IsValidMessage::Handle(MessageClient& client) +bool IsValidRequest::Handle(MessageClient& client) { - client.Send(StatusMessage(true)); + client.Send(StatusResponse(true)); return true; } //--------------------------------------------------------------------------- -bool ReadMemoryMessage::Handle(MessageClient& client) +bool ReadMemoryRequest::Handle(MessageClient& client) { std::vector buffer(GetSize()); buffer.resize(GetSize()); if (ReadMemory(GetAddress(), buffer)) { - client.Send(ReadMemoryDataMessage(std::move(buffer))); + client.Send(ReadMemoryResponse(std::move(buffer))); } else { - client.Send(StatusMessage(false)); + client.Send(StatusResponse(false)); } return true; } //--------------------------------------------------------------------------- -bool WriteMemoryMessage::Handle(MessageClient& client) +bool WriteMemoryRequest::Handle(MessageClient& client) { - auto success = WriteMemory((void*)GetAddress(), GetData()); + const auto success = WriteMemory(const_cast(GetAddress()), GetData()); - client.Send(StatusMessage(success)); + client.Send(StatusResponse(success)); return true; } //--------------------------------------------------------------------------- -bool EnumerateRemoteSectionsAndModulesMessage::Handle(MessageClient& client) +bool EnumerateRemoteSectionsAndModulesRequest::Handle(MessageClient& client) { EnumerateRemoteSectionsAndModules( - [&](auto p1, auto p2, auto p3) { client.Send(EnumerateRemoteModuleCallbackMessage(p1, p2, std::move(p3))); }, - [&](auto p1, auto p2, auto p3, auto p4, auto p5, auto p6, auto p7) { client.Send(EnumerateRemoteSectionCallbackMessage(p1, p2, std::move(p3), p4, p5, p6, std::move(p7))); } + [&](auto p1, auto p2, auto p3) { client.Send(EnumerateRemoteModuleResponse(p1, p2, std::move(p3))); }, + [&](auto p1, auto p2, auto p3, auto p4, auto p5, auto p6, auto p7) { client.Send(EnumerateRemoteSectionResponse(p1, p2, p3, p4, p5, std::move(p6), std::move(p7))); } ); // Report enumeration complete to client. - client.Send(StatusMessage(true)); + client.Send(StatusResponse(true)); return true; } diff --git a/PipeServer/Messages.hpp b/PipeServer/Messages.hpp index d2c54a3..d6c5165 100644 --- a/PipeServer/Messages.hpp +++ b/PipeServer/Messages.hpp @@ -2,15 +2,36 @@ #include -#include "BinaryReader.hpp" -#include "BinaryWriter.hpp" +#include "ReClassNET_Plugin.hpp" + +#include "PipeStream/BinaryReader.hpp" +#include "PipeStream/BinaryWriter.hpp" class MessageClient; +enum class MessageType +{ + StatusResponse = 1, + OpenProcessRequest = 2, + CloseProcessRequest = 3, + IsValidRequest = 4, + ReadMemoryRequest = 5, + ReadMemoryResponse = 6, + WriteMemoryRequest = 7, + EnumerateRemoteSectionsAndModulesRequest = 8, + EnumerateRemoteSectionResponse = 9, + EnumerateRemoteModuleResponse = 10, + EnumerateProcessHandlesRequest = 11, + EnumerateProcessHandlesResponse = 12, + ClosePipeRequest = 13 +}; +//--------------------------------------------------------------------------- class IMessage { public: - virtual int GetType() const = 0; + virtual ~IMessage() = default; + + virtual MessageType GetMessageType() const = 0; virtual void ReadFrom(BinaryReader& br) = 0; virtual void WriteTo(BinaryWriter& bw) const = 0; @@ -21,32 +42,31 @@ class IMessage } }; //--------------------------------------------------------------------------- -class StatusMessage : public IMessage +class StatusResponse : public IMessage { public: - static const int StaticType = 1; - virtual int GetType() const override { return StaticType; } + MessageType GetMessageType() const override { return MessageType::StatusResponse; } bool GetSuccess() const { return success; } - StatusMessage() + StatusResponse() : success(false) { } - StatusMessage(bool _success) + StatusResponse(bool _success) : success(_success) { } - virtual void ReadFrom(BinaryReader& reader) override + void ReadFrom(BinaryReader& reader) override { success = reader.ReadBoolean(); } - virtual void WriteTo(BinaryWriter& writer) const override + void WriteTo(BinaryWriter& writer) const override { writer.Write(success); } @@ -55,311 +75,303 @@ class StatusMessage : public IMessage bool success; }; //--------------------------------------------------------------------------- -class OpenProcessMessage : public IMessage +class OpenProcessRequest : public IMessage { public: - static const int StaticType = 2; - virtual int GetType() const override { return StaticType; } + MessageType GetMessageType() const override { return MessageType::OpenProcessRequest; } - virtual void ReadFrom(BinaryReader& reader) override + void ReadFrom(BinaryReader& reader) override { } - virtual void WriteTo(BinaryWriter& writer) const override + void WriteTo(BinaryWriter& writer) const override { } - virtual bool Handle(MessageClient& client) override; + bool Handle(MessageClient& client) override; }; //--------------------------------------------------------------------------- -class CloseProcessMessage : public IMessage +class CloseProcessRequest : public IMessage { public: - static const int StaticType = 3; - virtual int GetType() const override { return StaticType; } + MessageType GetMessageType() const override { return MessageType::CloseProcessRequest; } - virtual void ReadFrom(BinaryReader& reader) override + void ReadFrom(BinaryReader& reader) override { } - virtual void WriteTo(BinaryWriter& writer) const override + void WriteTo(BinaryWriter& writer) const override { } - virtual bool Handle(MessageClient& client) override; + bool Handle(MessageClient& client) override; }; //--------------------------------------------------------------------------- -class IsValidMessage : public IMessage +class IsValidRequest : public IMessage { public: - static const int StaticType = 4; - virtual int GetType() const override { return StaticType; } + MessageType GetMessageType() const override { return MessageType::IsValidRequest; } - virtual void ReadFrom(BinaryReader& reader) override + void ReadFrom(BinaryReader& reader) override { } - virtual void WriteTo(BinaryWriter& writer) const override + void WriteTo(BinaryWriter& writer) const override { } - virtual bool Handle(MessageClient& client) override; + bool Handle(MessageClient& client) override; }; //--------------------------------------------------------------------------- -class ReadMemoryMessage : public IMessage +class ReadMemoryRequest : public IMessage { public: - static const int StaticType = 5; - virtual int GetType() const override { return StaticType; } + MessageType GetMessageType() const override { return MessageType::ReadMemoryRequest; } const void* GetAddress() const { return address; } - const int GetSize() const { return size; } + int GetSize() const { return size; } - ReadMemoryMessage() - : address(0), + ReadMemoryRequest() + : address(nullptr), size(0) { } - ReadMemoryMessage(const void* _address, int _size) + ReadMemoryRequest(const void* _address, int _size) : address(_address), size(_size) { } - virtual void ReadFrom(BinaryReader& reader) override + void ReadFrom(BinaryReader& reader) override { address = reader.ReadIntPtr(); size = reader.ReadInt32(); } - virtual void WriteTo(BinaryWriter& writer) const override + void WriteTo(BinaryWriter& writer) const override { writer.Write(address); writer.Write(size); } - virtual bool Handle(MessageClient& client) override; + bool Handle(MessageClient& client) override; private: const void* address; int size; }; //--------------------------------------------------------------------------- -class ReadMemoryDataMessage : public IMessage +class ReadMemoryResponse : public IMessage { public: - static const int StaticType = 6; - virtual int GetType() const override { return StaticType; } + MessageType GetMessageType() const override { return MessageType::ReadMemoryResponse; } const std::vector& GetData() const { return data; } - ReadMemoryDataMessage() + ReadMemoryResponse() { } - ReadMemoryDataMessage(std::vector&& _data) + ReadMemoryResponse(std::vector&& _data) : data(std::move(_data)) { } - virtual void ReadFrom(BinaryReader& reader) override + void ReadFrom(BinaryReader& reader) override { - auto size = reader.ReadInt32(); + const auto size = reader.ReadInt32(); data = reader.ReadBytes(size); } - virtual void WriteTo(BinaryWriter& writer) const override + void WriteTo(BinaryWriter& writer) const override { - writer.Write((int)data.size()); - writer.Write(data.data(), 0, (int)data.size()); + writer.Write(static_cast(data.size())); + writer.Write(data.data(), 0, static_cast(data.size())); } private: std::vector data; }; //--------------------------------------------------------------------------- -class WriteMemoryMessage : public IMessage +class WriteMemoryRequest : public IMessage { public: - static const int StaticType = 7; - virtual int GetType() const override { return StaticType; } + MessageType GetMessageType() const override { return MessageType::WriteMemoryRequest; } const void* GetAddress() const { return address; } const std::vector& GetData() const { return data; } - WriteMemoryMessage() + WriteMemoryRequest() + : address(nullptr) { } - WriteMemoryMessage(const void* _address, std::vector&& _data) + WriteMemoryRequest(const void* _address, std::vector&& _data) : address(_address), data(std::move(_data)) { } - virtual void ReadFrom(BinaryReader& reader) override + void ReadFrom(BinaryReader& reader) override { address = reader.ReadIntPtr(); - auto size = reader.ReadInt32(); + const auto size = reader.ReadInt32(); data = reader.ReadBytes(size); } - virtual void WriteTo(BinaryWriter& writer) const override + void WriteTo(BinaryWriter& writer) const override { writer.Write(address); - writer.Write((int)data.size()); - writer.Write(data.data(), 0, (int)data.size()); + writer.Write(static_cast(data.size())); + writer.Write(data.data(), 0, static_cast(data.size())); } - virtual bool Handle(MessageClient& client) override; + bool Handle(MessageClient& client) override; private: const void* address; std::vector data; }; //--------------------------------------------------------------------------- -class EnumerateRemoteSectionsAndModulesMessage : public IMessage +class EnumerateRemoteSectionsAndModulesRequest : public IMessage { public: - static const int StaticType = 8; - virtual int GetType() const override { return StaticType; } + MessageType GetMessageType() const override { return MessageType::EnumerateRemoteSectionsAndModulesRequest; } - virtual void ReadFrom(BinaryReader& reader) override + void ReadFrom(BinaryReader& reader) override { } - virtual void WriteTo(BinaryWriter& writer) const override + void WriteTo(BinaryWriter& writer) const override { } - virtual bool Handle(MessageClient& client) override; + bool Handle(MessageClient& client) override; }; //--------------------------------------------------------------------------- -class EnumerateRemoteSectionCallbackMessage : public IMessage +class EnumerateRemoteSectionResponse : public IMessage { public: - static const int StaticType = 9; - virtual int GetType() const override { return StaticType; } + MessageType GetMessageType() const override { return MessageType::EnumerateRemoteSectionResponse; } - const void* GetBaseAddress() const { return baseAddress; } - const void* GetRegionSize() const { return regionSize; } + RC_Pointer GetBaseAddress() const { return baseAddress; } + RC_Pointer GetRegionSize() const { return size; } + SectionType GetType() const { return type; } + SectionCategory GetCategory() const { return category; } + SectionProtection GetProtection() const { return protection; } const std::wstring& GetName() const { return name; } - int GetState() const { return state; } - int GetProtection() const { return protection; } - int GetSectionType() const { return sectionType; } const std::wstring& GetModulePath() const { return modulePath; } - EnumerateRemoteSectionCallbackMessage() - : baseAddress(0), - regionSize(0), - state(0), - protection(0), - sectionType(0) + EnumerateRemoteSectionResponse() + : baseAddress(nullptr), + size(nullptr), + type(SectionType::Unknown), + category(SectionCategory::Unknown), + protection(SectionProtection::NoAccess) { } - EnumerateRemoteSectionCallbackMessage(const void* _baseAddress, const void* _regionSize, std::wstring&& _name, int _state, int _protection, int _type, std::wstring&& _modulePath) + EnumerateRemoteSectionResponse(RC_Pointer _baseAddress, RC_Pointer _size, SectionType _type, SectionCategory _category, SectionProtection _protection, std::wstring&& _name, std::wstring&& _modulePath) : baseAddress(_baseAddress), - regionSize(_regionSize), - name(std::move(_name)), - state(_state), + size(_size), + type(_type), + category(_category), protection(_protection), - sectionType(_type), + name(std::move(_name)), modulePath(std::move(_modulePath)) { } - virtual void ReadFrom(BinaryReader& reader) override + void ReadFrom(BinaryReader& reader) override { baseAddress = reader.ReadIntPtr(); - regionSize = reader.ReadIntPtr(); + size = reader.ReadIntPtr(); + type = static_cast(reader.ReadInt32()); + category = static_cast(reader.ReadInt32()); + protection = static_cast(reader.ReadInt32()); name = reader.ReadString(); - state = reader.ReadInt32(); - protection = reader.ReadInt32(); - sectionType = reader.ReadInt32(); modulePath = reader.ReadString(); } - virtual void WriteTo(BinaryWriter& writer) const override + void WriteTo(BinaryWriter& writer) const override { writer.Write(baseAddress); - writer.Write(regionSize); + writer.Write(size); + writer.Write(static_cast(type)); + writer.Write(static_cast(category)); + writer.Write(static_cast(protection)); writer.Write(name); - writer.Write(state); - writer.Write(protection); - writer.Write(sectionType); writer.Write(modulePath); } private: - const void* baseAddress; - const void* regionSize; + RC_Pointer baseAddress; + RC_Pointer size; + SectionType type; + SectionCategory category; + SectionProtection protection; std::wstring name; - int state; - int protection; - int sectionType; std::wstring modulePath; }; //--------------------------------------------------------------------------- -class EnumerateRemoteModuleCallbackMessage : public IMessage +class EnumerateRemoteModuleResponse : public IMessage { public: - static const int StaticType = 10; - virtual int GetType() const override { return StaticType; } + MessageType GetMessageType() const override { return MessageType::EnumerateRemoteModuleResponse; } const void* GetBaseAddress() const { return baseAddress; } - const void* GetRegionSize() const { return regionSize; } + const void* GetRegionSize() const { return size; } const std::wstring& GetModulePath() const { return modulePath; } - EnumerateRemoteModuleCallbackMessage() - : baseAddress(0), - regionSize(0) + EnumerateRemoteModuleResponse() + : baseAddress(nullptr), + size(nullptr) { } - EnumerateRemoteModuleCallbackMessage(const void* _baseAddress, const void* _regionSize, std::wstring&& _modulePath) + EnumerateRemoteModuleResponse(const void* _baseAddress, const void* _regionSize, std::wstring&& _modulePath) : baseAddress(_baseAddress), - regionSize(_regionSize), + size(_regionSize), modulePath(std::move(_modulePath)) { } - virtual void ReadFrom(BinaryReader& reader) override + void ReadFrom(BinaryReader& reader) override { baseAddress = reader.ReadIntPtr(); - regionSize = reader.ReadIntPtr(); + size = reader.ReadIntPtr(); modulePath = reader.ReadString(); } - virtual void WriteTo(BinaryWriter& writer) const override + void WriteTo(BinaryWriter& writer) const override { writer.Write(baseAddress); - writer.Write(regionSize); + writer.Write(size); writer.Write(modulePath); } private: const void* baseAddress; - const void* regionSize; + const void* size; std::wstring modulePath; }; //--------------------------------------------------------------------------- diff --git a/PipeServer/NamedPipeServerStream.cpp b/PipeServer/NamedPipeServerStream.cpp deleted file mode 100644 index ef433db..0000000 --- a/PipeServer/NamedPipeServerStream.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -namespace fs = std::experimental::filesystem; - -#include "NamedPipeServerStream.hpp" -#include "Exceptions.hpp" - -NamedPipeServerStream::NamedPipeServerStream(const std::wstring& pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode) - : NamedPipeServerStream(pipeName, direction, maxNumberOfServerInstances, transmissionMode, 0, 0) -{ - -} -//--------------------------------------------------------------------------- -NamedPipeServerStream::NamedPipeServerStream(const std::wstring& pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, int inBufferSize, int outBufferSize) - : PipeStream(direction, transmissionMode) -{ - auto normalizedPipePath = (fs::path("\\\\.\\pipe") / pipeName).wstring(); - - Create(normalizedPipePath, direction, maxNumberOfServerInstances, transmissionMode, inBufferSize, outBufferSize); -} -//--------------------------------------------------------------------------- -NamedPipeServerStream::~NamedPipeServerStream() -{ - state = PipeState::Closed; -} -//--------------------------------------------------------------------------- -void NamedPipeServerStream::Create(const std::wstring& fullPipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, int inBufferSize, int outBufferSize) -{ - int pipeModes = (int)transmissionMode << 2 | (int)transmissionMode << 1; - - if (maxNumberOfServerInstances == MaxAllowedServerInstances) - { - maxNumberOfServerInstances = 255; - } - - handle = SafePipeHandle(CreateNamedPipeW(fullPipeName.c_str(), (int)direction, pipeModes, maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, nullptr), true); - - if (handle.IsInvalid()) - { - throw IOException(GetLastError()); - } -} -//--------------------------------------------------------------------------- -void NamedPipeServerStream::WaitForConnection() -{ - CheckConnectOperationsServer(); - - if (!ConnectNamedPipe(handle.GetHandle(), nullptr)) - { - int errorCode = GetLastError(); - if (errorCode != ERROR_PIPE_CONNECTED) - { - throw IOException(errorCode); - } - - if (errorCode == ERROR_PIPE_CONNECTED && state == PipeState::Connected) - { - throw InvalidOperationException(); - } - } - state = PipeState::Connected; -} -//--------------------------------------------------------------------------- -void NamedPipeServerStream::Disconnect() -{ - CheckDisconnectOperations(); - - if (!DisconnectNamedPipe(handle.GetHandle())) - { - throw IOException(GetLastError()); - } - - state = PipeState::Disconnected; -} -//--------------------------------------------------------------------------- -void NamedPipeServerStream::CheckConnectOperationsServer() -{ - if (state == PipeState::Closed || state == PipeState::Broken) - { - throw InvalidOperationException(); - } -} -//--------------------------------------------------------------------------- -void NamedPipeServerStream::CheckDisconnectOperations() -{ - if (state == PipeState::WaitingToConnect || state == PipeState::Disconnected || state == PipeState::Closed) - { - throw InvalidOperationException(); - } -} -//--------------------------------------------------------------------------- diff --git a/PipeServer/NamedPipeServerStream.hpp b/PipeServer/NamedPipeServerStream.hpp deleted file mode 100644 index 5bda340..0000000 --- a/PipeServer/NamedPipeServerStream.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "PipeStream.hpp" - -class NamedPipeServerStream : public PipeStream -{ -public: - static const int MaxAllowedServerInstances = -1; - - NamedPipeServerStream(const std::wstring& pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode); - - NamedPipeServerStream(const std::wstring& pipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, int inBufferSize, int outBufferSize); - - ~NamedPipeServerStream(); - -private: - void Create(const std::wstring& fullPipeName, PipeDirection direction, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, int inBufferSize, int outBufferSize); - -public: - void WaitForConnection(); - - void Disconnect(); - -private: - void CheckConnectOperationsServer(); - - void CheckDisconnectOperations(); -}; diff --git a/PipeServer/PipeServer.vcxproj b/PipeServer/PipeServer.vcxproj index cec2389..e6c449f 100644 --- a/PipeServer/PipeServer.vcxproj +++ b/PipeServer/PipeServer.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,32 +22,32 @@ {75CAA2A9-D512-40E0-8918-B7F87806805E} Win32Proj PipeServer - 8.1 + 10.0 DynamicLibrary true - v140 + v142 Unicode DynamicLibrary false - v140 + v142 true Unicode DynamicLibrary true - v140 + v142 Unicode DynamicLibrary false - v140 + v142 true Unicode @@ -146,27 +146,28 @@ - - - - - + + + + + - - - - - - - - + + + + + + + + + diff --git a/PipeServer/PipeServer.vcxproj.filters b/PipeServer/PipeServer.vcxproj.filters index d0861f2..fe72b48 100644 --- a/PipeServer/PipeServer.vcxproj.filters +++ b/PipeServer/PipeServer.vcxproj.filters @@ -2,25 +2,57 @@ - - - - - + + PipeStream + + + PipeStream + + + PipeStream + + + PipeStream + + + PipeStream + - - - - - - - - + + + PipeStream + + + PipeStream + + + PipeStream + + + PipeStream + + + PipeStream + + + PipeStream + + + PipeStream + + + PipeStream + + + + + {1e4c323a-61da-425f-b676-5d1d35f0a94e} + \ No newline at end of file diff --git a/PipeServer/PipeStream b/PipeServer/PipeStream new file mode 160000 index 0000000..091780e --- /dev/null +++ b/PipeServer/PipeStream @@ -0,0 +1 @@ +Subproject commit 091780ead7c00508892eb4fe70c0d7beccb77972 diff --git a/PipeServer/PipeStream.cpp b/PipeServer/PipeStream.cpp deleted file mode 100644 index 206ede7..0000000 --- a/PipeServer/PipeStream.cpp +++ /dev/null @@ -1,208 +0,0 @@ -#include "PipeStream.hpp" -#include "Exceptions.hpp" - -PipeStream::PipeStream(PipeDirection direction) - : PipeStream(direction, PipeTransmissionMode::Byte) -{ - -} -//--------------------------------------------------------------------------- -PipeStream::PipeStream(PipeDirection direction, PipeTransmissionMode transmissionMode) - : readMode(transmissionMode), - pipeDirection(direction), - isMessageComplete(true), - state(PipeState::WaitingToConnect) -{ - if ((int)(pipeDirection & PipeDirection::In) != 0) - { - canRead = true; - } - if ((int)(pipeDirection & PipeDirection::Out) != 0) - { - canWrite = true; - } -} -//--------------------------------------------------------------------------- -bool PipeStream::IsMessageComplete() const -{ - if (state == PipeState::WaitingToConnect || state == PipeState::Disconnected || state == PipeState::Closed || readMode != PipeTransmissionMode::Message) - { - throw InvalidOperationException(); - } - - return isMessageComplete; -} -//--------------------------------------------------------------------------- -int PipeStream::Read(uint8_t* buffer, int offset, int count) -{ - if (!canRead) - { - throw InvalidOperationException(); - } - - CheckReadOperations(); - - return ReadCore(buffer, offset, count); -} -//--------------------------------------------------------------------------- -int PipeStream::ReadByte() -{ - CheckReadOperations(); - - uint8_t buffer[1]; - int n = ReadCore(buffer, 0, 1); - - if (n == 0) - { - return -1; - } - - return (int)buffer[0]; -} -//--------------------------------------------------------------------------- -void PipeStream::Write(const uint8_t* buffer, int offset, int count) -{ - if (!canWrite) - { - throw InvalidOperationException(); - } - - CheckWriteOperations(); - - WriteCore(buffer, offset, count); -} -//--------------------------------------------------------------------------- -void PipeStream::WriteByte(uint8_t value) -{ - CheckWriteOperations(); - - uint8_t buffer[1] = { value }; - WriteCore(buffer, 0, 1); -} -//--------------------------------------------------------------------------- -void PipeStream::CheckReadOperations() -{ - if (state == PipeState::WaitingToConnect || state == PipeState::Disconnected || state == PipeState::Closed || handle.IsInvalid()) - { - throw InvalidOperationException(); - } -} -//--------------------------------------------------------------------------- -void PipeStream::CheckWriteOperations() -{ - if (state == PipeState::WaitingToConnect || state == PipeState::Disconnected || state == PipeState::Broken || state == PipeState::Closed || handle.IsInvalid()) - { - throw InvalidOperationException(); - } -} -//--------------------------------------------------------------------------- -void PipeStream::WinIOError(int errorCode) -{ - if (errorCode == ERROR_BROKEN_PIPE || errorCode == ERROR_PIPE_NOT_CONNECTED || errorCode == ERROR_NO_DATA) - { - state = PipeState::Broken; - - throw IOException(errorCode); - - } - else if (errorCode == ERROR_HANDLE_EOF) - { - throw IOException(); - } - else - { - if (errorCode == ERROR_INVALID_HANDLE) - { - handle = SafePipeHandle(); - state = PipeState::Broken; - } - - throw IOException(errorCode); - } -} -//--------------------------------------------------------------------------- -int PipeStream::ReadCore(uint8_t* buffer, int offset, int count) -{ - int hr = 0; - int r = ReadFileNative(handle, buffer, offset, count, hr); - if (r == -1) - { - if (hr == ERROR_BROKEN_PIPE || hr == ERROR_PIPE_NOT_CONNECTED) - { - state = PipeState::Broken; - r = 0; - } - else - { - throw IOException(hr); - } - } - isMessageComplete = hr != ERROR_MORE_DATA; - - return r; -} -//--------------------------------------------------------------------------- -int PipeStream::ReadFileNative(const SafePipeHandle& handle, uint8_t* buffer, int offset, int count, int& hr) -{ - if (count == 0) - { - hr = 0; - return 0; - } - - DWORD numBytesRead = 0; - int r = ReadFile(handle.GetHandle(), buffer + offset, count, &numBytesRead, nullptr); - if (r == 0) - { - hr = GetLastError(); - - if (hr == ERROR_MORE_DATA) - { - return numBytesRead; - } - - return -1; - } - else - { - hr = 0; - } - - return numBytesRead; -} -//--------------------------------------------------------------------------- -void PipeStream::WriteCore(const uint8_t* buffer, int offset, int count) -{ - int hr = 0; - int r = WriteFileNative(handle, buffer, offset, count, hr); - - if (r == -1) - { - throw IOException(hr); - } -} -//--------------------------------------------------------------------------- -int PipeStream::WriteFileNative(const SafePipeHandle& handle, const uint8_t* buffer, int offset, int count, int& hr) -{ - if (count == 0) - { - hr = 0; - return 0; - } - - DWORD numBytesWritten = 0; - int r = WriteFile(handle.GetHandle(), buffer + offset, count, &numBytesWritten, nullptr); - if (r == 0) - { - hr = GetLastError(); - - return -1; - } - else - { - hr = 0; - } - - return numBytesWritten; -} -//--------------------------------------------------------------------------- diff --git a/PipeServer/PipeStream.hpp b/PipeServer/PipeStream.hpp deleted file mode 100644 index 5adcedf..0000000 --- a/PipeServer/PipeStream.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#pragma once - -#include "Stream.hpp" -#include "SafeHandle.hpp" - -class SafePipeHandle : public SafeHandleZeroOrMinusOneIsInvalid -{ -public: - SafePipeHandle() - : SafeHandleZeroOrMinusOneIsInvalid(true) - { - } - - SafePipeHandle(HANDLE preexistingHandle, bool ownsHandle) - : SafeHandleZeroOrMinusOneIsInvalid(ownsHandle) - { - SetHandle(preexistingHandle); - } - - SafePipeHandle(SafePipeHandle&& copy) - : SafeHandleZeroOrMinusOneIsInvalid(true) - { - handle = copy.handle; - - copy.ownsHandle = false; - copy.handle = nullptr; - } - - virtual ~SafePipeHandle() - { - if (handle != nullptr && ownsHandle) - { - CloseHandle(handle); - - handle = nullptr; - } - } - - SafePipeHandle& operator=(SafePipeHandle&& copy) - { - handle = copy.handle; - - copy.handle = nullptr; - - return *this; - } -}; - -enum class PipeDirection -{ - In = 1, - Out = 2, - InOut = In | Out, -}; - -inline PipeDirection operator |(PipeDirection a, PipeDirection b) -{ - return static_cast(static_cast(a) | static_cast(b)); -} - -inline PipeDirection operator &(PipeDirection a, PipeDirection b) -{ - return static_cast(static_cast(a) & static_cast(b)); -} - -enum class PipeTransmissionMode -{ - Byte = 0, - Message = 1, -}; - -enum class PipeOptions -{ - None = 0x0, - WriteThrough = (int)0x80000000, - Asynchronous = (int)0x40000000, -}; - -enum class PipeState -{ - WaitingToConnect = 0, - Connected = 1, - Broken = 2, - Disconnected = 3, - Closed = 4, -}; - -class PipeStream : public Stream -{ -protected: - PipeStream(PipeDirection direction); - - PipeStream(PipeDirection direction, PipeTransmissionMode transmissionMode); - -public: - bool IsMessageComplete() const; - - virtual int Read(uint8_t* buffer, int offset, int count) override; - - virtual int ReadByte() override; - - virtual void Write(const uint8_t* buffer, int offset, int count); - - virtual void WriteByte(uint8_t value) override; - -private: - void CheckReadOperations(); - - void CheckWriteOperations(); - - void WinIOError(int errorCode); - - int ReadCore(uint8_t* buffer, int offset, int count); - - int ReadFileNative(const SafePipeHandle& handle, uint8_t* buffer, int offset, int count, int& hr); - - void WriteCore(const uint8_t* buffer, int offset, int count); - - int WriteFileNative(const SafePipeHandle& handle, const uint8_t* buffer, int offset, int count, int& hr); - -protected: - SafePipeHandle handle; - PipeState state; - -private: - bool canRead; - bool canWrite; - bool isMessageComplete; - PipeTransmissionMode readMode; - PipeDirection pipeDirection; -}; diff --git a/PipeServer/ReClassNET_Plugin.hpp b/PipeServer/ReClassNET_Plugin.hpp new file mode 100644 index 0000000..f2a3ff8 --- /dev/null +++ b/PipeServer/ReClassNET_Plugin.hpp @@ -0,0 +1,259 @@ +#pragma once + +#include +#include + +// Types + +using RC_Pointer = void*; +using RC_Size = size_t; +using RC_UnicodeChar = wchar_t; + +// Constants + +const int PATH_MAXIMUM_LENGTH = 260; + +// Enumerations + +enum class ProcessAccess +{ + Read, + Write, + Full +}; + +enum class SectionProtection +{ + NoAccess = 0, + + Read = 1, + Write = 2, + Execute = 4, + + Guard = 8 +}; + +inline SectionProtection operator|(SectionProtection lhs, SectionProtection rhs) +{ + using T = std::underlying_type_t; + + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +inline SectionProtection& operator|=(SectionProtection& lhs, SectionProtection rhs) +{ + using T = std::underlying_type_t; + + lhs = static_cast(static_cast(lhs) | static_cast(rhs)); + + return lhs; +} + +enum class SectionType +{ + Unknown, + + Private, + Mapped, + Image +}; + +enum class SectionCategory +{ + Unknown, + CODE, + DATA, + HEAP +}; + +enum class ControlRemoteProcessAction +{ + Suspend, + Resume, + Terminate +}; + +enum class DebugContinueStatus +{ + Handled, + NotHandled +}; + +enum class HardwareBreakpointRegister +{ + InvalidRegister, + + Dr0, + Dr1, + Dr2, + Dr3 +}; + +enum class HardwareBreakpointTrigger +{ + Execute, + Access, + Write, +}; + +enum class HardwareBreakpointSize +{ + Size1 = 1, + Size2 = 2, + Size4 = 4, + Size8 = 8 +}; + +enum class DebugEventType +{ + CreateProcess, + ExitProcess, + CreateThread, + ExitThread, + LoadDll, + UnloadDll, + Exception +}; + +// Structures + +#pragma pack(push, 1) + +struct EnumerateProcessData +{ + RC_Size Id; + RC_UnicodeChar ModulePath[PATH_MAXIMUM_LENGTH]; +}; + +struct InstructionData +{ + int Length; + uint8_t Data[15]; + RC_UnicodeChar Instruction[64]; +}; + +struct EnumerateRemoteSectionData +{ + RC_Pointer BaseAddress; + RC_Size Size; + SectionType Type; + SectionCategory Category; + SectionProtection Protection; + RC_UnicodeChar Name[16]; + RC_UnicodeChar ModulePath[PATH_MAXIMUM_LENGTH]; +}; + +struct EnumerateRemoteModuleData +{ + RC_Pointer BaseAddress; + RC_Size Size; + RC_UnicodeChar Path[PATH_MAXIMUM_LENGTH]; +}; + +struct CreateProcessDebugInfo +{ + RC_Pointer FileHandle; + RC_Pointer ProcessHandle; +}; + +struct ExitProcessDebugInfo +{ + RC_Size ExitCode; +}; + +struct CreateThreadDebugInfo +{ + RC_Pointer ThreadHandle; +}; + +struct ExitThreadDebugInfo +{ + RC_Size ExitCode; +}; + +struct LoadDllDebugInfo +{ + RC_Pointer FileHandle; + RC_Pointer BaseOfDll; +}; + +struct UnloadDllDebugInfo +{ + RC_Pointer BaseOfDll; +}; + +struct ExceptionDebugInfo +{ + RC_Size ExceptionCode; + RC_Size ExceptionFlags; + RC_Pointer ExceptionAddress; + + HardwareBreakpointRegister CausedBy; + + bool IsFirstChance; + + struct RegisterInfo + { +#ifdef _WIN64 + RC_Pointer Rax; + RC_Pointer Rbx; + RC_Pointer Rcx; + RC_Pointer Rdx; + RC_Pointer Rdi; + RC_Pointer Rsi; + RC_Pointer Rsp; + RC_Pointer Rbp; + RC_Pointer Rip; + + RC_Pointer R8; + RC_Pointer R9; + RC_Pointer R10; + RC_Pointer R11; + RC_Pointer R12; + RC_Pointer R13; + RC_Pointer R14; + RC_Pointer R15; +#else + RC_Pointer Eax; + RC_Pointer Ebx; + RC_Pointer Ecx; + RC_Pointer Edx; + RC_Pointer Edi; + RC_Pointer Esi; + RC_Pointer Esp; + RC_Pointer Ebp; + RC_Pointer Eip; +#endif + }; + RegisterInfo Registers; +}; + +struct DebugEvent +{ + DebugContinueStatus ContinueStatus; + + RC_Pointer ProcessId; + RC_Pointer ThreadId; + + DebugEventType Type; + + union + { + CreateProcessDebugInfo CreateProcessInfo; + ExitProcessDebugInfo ExitProcessInfo; + CreateThreadDebugInfo CreateThreadInfo; + ExitThreadDebugInfo ExitThreadInfo; + LoadDllDebugInfo LoadDllInfo; + UnloadDllDebugInfo UnloadDllInfo; + ExceptionDebugInfo ExceptionInfo; + }; +}; + +#pragma pack(pop) + +// Callbacks + +typedef void(__stdcall *EnumerateProcessCallback)(EnumerateProcessData* data); + +typedef void(__stdcall EnumerateRemoteSectionsCallback)(EnumerateRemoteSectionData* data); +typedef void(__stdcall EnumerateRemoteModulesCallback)(EnumerateRemoteModuleData* data); diff --git a/PipeServer/SafeHandle.hpp b/PipeServer/SafeHandle.hpp deleted file mode 100644 index 04f92a9..0000000 --- a/PipeServer/SafeHandle.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include - -class SafeHandle -{ -protected: - SafeHandle(HANDLE invalidHandleValue, bool _ownsHandle) - : handle(invalidHandleValue), - ownsHandle(_ownsHandle) - { - } - -public: - virtual ~SafeHandle() - { - - } - - virtual bool IsInvalid() = 0; - - HANDLE GetHandle() const - { - return handle; - } - -protected: - void SetHandle(HANDLE _handle) - { - handle = _handle; - } - -protected: - HANDLE handle; - bool ownsHandle; -}; - -class SafeHandleZeroOrMinusOneIsInvalid : public SafeHandle -{ -protected: - SafeHandleZeroOrMinusOneIsInvalid(bool ownsHandle) - : SafeHandle(nullptr, ownsHandle) - { - } - -public: - virtual bool IsInvalid() - { - return handle == nullptr || handle == INVALID_HANDLE_VALUE; - } -}; diff --git a/PipeServer/Stream.hpp b/PipeServer/Stream.hpp deleted file mode 100644 index 37198b3..0000000 --- a/PipeServer/Stream.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - -class Stream -{ -public: - virtual ~Stream() - { - - } - //--------------------------------------------------------------------------- - virtual int Read(uint8_t* buffer, int offset, int count) = 0; - //--------------------------------------------------------------------------- - virtual int ReadByte() - { - uint8_t oneByteArray[1]; - int r = Read(oneByteArray, 0, 1); - if (r == 0) - { - return -1; - } - return oneByteArray[0]; - } - //--------------------------------------------------------------------------- - virtual void Write(const uint8_t* buffer, int offset, int count) = 0; - //--------------------------------------------------------------------------- - virtual void WriteByte(uint8_t value) - { - uint8_t oneByteArray[1] = { value }; - Write(oneByteArray, 0, 1); - } - //--------------------------------------------------------------------------- -}; diff --git a/PipeServer/dllmain.cpp b/PipeServer/dllmain.cpp index 2c9ebea..e2f34cf 100644 --- a/PipeServer/dllmain.cpp +++ b/PipeServer/dllmain.cpp @@ -2,8 +2,9 @@ namespace fs = std::experimental::filesystem; #include -#include "NamedPipeServerStream.hpp" +#include "PipeStream/NamedPipeServerStream.hpp" #include "MessageClient.hpp" +#include "PipeStream/Exceptions.hpp" std::wstring CreatePipeName() { @@ -25,23 +26,19 @@ MessageClient CreateClient(NamedPipeServerStream& pipe) { MessageClient client(pipe); - client.RegisterMessage(StatusMessage::StaticType, []() { return std::make_unique(); }); - client.RegisterMessage(OpenProcessMessage::StaticType, []() { return std::make_unique(); }); - client.RegisterMessage(CloseProcessMessage::StaticType, []() { return std::make_unique(); }); - client.RegisterMessage(IsValidMessage::StaticType, []() { return std::make_unique(); }); - client.RegisterMessage(ReadMemoryMessage::StaticType, []() { return std::make_unique(); }); - client.RegisterMessage(ReadMemoryDataMessage::StaticType, []() { return std::make_unique(); }); - client.RegisterMessage(WriteMemoryMessage::StaticType, []() { return std::make_unique(); }); - client.RegisterMessage(EnumerateRemoteSectionsAndModulesMessage::StaticType, []() { return std::make_unique(); }); - client.RegisterMessage(EnumerateRemoteSectionCallbackMessage::StaticType, []() { return std::make_unique(); }); - client.RegisterMessage(EnumerateRemoteModuleCallbackMessage::StaticType, []() { return std::make_unique(); }); + client.RegisterMessage(); + client.RegisterMessage(); + client.RegisterMessage(); + client.RegisterMessage(); + client.RegisterMessage(); + client.RegisterMessage(); return client; } //--------------------------------------------------------------------------- void PipeThread(void*) { - auto name = CreatePipeName(); + const auto name = CreatePipeName(); while (true) { diff --git a/Plugin/Extensions.cs b/Plugin/Extensions.cs index e552802..bd1b061 100644 --- a/Plugin/Extensions.cs +++ b/Plugin/Extensions.cs @@ -10,7 +10,7 @@ public static IntPtr ReadIntPtr(this BinaryReader br) { Contract.Requires(br != null); -#if WIN64 +#if RECLASSNET64 return (IntPtr)br.ReadInt64(); #else return (IntPtr)br.ReadInt32(); @@ -21,7 +21,7 @@ public static void Write(this BinaryWriter bw, IntPtr value) { Contract.Requires(bw != null); -#if WIN64 +#if RECLASSNET64 bw.Write(value.ToInt64()); #else bw.Write(value.ToInt32()); diff --git a/Plugin/MemoryPipePlugin.csproj b/Plugin/MemoryPipePlugin.csproj index f7e2668..fc51cbc 100644 --- a/Plugin/MemoryPipePlugin.csproj +++ b/Plugin/MemoryPipePlugin.csproj @@ -9,8 +9,9 @@ Properties MemoryPipePlugin MemoryPipePlugin - v4.6.1 + v4.7.2 512 + x86 @@ -18,7 +19,7 @@ full false ..\bin\Debug\x86\ - TRACE;DEBUG;WIN32 + TRACE;DEBUG;RECLASSNET32 prompt 4 false @@ -28,7 +29,7 @@ pdbonly true ..\bin\Release\x86\ - TRACE;WIN32;RELEASE + TRACE;RECLASSNET32;RELEASE prompt 4 @@ -38,7 +39,7 @@ full false ..\bin\Debug\x64\ - TRACE;DEBUG;WIN64 + TRACE;DEBUG;RECLASSNET64 prompt 4 false @@ -48,7 +49,7 @@ pdbonly true ..\bin\Release\x64\ - TRACE;WIN64;RELEASE + TRACE;RECLASSNET64;RELEASE prompt 4 @@ -56,10 +57,6 @@ - - ..\packages\UnmanagedExports.1.2.7\lib\net\RGiesecke.DllExport.Metadata.dll - False - @@ -71,6 +68,7 @@ + @@ -82,12 +80,6 @@ Resources.resx - - - {BFB8917D-E9B4-463F-A6E8-612C35728C78} - ReClass.NET - - ResXFileCodeGenerator @@ -96,13 +88,15 @@ - + - + + {bfb8917d-e9b4-463f-a6e8-612c35728c78} + ReClass.NET + -