Matlab persistent lolbin – 2 years too late, but always…

I just realized I have never published a post about lolbinish/persistencish Matlab feature that I referred to in this twit. The Tl;dr; is that Matlab can load a DLL of our choice when we use its feature that is both Matlab-user friendly, and … unbelievable.

Using the following command line invocation:

MATLAB.exe -nosplash -nodesktop -r "run('c:\test\test.m'); exit;"

we can instruct matlab to load the matlab file named ‘test.m’ in a batch-like fashion.

The ‘test.m’ in this example include a short piece of code shown below:

x = foo();

When matlab loads the ‘test.m’, it tries to resolve the function ‘foo’ that it will eventually recognize as unknown; as a result, it will look for locally present Matlab executable files (*.mex32 on 32-, and *.mexw64 on 64-bit Windows), and will try to find that function there. In our case (on 64-bit version of OS/matlab) it will look for a ‘foo.mexw64’ file, load it (it is a DLL), and then call a function mexFunction acting as an interface between matlab and the matlab executable.

The example session is shown in this animation:

It’s obvious there are at least two scenarios where this ‘feature’ can be used for offensive purposes:

  • niche Lolbin – having a library of your choice loaded by matlab may help to evade security software
  • niche and stealthy persistence – matlab files can be modified in a viral way to force the loading our our library of choice at some random moment in the future

Environment… is variable

I love environmental variables. They are often post-worthy, and sometimes they are just simply cool.

Yet, many are still not known. Many are still not described.

Looking for ‘easy’ research targets inside the Windows directory one can scan executables and DLLs looking for either a string or an import reference to the functions that operate on Environment variables:

  • RtlSetEnvironmentVariable
  • setenv
  • SetEnvironmentVariable
  • GetEnv
  • GetEnvironmentVariable
  • ExpandEnvironment

These produce really interesting hits!

Looking at the code of puiobj.dll (PrintUI Objects DLL) we can find a weirdly named environment variable F2ED815E-5F18-4860-A8F2-16471D53C5CF that takes a integer value that seems to be a flag controlling how printer queue jobs are presented.

Looking at curl.exe we see the familiar CURL_HOME reference that can alter the way curl works (configuration file location).

The xcopy.exe takes into consideration the value of COPYCMD.

In 2022 no one remembers mswsock.dll, but it also uses environment variables:

  • SanTcpBypass
  • SanResizeDisable
  • SanRecvPollCount

The same goes for oleaut32.dll:

Many of environment variable tricks are known by now. Today I posted on Twitter and Mastodon about the use of environment variables inside the LNK files which — while not really being a proper evasion since the shell functions are processed within a context of executing process — may give some new opportunities to attackers too.

But there is always more…

Environment variables are very, very prevalent and all over the place. Many of them are kinda invisible, f.ex. many batch files and the aforementioned LNK files rely a lot them, and many of them are batch-file specific, often used internally and not very well documented.

