Yesterday, one of my customers asked about x64 payloads in Cobalt Strike. Specifically, he wanted to know why Cobalt Strike doesn’t expose them. I’ve already replied to the question, but I think it makes an interesting blog post.
Cobalt Strike’s listener management feature pretends that 64-bit payloads don’t exist. Beacon is a 32-bit payload with no 64-bit equivalent. This raises a question. Can I use Cobalt Strike to attack 64-bit Windows systems? Of course, the answer is yes.
If my attack will land in a 64-bit process, my approach is to make the attack smart enough to “do the right thing” and stage a 32-bit payload. Here are some examples of this:
Cobalt Strike’s Java Attacks inject shellcode into memory through a JNI DLL. The attacks ship with both 32-bit and 64-bit JNI DLLs. This allows the attacks to work from a 32-bit or 64-bit JVM. It doesn’t matter. The DLL is smart enough to spawn a 32-bit process and inject the 32-bit payload stager–even from a 64-bit process.
Cobalt Strike’s PsExec with PowerShell dialogs let you state whether the target system is 32-bit or 64-bit. When the target is a 64-bit system, Cobalt Strike will set the proper Metasploit Framework option to use the 32-bit version of PowerShell to stage the desired payload.
If you’re using psh_web_delivery to stage a payload (a new favorite module), change the one-liner to include the path to 32-bit PowerShell when you’re targeting a 64-bit system. It’ll work.
c:\windows\syswow64\WindowsPowerShell\v1.0\powershell.exe [blah]
While it’s not technically an attack that delivers a payload, Cobalt Strike’s Browser Pivoting feature is smart enough to detect a 32-bit or 64-bit Internet Explorer process. It will inject the right DLL to enable the activity.
On the flip side, if the application I’m targeting is a 32-bit application, I have to deliver a 32-bit payload to it anyways. 32-bit applications in a 64-bit world are more common than you may initially think.
The default Microsoft Office package is 32-bit. A 64-bit package is available, but Microsoft makes the user jump through a lot of hoops to grab it. Why? According to Microsoft, the 64-bit package offers little benefit to the user at the expense of breaking compatibility with existing add-ons.
The Microsoft Office 64-bit Download screen. You must skillfully find and click two small links, away from the normal Download page to even get here.
Similarly, modern versions of Windows include both 32-bit and 64-bit versions of Internet Explorer. The 32-bit version of Internet Explorer is the default for Windows 7. It looks like it’s this way for Windows 8 too. Defaults are one thing, but ground truth reality on your customer’s network is what matters most. Cobalt Strike’s System Profiler will detect if a 32-bit or 64-bit Internet Explorer is in use and make that information available to you.
Cobalt Strike’s System Profiler run against 64-bit Internet Explorer on 64-bit Windows 7. Notice the *64 next to these applications.
All of that said, you may still want a 64-bit payload to deliver when you attack a 64-bit application. Let’s take a look at the list of Metasploit Framework Windows exploits that support 64-bit targets:
# pwd /opt/metasploit/msf3/modules/exploits/windows # grep -r ARCH_X86_64 . ./smb/psexec_psh.rb: [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] ./postgres/postgres_payload.rb: [ 'Windows x86_64', { 'Arch' => ARCH_X86_64 } ], ./local/ms13_005_hwnd_broadcast.rb: [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] ./local/wmi.rb: [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] ./local/ms10_092_schelevator.rb: 'Arch' => [ ARCH_X86, ARCH_X86_64 ], ./local/always_install_elevated.rb: 'Arch' => [ ARCH_X86, ARCH_X86_64 ], ./local/ikeext_service.rb: [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] ./misc/psh_web_delivery.rb: [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] ./http/oracle_endeca_exec.rb: 'Arch' => [ ARCH_X86_64, ARCH_X86 ], ./winrm/winrm_script_exec.rb: 'Arch' => [ ARCH_X86, ARCH_X86_64 ],
Most of these attacks can deliver a 32-bit payload on a 64-bit system with the right options set (e.g., EXE::Custom, RUN_WOW64, etc.)
There is one place where you need a 64-bit payload though. Some post-exploitation tasks will fail if you attempt them from a 32-bit payload on a 64-bit system. For example, when you run mimikatz from Meterpreter, the current process’s architecture must match the native architecture. That said, you have the option to migrate a 32-bit Meterpreter to a 64-bit process and it’ll magically work.
Now, let’s get back to the original question: why do I always use 32-bit payloads? I use 32-bit payloads because they work in most situations. I’m either targeting a 32-bit application or I’m using an attack that’s smart enough to adjust accordingly. There are few attacks in the Metasploit Framework that exclusively require a 64-bit payload. I can migrate to a 64-bit process if I need to. Right now, I don’t see a benefit to adding 64-bit listeners into Cobalt Strike’s workflow. What are your thoughts?