PE-sieve
Scans all running processes. Recognizes and dumps a variety of potentially malicious implants (replaced/implanted PEs, shellcodes, hooks, in-memory patches).
Loading...
Searching...
No Matches
module_cache.cpp
Go to the documentation of this file.
1#include "module_cache.h"
2#include <psapi.h>
3
4BYTE* pesieve::ModulesCache::loadCached(LPSTR szModName, size_t& module_size)
5{
6 BYTE *mapped_pe = getMappedCached(szModName, module_size);
7 if (mapped_pe) {
8 return mapped_pe; // retrieved from cache
9 }
10 size_t raw_size = 0;
11 BYTE* raw_buf = peconv::load_file(szModName, raw_size);
12 if (!raw_buf) {
13 return nullptr; // failed to load the file
14 }
15
16 bool force_free_cache = false;
17 // Add to cache if needed...
18 {
20 size_t currCntr = usageBeforeCounter[szModName]++;
21 const size_t cachedModulesCntr = cachedModules.size();
22 const bool is_cache_available = isCacheAvailable(raw_size);
23 if (currCntr >= MinUsageCntr && is_cache_available) {
24 bool is_cached = false;
25 CachedModule* mod_cache = new(std::nothrow) CachedModule(raw_buf, raw_size);
26 if (mod_cache) {
27 if (mod_cache->moduleData) {
28 cachedModules[szModName] = mod_cache;
29 is_cached = true;
30#ifdef _DEBUG
31 std::cout << "Added to cache: " << szModName << " Total cached: " << cachedModulesCntr << "\n";
32#endif
33 }
34 }
35 if (!is_cached) {
36 delete mod_cache;
37 // possibly running out of memory, make sure to free some cache:
38 force_free_cache = true;
39 }
40 }
41 }
42
43 // after adding file to the cache, wipe out the old ones:
44 prepareCacheSpace(raw_size, force_free_cache);
45
46 // return the mapped module:
47 mapped_pe = peconv::load_pe_module(raw_buf, raw_size, module_size, false, false);
48 peconv::free_file(raw_buf);
49 return mapped_pe;
50}
51
52bool pesieve::ModulesCache::isCacheAvailable(const size_t neededSize)
53{
54 bool hasFree = false;
55 SIZE_T minSize = 0;
56 SIZE_T maxSize = 0;
57 DWORD info = 0;
58
59 if (!GetProcessWorkingSetSizeEx(GetCurrentProcess(), &minSize, &maxSize, &info)) {
60#ifdef _DEBUG
61 std::cout << "GetProcessWorkingSetSizeEx failed!\n";
62#endif
63 return false;
64 }
65
66 MEMORYSTATUSEX memStatus = { 0 };
67 memStatus.dwLength = sizeof(MEMORYSTATUSEX);
68
69 if ((info & QUOTA_LIMITS_HARDWS_MAX_DISABLE) == QUOTA_LIMITS_HARDWS_MAX_DISABLE) { // The working set may exceed the maximum working set limit if there is abundant memory
70 if (GlobalMemoryStatusEx(&memStatus)) {
71 if (memStatus.ullAvailVirtual > ((DWORDLONG)neededSize * 2) && (memStatus.dwMemoryLoad < 50)) {
72 hasFree = true;
73 }
74 }
75 }
76
77 PROCESS_MEMORY_COUNTERS ppsmemCounter = { 0 };
78 ppsmemCounter.cb = sizeof(PROCESS_MEMORY_COUNTERS);
79 GetProcessMemoryInfo(GetCurrentProcess(), &ppsmemCounter, sizeof(PROCESS_MEMORY_COUNTERS));
80
81 // hard limit is enabled, use it to calculate how much you can use
82 if (maxSize > ppsmemCounter.PeakWorkingSetSize) {
83 size_t freeMem = maxSize - ppsmemCounter.WorkingSetSize;
84 size_t percW1 = size_t(((double)ppsmemCounter.WorkingSetSize / (double)maxSize) * 100.0);
85 if (freeMem > (neededSize * 2) && (percW1 < 60)) {
86 hasFree = true;
87 }
88 }
89 size_t freeMemP = ppsmemCounter.PeakWorkingSetSize - ppsmemCounter.WorkingSetSize;
90 size_t percPeak = size_t(((double)ppsmemCounter.WorkingSetSize / (double)ppsmemCounter.PeakWorkingSetSize) * 100.0);
91
92 if (freeMemP > (neededSize * 2) && (percPeak < 70)) {
93 hasFree = true;
94 }
95
96#ifdef _DEBUG
97 if (!hasFree) {
98 std::cout << "C: " << std::hex << ppsmemCounter.WorkingSetSize
99 << "\tP: " << std::hex << ppsmemCounter.PeakWorkingSetSize
100 << "\tMin: " << minSize
101 << "\tMax: " << maxSize
102 << "\tGlobalMem Av Virt: " << std::hex << memStatus.ullAvailVirtual
103 << std::dec << "\tPerc: " << memStatus.dwMemoryLoad
104 << std::dec << " PercPeak: " << percPeak
105 << " HasFree: " << hasFree
106 << " modulesCount: " << cachedModules.size()
107 << std::endl;
108 }
109#endif
110 return hasFree;
111}
BYTE * getMappedCached(const std::string &modName, size_t &mappedSize)
bool isCacheAvailable(const size_t neededSize)
BYTE * loadCached(LPSTR szModName, size_t &original_size)
std::map< std::string, CachedModule * > cachedModules
the list of all the cached modules
static const size_t MinUsageCntr
how many times loading of the module must be requested before the module is added to cache
std::map< std::string, size_t > usageBeforeCounter
how many times loading of the same module was requested before it was cached
bool prepareCacheSpace(const size_t neededSize, bool force_free)
std::string info()
The string with the basic information about the scanner.
Definition pe_sieve.cpp:274