7LPVOID
search_name(std::string name,
const char* modulePtr,
size_t moduleSize)
9 const char* namec = name.c_str();
10 const size_t searched_len = name.length() + 1;
11 const char* found_ptr = std::search(modulePtr, modulePtr + moduleSize, namec, namec + searched_len);
15 size_t o = found_ptr - modulePtr;
17 return (LPVOID)(found_ptr);
24 LOG_DEBUG(
"Found name: %s.", found_name.c_str());
25 LPSTR name_ptr = (LPSTR)((ULONGLONG)
modulePtr + lib_desc->Name);
26 size_t full_name_len = found_name.length() + 1;
34 memcpy(name_ptr, found_name.c_str(), full_name_len);
40 LPSTR name_ptr =
nullptr;
41 if (lib_desc->Name != 0) {
42 name_ptr = (LPSTR)((ULONGLONG)
modulePtr + lib_desc->Name);
46 DWORD cave_size = DWORD(dll_name.length() + 1 + 5);
49 LOG_ERROR(
"Cannot save the DLL name: %s.", dll_name.c_str());
52 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 ULONGLONG searchedAddr = ULONGLONG(*call_via_val);
84 bool is_name_saved =
false;
86 FIELD_T lastOrdinal = 0;
87 std::set<ExportedFunc>::iterator funcname_itr = addr_to_func[searchedAddr].begin();
89 for (funcname_itr = addr_to_func[searchedAddr].begin();
90 funcname_itr != addr_to_func[searchedAddr].end();
96 const char* names_start = ((
const char*)
modulePtr + impAddr);
104 if (funcname_itr != addr_to_func[searchedAddr].begin()) {
105 LOG_DEBUG(
">[*][0x%llx] %s.", (
unsigned long long)searchedAddr, found_func.
toString().c_str());
107 const ULONGLONG name_offset = (ULONGLONG)found_ptr - (ULONGLONG)
modulePtr;
108 LOG_DEBUG(
"Found the name at: 0x%llx.", (
unsigned long long) name_offset);
109 if (name_offset <
sizeof(WORD)) {
112 const ULONGLONG imp_rva = name_offset -
sizeof(WORD);
113 const PIMAGE_IMPORT_BY_NAME imp_field =
reinterpret_cast<PIMAGE_IMPORT_BY_NAME
>(imp_rva);
114 ::memcpy(thunk_ptr, &imp_field,
sizeof(FIELD_T));
115 LOG_DEBUG(
"Wrote found to offset: %p.", call_via_ptr);
116 is_name_saved =
true;
120 if (!is_name_saved && lastOrdinal != 0) {
121 LOG_DEBUG(
"Filling ordinal: 0x%llx.", (
unsigned long long)lastOrdinal);
122 FIELD_T ord_thunk = lastOrdinal | ordinal_flag;
123 memcpy(thunk_ptr, &ord_thunk,
sizeof(FIELD_T));
124 is_name_saved =
true;
126 return is_name_saved;
129template <
typename FIELD_T,
typename IMAGE_THUNK_DATA_T>
133 FIELD_T ordinal = foundFunc.
funcOrdinal | ordinal_flag;
134 FIELD_T* by_ord = (FIELD_T*) desc;
140 PIMAGE_IMPORT_BY_NAME by_name = (PIMAGE_IMPORT_BY_NAME) ((ULONGLONG)
modulePtr + desc->u1.AddressOfData);
142 LPSTR func_name_ptr =
reinterpret_cast<LPSTR
>(by_name->Name);
143 std::string found_name = foundFunc.
funcName;
146 if (is_nameptr_valid) {
148 memcpy(func_name_ptr, found_name.c_str(), found_name.length() + 1);
155template <
typename FIELD_T,
typename IMAGE_THUNK_DATA_T>
157 IN OUT IMAGE_IMPORT_DESCRIPTOR* lib_desc,
158 IN
const FIELD_T ordinal_flag,
159 IN std::map<ULONGLONG, std::set<ExportedFunc>> &addr_to_func,
163 if (!lib_desc)
return false;
165 FIELD_T call_via = lib_desc->FirstThunk;
166 if (!call_via)
return false;
168 size_t processed_imps = 0;
169 size_t recovered_imps = 0;
171 FIELD_T thunk_addr = lib_desc->OriginalFirstThunk;
173 thunk_addr = call_via;
176 BYTE* call_via_ptr = (BYTE*)((ULONGLONG)
modulePtr + call_via);
177 BYTE* thunk_ptr = (BYTE*)((ULONGLONG)
modulePtr + thunk_addr);
180 call_via_ptr +=
sizeof(FIELD_T), thunk_ptr +=
sizeof(FIELD_T)
183 FIELD_T *thunk_val = (FIELD_T*)thunk_ptr;
184 FIELD_T *call_via_val = (FIELD_T*)call_via_ptr;
185 if (*call_via_val == 0) {
189 IMAGE_THUNK_DATA_T* desc = (IMAGE_THUNK_DATA_T*)thunk_ptr;
191 LOG_WARNING(
"Invalid descriptor pointer: [0x%llx].", (
unsigned long long)desc);
194 if (!desc->u1.Function) {
197 ULONGLONG searchedAddr = ULONGLONG(*call_via_val);
198 std::map<ULONGLONG,std::set<ExportedFunc>>::const_iterator found_itr = addr_to_func.find(searchedAddr);
199 if (found_itr == addr_to_func.end() || found_itr->second.size() == 0) {
203 notCovered->insert(thunkRVA, searchedAddr);
207 std::set<ExportedFunc>::const_iterator funcname_itr = found_itr->second.begin();
210 LOG_DEBUG(
"[*][0x%llx] %s.", (
unsigned long long)searchedAddr, funcname_itr->toString().c_str());
212 if (!is_name_saved) {
216 if (is_name_saved) recovered_imps++;
219 return (recovered_imps == processed_imps);
225 bool is_filled =
false;
232 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)
LPVOID search_name(std::string name, const char *modulePtr, size_t moduleSize)
A definition of ImportsUneraser class - for recovery of a partialy erased Import Table.
#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)