As we all know that the IAT of a binary gives a vague idea of what the file is capable of. And a simple way to avoid this is by using a technique like API Hashing / String Hashing. +1 since they also can't use strings to take a peek at us.
Analyzing Mapping Injection
I'll start with running strings on the Mapping Injection implementation which can be found here.
We can see a lot of stuff here, keeping aside the variables/print messages/etc, we also see a list of Windows API being used here like the MapViewOfFile (You might see some extra APIs at the bottom but that's because CRT included them). A better way would be to look at it using something like PE bear and we see a list of APIs being used.
But what if we want them to suffer more, then we can just use API hashing instead and avoid the string MapViewOfFile to display anywhere in the code, so that it looks a little less suspiciuos.
Simple Explanation
What we are going to do is basically Hash required functions in Kernel32.dll or any other module according to our needs, and then note their hash, then in our Malware, when we want to get the base address of that function, instead of matching the string, we will match with the hash value of the modules and get the ones that match with it.
Some of the common hashing techniques include
djb2
CRC32
FNV-1a
SuperFastHash
LoseLose
Murmur
and many more, the source code of which could be found here, we can even develop our own custom hashing technique. There's also this github which does the job of printing the hashes in a few different format.
Generating Hashes
I'll go with the LoseLose (LoseLose is weak and susceptible to hash collision, I found it the hard way) MurMur Implementation and generate the hashes for necessary winapi for running Mapping Injection. Here's the C code to get the necessary hashes
Running the code will give me this
API Hashing
Okay so we have the necessary hashes, now we need a way to get our necessary function by it's hash value, I've written a small code which is pretty similar to the GetProcAddress instead that it calculates the hash for all of the exports and returns the VA for the export having the same hash value.
Then I'll check the value for a single API to make sure we are getting the correct API, and then perform the Injection.
I can see that both the hash value matches and looking at x64dbg, I can confirm it is for the MapViewOfFile API.
Now I just need to get all the functions and the rest of the process is similar to that of Mapping Injection. Here I'll just perform the Remote Mapping Injection instead of both Local & Remote.
Only a slight change would be while calling the MapViewOfFileNuma2 function, looking at the MSDN for MapViewOfFile2, Microsoft recommends calling the numa2 with the final parameter being set to NUMA_NO_PREFERRED_NODE. The full source can be found at the end of the page.
After everything has been done, I'll check the pe binary again in PE-bear and this time, we don't see any of the Mapping related APIs which we used.
Again, the extra APIs are due to CRT adding some of their own, if we configure it to be build for a Release, then we see that some of the API have been removed lowering the count, although to completely eliminate them, we would have to remove CRT (as shown here).
Pitfall
So Initially I thought of using the LoseLoseA for hashing, but the program wasn't working and after some debugging, I realized that this function is susceptible to hash collision. Both the MapViewOfFileNuma2 and the GetPackageContext function have the same hash value of 0x6B1, and since the GetPackageContext function appears first, I was getting the VA for that. Fortunately, I debugged it well to point out the mistake early.
If you are trying to use a hashing function, or creating your own, then make sure it is a strong hash and isn't susceptible to something like hash collision.
That's it for now, I know I have gone hiatus for a while, but now I'll be more active and keep posting. I'll also write a Rust implementation soon soon.