diff --git a/GleeBug/GleeBug.vcxproj b/GleeBug/GleeBug.vcxproj
index 1d5a1ef..578546d 100644
--- a/GleeBug/GleeBug.vcxproj
+++ b/GleeBug/GleeBug.vcxproj
@@ -164,6 +164,7 @@
+
@@ -177,6 +178,9 @@
+
+
+
diff --git a/GleeBug/GleeBug.vcxproj.filters b/GleeBug/GleeBug.vcxproj.filters
index b04db63..8fd3aba 100644
--- a/GleeBug/GleeBug.vcxproj.filters
+++ b/GleeBug/GleeBug.vcxproj.filters
@@ -65,6 +65,9 @@
Source Files
+
+ Source Files
+
@@ -100,5 +103,14 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/GleeBug/Static.Pe.cpp b/GleeBug/Static.Pe.cpp
new file mode 100644
index 0000000..ce6f0a6
--- /dev/null
+++ b/GleeBug/Static.Pe.cpp
@@ -0,0 +1,107 @@
+#include "Static.Pe.h"
+
+namespace GleeBug
+{
+ Pe::Pe(File & file)
+ : _file(file)
+ {
+ Clear();
+ }
+
+ void Pe::Clear()
+ {
+ _fileSize = 0;
+ _data.clear();
+ _offset = 0;
+ _dosHeader = Region();
+ _afterDosData = Region();
+ _ntHeaders32 = Region();
+ _ntHeaders64 = Region();
+ _sectionHeaders = Region();
+ }
+
+ bool Pe::ParseHeaders()
+ {
+ //clear all current data
+ Clear();
+
+ //read the DOS header
+ _dosHeader = readRegion();
+ if (!_dosHeader)
+ return false;
+
+ //verify the DOS header
+ if (_dosHeader()->e_magic != IMAGE_DOS_SIGNATURE)
+ return false;
+
+ //get the NT headers offset
+ auto newOffset = uint32(_dosHeader()->e_lfanew);
+
+ //verify the new offset
+ if (newOffset < 0 || newOffset < _offset || newOffset >= _file.GetSize())
+ return false;
+
+ //read the data between the DOS header and the NT headers
+ auto offsetDiff = newOffset - _offset;
+ _afterDosData = readRegion(offsetDiff);
+
+ //read & verify the signature
+ auto signature = readRegion();
+ if (!signature || *(signature()) != IMAGE_NT_SIGNATURE)
+ return false;
+
+ //read the file header
+ auto ifh = readRegion();
+ if (!ifh)
+ return false;
+ switch (ifh()->Machine)
+ {
+ case IMAGE_FILE_MACHINE_I386:
+ _ntHeaders32 = Region(&_data, signature.Offset()); //this region is not valid at this point
+ if (!readRegion()) //read the optional header data
+ return false;
+ if (!_ntHeaders32) //validate we read the entire NT headers region
+ return false;
+ break;
+ case IMAGE_FILE_MACHINE_AMD64:
+ _ntHeaders64 = Region(&_data, signature.Offset()); //this region is not valid at this point
+ if (!readRegion()) //read the optional header data
+ return false;
+ if (!_ntHeaders64) //validate we read the entire NT headers region
+ return false;
+ break;
+ default: //unsupported machine
+ return false;
+ }
+
+#define IMAGE_FIRST_SECTION123( ntheader ) ((PIMAGE_SECTION_HEADER) \
+ ((ULONG_PTR)(ntheader) + \
+ FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \
+ ((ntheader))->FileHeader.SizeOfOptionalHeader \
+ ))
+ return true;
+ }
+
+ uint32 Pe::readData(uint32 size)
+ {
+ std::vector temp(size);
+
+ if (!_file.Read(_offset, temp.data(), size))
+ return INVALID_VALUE;
+
+ auto result = _offset;
+ _offset += size;
+ _data.insert(_data.end(), temp.begin(), temp.end());
+ return result;
+ }
+
+ bool Pe::IsValidPe() const
+ {
+ return false;
+ }
+
+ bool Pe::IsPe64() const
+ {
+ return false;
+ }
+};
\ No newline at end of file
diff --git a/GleeBug/Static.Pe.h b/GleeBug/Static.Pe.h
new file mode 100644
index 0000000..c52ba46
--- /dev/null
+++ b/GleeBug/Static.Pe.h
@@ -0,0 +1,47 @@
+#ifndef _STATIC_PE_H
+#define _STATIC_PE_H
+
+#include "Static.File.h"
+#include "Static.Region.h"
+
+namespace GleeBug
+{
+ class Pe
+ {
+ public:
+ explicit Pe(File & file);
+
+ void Clear();
+ bool ParseHeaders();
+ bool IsValidPe() const;
+ bool IsPe64() const;
+
+ const Region & GetDosHeader() const { return _dosHeader; }
+ const Region & GetAfterDosData() const { return _afterDosData; }
+ const Region & GetNtHeaders32() const { return _ntHeaders32; }
+ const Region & GetNtHeaders64() const { return _ntHeaders64; }
+ const Region & GetSectionHeaders() const { return _sectionHeaders; }
+
+ private:
+ uint32 readData(uint32 size);
+
+ template
+ inline Region readRegion(uint32 count = 1)
+ {
+ return Region(&_data, readData(sizeof(T) * count), count);
+ }
+
+ File & _file;
+ uint32 _fileSize;
+ std::vector _data;
+ uint32 _offset;
+
+ Region _dosHeader;
+ Region _afterDosData;
+ Region _ntHeaders32;
+ Region _ntHeaders64;
+ Region _sectionHeaders;
+ };
+};
+
+#endif //_STATIC_PE_H
\ No newline at end of file
diff --git a/GleeBug/Static.Region.h b/GleeBug/Static.Region.h
new file mode 100644
index 0000000..af37887
--- /dev/null
+++ b/GleeBug/Static.Region.h
@@ -0,0 +1,106 @@
+#ifndef _STATIC_REGION_H
+#define _STATIC_REGION_H
+
+#include "Static.Global.h"
+
+namespace GleeBug
+{
+ /**
+ \brief An immutable region object. Used to indicate a region of data in a vector.
+ \tparam T Type of the data in the region.
+ */
+ template
+ class Region
+ {
+ public:
+ /**
+ \brief Default constructor (constructs an invalid region).
+ */
+ explicit Region()
+ : Region(nullptr, INVALID_VALUE, INVALID_VALUE)
+ {
+ }
+
+ /**
+ \brief Constructor (constructs a valid region).
+ \param [in] data Pointer to the vector that holds the actual data. Use nullptr to create an invalid region.
+ \param offset The offset. Use INVALID_VALUE to create an invalid region.
+ \param count (Optional) Number of Ts in the region. Use INVALID_VALUE to create an invalid region.
+ */
+ explicit Region(std::vector* data, uint32 offset, uint32 count = 1)
+ : _data(data),
+ _offset(offset),
+ _count(count)
+ {
+ }
+
+ /**
+ \brief Returns a pointer inside the data to the start of this region.
+ \return nullptr if the region is invalid, a pointer to the data otherwise.
+ */
+ T* Data() const
+ {
+ if (!Valid())
+ return nullptr;
+ return (T*)(_data->data() + _offset);
+ }
+
+ /**
+ \brief Gets the offset in the data of this region.
+ */
+ uint32 Offset() const
+ {
+ return _offset;
+ }
+
+ /**
+ \brief Gets the number of Ts in this region.
+ */
+ uint32 Count() const
+ {
+ return _count;
+ }
+
+ /**
+ \brief Gets the size of this region in bytes. Basically: sizeof(T) * Count().
+ */
+ uint32 Size() const
+ {
+ return Valid() ? _count * sizeof(T) : INVALID_VALUE;
+ }
+
+ /**
+ \brief Returns if this region is valid.
+ */
+ bool Valid() const
+ {
+ return _offset != INVALID_VALUE &&
+ _count != INVALID_VALUE &&
+ _data && _data->data() &&
+ _offset + _count * sizeof(T) <= _data->size();
+ }
+
+ /**
+ \brief Returns Valid().
+ */
+ operator bool() const
+ {
+ return Valid();
+ }
+
+ /**
+ \brief Returns Data().
+ */
+ T* operator ()() const
+ {
+ return Data();
+ }
+
+ private:
+ std::vector* _data;
+ uint32 _offset;
+ uint32 _count;
+ };
+};
+
+#endif //_STATIC_REGION_H
\ No newline at end of file
diff --git a/MyDebugger/main.cpp b/MyDebugger/main.cpp
index 93abbae..836f74c 100644
--- a/MyDebugger/main.cpp
+++ b/MyDebugger/main.cpp
@@ -1,13 +1,16 @@
#include
#include "MyDebugger.h"
+#include "GleeBug/Static.File.h"
+#include "GleeBug/Static.Pe.h"
-int main()
-{
#ifdef _WIN64
- wchar_t szFilePath[256] = L"c:\\test64.exe";
+wchar_t szFilePath[256] = L"c:\\test64.exe";
#else //x86
- wchar_t szFilePath[256] = L"c:\\test32.exe";
+wchar_t szFilePath[256] = L"c:\\test32.exe";
#endif //_WIN64
+
+static void testDebugger()
+{
wchar_t szCommandLine[256] = L"";
wchar_t szCurrentDir[256] = L"c:\\";
MyDebugger dbg;
@@ -21,6 +24,51 @@ int main()
{
puts("Debugger::Init failed!");
}
+}
+
+static void testStatic()
+{
+ using namespace GleeBug;
+ File file(szFilePath, File::ReadOnly);
+ if (file.Open())
+ {
+ Pe pe(file);
+ if (pe.ParseHeaders())
+ {
+ PIMAGE_DOS_HEADER idh = pe.GetDosHeader().Data();
+ puts("DOS Header:");
+ printf(" e_magic: %02X\n", idh->e_magic);
+ printf(" e_lfanew: %08X\n", idh->e_lfanew);
+#ifdef _WIN64
+ PIMAGE_NT_HEADERS64 inth = pe.GetNtHeaders64().Data();
+#else //x32
+ PIMAGE_NT_HEADERS32 inth = pe.GetNtHeaders32().Data();
+#endif //_WIN64
+ puts("\nNT Headers:");
+ printf(" Signature: %08X\n", inth->Signature);
+ PIMAGE_FILE_HEADER ifh = &inth->FileHeader;
+ puts("\n File Header:");
+ printf(" Machine : %02X\n", ifh->Machine);
+ printf(" TimeDateStamp: %08X\n", ifh->TimeDateStamp);
+ PIMAGE_OPTIONAL_HEADER ioh = &inth->OptionalHeader;
+ puts("\n Optional Header:");
+ printf(" Magic : %04X\n", ioh->Magic);
+ printf(" ImageBase: %p\n", ioh->ImageBase);
+ printf(" Subsystem: %04X\n", ioh->Subsystem);
+ puts("\n Section Headers:");
+ }
+ else
+ puts("Pe::ParseHeaders failed!");
+ }
+ else
+ {
+ puts("File::Open failed!");
+ }
+}
+
+int main()
+{
+ testStatic();
system("pause");
return 0;
}
\ No newline at end of file