12template <
typename FIELD_T>
15 if (!modulePtr || call_via == 0)
return 0;
17 size_t addrCounter = 0;
20 LPVOID thunk_ptr = (LPVOID)((ULONGLONG)modulePtr + thunk_addr);
21 if (!
validate_ptr(modulePtr, moduleSize, thunk_ptr,
sizeof(FIELD_T))) {
25 LPVOID call_via_ptr = (LPVOID)((ULONGLONG)modulePtr + call_via);
26 if (!
validate_ptr(modulePtr, moduleSize, call_via_ptr,
sizeof(FIELD_T))) {
29 FIELD_T *call_via_val =
reinterpret_cast<FIELD_T*
>(call_via_ptr);
30 if ((*call_via_val) == 0) {
34 ULONGLONG searchedAddr = ULONGLONG(*call_via_val);
35 if (exportsMap.find_export_by_va(searchedAddr) !=
nullptr) {
36 addresses.insert(searchedAddr);
40 call_via +=
sizeof(FIELD_T);
42 thunk_addr +=
sizeof(FIELD_T);
51 std::set<std::string> currDllNames;
53 const std::set<ExportedFunc>* exports_for_va = exportsMap.
find_exports_by_va(func_addr);
54 if (!exports_for_va) {
55 LOG_WARNING(
"Cannot find any DLL exporting: 0x%llx.", (
unsigned long long)func_addr);
59 for (std::set<ExportedFunc>::iterator strItr = exports_for_va->begin();
60 strItr != exports_for_va->end();
63 currDllNames.insert(strItr->libName);
68std::set<std::string>
get_dlls_intersection(
const std::set<std::string> &dllNames,
const std::set<std::string> &currDllNames)
70 std::set<std::string> resultSet;
71 std::set_intersection(dllNames.begin(), dllNames.end(),
72 currDllNames.begin(), currDllNames.end(),
73 std::inserter(resultSet, resultSet.begin())
81 std::set<std::string> mainDllsSet;
82 std::set<std::string> reserveDllSet;
87 std::set<ULONGLONG>::iterator addrItr;
89 for (addrItr = addresses.begin(); addrItr != addresses.end(); ++addrItr) {
90 ULONGLONG searchedAddr = *addrItr;
98 mainDllsSet = currDllNames;
104 if (resultSet.size() > 0) {
106 mainDllsSet = resultSet;
111 if (resultSet.size() > 0) {
113 reserveDllSet = mainDllsSet;
114 mainDllsSet = resultSet;
118 reserveDllSet = currDllNames;
120 if (mainDllsSet.size() > 0) {
121 const std::string main_dll = *(mainDllsSet.begin());
130 if (found_name.length() == 0) {
135 LOG_DEBUG(
"Found DLL name: %s.", found_name.c_str());
140 IN
const std::string &chosenDll,
142 OUT std::map<ULONGLONG, std::set<ExportedFunc>> &addr_to_func,
143 OUT std::set<ULONGLONG> ¬_found
146 std::set<ULONGLONG> coveredAddresses;
147 std::set<ULONGLONG>::iterator addrItr;
148 for (addrItr = addresses.begin(); addrItr != addresses.end(); ++addrItr) {
150 ULONGLONG searchedAddr = *addrItr;
152 const std::set<ExportedFunc>* exports_for_va = exportsMap.find_exports_by_va(searchedAddr);
153 if (exports_for_va ==
nullptr) {
154 not_found.insert(searchedAddr);
155 LOG_WARNING(
"Cannot find any DLL exporting: 0x%llx.", (
unsigned long long)searchedAddr);
159 for (std::set<ExportedFunc>::iterator strItr = exports_for_va->begin();
160 strItr != exports_for_va->end();
163 std::string dll_name = strItr->libName;
164 if (dll_name != chosenDll) {
168 addr_to_func[searchedAddr].insert(func);
169 coveredAddresses.insert(searchedAddr);
171 if (addr_to_func.find(searchedAddr) == addr_to_func.end()) {
172 const ExportedFunc* func = exportsMap.find_export_by_va(searchedAddr);
173 not_found.insert(searchedAddr);
175 LOG_WARNING(
"Function '%s' not found in the covering DLL: %s.", func->
toString().c_str(), chosenDll.c_str());
178 LOG_WARNING(
"Function at [0x%llx] not found in the covering DLL: %s.", (
unsigned long long)searchedAddr, chosenDll.c_str());
182 return coveredAddresses.size();
205 LOG_WARNING(
"Function not recovered: [0x%llx].", (
unsigned long long)searchedAddr);
212 const bool skip_bound =
false;
218 DWORD maxSize = importsDir->Size;
219 DWORD impAddr = importsDir->VirtualAddress;
221 IMAGE_IMPORT_DESCRIPTOR* lib_desc =
nullptr;
222 DWORD parsedSize = 0;
225 while (parsedSize < maxSize) {
227 lib_desc = (IMAGE_IMPORT_DESCRIPTOR*)(impAddr + parsedSize + (ULONG_PTR) modulePtr);
228 if (!
validate_ptr(modulePtr, moduleSize, lib_desc,
sizeof(IMAGE_IMPORT_DESCRIPTOR))) {
229 LOG_ERROR(
"Invalid import descriptor pointer.");
232 parsedSize +=
sizeof(IMAGE_IMPORT_DESCRIPTOR);
233 if (!lib_desc->OriginalFirstThunk && !lib_desc->FirstThunk) {
236 const bool is_bound = (lib_desc->TimeDateStamp == (-1));
237 if (is_bound && skip_bound) {
240 LOG_DEBUG(
"Imported Lib: %x : %x : %x", lib_desc->FirstThunk, lib_desc->OriginalFirstThunk, lib_desc->Name);
242 std::string lib_name =
"";
243 if (lib_desc->Name != 0) {
244 LPSTR name_ptr = (LPSTR)((ULONGLONG) modulePtr + lib_desc->Name);
250 const DWORD call_via = lib_desc->FirstThunk;
251 const DWORD thunk_addr = lib_desc->OriginalFirstThunk;
252 std::set<ULONGLONG> addresses;
254 find_addresses_to_fill<DWORD>(call_via, thunk_addr, modulePtr, moduleSize, exportsMap, addresses);
256 find_addresses_to_fill<ULONGLONG>(call_via, thunk_addr, modulePtr, moduleSize, exportsMap, addresses);
260 bool is_lib_erased =
false;
264 if (lib_name.length() == 0) {
265 is_lib_erased =
true;
266 if (is_all_covered) {
268 lib_name = dllCoverage.
dllName;
271 if (lib_name.length() == 0) {
286 const std::string dll_with_ext = exportsMap.get_dll_fullname(dllCoverage.
dllName);
std::string toString() const
const std::set< ExportedFunc > * find_exports_by_va(ULONGLONG va) const
std::string mappedDllName
const peconv::ExportsMapper & exportsMap
size_t mapAddressesToFunctions(const std::string &_mappedDllName)
std::set< ULONGLONG > notFound
std::set< ULONGLONG > & addresses
std::map< ULONGLONG, std::set< ExportedFunc > > addrToFunc
bool uneraseDllName(IMAGE_IMPORT_DESCRIPTOR *lib_desc, const std::string &dll_name)
bool uneraseDllImports(IN OUT IMAGE_IMPORT_DESCRIPTOR *lib_desc, IN ImportedDllCoverage &dllCoverage, OUT OPTIONAL ImpsNotCovered *not_covered)
void insert(DWORD thunkRVA, ULONGLONG searchedAddr)
std::map< DWORD, ULONGLONG > thunkToAddr
Functions related to operations on files. Wrappers for read/write.
std::string find_covering_dll(std::set< ULONGLONG > &addresses, const peconv::ExportsMapper &exportsMap)
size_t map_addresses_to_functions(std::set< ULONGLONG > &addresses, IN const std::string &chosenDll, IN const peconv::ExportsMapper &exportsMap, OUT std::map< ULONGLONG, std::set< ExportedFunc > > &addr_to_func, OUT std::set< ULONGLONG > ¬_found)
std::set< std::string > get_all_dlls_exporting_function(ULONGLONG func_addr, const peconv::ExportsMapper &exportsMap)
size_t find_addresses_to_fill(FIELD_T call_via, FIELD_T thunk_addr, LPVOID modulePtr, size_t moduleSize, IN const peconv::ExportsMapper &exportsMap, OUT std::set< ULONGLONG > &addresses)
std::set< std::string > get_dlls_intersection(const std::set< std::string > &dllNames, const std::set< std::string > &currDllNames)
Functions and classes responsible for fixing Import Table. A definition of ImportedDllCoverage class.
A definition of ImportsUneraser class - for recovery of a partialy erased Import Table.
Compile-time configurable logging macros for peconv.
#define LOG_DEBUG(fmt,...)
#define LOG_ERROR(fmt,...)
#define LOG_WARNING(fmt,...)
bool is_valid_string(LPVOID modulePtr, const size_t moduleSize, const CHAR_T *name_ptr, const size_t max_len=260)
bool fix_imports(IN OUT PVOID modulePtr, IN size_t moduleSize, IN const peconv::ExportsMapper &exportsMap, OUT OPTIONAL peconv::ImpsNotCovered *notCovered)
bool validate_ptr(IN const void *buffer_bgn, IN size_t buffer_size, IN const void *field_bgn, IN size_t field_size)
bool is64bit(IN const BYTE *pe_buffer)
IMAGE_DATA_DIRECTORY * get_directory_entry(IN const BYTE *pe_buffer, IN DWORD dir_id, IN bool allow_empty=false)
std::string get_dll_shortname(const std::string &str)
Miscellaneous utility functions.