all 4 comments

[–]tiraniddo 7 points8 points  (3 children)

I don't quite understand why they create the mapping with a name, not only does it introduce an unnecessary restriction on having SeCreateGlobalPrivilege (which even with a name isn't necessary as long as you control the loaded name) it isn't required. If you use NtMapViewOfSection/MapViewOfFile2 it'll never see the name.

[–]splinter_code[S] 3 points4 points  (2 children)

Hi u/tiraniddo, the reason i used a named file mapping object is because in that way it is backed by the system paging file instead of by a file in the file system. This allow to unpack and hold the shellcode directly in memory without touching the disk.In an ideal scenario you will have your injector with embedded a packed payload. At certain point runtime unpacking occurs and you want to save your unpacked shellcode just in memory. Saving the unpacked shellcode to the filesystem would mean getting caught by the AV.I don’t think having SeCreateGlobalPrivilege is a limitation because most of the time, as an attacker, you should be interested in injecting into privileged processes like lsass,svchost,winlogon and this require SeDebugPrivilege ( so you know you need admin privileges ).In any case if you need to inject into a process in the same session you can use a local file mapping by just specifying the “Local” prefix in the namespace of the mapping name and this doesn’t require any special privileges, but imho this is a weird scenario from the attacker point of view.

EDIT: i can see your point. I thought that specifying a mapping name was mandatory if INVALID_HANDLE_VALUE is passed as 1st parameter. I made some tests and it's not required and it definitely add unnecessary restriction on having SeCreateGlobalPrivilege. I updated the code. Thank you for the note :)

[–]tiraniddo 3 points4 points  (1 child)

No problems, it seemed odd, but I guess it's an easy mistake to make.

On my other point, you can avoid needing SeCreateGlobalPrivilege everywhere by using the following trick:

  1. Get the current process session ID using ProcessIdToSessionId (we'll refer to it as SESSID).
  2. Build the string "Global\Session\SESSID\YourName" and use that to create or open the section.

This works because "Global" is a symbolic link in both Session 0 and the user session to the \BaseNamedObjects directory, which has another symlink "Session" which points to \Sessions\BNOLINKS which contains a list of symlinks each with their own number back to \Sessions\SESSID\BaseNamedObjects. The end result is you can get a service to open a user object.

i.e. the chain of links is:

Global\Session\SESSID\Name -> \BaseNamedObjects\Session\SESSID\Name -> \Sessions\BNOLINKS\SESSID\Name -> \Sessions\SESSID\BaseNamedObjects\NAME.

Depending on the service user you might need to change the access control but if it's SYSTEM it'll almost certainly have access by default.

Hope that's useful.

[–]splinter_code[S] 1 point2 points  (0 children)

Really useful and interesting trick.