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.

Attacking 64-bit Applications on 64-bit Windows

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.

Attacking 32-bit Applications on 64-bit Windows

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.

office64bit

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.

sysprofiler64bit

Cobalt Strike’s System Profiler run against 64-bit Internet Explorer on 64-bit Windows 7. Notice the *64 next to these applications.

Exploits that target 64-bit 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.)

Post Exploitation Considerations

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?