Enter Sandbox – part 17: The clique of clickers

Every sandbox needs to click stuff. Let it be ‘Next’, ‘Finish’, or ‘OK’ button – when the sample runs and the GUI shows up these buttons must be simply pressed somehow to ensure the execution continues.

Writing a clicker tool that handles it smoothly is not a trivial task.

First, it has to click only windows that are created by new processes – this can be kinda easily achieved by PID filtering f.ex. based on a process snapshot obtained prior to launching the sample, but don’t be fooled – the OS message boxes, or running services or programs may sometimes require additional clicking that are ‘out of band’ (e.g. hard error messages from csrss.exe process). There may also be some issues if sandbox tools don’t handle errors silently (e.g. exceptions in .NET tools).

Next, the actual clicking…

Oh boy… this is a tricky one…

Do we send a keyboard event, or mouse event?

Do we even know where the actual button we must click… is?

For installers that rely on Windows GUI system to draw its components – it’s quite easy. Every sych GUI control is a separate window which we can enumerate, find, inspect its class name, text and, send a message to, if we need to. Unfortunately, the generic solution is much harder to write, because:

  • Borland/Delphi/Embarcadero etc. use VCL and its own components (and programmers often created their own libraries with dedicated owner-drawn controls – this was really popular in late 90s and early naughties)
  • .NET uses its own components (Read about Windows Presentation Foundation (WPF))
  • Office uses its own GUI components (forms, etc.) – read about UI automation below and about Office UI Fabric
  • Java uses its own components; many testing frameworks rely on access to the source code (from what I learnt so far), so it’s hard to do a blackbox test
  • Adobe Flash and Silverlight are also custom drawn, same as Google Chrome, Mozilla Firefox and many other software packages may and often do use their own GUI libraries
  • Some (especially old-school) applications use their own components that are proprietary and only known to the software company that produced them, so it’s hard to write a generic clicker for them (Lotus Notes anyone?)
  • Then there are CLI tools that require manual input; these are impossible to handle in a generic way (interestingly, many executables submitted to VT are student projects and require manual input to produce some results; while not malicious, they pose a significant challenge to sandboxes)
  • The GUI elements can be localized
  • The localization itself is one issue, the other is the fact that localized software, especially the old one, often relies on the old ANSI code pages and ANSI APIs, so you have to guess what code page is being used by the sample’s GUI
  • The GUI elements can be ordered, or not (this may determine which button is ‘default‘ – in the absence of the standard buttons like ‘OK’, of ‘Finish’ this may be important)
  • The GUI elements can be bitmaps so no way to determine what to click… other than via known bitmap hashes, OCR/ICR, or a matrix clicking where you walk through the surface of the window and click every few pixels, moving both horizontally and vertically through the whole window area; it’s prone to errors and may force the app to exit early
  • The GUI elements can be drawn using a HTML code, so you may need to either access it via existing means (eg. via WM_HTML_GETOBJECT) or use Accessibility options (read below about that)
  • Many installers are interactive
    • The Installers often include EULA that has to be accepted (various keys used to accept, depending on language)
    • You may also need to choose options for installation e.g. installed UI languages, destination path, etc.
  • Many installers download other components from the net or drop generic component installers during the installation, so the clicker needs to work across multiple processes w/o disturbing parent while the child process is still being ‘processed’ (e.g. can’t send ‘Next’ to the parent process until the child process exited successfully; for examples, see anything that relies on winpcap)
  • There could be decoy GUI elements (e.g. transparent elements added to fool auto clickers, ad hoc passwords, captchas, etc.)

