I'm trying to detect whether a loaded module is being patched at run-time by a malicious process. In this case the module is an EXE being run.
My detection scheme is as follows:
MODULEINFO mInfo;
GetModuleInformation(myProc, myInstance, &modInfo, sizeof(MODULEINFO));
//
char* hash1 = hashBytes(mInfo.lpBaseOfDll, mInfo.SizeOfImage);
//.....some time later
char* hash2 = hashBytes(mInfo.lpBaseOfDll, mInfo.SizeOfImage);
//
bool moduleIsModified = compareHashes(hash1, hash2); //false == we're patched!
This worked fine at first...hashes would be identical if no patches occurred, and I could detect my own patches (bytes within the module address space changed with VirtualProect/CopyMemory) successfully.
However, I discovered that if I put the following code between the generation of hash1/hash2, the hashes will no longer match:
//char* hash1 = ....
std::ifstream stream(pathToModule); //this causes hashes to no longer match???
//char* hash1 = ....
Why is the creation of a file stream to a module changing the pre-loaded bytes of the module? My assumption that the module would sit statically in memory after being loaded (assuming no malicious patches) is obviously incorrect...but why? Is there a specific area of a module's loaded bytes that are dynamic?
A typical memory layout of a running process. 1. Text Segment: A text segment , also known as a code segment or simply as text, is one of the sections of a program in an object file or in memory, which contains executable instructions.
Memory Layout of C Programs. A typical memory representation of C program consists of following sections. 2. 3. 5. 1. Text Segment: A text segment , also known as a code segment or simply as text, is one of the sections of a program in an object file or in memory, which contains executable instructions.
Compile time memory allocation means reserving memory for variables, constants during the compilation process. So you must exactly know how many bytes you require? Many text also refer compile time memory allocation as static or stack memory allocation.
In programming each variable, constant occupies space in memory, defined by their data type. The compiler reserves required memory (bytes) during compilation according to the specified data type. For example, there is a declaration statement int number; here, int is data type and number is variable (also referred as identifier).
Paul Sanders' question pointed me in the right direction.
The .data segment of the module was changing during runtime, so excluding that segment from my hash keeps the result the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With