Have you ever found yourself using shellcode, only to discover that it’s broken? It happened to me recently.
While experimenting with shellcode from a seemingly functional source (https://shell-storm.org/shellcode/files/shellcode-827.html), I discovered a hidden vulnerability.
It took me a while to spot the problem; can you?
Spotting the Vulnerability
The suspicious line is:
To uncover the root of the issue, I started with what I already knew. The goal was to execute:
In order to do this, you need:
- The first argument as /bin/sh. That’s what the two pushes do in the disassembly
- The second argument is NULL.
- The third argument is NULL.
But wait: The suspicious line is moving a value that was not initialized! It is effectively becoming the second argument to execve, and it will be whatever junk is left in ecx, resulting in unpredictable behavior.
This issue can be categorized as a CWE-457: uninitialized value vulnerability.
Fixing the Shellcode
The solution lies in initializing the ecx and edx registers before they are used as arguments for execve. Prepending two instructions to the shellcode makes it work:
So the final working shellcode would be:
By taking this approach, the shellcode vulnerability is effectively addressed, and the code works as intended.
This serves as a reminder that even seemingly functional code can harbor subtle vulnerabilities that require careful analysis and remediation. In the realm of shellcode, paying close attention to instruction sequences can make all the difference between success and unexpected failures.