1

I have a situation where malicious files are being copied to the installation directory of some software and the software will load those files when making a call to LoadLibrary or DllImport (in .NET land).

If your software runs with administrator privileges, a P/Invoke on a malicious DLL can essentially run any code in an elevated fashion, using your application as a vehicle to do so on it's behalf.

Many of these techniques can be found in this question: Ways to inject malicious DLLs to exe file and run it

What I'm asking is how, as a software developer, can you prevent this type of attack? If I want to import user32.dll into my application and make a call, how do I know it's loading the right one?

In the LoadLibrary documentation they do hint at this problem existing but don't exactly explain what you are supposed to do to avoid it at all costs.

Do not use the SearchPath function to retrieve a path to a DLL for a subsequent LoadLibrary call. The SearchPath function uses a different search order than LoadLibrary and it does not use safe process search mode unless this is explicitly enabled by calling SetSearchPathMode with BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE. Therefore, SearchPath is likely to first search the user’s current working directory for the specified DLL. If an attacker has copied a malicious version of a DLL into the current working directory, the path retrieved by SearchPath will point to the malicious DLL, which LoadLibrary will then load.

A simple solution like checking if the file is in a search path you don't expect (such as side-by-side with your executable) doesn't work very well because the assembly name can be changed and a redirect put in place.

UPDATE: This article on Dynamic-Link Library Security explains things well, however, all these techniques can easily be bypassed by the same process copying the malicious files. I've seen DLL Redirection used to redirect to the malicious files as well. I fear even programmatic approaches can fail because your applications can be modified anyway to still load the malicious files.

Are all Windows applications doomed to have this security flaw in them?

3

.NET has an DefaultDllImportSearchPathsAttribute you can use on a per p/invoke or per assembly basis to constrain LoadLibrary to only get the DLL from 'safe' locations.

[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32)] 
2

DLLs and other binaries could be signed (see here for how to check signature).

If they are not, or if you don't want to go that way, but you know what library you are supposed to load, then you can verify the library's checksum before loading. Acquire a read lock on the library and release it only after successfully loading it; this way, you avoid the small chance of a race attack (replacing the DLL after the checksumming but before the loading).

But yes, you need to load the library using the explicit full path, otherwise an attacker can just place a the DLL with the same name in any directory that's checked before the right one. So:

  • get the full path
  • lock the file
  • verify its signature
  • load the file
  • unlock the file
  • lather, rinse, repeat for the other DLLs
  • Thanks for the answer. All files are signed (authenticode), but that means wintrust.dll just gets cracked (which is exactly what happens) meaning all tampering of signed files and internal checks to verify them goes unnoticed. I think there may be too many different checksums of things like kernel32.dll to make that check viable. Checksum checks can also be easily removed, which invalidates the signatures, but as mentioned before wintrust.dll just gets loaded in the same way always responding with "Valid" to internal checks. – BrutalDev Oct 24 '16 at 17:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.