POC – Badchar, alternative method

What is a bad char?

Badchars or bad characters are characters that the target program receives, and this filters them and acts as delimiters or, using their internal algorithms, eliminates them or substitutes them for other values, rendering our shellcode useless.

The search for bad chars is a crucial part of exploit creation methodology since if they are not localized and avoided during the payload generation, they make it unusable since it will not be interpreted correctly by the target system.

We will see more graphically the explanation on the part of the post of the generation of the payload for the object program.

The alternative “Manual” method

In this case, after seeing how to locate them in a more automated way with scripts in the post of my mentor Carlos, this method I present is an alternative, being this more manual and handmade, since it is interpreting us the search for those characters. This method is almost infallible, that is, it is based on human interpretation, we do not depend on scripts or other tools that may fail for any reason, or we do not have them. Also, note that this is a way to understand how scripts work for the search for bad chars.

Explanation of method

We are based on the use of a payload that is composed of a special pattern, only that instead of being like other complete patterns that go from 0x00 to 0Xff, it is rearranged in blocks of 4 Bytes so that when representing in the stack it is “legible “From left to right (usually the target systems use the Little Endian format, and the values are written from right to left), so you can figure out which values are missing, are replaced or the payload is cut off. Easy not? This would be the payload (excluding the value 0x00):

POC – Easy RM to MP3 Converter

Objetivo: Easy RM to mp3 converter v2.7.3.700 en Windows XP SP2

Herramientas: Immunity Debugger, mona.py, Sublime Text 3

We will use this program to test our method. The most important thing is to be organized and to bring everything well structured. On one side we will put our payload, and in another, we will have our POC scheme and the program and debugger “Immunity debugger” with the software Easy RM to mp3 loaded.

Illustration of loaded payload

I will not focus on the search for value and distance to override EIP since in this entry we are based on the search for bad chars.

According to the calculations obtained with mona.py, to overwrite the value of EIP, I must send a buffer of 26066. Previously we wrote the skeleton of the script to order the values that will receive the stack. We can use as an example the script of the image, which will create a .m3u file in the POC.

An example illustration of how to order the stack “Stack.”

Immunity and Python script

Now it is necessary to modify our payload, to add the hexadecimal values ordered in blocks of 4 Bytes so that it is shown to us in the Stack view of the Immunity Debugger. We will reorder the script as follows:

Illustration Stack “Stack”

Stack after buffering

If we look at the image, we see that the padding is correct since ESP (thick blue line), is pointing to the beginning of the payload (the 8 bytes with the nine character) and continues with our payload sequence. As we see the payload starts well, counting from 0x01 to 0x08 but in the next block, we see that the sequence is cut. If you look at it, you would miss 0x09 and 0x0a and then continue 0x0b and 0x0c, and from there it will be cut. What does this mean?

Because we have encountered an invalid character, which cuts the sequence and does not continue reading the payload. To identify it we have to remember that the “reading” is in Little endian format, so the stack is filling from right to left with our buffer:

Diagram of the stack once filled

In this diagram, we see how the program is reading the buffer, and this is loading the characters in the stack. As we see the first reads the 0x0c and the program puts it on the stack (to the right by the format Little endian), and then follows with 0x0b, but when it reaches 0x0a is cut, no longer adds it to the stack, and how We see the flow short and not continuous after that character with which the buffer reading ends. As we see in this example, the character 0x0a is a bad char, and causes a cut in the flow of the reading of the buffer, with which we must invest obviously in the payload. It can happen the substitution case, so we would see that the value of the buffer does not match the value stored in the stack:

Example of bad chars replacement

If we copy the payload in another document, but in this case ordered that is as the final representation of the stack, we notice that from the character 0x0a there is only 0x00, which are like a stack filling that makes the target program, and from Hence our pre_buffer:


After this point, we only have to replace the bad char 0x0a with another value or exclude it from the payload. In order not to break the order structure of the payload, we will replace the bad char by 0x99 that we know a valid value and we will look for the following bad char. We modified the variable payload of our script:

We execute, and we see the alignment of the stack as follows:

 Stack Illustration

Stack after deleting 0x0A

If we set the payload continues the series, and where it had to be the value 0x0A is 0x99 as we had put in our payload, which deduces that 0x0A is a bad char, and we have to exclude it from the final payload. We are still looking for more bad chars:

Illustration of stack with payload executed

Complete Stack after replacing the bad char 0x0A

As we see in the previous image, there are no more cuts in the payload (we see the end of the payload) and no substitutions (the pattern is complete). Now we only have to create a shellcode with MSF venom and include it in our POC, and overwrite EIP with an address to a JMP ESP or CALL ESP, but we will see more in detail.

Final notes and script

As everything is possible to automate the manual search process with scripts that generate the pattern. I share my own in Python (something coarse but functional), adding functions like specifying bad chars to generate the pattern again without them, creating a noose padding and a trailer of beginning and end of the payload. Any suggestion is welcome:

Autor : Miguel Cobas Barcala