A blog talking about offensive and defensive security and how to craft software in a secure way
Share
thesp0ngeFollowOSCP guy. I break code and rebuild it with security in mind, taekwon-do, husband, dad. Chaotic good drow ranger. I blog @codiceinsicuro and @the_armoredcode.
A tale of a restricted charset shellcode generation
During my OSCE exam preparation I had to deal with shellcode writing experience
where very few allower characters were available.
This brilliant talk by @muts, lead us to get in
touch with a new encoding technique. When you can’t directly write words on the
stack, due to bad characters, you can eventually let a register to contained
the desired word and then push the register into the stack.
As you can see from the video taken at Defcon 16, the code exploits the fact
that after the shellcode it has been written into the stack, very close to the
encoded payload, the execution flow continues until the decoded shellcode it
has been found.
Boom.
All the magic happens in two different pieces.
Init a register to 0
We can’t use XOR to init a register to zero. So we use math here and some
AND property to apply to reset all bits in our register.
On
shellerate
I created a zero_with_and routine. The basic idea is to get a random 32 bits
value, calculating its NOT and then build the shellcode. When the register it
has been put in AND with those two values, it will be set to zero.
Writing a word on the stack
We can’t write a word on the stack because of a restricted alphabet. We will
get rid of this by calculating the
two-complement of the word
we want to write and by finding 2 or 3 values that when added will result in
our word’s complement.
Those values will be subtracted from EAX register, after it has been set to 0.
At the end, EAX will be set to the desired word and it can be pushed into the
stack.
The whole generate.py source code is available on this gist.
Put all the pieces together with shellerate
This can be a really good shellcode encoding mechanism. That’s why I automated
this process and integrated it with
shellerate.
I asked my framework to generate a bind shell shellcode for Linux operating
system. The shell will listen on port 4444 for incoming connections.
Than I padded my shellcode, since I want to operate on 4 bytes long words and I
splitted my shellcode into words.
I encoded all the words using a restricted allowed charset alphabet and I
eventually appended a jump ESP call in order to use my shellcode in a C helper
like this:
Please note that I wrote my shellcode in a reverse order, from the last word to
the first. This way, since the stack is growing backwards, the ESP register
will point to the beginning of my decoded shellcode at the end of the process.
You can see the process in action here. As you can see, the shellcode is
working and a bind shellcode was listening on port 4444.
What about anti virus tool then? I submitted my a.out file to Virus Total and
only 3 engines out of 58 detected my encoded shellcode: pretty sweet
result.
Off by one
Next steps will be:
implementing this encoder into shellerate and release a new version of the
framework (with a working shellerate binary script of course)
make the AND process to use random values, so to increase shellcode entropy
having fun with other register mathematical instructions so to encode with
ADD, MUL, DIV, …