What can significantly help to code a good clicker is the use of mixed technologies and in general – be ready for lots of tuning:

  • Recognize installer / sample file type and apply appropriate playbook
    • This is very important, because sometimes you can use unattended options, if available
    • You can also try to decompile the installer to extract files w/o GUI
  • In a generic way:
    • If possible, enumerate windows and their children, and recognize standard controls
    • Ensure you you use proper windows APIs e.g. RealChildWindowFromPoint vs. ChildWindowFromPoint/ChildWindowFromPointEx
    • Recognize standard shortcuts/accelerators
    • Recognize default buttons (depends on the sequence of resources compiled into the binary)
    • Recognize ‘Next’, ‘Finish’, OK class of buttons, etc.
    • Recognize button classes in general (substrings: ‘button’, ‘btn’, etc.)
    • Recognize Window texts e.g. ‘Accept EULA’ type of buttons (checkboxes, or radiobuttons)
    • Recognize localized versions of the above
    • Recognize automation possibilities
      • The problem of automatic clicking is actually not reserved to sandboxes only
      • QA testing of any sort relies on it a lot: regression tests for coding and localization projects etc. involves lots of clicking and a huge progress has been made over the years to make it work smoothly, and fast
      • Luckily, many software packages support GUI controls’ automation via IAccessible interface
      • Have a read about Automated UI testing and Microsoft UI Automation
    • Have a look at other large projects where the localized strings for standard buttons are already localized e.g. LibreOffice
    • During windows enumeration search for both Unicode, and ANSI versions of these strings while enumerating windows
    • If no success, consider injecting instrumentation code that is ‘native’ to the installer’s platform
    • If no success, consider OCR/ICRing elements of the screen, or use the Babylon technique of hooking API/redrawing text and catching text printed using Text APIs
    • For Delphi, it’s a mundane task of understanding all versions of their VCLs (I have code some PoC code and it was painful, but I was able to read some labels from Delphi programs)
    • As a last resort, redirect trouble samples to a team doing manual malware analysis so the clicker can be tuned

And just to give you a localization sample… this is a list of ‘Agree’ buttons in various languages extracted from one of the Open Source projects:

  • Afrikaans Regso
  • Albanian Pranoj
  • Arabic موافق
  • Armenian Համաձայն եմ
  • Basque Onartu
  • Belarusian Згодзен
  • Bosnian Prihvatam
  • Breton A-du emaon
  • Bulgarian Съгласен
  • Catalan Hi estic d’acord
  • Cibemba Nasumina
  • Croatian Prihvaćam
  • Czech Souhlasím
  • Danish Acceptér
  • Dutch Akkoord
  • Efik Ami Mmenyịme
  • English I Agree
  • Esperanto Akceptite
  • Estonian Nõustun
  • Farsi موافقم
  • Finnish Hyväksyn
  • French J’accepte
  • Galician Aceito
  • Georgian ვეთანხმები
  • German Annehmen
  • Greek Συμφωνώ
  • Hebrew אני מסכים
  • Hindi सहमत
  • Hungarian Elfogadom
  • Icelandic Ég Samþykki
  • Igbo M Kwere
  • Indonesian Saya Setuju
  • Irish Glacaim Leis
  • Italian Accetto
  • Khmer I យល់​ព្រម​
  • Korean 동의함
  • Kurdish Ez Dipejirînim
  • Latvian Es piekrītu
  • Lithuanian Sutinku
  • Luxembourgish Unhuelen
  • Macedonian Да
  • Malagasy Ekeko
  • Mongolian Зєвшєєрлєє
  • Norwegian Godta
  • Pashto زه منم
  • Polish Zgadzam się
  • Portuguese Brasilian Eu Concordo
  • Romanian De acord
  • Russian Принимаю
  • Serbian Прихватам
  • Sesotho Kea Lumela
  • Shona Ndinobvuma
  • Simplified Chinese 我接受
  • Slovak Súhlasím
  • Slovenian Se strinjam
  • Spanish Acepto
  • Swahili Nakubali
  • Swedish Jag Godkänner
  • Tamil A நான் ஒப்புக்கொள்ளுகிறேன்
  • Thai ตกลง
  • Turkish Kabul Ediyorum
  • Twi Migye Tom
  • Ukrainian Приймаю
  • Uyghur قوشۇلىمەن
  • Uzbek Qabul qilaman
  • Valencian Accepte
  • Vietnamese Tôi đồng ý
  • Welsh Cytuno
  • Yoruba Mo Gbà
  • Zulu Ngiyavuma

