Avoiding NULL

The presence of NULL characters in payloads can be detrimental as they can prematurely terminate string-based operations, leading to unintended consequences or truncation of data.

Analysing Shellcode

Using the workflow we developed we can compile our shellcode into a .bin /raw file. We can take this raw file and analyse with a tool in my github repository here. You will need to install the keystone and capstone engines and the rich framework using pip:

pip.exe install keystone-engine
pip.exe install capstone
pip.exe install rich

We can compile our MessageBox shellcode from the previous section:

nasm -f bin -o messagebox.bin messagebox.asm

We can then use the Bad Character tool to check for null bytes:

python.exe .\bad-char-check.py --raw ..\x64\messagebox.bin 
    --badchars "0x00" --scroll 10 --platform x64

We can scroll through the shellcode until we find that there is two NULL bytes at 0x10d8:

NULL bytes

We can see the offending shellcode in our assembly:

Removing NULL Bytes

Various techniques exist to eliminate NULL bytes from shellcode, often requiring imaginative approaches to ensure that the payload remains free of these characters.

The shellcode below presents a way in which we can acheive the same objective but avoid NULL bytes:

After testing the .bin file again, we see that the NULL character has been eliminated:

NULL bytes eliminated

As we work through eliminating the null bytes it would be prudent to insert a breakpoint and test the shellcode to ensure that we acheive the same outcome:

The breakpoint has been entered at line 11. If we recompile this and debug it in Windbg Preview, we can hit the breakpoint. We can use the da @rcx command to show that the lpLibFileName is still correct:

Don't forget to remove any int3 instructions when you want to use your shellcode for real.

Bad Characters

This technique can be used to eliminate bad characters too, but sometimes instruction mnemonics include bad characters.

Let us imagine that 0x31 is a bad character:

Bad character

We can replace the xor rcx, rcx with:

We can debug in Windbg Preview and we find that rcx is zero:

There are many different ways to replace bad characters in your shellcode and sometimes it might be more beneficial to change your shellcode rather than rely upon decoding shellcode in memory. This is particularly true if the memory in which your shellcode has been copied does not have write permissions.

Exercises

  1. Work through the MessageBox shellcode and eliminate NULL bytes.

  2. Give yourself a handful of bad characters and eliminate them from your shellcode.

Last updated