Writeup: Sharky CTF 2020 - Simple

Information

  • category : reverse
  • points : 89

Description

A really simple crackme to get started ;) Your goal is to find the correct
input so that the program return 1. The correct input will be the flag.
Creator: Nofix

1 file: main.asm

Writeup

We have an asm file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
BITS 64

SECTION .rodata
some_array db 10,2,30,15,3,7,4,2,1,24,5,11,24,4,14,13,5,6,19,20,23,9,10,2,30,15,3,7,4,2,1,24
the_second_array db 0x57,0x40,0xa3,0x78,0x7d,0x67,0x55,0x40,0x1e,0xae,0x5b,0x11,0x5d,0x40,0xaa,0x17,0x58,0x4f,0x7e,0x4d,0x4e,0x42,0x5d,0x51,0x57,0x5f,0x5f,0x12,0x1d,0x5a,0x4f,0xbf
len_second_array equ $ - the_second_array

SECTION .text
GLOBAL main

main:
mov rdx, [rsp]
cmp rdx, 2
jne exit
mov rsi, [rsp+0x10]
mov rdx, rsi
mov rcx, 0
l1:
cmp byte [rdx], 0
je follow_the_label
inc rcx
inc rdx
jmp l1
follow_the_label:
mov al, byte [rsi+rcx-1]
mov rdi, some_array
mov rdi, [rdi+rcx-1]
add al, dil
xor rax, 42
mov r10, the_second_array
add r10, rcx
dec r10
cmp al, byte [r10]
jne exit
dec rcx
cmp rcx, 0
jne follow_the_label
win:
mov rdi, 1
mov rax, 60
syscall
exit:
mov rdi, 0
mov rax, 60
syscall

The code is so short that is easy to work directly on it.

Analyzing the code:
Two arrays are defined: some_array and the_second_array.

1
2
3
some_array db 10,2,30,15,3,7,4,2,1,24,5,11,24,4,14,13,5,6,19,20,23,9,10,2,30,15,3,7,4,2,1,24
the_second_array db 0x57,0x40,0xa3,0x78,0x7d,0x67,0x55,0x40,0x1e,0xae,0x5b,0x11,0x5d,0x40,0xaa,0x17,0x58,0x4f,0x7e,0x4d,0x4e,0x42,0x5d,0x51,0x57,0x5f,0x5f,0x12,0x1d,0x5a,0x4f,0xbf
len_second_array equ $ - the_second_array

Entering the main, a control about number of parameters is executed.
If it’s different from 2, it jump to exit.

1
2
3
4
main:
mov rdx, [rsp]
cmp rdx, 2
jne exit

In the label ‘l1’ it’s computed the length of the string passed as parameter.
At the end of this loop we have the length value stored in RCX.

1
2
3
4
5
6
l1:
cmp byte [rdx], 0
je follow_the_label
inc rcx
inc rdx
jmp l1

The important part of the program is the follow_the_label.
follow_the_label uses the parameter string (we would call it StrPar) and some_array.
The sum of StrPar[ECX-1] and some_array[ECX-1] is stored in AL and then it’s xored with 42.

1
2
3
4
5
6
follow_the_label:
mov al, byte [rsi+rcx-1]
mov rdi, some_array
mov rdi, [rdi+rcx-1]
add al, dil
xor rax, 42

The result of these operations is compared with the value of the_second_array[ECX-1].
If they are different the program will jump to exit, otherwise ECX is compared by 0.
If it match the program will jump to ‘win’ otherwise ECX is decremented and the loop in follow_the_label is repeated.

1
2
3
4
5
6
7
8
mov r10, the_second_array
add r10, rcx
dec r10
cmp al, byte [r10]
jne exit
dec rcx
cmp rcx, 0
jne follow_the_label

In the ‘win’ label the program returns 1.

1
2
3
4
win:
mov rdi, 1
mov rax, 60
syscall

The goal is to find the right string that passed as parameter to the program, ensure us
to continue the loop in follow_the_label until all the values of some_array are processed,
in order to jump at win.

This string will be the flag.

Summarising the operations made inside ‘follow_the_label’(knowing that StrPar would be the flag):

1
(flag[i] + some_array[i] ) ^ 42 == the_second_array[i]

By developing the equation:

1
2
Flag[i] + some_array[i] = the_second_array[i] ^ 42
Flag[i] = (the_second_array[i] ^ 42) - some_array[i]

So we just have to write a little exploit:

1
2
3
4
5
6
7
8
some_array = [10,2,30,15,3,7,4,2,1,24,5,11,24,4,14,13,5,6,19,20,23,9,10,2,30,15,3,7,4,2,1,24]
the_second_array = [0x57,0x40,0xa3,0x78,0x7d,0x67,0x55,0x40,0x1e,0xae,0x5b,0x11,0x5d,0x40,0xaa,0x17,0x58,0x4f,0x7e,0x4d,0x4e,0x42,0x5d,0x51,0x57,0x5f,0x5f,0x12,0x1d,0x5a,0x4f,0xbf]

flag = ''
for x,y in zip(the_second_array,some_array):
flag += chr((x ^ 42) - y)

print(flag)

We can check that the flag is correct by submitting it to the program as parameter:

1
2
3
4
5
6
7
8
$ nasm -f elf64 main.asm

$ ld -o main main.asm

$ ./main shkCTF{h3ll0_fr0m_ASM_my_fr13nd}

$ echo $?
1 # OUTPUT

Flag

shkCTF{h3ll0_fr0m_ASM_my_fr13nd}