Win16 and Win32 API bad old habits call back…

One of taboo secrets in a programming world of Windows is that everyone trusts Windows API. They are old, reliable, and really very well tested. They really behave themselves quite well. And even if program crashes, the system is smart enough to clean up all those handles, memory allocations that were not properly freed, and deal with any other booboo in a graceful way. All in all – system does the housekeeping for the naughty coders and returns itself to a proper state. This trust in system clean-up created an ecosystem where many programs just rely on OS to fix programmers’ errors.

I still remember reading somewhere (and not challenging it back then!) that when certain type of Windows API calls fail it means that you have a far more serious problem on your hands – the system is probably already very unstable. And the same article was literally suggesting not to bother checking errors for APIs that are 100% trusted to work. So… over a few decades, many programming books, forums, etc. used example code snippets that work, but no one bothers to check the actual result of many API calls. The assumption is that they don’t fail. It’s quite a wishful thinking, isn’t? That is, many programs written over last 30 years include API calls which by default are trusted 100% to work as expected and no one checks the errors or anticipates … slightly different user input or intervention.

Times changed, and to crash the system it’s not that easy anymore+living off the land is a thing. Yet the habits and a crazy amount of code that is based on all these old code snippets is enormous and still present in many programs.

There are some really good examples of bad code practices still used by many software developers – f.ex. relying on environment variables to determine systemroot or other paths is actually a very bad idea despite being advocated as a standard industry practice on many forums; the thing is that the user can control these variables by manipulating them prior to running the application and force the latter to behave in ways that were not anticipated. That can make these apps lolbin-friendly.

Another example is the file system and file handling enhancements. The other day I mentioned that there are changes introduced to Windows 10 that allow APIs to go beyond the Maximum Path Length Limitation when working with file names. This is a significant problem for older apps that may stop seeing files that (ab)use this new feature. This affects day to day work, reversing, sandboxes, and everything else. Such cases may not be handled well proactively as such changes are rarely ‘forward’-compatible.

Funnily enough, long file name is already a problem anyway. Even before that change was introduced.

If you want to run a simple test go ahead and try to rename your fav. app’s .exe to the below file name (remove new lines):

0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789
0123456789.exe

When you try to run it you may either see ‘Access denied’ (system or your shell doesn’t like it) or if it actually runs you may often witness a crash. Here, a simple example of sysmon crashing when renamed to such a long filename and then executed:

Even debugger and programs like Total Commander have a problem locating such files:

So… lots of subtleties here that I believe are not fully explored yet.

And then there many more interesting APIs and ‘code patterns’ to look for.

In my last post I mentioned that sometimes coders don’t adhere to exact API specification (as per MSDN) and as a result may be introducing limitations in their own programs that can be then abused when these discrepancies are discovered. The case I covered was very specific, but such subtleties is where many future problems may arise.

Enter GetModuleFileName (and its sibling GetModuleFileNameEx).

This innocent function is used by a lot of software including security tools. When we read the MSDN description we can learn that if the buffer for the path is too small, the function will truncate the path so that it fills in the buffer fully, will include the ASCIIZ as the last character and will return the ERROR_INSUFFICIENT_BUFFER.

Let me say it again – the OS will truncate the path to fit it into a buffer. Why would they do it instead of insisting on returning error? I really don’t know…

And since many coders assume their buffers are large enough – typical allocated buffers can only squeeze in ~260 characters, and it’s a buffer very often allocated on the stack, not dynamically – they rarely check the error… and yes, checking the source code of many programs you will notice that such approach (not checking if the buffer is too small, and using locally allocated buffer) is actually very common, including examples on MSDN. This discussion on Stackoverflow is far better.

If you are wondering why programmers allocate only ~260 characters. The devil is in the API name. It refers to the module file name, yet the returned data is actually a fully qualified path. While the length of a file name is obviously limited, the full path can be much longer than ~260 characters.

Consider a simple scenario where a trusted program is using GetModuleFileName and expects the path to be say max. 128 characters. The malicious user knows about it and renames the program to 140 characters knowing that the API will truncate the module file path to one that will point to a another file which could be malicious. If such program uses obtained information to e.g. copy its own binary to a destination folder (many apps do it), the copying function will refer to the other (malicious) file, due to that truncation. Yup, once such illogical path is retrieved the legitimate program may actually copy a file based on its (assumed to be correct) file name to the destination directory. By manipulating the file name and the path’s length the attacker can force the trusted program to copy a malicious file instead!

