Monday, November 17, 2014

Alphanumeric Shellcode of EXEC("/bin/sh") without binsh/BINSH Characters

Abstract

This is one of the CTF tasks from "Secure Programming" course in NCTU.

Problem

Input: a string with following restrictions
  • Alphabets and Numbers only, which means: [0-9], [a-z], and [A-Z]
  • No "binsh/BINSH" characters
This string will be executed as machine code on the target server, which we call shellcode. So, we can guess that the program looks like this:


Workable Shellcode

First, let's ignore the restrictions first. We may need a test code to execute "bin/sh" successfully for further steps. And here's is it:

Also, by referring to the system call document, what we learn that the registers should be set before calling "INT 0x80":

  • EAX: 0x0b
  • EBX: Address of "bin/sh" string
  • ECX, EDX: 0x00 (optional)

Try: msfencode

cat shellcode.txt | msfencode BufferRegister=ECX -i sc.bin -e x86/alpha_mixed -t python -b 'binshBINSH'
This piece of code should give out our solution. However, the encoder returns error saying that it can't find the solution.

Write It on My Own

Since the existing encoder can't solve this problem, we now have to solve it on our own. The things we know so far:

Issue 1: Storing Arbitrary Value on Stack

  • PUSH a small random value into the stack
  • POP to ECX
  • DEC ECX to the wanted value
  • PUSH ECX
For larger wanted value:
  • PUSH a small random value into the stack
  • POP to EAX
  • XOR EAX, <value> (this may need to be done twice to gain the wanted value)
  • PUSH EAX
Notice:
  • the value for XOR should be calculated manually
  • pick ECX for DEC/POP/PUSH instructions under our initial restrictions
  • pick EAX for XOR (0x35 opcode)

Issue 2: Storing Instructions on Stack

There are some instructions not accepted in our input shellcode, so we somehow generate the instructions as data and push them onto the stack. By having "-fno-stack-protector -z execstack" option while compiling in GCC, we can execute the pushed instructions later.

Issue 3: Move EIP to Stack

  • EIP is in the stack and pointing to the current shellcode
  • ESP is where our instructions ("POP EBX", "INT 0x80") is pushed on
It will be easy if we call a jump instruction to move the EIP to ESP, then our instructions will be executed. However, we only have o8 (8-bit immediately) jump instructions, which is not long enough to jump to ESP.
Therefore, I popped the stack in order to increase ESP in the begin of the shellcode.
  • POP ESP for many times: increase ESP value
  • make ESP locates after (and close to) the end of our shellcode
  • call a small 8-bit jump to our stack (where "POP EBX", "INT 0x80" locate)

Solution

Here's my solution:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXj0ZJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJRYQj0X5JCCX5Ul00Pj0X5JRYY5U007PTj0ZJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJRX5CG005q800Pj0X5kOOOPPj0ZJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJRXJJJJJJJJJJJDDDDDDDDDDDDu0

And, the details are in my Github repo.