Reverse Engineering

asmathic

petircysec

15 February 2020

Problem :lock:

No description, we’re just given this asm file (code below).

asmathic:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], 0x21ba79
        mov     DWORD PTR [rbp-8], 1
        jmp     .L2
.L5:
        mov     eax, DWORD PTR [rbp-8]
        and     eax, 1
        test    eax, eax
        jne     .L3
        mov     eax, DWORD PTR [rbp-8]
        add     eax, 2
        add     DWORD PTR [rbp-4], eax
        jmp     .L4
.L3:
        mov     eax, DWORD PTR [rbp-8]
        sub     eax, 1
        sub     DWORD PTR [rbp-4], eax
.L4:
        add     DWORD PTR [rbp-8], 1
.L2:
        cmp     DWORD PTR [rbp-8], 24
        jle     .L5
        mov     edx, DWORD PTR [rbp-4]
        mov     eax, edx
        add     eax, eax
        add     eax, edx
        mov     DWORD PTR [rbp-4], eax
        mov     DWORD PTR [rbp-12], 0
        mov     DWORD PTR [rbp-12], 0x11170
        sub     DWORD PTR [rbp-12], 0x4e20
        mov     edx, DWORD PTR [rbp-12]
        mov     eax, edx
        sal     eax, 2
        add     eax, edx
        add     eax, eax
        mov     DWORD PTR [rbp-12], eax
        mov     eax, DWORD PTR [rbp-4]
        imul    eax, DWORD PTR [rbp-12]
        mov     DWORD PTR [rbp-4], eax
        add     DWORD PTR [rbp-4], 26
        sar     DWORD PTR [rbp-4], 2
        xor     DWORD PTR [rbp-4], 133337
        mov     DWORD PTR [rbp-12], 0xf14b
        mov     edx, DWORD PTR [rbp-12]
        mov     eax, edx
        sal     eax, 2
        add     eax, edx
        mov     DWORD PTR [rbp-12], eax
        mov     eax, DWORD PTR [rbp-12]
        add     DWORD PTR [rbp-4], eax
        mov     eax, DWORD PTR [rbp-4]
        mov     edi, eax
        mov     eax, 0
        call    hex
        leave
        ret

Hint :bulb:

The flag should be “readable” in hexspeak

Solution :key:

Let’s try and “translate” this asm into a high level language, I’m going to use python.

First we look at the asmathic: section and see what it does, looks like it just assigns 2 vars, we’ll call the rbp-4 var as r4 in our script, and rbp-8 as r8

# mov     DWORD PTR [rbp-4], 0x21ba79
r4 = 2210425
# mov     DWORD PTR [rbp-8], 1
r8 = 1

Now we’re jumping to L2, it also looks like there isn’t any other reference to L2, so we’ll make L2 the main function of our script.

The first 2 lines in L2 could make us jump to L5, and in L5 we can either:

Let’s keep this in mind to make our if-else condition later.

# cmp     DWORD PTR [rbp-8], 24
# jle     .L5
while r8 <= 24:
    # to L5

In L5, the first 2 lines are quite understandable.

mov     eax, DWORD PTR [rbp-8]
and     eax, 1

We just do binary AND of r8 and 1, but then there’s this.

test    eax, eax
jne     .L3

Time to google, found this.

Now we know JE is actually JZ, and so JNE is JNZ, also our test will determine the zero flag (ZF), and we will follow JNE if ZF is not 0.

# mov     eax, DWORD PTR [rbp-8]
# and     eax, 1
# test    eax, eax
# jne     .L3
if r8 & 1 != 0:
    # to L3

So if ZF is 0, we won’t jump to L3, we’ll continue through L5 and jump to L4, since L4 is just 1 line, it’s easier if we just hardcode it instead of making a new function.

if r8 & 1 != 0:
    # to L3
else:
    # still in L5
    # mov     eax, DWORD PTR [rbp-8]
    # add     eax, 2
    # add     DWORD PTR [rbp-4], eax
    r4 = r4 + r8 + 2
    # jmp     .L4
    # now in L4
    # add     DWORD PTR [rbp-8], 1
    r8 = r8 + 1
    # to L2

