17 OUT_PADDED(outs, level,
"\"hooks_list\" : [\n");
19 std::map<DWORD, ULONGLONG>::iterator itr;
21 const DWORD thunk_rva = itr->first;
22 const ULONGLONG addr = itr->second;
29 OUT_PADDED(outs, (level + 1),
"\"thunk_rva\" : ");
30 outs <<
"\"" << std::hex << thunk_rva <<
"\"" <<
",\n";
32 std::map<DWORD, peconv::ExportedFunc*>::const_iterator found =
storedFunc.thunkToFunc.find(thunk_rva);
34 const peconv::ExportedFunc *func = found->second;
36 OUT_PADDED(outs, (level + 1),
"\"func_name\" : ");
37 outs <<
"\"" << func->toString() <<
"\"" <<
",\n";
40 OUT_PADDED(outs, (level + 1),
"\"target_va\" : ");
41 outs <<
"\"" << std::hex << (ULONGLONG)addr <<
"\"";
58 const peconv::ExportedFunc* func = exportsMap->find_export_by_va(addr);
60 return func->toString();
62 const ScannedModule* modExp = modulesInfo.findModuleContaining(addr);
64 if (module_start == 0) {
71 report <<
".(unknown_func)";
80 std::map<DWORD, peconv::ExportedFunc*>::const_iterator found =
storedFunc->thunkToFunc.find(thunk_rva);
82 const peconv::ExportedFunc* func = found->second;
86 return func->toString();
94 IN peconv::ImportsCollection *storedFunc,
95 IN peconv::ImpsNotCovered ¬Covered,
97 IN
const peconv::ExportsMapper *exportsMap)
99 const char delim =
';';
100 const char internal_delim =
':';
107 if (
report.is_open() ==
false) {
111 std::map<DWORD,ULONGLONG>::iterator itr;
114 const DWORD thunk_rva = itr->first;
115 const ULONGLONG addr = itr->second;
116 report << std::hex << thunk_rva << delim;
121 const ScannedModule* modExp = modulesInfo.findModuleContaining(addr);
122 const ULONGLONG module_start = (modExp) ? modExp->
getStart() : peconv::fetch_alloc_base(hProcess, (BYTE*)addr);
123 const ULONGLONG offset = addr - module_start;
124 report << std::hex << addr;
126 << std::hex << module_start <<
"+" << offset
154template <
typename FIELD_T>
157 if (!mod_buf || !mod_size) {
160 if (!peconv::validate_ptr(mod_buf, mod_size, (BYTE*)((ULONG_PTR)mod_buf + rva),
sizeof(FIELD_T))) {
164 FIELD_T* field_ptr = (FIELD_T*)((ULONG_PTR)mod_buf + rva);
168bool pesieve::IATScanner::isValidFuncFilled(ULONGLONG filled_val,
const peconv::ExportedFunc& definedFunc,
const peconv::ExportedFunc &possibleFunc)
170 if (!peconv::ExportedFunc::isTheSameFuncName(possibleFunc, definedFunc)) {
173 if (peconv::ExportedFunc::isTheSameDllName(possibleFunc, definedFunc)) {
176 ULONGLONG dll_base = this->exportsMap.find_dll_base_by_func_va(filled_val);
181 const std::string fullName = exportsMap.get_dll_path(dll_base);
183 if (isInSystemDir(fullName)) {
189bool pesieve::IATScanner::scanByOriginalTable(peconv::ImpsNotCovered ¬_covered)
191 if (!remoteModData.isInitialized()) {
192 std::cerr <<
"[-] Failed to initialize remote module header" << std::endl;
195 if (!moduleData.isInitialized() && !moduleData.loadOriginal()) {
196 std::cerr <<
"[-] Failed to initialize module data: " << moduleData.szModName << std::endl;
201 peconv::ImportsCollection collection;
202 if (!listAllImports(collection)) {
205 if (collection.size() == 0) {
210 if (!remoteModData.loadFullImage()) {
211 std::cerr <<
"[-] Failed to initialize remote module" << std::endl;
214 std::map<DWORD, peconv::ExportedFunc*>::iterator itr;
217 for (itr = collection.thunkToFunc.begin(); itr != collection.thunkToFunc.end(); ++itr) {
218 DWORD thunk_rva = itr->first;
221 ULONGLONG filled_val = 0;
222 if (moduleData.is64bit()) {
228 peconv::ExportedFunc* defined_func = itr->second;
234 const std::set<peconv::ExportedFunc>* possibleExports = exportsMap.find_exports_by_va(filled_val);
236 if (!possibleExports || possibleExports->size() == 0) {
239 const std::string dShortName = peconv::get_dll_shortname(defined_func->libName);
240 if (dShortName ==
"mscoree"
241 && (defined_func->funcName ==
"_CorExeMain" || defined_func->funcName ==
"_CorDllMain") )
246 not_covered.insert(thunk_rva, filled_val);
248 std::cout <<
"Function not covered: " << std::hex << thunk_rva <<
" [" << dShortName <<
"] func: [" << defined_func->funcName <<
"] val: " << std::hex << filled_val <<
"\n";
254 bool is_covered =
false;
255 std::set<peconv::ExportedFunc>::const_iterator cItr;
256 for (cItr = possibleExports->begin(); cItr != possibleExports->end(); ++cItr) {
257 const peconv::ExportedFunc possibleFunc = *cItr;
258 if (isValidFuncFilled(filled_val, *defined_func, possibleFunc)){
265 not_covered.insert(thunk_rva, filled_val);
267 std::cout <<
"Mismatch at RVA: " << std::hex << thunk_rva <<
" " << defined_func->libName<<
" func: " << defined_func->toString() <<
"\n";
269 for (cItr = possibleExports->begin(); cItr != possibleExports->end(); ++cItr) {
270 const peconv::ExportedFunc possibleFunc = *cItr;
271 std::cout <<
"\t proposed: " << possibleFunc.libName <<
" : " << possibleFunc.toString() <<
"\n";
281 if (!remoteModData.isInitialized()) {
282 std::cerr <<
"[-] Failed to initialize remote module header" << std::endl;
286 peconv::ImpsNotCovered not_covered;
289 if (!scanByOriginalTable(not_covered)) {
294 if (not_covered.count() > 0) {
296 std::cout <<
"[*] IAT: " << moduleData.szModName <<
" hooked: " << not_covered.count() <<
"\n";
306 if (not_covered.count()) {
307 listAllImports(
report->storedFunc);
310 filterResults(not_covered, *
report);
313 report->notCovered = not_covered;
316 if (
report->countHooked() == 0) {
323void pesieve::IATScanner::initExcludedPaths()
325 char sysWow64Path[
MAX_PATH] = { 0 };
326 ExpandEnvironmentStringsA(
"%SystemRoot%\\SysWoW64", sysWow64Path,
MAX_PATH);
327 this->m_sysWow64Path_str = sysWow64Path;
328 std::transform(m_sysWow64Path_str.begin(), m_sysWow64Path_str.end(), m_sysWow64Path_str.begin(), tolower);
330 char system32Path[
MAX_PATH] = { 0 };
331 ExpandEnvironmentStringsA(
"%SystemRoot%\\system32", system32Path,
MAX_PATH);
332 this->m_system32Path_str = system32Path;
333 std::transform(m_system32Path_str.begin(), m_system32Path_str.end(), m_system32Path_str.begin(), tolower);
336bool pesieve::IATScanner::isInSystemDir(
const std::string &moduleName)
338 std::string dirName = peconv::get_directory_name(moduleName);
339 std::transform(dirName.begin(), dirName.end(), dirName.begin(), tolower);
341 if (dirName == m_system32Path_str || dirName == m_sysWow64Path_str) {
347bool pesieve::IATScanner::filterResults(peconv::ImpsNotCovered ¬Covered,
IATScanReport &
report)
349 std::map<DWORD, ULONGLONG>::iterator itr;
350 for (itr = notCovered.thunkToAddr.begin(); itr != notCovered.thunkToAddr.end(); ++itr)
352 const DWORD thunk = itr->first;
353 const ULONGLONG addr = itr->second;
355 ScannedModule *modExp = modulesInfo.findModuleContaining(addr);
356 ULONGLONG module_start = (modExp) ? modExp->
getStart() : peconv::fetch_alloc_base(this->processHandle, (BYTE*)addr);
357 if (module_start == 0) {
359 report.notCovered.insert(thunk, addr);
365 report.notCovered.insert(thunk, addr);
370 std::string moduleName = this->exportsMap.get_dll_path(module_start);
371 if (isInSystemDir(moduleName)) {
373 std::cout <<
"Skipped: " << moduleName <<
"\n";
378 report.notCovered.insert(thunk, addr);
383bool pesieve::IATScanner::listAllImports(peconv::ImportsCollection &_storedFunc)
385 return moduleData.loadImportsList(_storedFunc);
A report from an IAT scan, generated by IATScanner.
const bool hooksToJSON(std::stringstream &outs, size_t level)
static std::string formatHookedFuncName(IN peconv::ImportsCollection *storedFunc, DWORD thunk_rva)
bool generateList(IN const std::string &fileName, IN HANDLE hProcess, IN const ModulesInfo &modulesInfo, IN const peconv::ExportsMapper *exportsMap)
peconv::ImportsCollection storedFunc
static std::string formatTargetName(IN const peconv::ExportsMapper *exportsMap, IN const ModulesInfo &modulesInfo, IN const ULONGLONG module_start, IN ULONGLONG addr)
static bool saveNotRecovered(IN const std::string &fileName, IN HANDLE hProcess, IN peconv::ImportsCollection *storedFunc, IN peconv::ImpsNotCovered ¬Covered, IN const ModulesInfo &modulesInfo, IN const peconv::ExportsMapper *exportsMap)
peconv::ImpsNotCovered notCovered
virtual IATScanReport * scanRemote()
A container of all the process modules that were scanned.
Represents a basic info about the scanned module, such as its base offset, size, and the status.
std::string getModName() const
bool isSuspicious() const
ULONGLONG getStart() const
FIELD_T get_thunk_at_rva(BYTE *mod_buf, size_t mod_size, DWORD rva)
DWORD(__stdcall *_PssCaptureSnapshot)(HANDLE ProcessHandle
enum pesieve::module_scan_status t_scan_status
@ PE_IATS_CLEAN_SYS_FILTERED
scan IAT, filter hooks if they lead to unpatched system module
@ PE_IATS_UNFILTERED
scan IAT, unfiltered
Final summary about the scanned process.