Dumping lsass using EDR toolset
In July 2021, I reported to PaloAltoNetworks that a tool belonging to Cortex XDR may be abused to dump LSASS and obtain credentials. After some months, they applied a fix to avoid the tool to dump Windows's processes.
The tool in question is cydump.exe, which can be seen named in the official documentation for Cortex XDR. When I first saw this executable while performing a red-team exercise, it seemed juicy, so I decided to take a look at it.
In this post I will describe how I reverse engineered the tool to find out how it works and use it to dump LSASS to get corporate credentials.
Reverse engineering cydump.exe
For this exercise I used cydump in version 7.3.2:
The binary is found in the Cortex's installation path, so I copied it to a virtual machine and started playing with Ghidra.
As the tool name suggest, it may be used to dump process memory, so my intuitition was right as there is a call to MiniDumpWriteDump
.
Starting at entry0
, I found a function which I renamed to call_dumper
:
undefined8 call_dumper(undefined8 param_1,undefined8 param_2,LPCWSTR command_line)
{
LPWSTR *main_argv_params;
ulonglong uVar1;
undefined8 uVar2;
int argc [4];
main_argv_params = CommandLineToArgvW(command_line,argc);
if (argc[0] != 0) {
uVar1 = dumpservice_cmp((ushort *)*main_argv_params,(ushort *)L"dumpservice");then
if ((int)uVar1 == 0) {
uVar2 = dumper_function(argc[0],(longlong)main_argv_params);
return uVar2;
}
}
return 0x57;
}
The third parameter passed to call_dumper
was returned by _get_wide_winmain_command_line()
which returns the command line executed with the tool.
This function checks if there was any parameters passed to the tool and then pass them to dumpservice_cmp
; function which will check if the first parameter is the string "dumpservice". If this check fails, it will exit, so this string MUST be in the command line. Next, it will execute the dumper_function
, which is the one calling MiniDumpWriteDump
.
The dumper_function
signature is as follows:
void dumper_function(int argc,longlong main_argv_params)
One of the first things the function do is check if there's 3 or more parameters, then it tries to get the process ID from the main parameters, and finally try to open that process. If it fails, it will return an error.
if (argc < 3) goto LAB_14000132d;
dwProcessId = wcstol(*(wchar_t **)(main_argv_params + 8),(wchar_t **)0x0,0x10);
hProcess = OpenProcess(0x450,0,dwProcessId);
if (hProcess == (HANDLE)0x0) {
DVar3 = GetLastError();
}
One thing to notice is that wcstol
is getting the processId in hexadecimal (0x10), which means that the process ID must be provided in hex base.
If this checks goes fine, the process will be dumped in a file called following the format "%s%s%s.%d.self.exe.dump", as can be seen at this function call...
FUN_140001000(output_buffer,0x104,L"%s%s%s.%d.self.exe.dump",va_start);
...which simply is a call to vsnprintf()
. The va_start
parameter will contain the third parameter passed to the command line, meaning that it could be the path to be written.
Testing our approach
Finally, after understanding how this tool may work, I decided to test it. I got the lsass.exe processId and converted it to hexadecimal. The command line should be:
cydump.exe dumpservice <hex_process_id> <path_to_write_dump>
BIG SUCCESS! I was able to dump lsass using XDR Cortex's tool!
Reporting to PaloAltoNetworks
I was concerned that someone could use this tool to dump processes and not be detected by the EDR, so I reported this case to PaloAltoNetworks. The timeline was as follows:
- July 2021 - case reported to PaloAltoNetworks. CPATR-14330 assigned.
- August 2021 - working on a fix so cydump.exe could only dump XDR Cortex's processes.
- July 2022 - Content update delivered to all Cortex XDR agents.