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%

Inserting data into other processes’ address space, part 1a

I never thought I will write the part 1a of my old post, but here it is.

As usual, I have not explored the below topic in-depth, but have certainly noticed the opportunities and since this is how many interesting developments start, I guess it is still worth … talking…

How do we copy data between processes?

In my old post I have listed a number of inter-process data exchange ideas, but I missed the one that I believe is the most important — at least in 2022 — the non-native stuff. And by that, I mean all these proprietary mechanisms of data exchange that have been developed over the years by vendors different than Microsoft. Many, of course, utilizing the core components of Windows OS, and the very same inter-process communication and cross-process access API functions. Being the ‘genuine’ software and all that, I bet it had to somehow pop up on the radar, and the be filtered out, with time by the likes of AV, EDR, and any other ‘watchmen’… cuz it’s genuine. It’s a stretch, of course, but to their credit, security solutions are getting better and better at detecting any sort of trickery…

With that in mind I started poking around DLLs of known vendors.

I soon discovered a DLL from NVidia (NvIFR.dll) that offers a particular set of exported functions:

  • NvIFR_ConnectToCrossProcessSharedSurfaceEXT
  • NvIFR_CopyFromCrossProcessSharedSurfaceEXT
  • NvIFR_CopyFromSharedSurfaceEXT
  • NvIFR_CopyToCrossProcessSharedSurfaceEXT
  • NvIFR_CopyToSharedSurfaceEXT
  • NvIFR_Create
  • NvIFR_CreateCrossProcessSharedSurfaceEXT
  • NvIFR_CreateEx
  • NvIFR_CreateSharedSurfaceEXT
  • NvIFR_DestroyCrossProcessSharedSurfaceEXT
  • NvIFR_DestroySharedSurfaceEXT
  • NvIFR_GetSDKVersion

hmmm Cross-Process, Shared, and Connect To, and Copy … that certainly sounds interesting!

I don’t have access to any native Nvidia setup, and I don’t play games, so it’s hard to test what these functions really do :(. Quick google for NvIFR_ConnectToCrossProcessSharedSurfaceEXT brought only this interesting reddit conversation.

Poking around the available code, we can speculate that Cross-process Surface interface seems to be accessible via this pipe:

\.\pipe\NVIFR_CPSS_%lld

After you write “[\x7F” to it, you can read a buffer of 2136 bytes (in the DLL version I looked at). The buffer we can then read will contain a name of the shared section we can now open, map, and … hopefully write to. The analysis of the code that follows is not straightforward, there are other DLLs being loaded, APIs resolved, and the complexities encountered would really benefit from ‘live’ analysis, but… c’est la vie.

And this is where this blurb ends. I know, I know, it’s not much, but imagine the possibilities. We can find more similar pieces of code, legitimate, genuine software, and cross-process data exchange snippets present inside these signed DLLs or executables… we may as well come up with many new ways of bypassing security solutions that might have not been possible in the past…