DEV Community

Gealber Morales
Gealber Morales

Posted on • Originally published at gealber.com

Challenge RE #9

Hi there, here we are again. This time with the 9th RE Challenge from Dennis Yurichev. Let's see what we have this time, the 8th one I found it extremely instructive, specially because I saw in first hand how a structure it's declare or manage at the end.

By the way, if you found any error in my explanations feel free to reach out. Typos will be a lot, normally I don't pay attention to them, mainly because as long as you understand the idea an 's' at the end of a verb is not such big thing. Enough of silly talk, let's try to understand what this assembly code does.

Analysis

The assembly code to understand is the following:

.LC0:
    .string "error!"
f:
    sub rsp, 8
    movzx   eax, BYTE PTR [rdi]
    cmp al, 89
    je  .L3
    jle .L21
    cmp al, 110
    je  .L6
    cmp al, 121
    jne .L2
.L3:
    mov eax, 1
    add rsp, 8
    ret
.L21:
    cmp al, 78
    je  .L6
.L2:
    mov edi, OFFSET FLAT:.LC0
    call    puts
    xor edi, edi
    call    exit
.L6:
    xor eax, eax
    add rsp, 8
    ret
Enter fullscreen mode Exit fullscreen mode

First thing that we encountered is a null terminated string, with the word "error!"...no mystery here. As always let's try to figure out the signature of f, I find this step extremely useful, and from our previous challenge another thing that's useful is to identify a struct in the code. If there's any of course. Let's do that, and as always let's analyze by chunks of code:

f:
    sub rsp, 8
    movzx   eax, BYTE PTR [rdi]
    cmp al, 89
    je  .L3
    jle .L21
    ;; ... more down in the code
.L3:
    mov eax, 1
    add rsp, 8
    ret
.L21:
    cmp al, 78
    je  .L6
Enter fullscreen mode Exit fullscreen mode

Here something to notice, is the comparison to numbers like 89. This number it's expressed in decimal. Also previous to that comparison we got the read of one byte from rdi which it's compared to 89. Mmm...no so hard to assume that in rdi we have our first parameter which it's a string. The code 89 represents letter Y in ASCII code, so you are comparing the first letter in the string to Y.

Depending on the result of the comparison, we jump to .L3 or .L21, the first case when we have a equal case and the second one when our letter it's less than Y. For checking the ASCII table you can use this link.

Now, what we have in .L3? This is interesting, we basically return the function with eax equal 1, and add 8 to the rsp register. Why this is needed? Easy, take into account that rsp is the Stack pointer register, at the start of the program we have the following instruction sub rsp,8 and at the end we have add rsp,8. With these two instruction, first we allocate space on the stack and later de allocate it(how to write deallocate? Is it correct?).

Why we need 8 bits on the stack? This can be a pointer to char in C. Let's continue, the rest of the program can give us more clues.

In .L21 we compare the character with N in ASCII code, in case it's equal to it we return 0 and deallocate the byte on stack that we allocated at the start of the program.

Let's put this into C code, this program seems fairly simple, just a couple of comparison to characters but still we need to see it by our own eyes. Given our previous discussion, we can infer that we receive a string on rdi and return an int. Fairly simple signature of f:

int f(char *str)
{
    char *result;

    if (*str == 'Y') {
        // mov  eax, 1
        // add  rsp, 8
        // ret
        return 1;
    }

    if (*str < 'Y') {
        if (*str == 'N') {
            return 0;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

As always I'll clean this code later. The rest of the code, it's also comparisons to characters. For example:

    cmp al, 110
    je  .L6
    cmp al, 121
    jne .L2
    ;; later down in the code...
    ;; ...
.L2:
    mov edi, OFFSET FLAT:.LC0
    call    puts
    xor edi, edi
    call    exit
.L6:
    xor eax, eax
    add rsp, 8
    ret
Enter fullscreen mode Exit fullscreen mode

Here we compare this first byte with letter n, in case it's equal we jump to .L6, returning 0. Later a comparison to y, in this case if it's not equal we print the string defined at the beginning, error!, and exit the program cleaning edi register where we stored our string.

I think we have everything to construct our code, let's do that.

int f(char *str)
{
    char *result;

    if (*str == 'Y')
    {
        return 1;
    }

    if ((*str < 'Y') && (*str == 'N'))
    {
        return 0;
    }

    if (*str == 'n')
    {
        return 0;
    }

    if (*str != 'y')
    {
        puts("error!");
        exit(0);
    }

    return 1;
}
Enter fullscreen mode Exit fullscreen mode

Kind of silly program to be honest 😂. One thing here to notice, is that the result variable that we saved in the stack was never used, at all.
This one doesn't deserve a formal description, too silly.

Conclusion

I think this is the less interesting of all, to be fair the author warn you that the problems are not enumerated according to difficulty.

Top comments (0)