Enter Sandbox – part 16: The symbols, the ApiSetSchema, and other possible future evasions

It’s been a while since I wrote about Sandboxes and I thought I will revive the series by listing a couple of ideas that I believe may be still under the radar of both sandbox solution creators, and reverse engineers.

Symbols

When we analyze Windows native OS libraries one of the most useful features we have at hand is leveraging debugging symbols. IDA, windbg, and many other reversing tools can use these symbols very efficiently – with symbols in place we can see names of internal functions, variables, and this code/data enrichment provides us with an invaluable context that speeds up the analysis.

Now, since the tools can use it, there is nothing that could stop malware from… doing the same.

Imagine the possibilities!

Instead of relying on export/import tables, a clever malware that leverages symbols could make calls to internal functions, or find ways to hook code deep inside the functions that are typically monitored (at least on the userland level). Symbols could also help to detect caves i.e. areas of code/data that are rarely used, and allow malware to overwrite them and persist in a much stealthier way than usual. There is a lot of potential for surgical modification of code to launch the payload code using the EPO (Entry Point Obscuring) technique.

Note that while there could be a need to download these PDB files directly on the infected system, nothing stops malware from sending copies of the DLLs from the system to its server first, decompiling / disassembling them on a remote server.  The malware could then craft the payload using hardcoded offsets obtained via symbols to deliver the required functionality. A side effect of such trickery would be that such crafted payloads would not run on sandboxes, and manual analysis would typically fail unless the file was analyzed on the exactly same system (meaning: with the same versions of libraries as existing on the victim’s system); obviously, ASLR needs to be taken into account for all offsets and calls. Another caveat is that such approach would require constant monitoring of Windows Update service; if files are replaced, the code would need to be updated to the most up to date version that works with the new libraries.

Leveraging functions of ApiSetSchema libraries

Now that we have not only kernel32.dll, but also KernelBase.dll, and the whole api-ms-*.dll zoo, it is possible to call these wrapper functions instead of the pure exports from kernel32.dll, advapi32.dll, etc..

Leveraging internal/undocumented functions

These can be either located via symbols, or via ApiSetSchema libraries; a quick browsing through internal functions referenced by kernel32.dll reveals a lot of interesting possibilities e.g.:

  • PrivCopyFileExW – undocumented function that allows to copy files
  • A couple of exported Internal functions that can be potentially used as callbacks (to run shellcodes, payload code, etc.)
    • Internal_EnumCalendarInfo
    • Internal_EnumDateFormats
    • Internal_EnumLanguageGroupLocales
    • Internal_EnumSystemCodePages
    • Internal_EnumSystemLanguageGroups
    • Internal_EnumSystemLocales
    • Internal_EnumTimeFormats
    • Internal_EnumUILanguages
  • A couple of exported Internal functions that can be used to access both the Registry and the File System bypassing documented APIs:
    • RegCreateKeyExInternalA
    • RegCreateKeyExInternalW
    • RegDeleteKeyExInternalA
    • RegDeleteKeyExInternalW
    • RegOpenKeyExInternalA
    • RegOpenKeyExInternalW
    • ReplaceFileExInternal

There is certainly more.

New technologies (well, sometimes not that new)

While it doesn’t really rely on symbols, it does fit the topic of the article – there is a class of APIs that are not commonly used yet, but certainly will be heavily utilized in the future:  I am talking about enclave functions; as per MS:

An enclave is an isolated region of code and data within the address space for an application. Only code that runs within the enclave can access data within the same enclave.

Example functions:

So, you got yourself yet another API set for both code injection and protection.

I am obviously not the first one to highlight it; a paper from 2015 (3 years ago!) by Alex Ionescu covers the topic and lists a number of possible issues enclaves bring to the world of security solutions including AV, EDR, and perhaps memory acquisition tools.