SLAE64 - Polymorphic shellcode


The sixth assignment of the SLAE64 exam states:

  • Take up to 3 shellcodes from Shell-Storm and create polymorphic version of them to beat pattern matching
  • The polymorphic versions cannot be larger than 150% of the original shellcode
  • Bonus points for making it shorter in length than original

When researching polymorphism one is certain to encounter the Polymorphic Shellcode Engine Using Spectrum Analysis article from Phrack Magazine.

Our polymorphic versions are a lot simpler than what is described in this seminal article. But as you'll see, even small adjustments may evade antivirus still.

Sample 1: Add map in /etc/hosts file

The original shellcode comes in at 110 bytes and my modified version has actually been slimmed down a bit to 95 bytes.

Most of the reduction in size is thanks to using the stack to push and pop arguments into the target registers. However one interesting optimisation comes from using the RBX and RCX instead of R8 and R10. A mov to R8/R10 here (not counting the source operand) encodes into two bytes and so does a mov to RBX/RCX. However pushing it onto the stack takes two bytes again for R8/R10, but it only takes a single byte opcode for RBX/RCX. A quick with of 2 bytes in total while slightly changing the signature.

I chose this particular shellcode because I think it's a nice initial foothold for a MITM attack.

Sample 2: shutdown -h now

The original shellcode comes in at 65 bytes and my modified version results in 61 bytes.

I used a similar technique as before with replacing the usage of R8/R10, though now with RDI/RSI as RBX/RCX cannot be used in this context.

Also, I've applied the "trick" used by the Msfvenom xor encoder for adding a negative number in order to set the syscall number for execve.

Lastly, I swapped some instances of push rax and push rdx because both registers were 0 as I've used cdq to clear RDX after having cleared RAX.

Sample 3: Execute /bin/sh

The original shellcode is a tiny 27 bytes and my modified version results in 30 bytes.

This rather compact shellcode cannot really be shrunk, so let's go the opposite direction while staying under the limit of 150% or 40 bytes in total.

By shuffling things around and reducing stack usage a little bit I eventually got at 30 bytes in total.

Wrapping up

I have uploaded the msfvenom code to jasperla/slae64 on GitHub:

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.
Student ID: SLAE64-1614