3

Right now I'm trying to solve r5 from here

I've already tried to understand pseudo-code from Hooper

function check_password {
    var_28 = arg0;
    if (strlen(var_28) != strlen("this_is_not_even_interesting_its_garbage")) {
            rax = 0xffffffff;
    }
    else {
            strcpy("this_is_not_even_interesting_its_garbage", var_28);
            var_18 = 0x1;
            while (var_18 != 0x0) {
                    var_18 = 0x0;
                    for (var_14 = 0x0; var_14 <= 0x27; var_14 = var_14 + 0x1) {
                            if ((*(int8_t *)(sign_extend_32(var_14) + 0x6010a0) & 0xff) != 0x0) {
                                    rax = random();
                                    rcx = *(int8_t *)(sign_extend_64(var_14) + 0x6010a0) & 0xff & 0xff;
                                    temp_3 = rax % rcx;
                                    *(int8_t *)(sign_extend_32(var_14) + 0x6010a0) = (*(int8_t *)(sign_extend_32(var_14) + 0x6010a0) & 0xff) - temp_3 + 0x1;
                                    var_18 = var_18 | *(int8_t *)(sign_extend_32(var_14) + 0x6010a0) & 0xff & 0xff;
                                    *(int8_t *)(sign_extend_32(var_14) + "this_is_not_even_interesting_its_garbage") = (*(int8_t *)(sign_extend_32(var_14) + "this_is_not_even_interesting_its_garbage") & 0xff) - temp_3 + 0x1;
                            }
                    }
            }
            rax = *master;
            rax = strcmp(rax, "this_is_not_even_interesting_its_garbage");
    }
    return rax;
}

but it's too complicated for me right now. So I know that the password length should be 40 but how does the other part of the code work?

The unclear parts are the unt8_t casts. I've used gdb to step through the code, and I saw the results of certain instructions but cannot understand why these are the results ?

  • The best way to start understanding these type of things it writing your own pseudo-code or simulator. That way you force yourself to actually read and comprehend the code in front of you. Have you tried doing that? What were the parts that were difficult? – NirIzr Aug 18 '16 at 21:12
  • @Nirlzr first of all I tried to run this code in gdb with breakpoints. I can see two loops in asm code, but what happens next is some kind of magick for me. While running it with gdb I've figured out that the first value of rcx in loop was 3. But I'm not sure from where is that digit – desu Aug 18 '16 at 21:23
  • So you'd say the line that you're having trouble with is rcx = *(int8_t *)(sign_extend_64(var_14) + 0x6010a0) & 0xff & 0xff;? Will you mind edit that in? Any other lines you're struggling with? – NirIzr Aug 18 '16 at 21:25
  • @Nirlzr all that lines with cast to int8_t looks strange for me – desu Aug 18 '16 at 21:32
  • @NirIzr I think that (int8_t *) is casting (sign_extend + offset) to the signed 8 bit int After that it takes the value from that pointer and doing bitwise and. But I don't know what result will it give to me. Looks like int and 0xff will always return int – desu Aug 18 '16 at 22:12
3

Although OP clarified only the inner for is unreadable to him, I'll write an answer that thoroughly explains the first few lines and then abruptly stops at the most crucial part of the inner for loop. While believing examples are a great way to learn, I do that to make this as educational as possible, without interfering with the learning process of independently solving exercises. I am also unfamiliar with the specific set of exercises and would like to avoid providing full answers where those were not intended by the creator.

I hope i hit that sweet spot of being educational enough yet not too much.

Good luck with the exercise, here goes:

var_18 = 0x1;

Set an internal state to 1.

while (var_18 != 0x0) {

While state is True, continue executing loop's content. The state is actually a boolean indicating processing is not finished yet.

var_18 = 0x0;

Set internal state to zero at every outer loop iteration. This means every iteration must set the "not finished yet" flag.

for (var_14 = 0x0; var_14 <= 0x27; var_14 = var_14 + 0x1) {

Inner for iterates 0x28 times, 40 in decimal. Since we know this is the length of the entire string, we can assume the inner loop somehow iterates over all characters of the string. This might be a coincidence, but we should keep an eye for it.

if ((*(int8_t *)(sign_extend_32(var_14) + 0x6010a0) & 0xff) != 0x0) {

Now here it gets a little bit more complicated, so we'll split it to several parts:

sign_extend_32(var_14)

Since we know var_14 is a non negative integer between 0 and 39 (including), there's no meaning to sign-extending it. Sign-extending is basically the operation of converting a shorter length value to longer, taking the sign bit into account. See this for more info about sign-extension. This is either a compiler or decompiler artifact. A more advanced decompiler might have removed this.

(int8_t *)(sign_extend_32(var_14) + 0x6010a0)

Add our var_14 to a relatively long hex offset. By the looks of it, it's probably an offset to table of 40 bytes. This is learnt from experience, taking a look at value at that address might clear it up. Adding var_14 and then casting to an int8 pointer further suggests that's the case, using var_14 as the index in that table.

(*(int8_t *)(sign_extend_32(var_14) + 0x6010a0) & 0xff)

If we weren't convinced yet, by now it's pretty clear as we read a byte from the resulting offset. AND-ing it with 0xff is yet another decompiler artifact, caused by how a compiler will read a byte in 64bit intel processors.

if ((*(int8_t *)(sign_extend_32(var_14) + 0x6010a0) & 0xff) != 0x0) {

back to the full line, this is reading the byte from the table, and skipping the current iteraction of the inner loop.

rax = random();

Simple. Set a random value into rax.

rcx = *(int8_t *)(sign_extend_64(var_14) + 0x6010a0) & 0xff & 0xff;

This is actually quite identical to the condition from before, only now the value of that index in the table is stored into rcx.

remaining lines of code

                                temp_3 = rax % rcx;
                                *(int8_t *)(sign_extend_32(var_14) + 0x6010a0) = (*(int8_t *)(sign_extend_32(var_14) + 0x6010a0) & 0xff) - temp_3 + 0x1;
                                var_18 = var_18 | *(int8_t *)(sign_extend_32(var_14) + 0x6010a0) & 0xff & 0xff;
                                *(int8_t *)(sign_extend_32(var_14) + "this_is_not_even_interesting_its_garbage") = (*(int8_t *)(sign_extend_32(var_14) + "this_is_not_even_interesting_its_garbage") & 0xff) - temp_3 + 0x1;
                        }
                }
        }
        rax = *master;
        rax = strcmp(rax, "this_is_not_even_interesting_its_garbage");
}
return rax;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.