79388447

Date: 2025-01-26 11:46:18
Score: 1
Natty:
Report link

Thanks to these comments, I could figure out what are going on under this issue.

While looking into this issue, I could find more pelicuralities.

  1. Performing SetRenameInformationFile within an exe as a standard user(without elevation) without a manifest specifiying requestedExecutionLevel in trustinfo(which handles execution level) triggers this issue.
  2. This issue occurs when trying to rename ADS under os drive(which is typically C:), while it does not occur in additional drives.

Difference between c++ and go program.

This is indeed related to the manifest file and the UAC virtualization as it is documented that

Specifying requestedExecutionLevel node will disable file and registry virtualization.

And this happens only in 32-bit program as UAC virtualization is only supported for 32-bit apps(as it is for pre-vista apps compatiblity, in which 64-bit was not popular and not used widely). When using g++ for compiling exe file, it embeds default manifest using pre-generated object file located in {mingw-root}/lib/default-manifest.o, which contains manifest file such as

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker"/>
      </requestedPrivileges>
   </security>
  </trustInfo>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!--The ID below indicates application support for Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!--The ID below indicates application support for Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!--The ID below indicates application support for Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
      <!--The ID below indicates application support for Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
      <!--The ID below indicates application support for Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </application>
  </compatibility>
</assembly>

which is mostly embed into exe file by default for several compilers(Visual Studio, mingw-64-gcc, rust, ...). However, golang does not embed or provide manifest for exe files by itself as they decided to make it a developer's responsibility to do that by themselves. 😢

Return value of ERROR_INVALID_NAME from SetFileInformationByHandle

As noted in the question, the error value ERROR_INVALID_NAME which is translated from STATUS_OBJECT_NAME_INVALID comes from luafv which stands for Least authorized User Account File Virtualization Filter Driver, which is used for UAC virtualization. From luafv!LuafvPerformRename the part where STATUS_OBJECT_NAME_INVALID(0xc0000033) comes into the scene it does something like

iterVal = 0;
if (uNameLen != 0) {
    do {
        if ((*(short *)(namePtr + iterVal * 2) == 0x5c) || (*(short *)(namePtr + iterVal * 2) == 0x3a)) 
        {
          esi = 0xc0000033;
          goto EXIT;
        }
        iterVal = iterVal + 1;
      } while (iterVal < uNameLen);
    }
  }

// ...

EXIT:
// release allocated objects...

return;

which reads through WCHAR(uint16) values from the name buffer to be used for renaming, if there is any backslash \(0x5c) or colon :(0x3a), it will set a register(particulary ESI) to 0xc0000033 then skip the actual call to FltSetInformationFile then do the releasing of the allocated resources. As every name used for renaming ADS starts with : according to the document, it is obvious that luafv cannot be used to rename ADS. So, it looks like renaming ADS does not work with UAC virtualization.

As, go currently supports Windows versions later than Windows 10, go compiled programs should not need compatibility for pre-vista Windows. Currently, to make 32-bit go compiled programs work without issue, manually embedding manifest file from the above(to also fix some potential issues) is the solution.

Remaining question

While trying to figure out why renaming ADS fails for files under os drive, I have checked that the directories I used for testing has ACL that allow the runner of the process to rename streams. As I was not using directories under C:\Windows, C:\Program Files which required administrator rights to access files inside them, I think that such issue should not happen for unrestricted directories. I wonder if Windows has drive-specific security setting for each drive but I could not find any reference about it.

Reasons:
  • Blacklisted phrase (0.5): Thanks
  • Blacklisted phrase (1): :(
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: Snshadow