Howdy fellas… me again ;)
This post is a bit different from the last one, you’ll probably have some fun with it…

1. Introduction
Long time ago (2009), in Brazil, we got a huge blackout we called “Apagão”. A brazilian blogger posted about a possible SQL Injection flaw into ONS’s system… Well, this isn’t relevant, but this post has literally shined in almost all internet news portals here in Brazil.
I, curious as I usually am, ended up reading a lot of other things on that blog that day…
Yesterday on #dclabs IRC channel, I have no idea why, but me and raph0x88 started chatting about Information Leakage when a programmer “forgots” to return() a value on his/her program (API/libraries included).
This post exists because more than curious I am really stubborn confident. One post that I’d read that day, was a post about strcmp() C function and its return value, but I’d never spent time testing it…

Translating, the post says something like:

As everyone knows (if don’t: man strcmp), the function strcmp() is responsible by compare two strings and return a value that has the same sign as the difference between the first differing pair of characters. This means that if we compare char by char, in the moment of the char in the left parameter differs to the char in the right parameter, the function will return the difference between them. If they match, the function returns 0 (zero).

Ok, back to our story and my relutant mind, I was thinking: Há, raph0x88 doesn’t know this “feature” of strcmp() – I can fool him! ;D. Below is 10% of our (portuguese) talk:

Long story short: I told raph0x88 that I was able to break any character of a string in less than 10 tries. He doubt it and I proposed a challenge: If I get it done, he’d MUST call me MASTER waKKu for one week – If I don’t, I’d call him.Well, as I said earlier I actually thought I would need only 1 try for each character, but my subconscious told me to say 10 ;)

I’ve never stopped to REALLY read strcmp()’s manpage and make sure of the statemant proposed by that blog, I’ve just believed in it and, as it is not really a praticable vulnerability (once it needs a huge number of wrong conditions). But raph0x88 was totally aware of strcmp()’s behaviour, he knew how the function plays with its return values.

Some time and google surfing later, I found that post on Maycon’s blog and thought: I’m going to have a MASTER week…
BUT, when doing my tests I got a damn surprise! I couldn’t reproduce that “behaviour” using current glibc!

Ok, no panic… One week isn’t that long, we could easily travel during the whole week :X but anyway, I’d need to provide some post about this “challenge” and is too soon to give up (at least so far).

2. Function Analysis
First of all: manpage of current strcmp():

RETURN VALUE
The strcmp() and strncmp() functions return an integer less than, equal to, or greater than zero if s1 (or the first n bytes thereof) is found, respectively, to be less than, to match, or be greater than s2.

Hmmm…
— returns -1 if comparison character in left string is lower than the one in right string.
— returns 0 if comparison character in left string is equal to the one in right string.
— returns 1 if comparison character in left string is greater than the one in right string.

The function returns as soon as it founds a different character, fair enough. Actually, I can’t think any better way to write, in a single function, a string comparison method able to differs lower than, equal to or greater than.

Hmmmm… “Blind SQL Injection” comes to mind, those who already played with a Blind SQL Injection knows that we can use a Binary Search algorithm to find EACH character using the fastest way possible, in this case (ASCII table), we’ve a MAXIMUM number of 7 tries.

Happens that in a Blind SQLi, I can compare 1 character against 1 character, when they match I go to the next… Easy, clean, fashion…

AHHHHHH!!! Beautiful, isn’t it?.. strcmp() returns -1 (to figure out why 255 you need to know that that exitcode is a 8 bits value and this computer works with Two’s Complement) if my character is LOWER than, returns +1 if it is GREATER than and returns 0 if they match… Hooray! handle it bro… Binary search + isolated chars + maximum of 7 tries == MASTER waKKu ;).

“WAIT, WHAT!?!?”… HOW WOULD I ISOLATE EACH CHARACTER FROM OUTSIDE OF THE PROGRAM!?!?
Even if I provide the right FIRST character, strcmp() will try to compare the SECOND character on both strings, that in this output’s case is 0x00 (end of string, null termination, nothing, nada, zip…) and will keep returning that my string is LOWER than the “passphrase”.

3. Frustration

Now I could start panic! I started with a lot of try-and-error approaches…

“That’s it! That’s it!”, I’ll keep incrementing my character, from the first ASCII until the returning value changes from +1 to -1, then I know the last character is the right one and can go to the next position… Well, that leaves me with a worst case of 94 tries characters EACH :/…

(2) I’ve found the number, but I’ve no way to know it. If I test I’ll still get -1 as return value…
So, if I decided to go with standard Binary Search algorithm, I’ll fall into an infinite loop, ‘coz I’ve no stop condition…

(1) Hm… Landed into a maximum of 3 values in range… I could test from 49 to 47, 1 by 1 and done… 10 tries for 1 character == MASTER waKKu.
Sounds promising, but there is one more iem, some moment that I need to go down (at a greater number) and moment that I need to go up (lower number)… That will costs me, at least one more piece of code to find out where to go…

Who cares about speed, huh?… My worst case is 7 and it is a way below my limits…
Now I stopped worring about “when” I’ll find the character. I’m pretty sure I’ll find it out, either on first try or on seventh, makes no difference.
New approach: Pushing limits ;)

Hmmm… One number below… Simple, add +1 and we’re done!
But…
If you recall my conditions: When I found the right value of the first character, strcmp() returns OK(0) to this comparison and go to the next, but then I’ve no second character and strcmp() says that my string is lower…
That means my condition is true for “lower than or equal to” instead of only lower than…

Recap time:
— When my character is lower than or equal to, I get +1
— When my character is greater than, I get -1 (255)

New crux: How to identify the end of “passphrase”?
The last character of all strings in memory is (at least should be :X) a 0x00 (true zero, not this “0”, this is value/ASCII 0x30), therefore if I follow our binary search algorithm trying to find for 0x00, we got:

Due to our min+max/2 calculations, we fell into an infinite loop always on min-1, in our case (ASCII), 31 (or hexa 0x1F).
Cool, that is our condition to end of string, when “x” becomes 31 (0x1f) means that we’ve reached the end of “pasphrase”.

6. The final code

One more “particular item” last (sorry ;))… I told raph0x88 that my solution would be in C (because ain’t not that great on it and he’s, so I should beat him on his rules (sounds hacky, huh?)).