libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
exported_func.cpp
Go to the documentation of this file.
2
3#include <string>
4#include <algorithm>
5#include <sstream>
6#include <iomanip>
7#include <iostream>
8#include "peconv/file_util.h"
9
10using namespace peconv;
11
12std::string peconv::get_dll_shortname(const std::string& str)
13{
14 std::size_t len = str.length();
15 size_t ext_pos = len;
16 size_t separator_pos = 0;
17 for (size_t k = len; k != 0; k--) {
18 size_t i = k - 1;
19 char c = str[i];
20 // search first '.' from the end:
21 if (c == '.' && ext_pos == len) {
22 ext_pos = i;
23 }
24 // search first path separator from the end:
25 if (c == '\\' || c == '/') {
26 separator_pos = k;
27 break;
28 }
29 }
30 const size_t new_len = ext_pos - separator_pos;
31 std::string name = str.substr(separator_pos, new_len);
32 std::transform(name.begin(), name.end(), name.begin(), tolower);
33 return name;
34}
35
37{
38 // names can be also mangled, i.e. MSVCRT.??0__non_rtti_object@std@@QAE@ABV01@@Z
39 bool has_dot = false;
40 size_t len = 0;
41 while ((*fPtr >= 'a' && *fPtr <= 'z')
42 || (*fPtr >= 'A' && *fPtr <= 'Z')
43 || (*fPtr >= '0' && *fPtr <= '9')
44 || (*fPtr == '.')
45 || (*fPtr == '_')
46 || (*fPtr == '#')
47 || (*fPtr == '@')
48 || (*fPtr == '?')
49 || (*fPtr == '-'))
50 {
51 if (*fPtr == '.') has_dot = true;
52 len++;
53 fPtr++;
54 }
55 if (*fPtr == '\0') {
56 if (!has_dot) {
57 return 0; //this is not a valid forwarder
58 }
59 return len;
60 }
61 return 0;
62}
63
64std::string peconv::get_func_name(const std::string& str)
65{
66 std::size_t len = str.length();
67 std::size_t ext = str.find_last_of(".");
68 if (ext >= len) return "";
69
70 std::string name = str.substr(ext+1, len - (ext+1));
71 return name;
72}
73
74std::string peconv::ordinal_to_string(DWORD func_ordinal)
75{
76 std::stringstream stream;
77 stream << "#";
78 stream << std::dec << func_ordinal;
79 return stream.str();
80}
81
82bool peconv::is_ordinal_string(const std::string& func_name_str)
83{
84 if (func_name_str.length() < 2) return false;
85 return (func_name_str[0] == '#');
86}
87
88DWORD peconv::ordinal_string_to_val(const std::string& func_name_str)
89{
90 if (!is_ordinal_string(func_name_str)) return 0;
91 const char* func_name = func_name_str.c_str();
92 return atoi(func_name + 1);
93}
94
95std::string peconv::format_dll_func(const std::string& str)
96{
97 std::string dllName = get_dll_shortname(str);
98 std::string funcName = get_func_name(str);
99 if (dllName.length() == 0 || funcName.length() == 0) {
100 return "";
101 }
102 std::transform(dllName.begin(), dllName.end(), dllName.begin(), tolower);
103 return dllName + "." + funcName;
104}
105
106ExportedFunc::ExportedFunc(std::string libName, std::string funcName, DWORD funcOrdinal)
107{
108 this->libName = ExportedFunc::formatName(libName);
109 this->funcName = funcName;
110 this->funcOrdinal = funcOrdinal;
111 this->isByOrdinal = false;
112}
113
114ExportedFunc::ExportedFunc(std::string libName, DWORD funcOrdinal)
115{
116 this->libName = ExportedFunc::formatName(libName);
117 this->funcOrdinal = funcOrdinal;
118 this->isByOrdinal = true;
119}
120
122{
123 this->libName = other.libName;
124 this->funcName = other.funcName;
125 this->funcOrdinal = other.funcOrdinal;
126 this->isByOrdinal = other.isByOrdinal;
127}
128
129ExportedFunc::ExportedFunc(const std::string &forwarderName)
130{
131 this->libName = get_dll_shortname(forwarderName);
132 std::string func_name_str = get_func_name(forwarderName);
133 if (func_name_str.length() < 2) {
134 this->funcOrdinal = -1;
135 this->funcName = "";
136 this->isByOrdinal = false;
137#ifdef _DEBUG
138 std::cerr << "Invalid function data" << std::endl;
139#endif
140 return;
141 }
142 if (is_ordinal_string(func_name_str)) {
143 // it is an ordinal in a string form, i.e.: "COMBASE.#110"
144 this->funcOrdinal = peconv::ordinal_string_to_val(func_name_str);
145 this->isByOrdinal = true;
146 this->funcName = "";
147 //std::cout << "[O] Adding forwarded func: " << forwarderName << " parsed: " << this->toString() << std::endl;
148 } else {
149 this->funcName = func_name_str;
150 this->isByOrdinal = false;
151 this->funcOrdinal = 0;
152 //std::cout << "[N] Adding forwarded func:" << this->toString() << std::endl;
153 }
154}
155
156std::string ExportedFunc::formatName(std::string name)
157{
158 if (name.length() == 0) {
159 return "";
160 }
161 std::transform(name.begin(), name.end(), name.begin(), tolower);
162 return name;
163}
164
166{
167 if (!func1.isByOrdinal && !func2.isByOrdinal) {
168 if (func1.funcName == func2.funcName) {
169 return true;
170 }
171 }
172 if (func1.funcOrdinal == func2.funcOrdinal) {
173 return true;
174 }
175 return false;
176}
177
178namespace peconv
179{
180 bool is_valid_extension(const std::string &ext)
181 {
182 if (ext.length() > 3) {
183 //probably not an extension
184 return false;
185 }
186 for (size_t j = 0; j < ext.length(); j++) {
187 if (!isalpha(ext[j])) {
188 return false;
189 }
190 }
191 return true;
192 }
193
194 std::string remove_module_extension(IN const std::string str)
195 {
196 size_t len = str.length();
197 size_t ext_pos = find_extension_pos(str);
198 if (ext_pos == len) {
199 return str;
200 }
201 std::string ext = str.substr(ext_pos + 1);
202 if (is_valid_extension(ext)) {
203 std::string str1 = str.substr(0, ext_pos);
204 return str1;
205 }
206 return str;
207 }
208}; //namespace peconv
209
211{
212 const std::string file1 = peconv::get_file_name(func1.libName);
213 const std::string file2 = peconv::get_file_name(func2.libName);
214 if (file1 == file2) {
215 return true;
216 }
217 const std::string short1 = peconv::remove_module_extension(file1);
218 const std::string short2 = peconv::remove_module_extension(file2);
219 if (short1 == short2) {
220 return true;
221 }
222 return false;
223}
224
226{
227 if (!peconv::ExportedFunc::isTheSameFuncName(func1, func2)) {
228 return false;
229 }
230 if (!isTheSameDllName(func1, func2)) {
231 return false;
232 }
233 return true;
234}
235
236std::string ExportedFunc::toString() const
237{
238 if (!isValid()) {
239 return "[Invalid func]";
240 }
241 std::stringstream stream;
242 stream << this->libName;
243 stream << ".";
244 if (!this->isByOrdinal) {
245 stream << this->funcName;
246 stream << " ";
247 }
248 stream << ordinal_to_string(this->funcOrdinal);
249 return stream.str();
250}
251
252std::string ExportedFunc::nameToString() const
253{
254 if (!isValid()) {
255 return "";
256 }
257 if (this->isByOrdinal) {
258 return ordinal_to_string(this->funcOrdinal);
259 }
260 return this->funcName;
261}
static bool isTheSameFunc(const peconv::ExportedFunc &func1, const peconv::ExportedFunc &func2)
Compares functions' names. If function is defined by an ordinal, compares ordinals....
std::string nameToString() const
static bool isTheSameDllName(const peconv::ExportedFunc &func1, const peconv::ExportedFunc &func2)
Compares functions' DLL names.
static bool isTheSameFuncName(const peconv::ExportedFunc &func1, const peconv::ExportedFunc &func2)
Compares functions' names. If function is defined by an ordinal, compares ordinals....
static std::string formatName(std::string name)
std::string toString() const
A definition of ExportedFunc class - used for storing the details of the exported function....
Functions related to operations on files. Wrappers for read/write.
bool is_ordinal_string(const std::string &str)
std::string ordinal_to_string(DWORD func_ordinal)
size_t forwarder_name_len(BYTE *fPtr)
std::string get_func_name(const std::string &str)
bool is_valid_extension(const std::string &ext)
std::string remove_module_extension(IN const std::string str)
std::string format_dll_func(const std::string &str)
DWORD ordinal_string_to_val(const std::string &str)
std::string get_dll_shortname(const std::string &str)
size_t find_extension_pos(IN const std::string str)
std::string get_file_name(IN const std::string full_path)