libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
exported_func.cpp
Go to the documentation of this file.
2#include "peconv/logger.h"
3
4#include <string>
5#include <algorithm>
6#include <sstream>
7#include <iomanip>
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
107{
108 this->libName = ExportedFunc::formatName(libName);
109 this->funcName = funcName;
110 this->funcOrdinal = funcOrdinal;
111 this->isByOrdinal = false;
112}
113
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 const 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 LOG_WARNING("Invalid function name: %s from forwarder: %s", func_name_str.c_str(), forwarderName.c_str());
138 return;
139 }
140 if (is_ordinal_string(func_name_str)) {
141 // it is an ordinal in a string form, i.e.: "COMBASE.#110"
142 this->funcOrdinal = peconv::ordinal_string_to_val(func_name_str);
143 this->isByOrdinal = true;
144 this->funcName = "";
145 //std::cout << "[O] Adding forwarded func: " << forwarderName << " parsed: " << this->toString() << std::endl;
146 } else {
147 this->funcName = func_name_str;
148 this->isByOrdinal = false;
149 this->funcOrdinal = 0;
150 //std::cout << "[N] Adding forwarded func:" << this->toString() << std::endl;
151 }
152}
153
154std::string ExportedFunc::formatName(std::string name)
155{
156 if (name.length() == 0) {
157 return "";
158 }
159 std::transform(name.begin(), name.end(), name.begin(), tolower);
160 return name;
161}
162
164{
165 if (!func1.isByOrdinal && !func2.isByOrdinal) {
166 if (func1.funcName == func2.funcName) {
167 return true;
168 }
169 }
170 if (func1.funcOrdinal == func2.funcOrdinal) {
171 return true;
172 }
173 return false;
174}
175
176namespace peconv
177{
178 bool is_valid_extension(const std::string &ext)
179 {
180 if (ext.length() > 3) {
181 //probably not an extension
182 return false;
183 }
184 for (size_t j = 0; j < ext.length(); j++) {
185 if (!isalpha(ext[j])) {
186 return false;
187 }
188 }
189 return true;
190 }
191
192 std::string remove_module_extension(IN const std::string str)
193 {
194 size_t len = str.length();
195 size_t ext_pos = find_extension_pos(str);
196 if (ext_pos == len) {
197 return str;
198 }
199 std::string ext = str.substr(ext_pos + 1);
200 if (is_valid_extension(ext)) {
201 std::string str1 = str.substr(0, ext_pos);
202 return str1;
203 }
204 return str;
205 }
206}; //namespace peconv
207
209{
210 const std::string file1 = peconv::get_file_name(func1.libName);
211 const std::string file2 = peconv::get_file_name(func2.libName);
212 if (file1 == file2) {
213 return true;
214 }
215 const std::string short1 = peconv::remove_module_extension(file1);
216 const std::string short2 = peconv::remove_module_extension(file2);
217 if (short1 == short2) {
218 return true;
219 }
220 return false;
221}
222
224{
225 if (!peconv::ExportedFunc::isTheSameFuncName(func1, func2)) {
226 return false;
227 }
228 if (!isTheSameDllName(func1, func2)) {
229 return false;
230 }
231 return true;
232}
233
234std::string ExportedFunc::toString() const
235{
236 if (!isValid()) {
237 return "[Invalid func]";
238 }
239 std::stringstream stream;
240 stream << this->libName;
241 stream << ".";
242 if (!this->isByOrdinal) {
243 stream << this->funcName;
244 stream << " ";
245 }
246 stream << ordinal_to_string(this->funcOrdinal);
247 return stream.str();
248}
249
250std::string ExportedFunc::nameToString() const
251{
252 if (!isValid()) {
253 return "";
254 }
255 if (this->isByOrdinal) {
256 return ordinal_to_string(this->funcOrdinal);
257 }
258 return this->funcName;
259}
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.
#define LOG_WARNING(fmt,...)
Definition logger.h:44
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)