-
Notifications
You must be signed in to change notification settings - Fork 0
/
PeFile.cpp
150 lines (116 loc) · 3.55 KB
/
PeFile.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "stdafx.h"
#include "PeErrors.h"
#include "PeFile.h"
PeFile::PeFile(string peFileName) :
m_peFileName(peFileName)
{
}
//
// Read operations
//
UINT PeFile::ReadPeFile()
{
UINT ret = PE_SUCCESS;
ret = m_dosHeader.ReadDosHeader(*this, 0);
RETURN_ON_FAILURE(ret);
ret = m_coffHeader.ReadCoffHeader(*this, m_dosHeader.e_lfanew);
RETURN_ON_FAILURE(ret);
ret = m_optionalHeader.ReadOptionalHeader(*this, m_coffHeader.FileAddress + m_coffHeader.BlockSize);
RETURN_ON_FAILURE(ret);
ret = ReadSections();
RETURN_ON_FAILURE(ret);
ret = ReadImports();
RETURN_ON_FAILURE(ret);
int exportTableIndex = static_cast<int>(DataDirectoryType::Export);
DWORD64 fileOffset = RvaToFa(m_optionalHeader.DataDirectories[exportTableIndex].VirtualAddress);
ret = m_exports.ReadExport(*this, fileOffset);
RETURN_ON_FAILURE(ret);
return ret;
}
const string & PeFile::GetPeFilePath() const
{
return m_peFileName;
}
UINT PeFile::ReadSections()
{
UINT ret = PE_SUCCESS;
// Start at the first section table
DWORD64 fileOffset = m_optionalHeader.FileAddress + m_optionalHeader.BlockSize;
// Read sections following optional header
for (int i = 0; i < m_coffHeader.NumberOfSections; i++) {
Section section = {};
// Read ith section table
section.ReadSectionTable(*this, fileOffset);
m_sections.push_back(section);
// Calculate FileAddress of the next Section Header
fileOffset += section.SectionTableBlockSize;
}
return ret;
}
UINT PeFile::ReadImports()
{
UINT ret = PE_SUCCESS;
// Start at the first Import Directory Table entry
int importTableIndex = static_cast<int>(DataDirectoryType::Import);
DWORD64 fileOffset = RvaToFa(m_optionalHeader.DataDirectories[importTableIndex].VirtualAddress);
while (true) {
Import import = {};
ret = import.ReadImport(*this, fileOffset);
if (ret == PE_REACHED_NULL_ENTRY) // Reached terminating entry
return PE_SUCCESS;
m_imports.push_back(import);
// Calculate fileOffset of the next Import Direcotry
fileOffset += import.BlockSize;
}
return PE_SUCCESS;
}
//
// Dump operations
//
void PeFile::DumpPeFile()
{
m_dosHeader.DumpDosHeader(*this);
printf(BLOCK_BREAK"\n");
m_coffHeader.DumpCoffHeader(*this);
printf(BLOCK_BREAK"\n");
m_optionalHeader.DumpOptionalHeader(*this);
printf(BLOCK_BREAK"\n");
printf("Dumping Sections...\n");
for (auto& section : m_sections) {
section.DumpSection(*this);
printf(SECTION_BREAK"\n");
}
printf(BLOCK_BREAK"\n");
for (auto& import : m_imports) {
import.DumpImport(*this);
printf(SECTION_BREAK"\n");
}
printf(BLOCK_BREAK"\n");
m_exports.DumpExport(*this);
}
//
// Generic operations
//
Section PeFile::LocateInSection(DWORD rva) const
{
Section empty = {};
for (auto& section : m_sections)
if (rva >= section.VirtualAddress &&
rva <= section.VirtualAddress + section.VirtualSize)
// file address = file offset of section + (offset of within section)
return section;
return empty;
}
DWORD PeFile::RvaToFa(DWORD rva) const
{
Section section = LocateInSection(rva);
return section.PointerToRawData + (rva - section.VirtualAddress);
}
bool PeFile::IsPe32() const
{
return m_optionalHeader.Magic == 0x10b;
}
DataDirectoryEntry PeFile::GetDataDirectories(DataDirectoryType type) const
{
return m_optionalHeader.DataDirectories[static_cast<DWORD>(type)];
}