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
The flag should be “readable” in hexspeak
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.
# 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.
0xc0ffeeb4be