Now let’s finish the L3 section, which will then continue down to L4.

if r8 & 1 != 0:
    # now in L3
    # mov     eax, DWORD PTR [rbp-8]
    # sub     eax, 1
    # sub     DWORD PTR [rbp-4], eax
    r4 = r4 - (r8 - 1)
    # now in L4
    # add     DWORD PTR [rbp-8], 1
    r8 = r8 + 1
else:
    ...

Now that the complicated part is done, we will translate the rest of L2 after the first 2 lines (the cmp and jle part). So the final script looks like this.

Download solve.py

# main
# mov     DWORD PTR [rbp-4], 0x21ba79
r4 = 2210425
# mov     DWORD PTR [rbp-8], 1
r8 = 1
# jmp     .L2

# now in L2
# cmp     DWORD PTR [rbp-8], 24
# jle     .L5
while r8 <= 24:
    # now in L5
    # mov     eax, DWORD PTR [rbp-8]
    # and     eax, 1
    # test    eax, eax
    # jne     .L3
    if r8 & 1 != 0:
        # now in L3
        # mov     eax, DWORD PTR [rbp-8]
        # sub     eax, 1
        # sub     DWORD PTR [rbp-4], eax
        r4 = r4 - (r8 - 1)
        # now in L4
        # add     DWORD PTR [rbp-8], 1
        r8 = r8 + 1
    else:
        # still in L5
        # mov     eax, DWORD PTR [rbp-8]
        # add     eax, 2
        # add     DWORD PTR [rbp-4], eax
        r4 = r4 + r8 + 2
        # jmp     .L4
        # now in L4
        # add     DWORD PTR [rbp-8], 1
        r8 = r8 + 1

# now back in L2
# mov     edx, DWORD PTR [rbp-4]
# mov     eax, edx
# add     eax, eax
# add     eax, edx
# mov     DWORD PTR [rbp-4], eax
r4 = r4 * 3

# mov     DWORD PTR [rbp-12], 0
# mov     DWORD PTR [rbp-12], 0x11170
# sub     DWORD PTR [rbp-12], 0x4e20
r12 = 70000 - 20000

# mov     edx, DWORD PTR [rbp-12]
# mov     eax, edx
eax = r12

# sal     eax, 2
eax = eax << 2

# add     eax, edx
eax = eax + r12

# add     eax, eax
eax = eax * 2

# mov     DWORD PTR [rbp-12], eax
r12 = eax

# mov     eax, DWORD PTR [rbp-4]
# imul    eax, DWORD PTR [rbp-12]
# mov     DWORD PTR [rbp-4], eax
r4 = r4 * r12

# add     DWORD PTR [rbp-4], 26
r4 = r4 + 26

# sar     DWORD PTR [rbp-4], 2
r4 = r4 >> 2

# xor     DWORD PTR [rbp-4], 133337
r4 = r4 ^ 133337

# mov     DWORD PTR [rbp-12], 0xf14b
r12 = 61771

# mov     edx, DWORD PTR [rbp-12]
# mov     eax, edx
eax = r12

# sal     eax, 2
eax = eax << 2

# add     eax, edx
eax = eax + r12

# mov     DWORD PTR [rbp-12], eax
# mov     eax, DWORD PTR [rbp-12]
r12 = eax

# add     DWORD PTR [rbp-4], eax
r4 = r4 + eax

# mov     eax, DWORD PTR [rbp-4]
eax = r4

print("eax is %d (%s)" % (eax, hex(eax)))
print("r4 is %d (%s)" % (r4, hex(r4)))
print("r8 is %d (%s)" % (r8, hex(r8)))
print("r12 is %d (%s)" % (r12, hex(r12)))

I didn’t translate the rest because it seemed irrelevant, and we got the flag in our eax and r4 vars as hex numbers by referring to the hint.

python solve.py 
eax is 828927554750 (0xc0ffeeb4be)
r4 is 828927554750 (0xc0ffeeb4be)
r8 is 25 (0x19)
r12 is 308855 (0x4b677)

I actually failed for a while because I put in if r8 & 1 == 0 instead of if r8 & 1 != 0, so yeah.

Flag :checkered_flag:

0xc0ffeeb4be

Takeaway :books: