8 LPVOID search_name(std::string name,
const char* modulePtr,
size_t moduleSize)
10 const char* namec = name.c_str();
11 const size_t searched_len = name.length() + 1;
12 const char* found_ptr = std::search(modulePtr, modulePtr + moduleSize, namec, namec + searched_len);
13 const size_t o = found_ptr - modulePtr;
15 return (LPVOID)(found_ptr);
23 LOG_DEBUG(
"Found name: %s.", found_name.c_str());
24 LPSTR name_ptr = (LPSTR)((ULONGLONG)
modulePtr + lib_desc->Name);
25 size_t full_name_len = found_name.length() + 1;
33 ::memcpy(name_ptr, found_name.c_str(), full_name_len);
39 LPSTR name_ptr =
nullptr;
40 if (lib_desc->Name != 0) {
41 name_ptr = (LPSTR)((ULONGLONG)
modulePtr + lib_desc->Name);
43 const size_t dll_len = dll_name.length();
46 const DWORD cave_size = DWORD(dll_len + 1 + 5);
49 LOG_ERROR(
"Cannot save the DLL name: %s.", dll_name.c_str());
52 const DWORD cave_rva =
static_cast<DWORD
>(ptr -
modulePtr);
53 lib_desc->Name = cave_rva;
62template <
typename FIELD_T>
66 const FIELD_T ordinal_flag,
67 std::map<ULONGLONG, std::set<ExportedFunc>> &addr_to_func
70 if (!call_via_ptr || !
modulePtr || !lib_desc) {
74 if (!importsDir)
return false;
76 const DWORD impAddr = importsDir->VirtualAddress;
78 FIELD_T *call_via_val = (FIELD_T*)call_via_ptr;
79 if (*call_via_val == 0) {
83 const ULONGLONG searchedAddr = ULONGLONG(*call_via_val);
85 auto found = addr_to_func.find(searchedAddr);
86 if (found == addr_to_func.end()) {
87 LOG_WARNING(
"No mapped export mapped to the given address: 0x%llx.", (
unsigned long long)searchedAddr);
90 const auto &exportsWithAddr = found->second;
91 bool is_name_saved =
false;
92 FIELD_T lastOrdinal = 0;
94 std::set<ExportedFunc>::iterator funcname_itr;
95 for (funcname_itr = exportsWithAddr.begin();
96 funcname_itr != exportsWithAddr.end();
104 const char* names_start = ((
const char*)
modulePtr + impAddr);
106 BYTE* found_ptr = (BYTE*)search_name(found_func.
funcName, names_start, remaining_size);
112 if (funcname_itr != exportsWithAddr.begin()) {
113 LOG_DEBUG(
">[*][0x%llx] %s.", (
unsigned long long)searchedAddr, found_func.
toString().c_str());
115 const ULONGLONG name_offset = (ULONGLONG)found_ptr - (ULONGLONG)
modulePtr;
116 LOG_DEBUG(
"Found the name at: 0x%llx.", (
unsigned long long) name_offset);
117 if (name_offset <
sizeof(WORD)) {
120 const ULONGLONG imp_rva = name_offset -
sizeof(WORD);
121 const PIMAGE_IMPORT_BY_NAME imp_field =
reinterpret_cast<PIMAGE_IMPORT_BY_NAME
>(imp_rva);
122 ::memcpy(thunk_ptr, &imp_field,
sizeof(FIELD_T));
123 LOG_DEBUG(
"Wrote found to offset: %p.", call_via_ptr);
124 is_name_saved =
true;
128 if (!is_name_saved && lastOrdinal != 0) {
129 LOG_DEBUG(
"Filling ordinal: 0x%llx.", (
unsigned long long)lastOrdinal);
130 FIELD_T ord_thunk = lastOrdinal | ordinal_flag;
131 ::memcpy(thunk_ptr, &ord_thunk,
sizeof(FIELD_T));
132 is_name_saved =
true;
134 return is_name_saved;
137template <
typename FIELD_T,
typename IMAGE_THUNK_DATA_T>
141 FIELD_T ordinal = foundFunc.
funcOrdinal | ordinal_flag;
142 FIELD_T* by_ord = (FIELD_T*) desc;
144 LOG_DEBUG(
"Saved ordinal: %ld", (
unsigned long) ordinal);
147 PIMAGE_IMPORT_BY_NAME by_name = (PIMAGE_IMPORT_BY_NAME) ((ULONGLONG)
modulePtr + desc->u1.AddressOfData);
149 LOG_ERROR(
"Invalid pointer to IMAGE_IMPORT_BY_NAME.");
152 LPSTR func_name_ptr =
reinterpret_cast<LPSTR
>(by_name->Name);
153 std::string found_name = foundFunc.
funcName;
155 const size_t full_name_len = found_name.length() + 1;
157 LOG_ERROR(
"Cannot save the name: not enough space.");
161 ::memcpy(func_name_ptr, found_name.c_str(), full_name_len);
162 LOG_DEBUG(
"Saved name: %s", found_name.c_str());
166template <
typename FIELD_T,
typename IMAGE_THUNK_DATA_T>
168 IN OUT IMAGE_IMPORT_DESCRIPTOR* lib_desc,
169 IN
const FIELD_T ordinal_flag,
170 IN std::map<ULONGLONG, std::set<ExportedFunc>> &addr_to_func,
174 if (!lib_desc)
return false;
176 FIELD_T call_via = lib_desc->FirstThunk;
177 if (!call_via)
return false;
179 size_t processed_imps = 0;
180 size_t recovered_imps = 0;
182 FIELD_T thunk_addr = lib_desc->OriginalFirstThunk;
184 thunk_addr = call_via;
187 BYTE* call_via_ptr = (BYTE*)((ULONGLONG)
modulePtr + call_via);
188 BYTE* thunk_ptr = (BYTE*)((ULONGLONG)
modulePtr + thunk_addr);
191 call_via_ptr +=
sizeof(FIELD_T), thunk_ptr +=
sizeof(FIELD_T)
194 FIELD_T *call_via_val = (FIELD_T*)call_via_ptr;
195 if (*call_via_val == 0) {
199 IMAGE_THUNK_DATA_T* desc = (IMAGE_THUNK_DATA_T*)thunk_ptr;
201 LOG_WARNING(
"Invalid descriptor pointer: [0x%llx].", (
unsigned long long)desc);
204 if (!desc->u1.Function) {
207 ULONGLONG searchedAddr = ULONGLONG(*call_via_val);
208 std::map<ULONGLONG,std::set<ExportedFunc>>::const_iterator found_itr = addr_to_func.find(searchedAddr);
209 if (found_itr == addr_to_func.end() || found_itr->second.size() == 0) {
213 notCovered->insert(thunkRVA, searchedAddr);
217 std::set<ExportedFunc>::const_iterator funcname_itr = found_itr->second.begin();
220 LOG_DEBUG(
"[*][0x%llx] %s.", (
unsigned long long)searchedAddr, funcname_itr->toString().c_str());
221 bool is_name_saved = writeFoundFunction<FIELD_T, IMAGE_THUNK_DATA_T>(desc, ordinal_flag, *funcname_itr);
222 if (!is_name_saved) {
223 is_name_saved = findNameInBinaryAndFill<FIELD_T>(lib_desc, call_via_ptr, thunk_ptr, ordinal_flag, addr_to_func);
226 if (is_name_saved) recovered_imps++;
229 return (recovered_imps == processed_imps);
235 bool is_filled =
false;
237 is_filled = fillImportNames<DWORD, IMAGE_THUNK_DATA32>(lib_desc, IMAGE_ORDINAL_FLAG32, dllCoverage.addrToFunc, notCovered);
239 is_filled = fillImportNames<ULONGLONG, IMAGE_THUNK_DATA64>(lib_desc, IMAGE_ORDINAL_FLAG64, dllCoverage.addrToFunc, notCovered);
242 LOG_ERROR(
"Could not fill some import names.");
#define MASK_TO_WORD(val)
#define MASK_TO_DWORD(val)
std::string toString() const
bool writeFoundDllName(IMAGE_IMPORT_DESCRIPTOR *lib_desc, const std::string &dll_name)
bool fillImportNames(IN OUT IMAGE_IMPORT_DESCRIPTOR *lib_desc, IN const FIELD_T ordinal_flag, IN std::map< ULONGLONG, std::set< ExportedFunc > > &addr_to_func, OUT OPTIONAL ImpsNotCovered *not_covered)
bool uneraseDllName(IMAGE_IMPORT_DESCRIPTOR *lib_desc, const std::string &dll_name)
bool writeFoundFunction(IMAGE_THUNK_DATA_T *desc, const FIELD_T ordinal_flag, const ExportedFunc &foundFunc)
bool uneraseDllImports(IN OUT IMAGE_IMPORT_DESCRIPTOR *lib_desc, IN ImportedDllCoverage &dllCoverage, OUT OPTIONAL ImpsNotCovered *not_covered)
bool findNameInBinaryAndFill(IMAGE_IMPORT_DESCRIPTOR *lib_desc, LPVOID call_via_ptr, LPVOID thunk_ptr, const FIELD_T ordinal_flag, std::map< ULONGLONG, std::set< ExportedFunc > > &addr_to_func)
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,...)
PBYTE find_ending_cave(BYTE *module_ptr, size_t module_size, const DWORD cave_size, const DWORD req_charact=IMAGE_SCN_MEM_READ, bool reserve=true)
bool validate_ptr(IN const void *buffer_bgn, IN size_t buffer_size, IN const void *field_bgn, IN size_t field_size)
IMAGE_DATA_DIRECTORY * get_directory_entry(IN const BYTE *pe_buffer, IN DWORD dir_id, IN bool allow_empty=false)