In other words.. by exploiting the fact API return value is not tested/handled properly, one can modify the logic of the program & potentially make it behave in a way not intended/anticipated by the author.

Using a shorter path as an example:

Consider c:\folder\good.exe being that ‘hacked’ long file name; the program, when executed, copies its own file to a destination directory, but since it allocates a much smaller buffer (15 characters instead of 19) to retrieve its full path it is resulting in a truncation that points to a different file name:

  • c:\folder\good.exe –> the actual path assumed by the program, but it will be truncated since the buffer is too small (short by 4 characters)
  • c:\folder\good –> the actual path seen by the program’s code due to truncation&may make the program copy the ‘good’ file instead of ‘good.exe’

The below screenshot from Olly shows how it works:

The first call copies the full path to the 19 characters long buffer. The second, copies the file name partially and returns the error which is ignored by many apps.

I kinda focused on file copying, but the buggy code could be abused in many other ways. For example, if an application uses the returned path as an input to other API functions, these functions may end up reading wrong files, presenting incorrect information on GUI, writing incorrect information to logs, etc..

There are many APIs that can be abused this, or similar way; I am not the first one to point it out – many vulnerability researchers focus on this area for at least 20 years and some do it in a very systematic way. They found lots of programs (including OS) that e.g. don’t check the registry data type when they use Registry APIs; this often leads to a type confusion vulnerabilities that can be abused and in some cases, exploited.

The bottom double line is this:

  • if you can change the path/file name to a long enough one, you can at least crash some apps.
  • if you can change the path/file name to a long enough one, and the app is coded poorly and using the obtained name to make some decisions, you can influence these decisions

Beyond good ol’ Run key, Part 79

This persistence post targets users of Total Commander (TC).

I love TC and have been using it for many years. Quite frankly… I really can’t imagine working on Windows w/o using this tool, and I really pity anyone who is using Windows Explorer either by choice or by force. The other good alternative to TC is FAR, but its far (unintended pun) less popular, and definitely not present in the corporate environment as much as TC…

Anyway…

Being so popular makes TC an obvious target and since it has such a rich functionality it’s very easy to abuse these features to stay on the system persistently.

There are many ways to do it… I doubt I can cover all of them, but let’s jot down some notes:

  • The system of plug-ins is an easy target, so I will skip its description as it’s boring (okay, you just drop a DLL into TC’s plug-in directory and ensure it’s registered to handle some filetypes, of viewer, etc.). These are officially supported plug-in types:
    • Packer Plug-ins
    • File-system Plug-ins
    • Lister Plug-ins
    • Content Plug-ins
    • (note that existing plugins can be swapped, or be a subject to side-loading issues, etc.)
  • Not many people know about it, but the TC accepts command line arguments, including:
    • /i=name.ini – a different location of wincmd.ini file; a changed .ini file may include some extras
    • /INSTALLDRIVERQ- installs ‘cglptnt’ service pointing to C:\WINDOWS\system32\DRIVERS\cglptnt.sys that is copied there by TC – this file could be swapped
  • The next one is one that I kinda like as an idea as it’s quite subtle
    • TC offers a really cool functionality that allows you to quickly ‘jump to the directory’ from the menu
    • The function is activated by the CTRL+D keyboard shortcut
    • The actual ‘jump’ is implemented via a ‘cd’ command, so every new directory added to the menu will have a Command set to ‘cd <directory’:
    • You can change this ‘cd’ command to e.g. c:\windows\system32\calc.exe
    • Next time someone attempts to change the directory to Windows, the calculator will be spawn:
    • The caveat is that the directory itself is not changed in such case – I guess malware could send that sequence of keys to TC to force the directory change or simply modify the entry back to its original content and user would be none the wiser – the command would work the second time they try; since it’s not a typical persistence (it only works when the menu is used), it could be used as a ‘backup’
  • The TC can handle some UAC kinda graciously
    • For example, if you want to enter c:\Windows\CSC directory, you will get this message box:
    • Hitting ‘As Administrator’ will engage Tcmadmin.exe program that is located in the TC program directory; swapping this program with your own will make TC launch your own program anytime it handles UAC business

There are probably many other ways… and as a side note, since TC includes a native client for (S)FTP, it can be used to download/upload stuff as well…

So, in a way, TC is an ultimate… LOLBIN.

There you have it… but want to emphasize one thing – this post is not to scaremonger  you – TC is awesome and consider purchasing it, and… keeping an eye on its config files…