Here’s a snapshot of various environment variables (many of which are not very well known, I think) present inside the LNK and BAT files on a win10 system with a Visual Studio, Bon Jour, NPCAP, Powershell and Python present:

  • %ARGS%
  • %AUT%
  • %AUTDIR%
  • %CABOUTPUT%
  • %CD%
  • %CLIENTPATH%
  • %CRT%
  • %CURRDIR%
  • %CabOutput%
  • %CommandPromptType%
  • %CommonProgramFiles%
  • %DEVENVDIR%
  • %DIR%
  • %DIRECTIVEFILE%
  • %DevEnvDir%
  • %DoDump%
  • %Dot11Support%
  • %ERRORLEVEL%
  • %ExtensionSDKDir%
  • %FSHARPINSTALLDIR%
  • %Framework40Version%
  • %FrameworkDIR32%
  • %FrameworkDIR64%
  • %FrameworkDir%
  • %FrameworkDir32%
  • %FrameworkDir64%
  • %FrameworkVersion%
  • %FrameworkVersion32%
  • %FrameworkVersion64%
  • %HOMEDRIVE%
  • %HOMEPATH%
  • %IFCPATH%
  • %INCLUDE%
  • %KEY_NAME%
  • %LEGACY_MACHINE_SETUP_LOGS_PATH%
  • %LIB%
  • %LIBPATH%
  • %LOCALAPPDATA%
  • %LoopbackAdapter%
  • %MACHINE_AMD64_SETUP_LOGS_PATH%
  • %MACHINE_I386_SETUP_LOGS_PATH%
  • %NETFXSDKDir%
  • %NPCAP_DIR%
  • %OUTPUTDIR%
  • %OutputDir%
  • %PATH%
  • %PERMACHINECLIENTPATH64%
  • %PERMACHINECLIENTPATH86%
  • %PERMACHINE_START_MENU_PATH%
  • %PERUSER_START_MENU_PATH%
  • %PROCESSOR_ARCHITECTURE%
  • %PROGRAMDATA%
  • %PROMPT%
  • %PYTHONHOME%
  • %ProgramFiles%
  • %ProgramW6432%
  • %RANDOM%
  • %RETURNCODE%
  • %SDK%
  • %SENDMAIL%
  • %SID%
  • %SQUISHRUNNER%
  • %SQUISHSERVER%
  • %START_TYPE%
  • %ScriptName%
  • %SendMail%
  • %SyncLogsExclude%
  • %SyncSettingsExclude%
  • %SystemRoot%
  • %TARGET%
  • %TEMP%
  • %TEMPFILE%
  • %TESTCASE%
  • %TESTSUITE%
  • %TEST_INCLUDE%
  • %TEST_LIB%
  • %TMP%
  • %UCRTVersion%
  • %USERPROFILE%
  • %UniversalCRTSdkDir%
  • %VCIDEInstallDir%
  • %VCINSTALLDIR%
  • %VCLIB_GENERAL_OVERRIDE%
  • %VCToolsInstallDir%
  • %VCToolsVersion%
  • %VCVARS_USER_VERSION%
  • %VC_ATLMFC_IncludePath%
  • %VC_ExecutablePath_ARM_ARM%
  • %VC_ExecutablePath_ARM_ARM64%
  • %VC_ExecutablePath_ARM_x64%
  • %VC_ExecutablePath_ARM_x86%
  • %VC_ExecutablePath_x64_ARM%
  • %VC_ExecutablePath_x64_ARM64%
  • %VC_ExecutablePath_x64_x64%
  • %VC_ExecutablePath_x64_x86%
  • %VC_ExecutablePath_x86_ARM%
  • %VC_ExecutablePath_x86_ARM64%
  • %VC_ExecutablePath_x86_x64%
  • %VC_ExecutablePath_x86_x86%
  • %VC_IFCPath%
  • %VC_LibraryPath_ATL_ARM%
  • %VC_LibraryPath_ATL_ARM64%
  • %VC_LibraryPath_ATL_ARM64EC%
  • %VC_LibraryPath_ATL_ARM64EC_spectre%
  • %VC_LibraryPath_ATL_ARM64_spectre%
  • %VC_LibraryPath_ATL_ARM_spectre%
  • %VC_LibraryPath_ATL_x64%
  • %VC_LibraryPath_ATL_x64_spectre%
  • %VC_LibraryPath_ATL_x86%
  • %VC_LibraryPath_ATL_x86_spectre%
  • %VC_LibraryPath_VC_ARM%
  • %VC_LibraryPath_VC_ARM64%
  • %VC_LibraryPath_VC_ARM64EC%
  • %VC_LibraryPath_VC_ARM64EC_Desktop%
  • %VC_LibraryPath_VC_ARM64EC_Desktop_spectre%
  • %VC_LibraryPath_VC_ARM64EC_OneCore%
  • %VC_LibraryPath_VC_ARM64EC_OneCore_spectre%
  • %VC_LibraryPath_VC_ARM64EC_Store%
  • %VC_LibraryPath_VC_ARM64_Desktop%
  • %VC_LibraryPath_VC_ARM64_Desktop_spectre%
  • %VC_LibraryPath_VC_ARM64_OneCore%
  • %VC_LibraryPath_VC_ARM64_OneCore_spectre%
  • %VC_LibraryPath_VC_ARM64_Store%
  • %VC_LibraryPath_VC_ARM_Desktop%
  • %VC_LibraryPath_VC_ARM_Desktop_spectre%
  • %VC_LibraryPath_VC_ARM_OneCore%
  • %VC_LibraryPath_VC_ARM_OneCore_spectre%
  • %VC_LibraryPath_VC_ARM_Store%
  • %VC_LibraryPath_VC_x64%
  • %VC_LibraryPath_VC_x64_Desktop%
  • %VC_LibraryPath_VC_x64_Desktop_spectre%
  • %VC_LibraryPath_VC_x64_OneCore%
  • %VC_LibraryPath_VC_x64_OneCore_spectre%
  • %VC_LibraryPath_VC_x64_Store%
  • %VC_LibraryPath_VC_x86%
  • %VC_LibraryPath_VC_x86_Desktop%
  • %VC_LibraryPath_VC_x86_Desktop_spectre%
  • %VC_LibraryPath_VC_x86_OneCore%
  • %VC_LibraryPath_VC_x86_OneCore_spectre%
  • %VC_LibraryPath_VC_x86_Store%
  • %VC_VC_IncludePath%
  • %VIRTUAL_ENV%
  • %VS160COMNTOOLS%
  • %VSCMD_ARG_APP_PLAT%
  • %VSCMD_ARG_CHAMELEON%
  • %VSCMD_ARG_CLEAN_ENV%
  • %VSCMD_ARG_HELP%
  • %VSCMD_ARG_HOST_ARCH%
  • %VSCMD_ARG_NO_EXT%
  • %VSCMD_ARG_STARTDIR%
  • %VSCMD_ARG_TGT_ARCH%
  • %VSCMD_ARG_VCVARS_SPECTRE%
  • %VSCMD_ARG_VCVARS_VER%
  • %VSCMD_ARG_WINSDK%
  • %VSCMD_ARG_no_logo%
  • %VSCMD_BANNER_SHELL_NAME_ALT%
  • %VSCMD_BANNER_TEXT_ALT%
  • %VSCMD_DEBUG%
  • %VSCMD_SKIP_SENDTELEMETRY%
  • %VSCMD_START_DIR%
  • %VSCMD_TEST%
  • %VSCMD_VCVARSALL_INIT%
  • %VSCMD_VER%
  • %VSINSTALLDIR%
  • %WORKINGDIR%
  • %WORKINGDIRONEDRIVE%
  • %WindowsLibPath%
  • %WindowsSDKDir%
  • %WindowsSDKLibVersion%
  • %WindowsSDKNotFound%
  • %WindowsSDKVersion%
  • %WindowsSDK_ExecutablePath_x64%
  • %WindowsSDK_ExecutablePath_x86%
  • %WindowsSdkBinPath%
  • %WindowsSdkDir%
  • %WindowsSdkVerBinPath%
  • %cmd%
  • %computername%
  • %comspec%
  • %dir%
  • %errorlevel%
  • %findSDK%
  • %match%
  • %originPolicy%
  • %result%
  • %returnValue%
  • %scriptPath%
  • %systemroot%
  • %temp%
  • %windir%