Insomni’hack Teaser 2019 CTF – Babyrust Write-up [RE]

Buenos días. Nos encontramos ante un reto de reversing bastante sencillo e ideal para comenzar. El CTF terminó apenas una hora y participe con el equipo PKTeam. Para la resolución del reto use radare2 para debuggear el binario y Hopper para ver el pseudocódigo. Del mismo modo si ustedes quieren practicar este reto pueden pedírmelo por privado en Telegram @naivenom o descargarlo directamente de la página del CTF pero desconozco la disponibilidad que tendrá la web. https://teaser.insomnihack.ch/challenges/

Análisis de la función beginer_reverse

Antes de comenzar recomiendo que echéis un ojo a la función desensamblada al final de la entrada a la misma vez que se ven instrucción por instrucción. En la función main vemos como se le pasa la dirección de una función al registro rcx.

[0x5631bdca8b10]> pd
            ;-- main:
            0x5631bdca8b10      50             push rax
            0x5631bdca8b11      4889f0         mov rax, rsi
            0x5631bdca8b14      4863d7         movsxd rdx, edi
            0x5631bdca8b17      488d0d82fbff.  lea rcx, sym.beginer_reverse::main::h80fa15281f646bc1 ; 0x5631bdca86a0 ; "UAWAVAUATSH\x81\xec\x88"
            0x5631bdca8b1e      48890c24       mov qword [rsp], rcx

Como reversers nos interesa ver el punto de entrada de la iteración como usuarios de la aplicación. Para ello rápidamente dentro de la función localizamos la llamada que leerá de nuestro input los bytes introducidos.
0x55c41831d769 e802a10000 call sym.std::io::stdio::Stdin::read_line::h85c3421ca914511e ;[1]
En esta instrucción nos pide un input como usuario. Introducimos: AAAA

0x55c41831d76e 48837c245801 cmp qword [rsp + 0x58], 1
Seguidamente compara el valor del stack con 1. Vemos lo que contiene:

[0x55c41831d6c0]> px@rsp+0x58
- offset -       0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x7ffc4817bdd8  0000 0000 0000 0000 0500 0000 0000 0000  ................

Contiene 0x0.
Por lo tanto no saltará en la instrucción siguiente JE.

0x55c41831d77a 488b0424 mov rax, qword [rsp]
En esta instruccion se mueve el contenido del registro rsp. rsp contiene un puntero por tanto el valor del registro rax será el contenido del puntero. Es decir, rax ahora contiene 0x2.

0x55c41831d77e f04881280100. lock sub qword [rax], 1
Después de esta instruccion rax vale 0x1.

En nuestro caso de input saltará con la siguiente instrucción JNE.

0x55c41831d790 4c8b6c2408 mov r13, qword [rsp + 8]
Mueve el contenido del stack en el registro r13.

[0x55c41831d795]> px@r13
- offset -       0 1  2 3  4 5  6 7  8 9  A B  C D  0123456789ABCD
0x7f9ba7a20018  4141 4141 0a00 0000 0000 0000 0000  AAAA..........

0x55c41831d795 488b442418 mov rax, qword [rsp + 0x18]
Mueve a rax el valor del stack, en este caso 0x5 debido a que introducimos 5 bytes las A y el salto de linea.

0x55c41831d79a 4885c0 test rax, rax
Ahora hace la instrucción test, y como no es 0x0 no saltará en la siguiente instrucción JE. La hipótesis es que no tiene que saltar porque se presupone que tiene que existir un input por parte del usuario de la aplicación y siempre se cuenta con el salto de linea en este caso.

0x55ac9742679f 4a8d0c28 lea rcx, [rax + r13]
Ahora mueve una dirección de memoria al registro rcx. La resultante es la suma del contenido de rax=0x5 + la direccion de memoria que contiene el registro r13.

[0x55ac974267a3]> px@rax+r13
- offset -       0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x7fc66802001d  0000 0000 0000 0000 0000 0000 0000 0000  ................
0x7fc66802002d  0000 0000 0000 0000 0000 0000 0000 0000  ................
[0x55ac974267a3]> px@rcx
- offset -       0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x7fc66802001d  0000 0000 0000 0000 0000 0000 0000 0000  ................
0x7fc66802002d  0000 0000 0000 0000 0000 0000 0000 0000  ................

0x55ac974267a3 0fb651ff movzx edx, byte [rcx - 1]
Mueve a edx:0xa que corresponde al salto de linea.

0x55ac974267a7 41b801000000 mov r8d, 1
Mueve el valor 0x1 a r8.

0x55ac974267ad 84d2 test dl, dl
Como el valor del registro dl no es 0x0 no saltará en la siguiente instrucción JS. Sabiendo que coge el último valor si queremos que salte deberíamos de introducir el input con un script seteando el ultimo valor a NULL o 0x0.

0x55ac974267b1 4c29c0 sub rax, r8
Le resta 1 al registro rax quedando ahora como 0x4.

0x55ac974267b4 4889442418 mov qword [rsp + 0x18], rax
Lo mueve al stack

0x55ac974267b9 4a8d0c28 lea rcx, [rax + r13]
En rcx ahora tenemos.

[0x55ac974267a3]> px@rcx
- offset -       0 1  2 3  4 5  6 7  8 9  A 0123456789A
0x7fc66802001c  0a00 0000 0000 0000 0000 00 ...........

El valor del salto de linea, o el ultimo valor de lo introducido por input.

0x55ac9742683e      48c744242004.  mov qword [rsp + 0x20], 4                                                                                                                                            
0x55ac97426847      0f57c0         xorps xmm0, xmm0                                                                                                                                                     
0x55ac9742684a      0f11442428     movups xmmword [rsp + 0x28], xmm0                                                                                                                                    
0x55ac9742684f      4885c0         test rax, rax

Se mueve al stack el valor de 4.

[0x55ac97426822]> px@rsp+0x20
- offset -       0 1  2 3  4 5  6 7  8 9  A 0123456789A
0x7ffc62509b80  04
[0x55ac97426822]> px@rsp+0x28
- offset -       0 1  2 3  4 5  6 7  8 9  A 0123456789A
0x7ffc62509b88  0000 0000 0000 0000 0000 00 ...........
0x7ffc62509b93  0000 0000 0096 a618 69c6 7f ........i..

Por último hace un test rax,rax pero resulta que rax es 0x4 por lo tanto no saltará en la siguiente instrucción JE.

0x55ac97426858 4c29e9 sub rcx, r13
Deja el registro rcx como 0x4.

0x55ac9742685d      41be04000000   mov r14d, 4                                                                                                                                                          
0x55ac97426863      bf04000000     mov edi, 4                                                                                                                                                           
0x55ac97426868      31ed           xor ebp, ebp                                                                                                                                                         
0x55ac9742686a      48894c2438     mov qword [rsp + 0x38], rcx                                                                                                                                          
0x55ac9742686f      90             nop 

Mueve a esos registros el valor de 0x4 y por último mueve el 0x4 del registro rcx al stack.

0x55ac97426870      450fb6642d00   movzx r12d, byte [r13 + rbp]                                                                                                                                         
0x55ac97426876      4889f3         mov rbx, rsi                                                                                                                                                         
0x55ac97426879      4839f5         cmp rbp, rsi                                                                                                                                                         
0x55ac9742687c      757f           jne 0x55ac974268fd

Mueve al registro r12 el primer valor de nuestro input siendo 0x41. Seguidamente mueve el valor de rsi a rbx quedando como 0x0 y por último compara el valor de rbp=0x0 con rsi=0x0. En este caso no va a saltar en la siguiente instruccion JNE ya que es cero y son iguales.

0x55ac9742687e 4883c301 add rbx, 1
Le suma uno a rbx. ¿Posible contador?. En la siguiente instrucción JB no salta. Salta si está abajo o salta si no está arriba o si no es igual.

0x55ac97426888 488d0436 lea rax, [rsi + rsi]
Deja a rax como 0x0.

0x55ac9742688c 4839c3 cmp rbx, rax
Compara el valor de rbx=0x1 con rax=0x0.

0x55ac97426893      4889d8         mov rax, rbx                                                                                                                                                         
0x55ac97426896      ba04000000     mov edx, 4

El valor de rax es igual ahora a 0x1. Y el valor de rdx es 0x4.

0x55ac9742689b 48f7e2 mul rdx
Después de esta instrucción el valor de rax=0x4 y el valor de rdx=0x0. En la siguiente instrucción JO no salta. Salta si hay desbordamiento (overflow).

0x55b3e50c18a4 4989c7 mov r15, rax
0x55b3e50c18a7 4885f6 test rsi, rsi
0x55b3e50c18aa 7423 je 0x55b3e50c18cf

El valor de r15 ahora es 0x4. Seguidamente como rsi es igual a 0x0 va a tomar el salto JE.

0x55b3e50c18cf be04000000 mov esi, 4
0x55b3e50c18d4 4c89ff mov rdi, r15
0x55b3e50c18d7 e874050000 call sym.__rust_alloc
0x55b3e50c18dc 4989c6 mov r14, rax
0x55b3e50c18df 4885c0 test rax, rax
0x55b3e50c18e2 488b4c2438 mov rcx, qword [rsp + 0x38] ; [0x38:8]=-1 ; '8' ; 56

Mueve a esi el valor de 4 y se mueve a rdi el valor del registro r15.
Después de la llamada a la función los valores de retorno están en los registros rax y rdx.

[0x55b3e50c18cf]> px@rax
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x7efe78620020 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x7efe78620030 0000 0000 0000 0000 0000 0000 0000 0000 ................
[0x55b3e50c18cf]> px@rdx
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x7efe7860db88 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x7efe7860db98 0000 0000 0000 0000 0000 0000 0000 0000 ................

Seguidamente se mueve al registro r14 el valor de rax. Hace un test rax,rax y luego mueve al registro rcx el valor del stack siendo 0x4.
Como rax contiene una dirección de memoria y no el valor 0x0 no toma el salto JE.

0x55b3e50c18ed 4c89742420 mov qword [rsp + 0x20], r14
0x55b3e50c18f2 48895c2428 mov qword [rsp + 0x28], rbx

Mueve al stack los contenidos de ambos registros.

0x55b3e50c18fd 458924ae mov dword [r14 + rbp*4], r12d
0x55b3e50c1901 4883c501 add rbp, 1

Mueve el valor de r12 a r14. En este punto tenemos que rbp=0x0. Después de ejecutarse la instrucción.

[0x55b3e50c1901]> px@r14
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E 0123456789ABCDE
0x7efe78620020 4100 0000 0000 0000 0000 0000 0000 00 A..............

Seguidamente le suma uno a rbp quedando rbp como=0x1.

0x55b3e50c1905 48896c2430 mov qword [rsp + 0x30], rbp
0x55b3e50c190a 4839e9 cmp rcx, rbp

Mueve el valor al stack y luego compara el valor de rcx=0x4 con el valor rbp. Como no son iguales saltara en el JNE.

0x55b3e50c1870 450fb6642d00 movzx r12d, byte [r13 + rbp]
0x55b3e50c1876 4889f3 mov rbx, rsi
0x55b3e50c1879 4839f5 cmp rbp, rsi

Ahora mueve el siguiente byte 0x41 o segunda A ya que el registro rbp=0x1.

[0x55b3e50c1870]> px@0x7efe78620019
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E 0123456789ABCDE
0x7efe78620019 4141 410a 0000 0041 0000 0000 0000 00 AAA....A.......

Finalmente compara el valor de rbp=0x1 con rsi=0x1. Como es igual no tomara el salto JNE.

0x55b3e50c187e 4883c301 add rbx, 1
Le suma 1 a rbx. Y no toma el salto JB.

0x55b3e50c1888 488d0436 lea rax, [rsi + rsi]
0x55b3e50c188c 4839c3 cmp rbx, rax
0x55b3e50c188f 480f42d8 cmovb rbx, rax
0x55b3e50c1893 4889d8 mov rax, rbx
0x55b3e50c1896 ba04000000 mov edx, 4
0x55b3e50c189b 48f7e2 mul rdx

Mismas instrucciones que lo visto anteriormente. Ahora al terminar el valor de rax=0x8 y el valor de rdx=0x0. No toma el salto JO de overflow.

0x55b3e50c18a4 4989c7 mov r15, rax
Mueve a r15 el valor del registro rax=0x8. Ahora hace test rsi, rsi pero como rsi=0x1 en la instrucción JE no saltara.

0x55b3e50c18ac 48c1e602 shl rsi, 2
0x55b3e50c18b0 ba04000000 mov edx, 4
0x55b3e50c18b5 4c89f9 mov rcx, r15
0x55b3e50c18b8 e8b3050000 call sym.__rust_realloc

Después de la primera instrucción rsi vale ahora=0x4 y rcx vale ahora=0x8. El valor de retorno de la función cuando se llama son los siguientes:

[0x55b3e50c18bd]> 1px@rax
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E 0123456789ABCDE
0x7efe78620020 4100 0000 0000 0000 0000 0000 0000 00 A..............
[0x55b3e50c18bd]> 1px@rdx
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E 0123456789ABCDE
0x55b3e5125118 0d00 0000 0000 0000 0000 1c00 0000 00 ...............
[0x55b3e50c18bd]> 1px@rcx
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E 0123456789ABCDE
0x55b3e510f900 0800 0000 0000 0000 1000 0000 0000 00 ...............
0x55b3e510f90f 0020 0000 0000 0000 0030 0000 0000 00 . .......0.....

0x55b3e50c18fd 458924ae mov dword [r14 + rbp*4], r12d
Otra vez estamos en esta instrucción pero ya sabemos que ahora con rbp=0x1 la cosa cambia y después de ejecutar tenemos nuestro 0x41 en esa dirección de memoria.

[0x55b3e50c18ed]> px@r14 + rbp*4
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E 0123456789ABCDE
0x7efe78620024 4100 0000 0000 0000 0000 0000 0000 00 A..............

Simulando rbp como 0x0 anteriormente visto:

[0x55b3e50c18ed]> px@r14 + 0*4
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E 0123456789ABCDE
0x7efe78620020 4100 0000 4100 0000 0000 0000 0000 00 A...A..........

0x55b3e50c1901 4883c501 add rbp, 1
Le suma uno a rbp.

Ahora otra vez va a realizar lo mismo en el bucle por lo tanto, en la siguiente iteración simulamos de nuevo rbp como 0x0 y vemos nuestro tercer byte que introdujimos 0x41.

[0x55b3e50c18f7]> px@r14 + 0*4
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E 0123456789ABCDE
0x7efe7862e010 4100 0000 4100 0000 4100 0000 0000 00 A...A...A......

Y ultima iteración.

[0x55b3e50c18fd]> px@r14 + 0*4
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E 0123456789ABCDE
0x7efe7862e010 4100 0000 4100 0000 4100 0000 4100 00 A...A...A...A..

Seguimos debuggeando y nos localizamos en otra parte del código.

0x55b3e50c191f 488d04ad0000. lea rax, [rbp*4]
0x55b3e50c1927 31c9 xor ecx, ecx
0x55b3e50c1929 0f1f80000000. nop dword [rax]
0x55b3e50c1930 4839c8 cmp rax, rcx

Le pasa a rax=0x10, es decir, 0x4*0x4. En la comparación no es igual por lo tanto no tomara el salto JE.

0x55b3e50c1935 418b140e mov edx, dword [r14 + rcx]
0x55b3e50c1939 83c2e0 add edx, 0xffffffffffffffe0
0x55b3e50c193c 4883c104 add rcx, 4
0x55b3e50c1940 83fa5f cmp edx, 0x5f ; '_' ; 95
0x55b3e50c1943 72eb jb 0x55b3e50c1930

Se mueve a rdx el valor primero 0x41 y luego se le suma quedando como 0x21. Seguidamente se le suma a rcx el valor de 4 quedando como:0x4 y finalmente se compara con 0x5f el valor de rdx que era 0x21. En el siguiente salto JB saltará. Salta si está abajo o salta si no está arriba o si no es igual.

0x55b3e50c1930 4839c8 cmp rax, rcx
Tras unas iteraciones ahora es igual estos registros por lo tanto saltará en el JE.

0x557d73c8a962 4c8b7c2440 mov r15, qword [rsp + 0x40]
Ahora andamos en esta localización en el código y le pasa el valor del stack a r15.

[0x557d73c8a930]> px@r15
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x7f5012229000 0e01 0000 1201 0000 6601 0000 c601 0000 ........f.......

0x557d73c8a967 4c8b442450 mov r8, qword [rsp + 0x50]
El valor de r8 ahora es 0x22.

0x557d73c8a96c 4c39c5 cmp rbp, r8
0x557d73c8a96f 490f47e8 cmova rbp, r8
0x557d73c8a973 4885ed test rbp, rbp

En la comparación compara rbp=0x4 con r8=0x22. Como rbp es distinto a 0x0 no saltará en el siguiente JE. En las siguientes intrucciones xorea algunos registros para dejarlos a cero.

0x557d73c8a980 4939d6 cmp r14, rdx
En esta instrucción compara r14 con rdx.

[0x557d73c8a973]> 1px@r14
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x7f501222e010 4100 0000 4100 0000 4100 0000 4100 0000 A...A...A...A...

rdx=0x0.
No realiza el salto lógicamente porque no es lo mismo en la siguiente instrucción JE.

0x557d73c8a985 418b3cb7 mov edi, dword [r15 + rsi*4]
0x557d73c8a989 c1ff02 sar edi, 2
0x557d73c8a98c 83f70a xor edi, 0xa
0x557d73c8a98f 31c0 xor eax, eax
0x557d73c8a991 413b3cb6 cmp edi, dword [r14 + rsi*4]
0x557d73c8a995 488d7601 lea rsi, [rsi + 1] ; 1
0x557d73c8a999 0f94c0 sete al
0x557d73c8a99c 4801c1 add rcx, rax ; '#'
0x557d73c8a99f 4883c2fc add rdx, 0xfffffffffffffffc
0x557d73c8a9a3 4839ee cmp rsi, rbp
0x557d73c8a9a6 72d8 jb 0x557d73c8a980

1. En la primera instrucción se le pasa al registro edi=0x10e.
2. Luego se convierte con la instrucción sar el registro edi=0x43.
3. Se xorea con 0xa el registro edi, quedando como=0x49.
4. En la comparacion se compara el valor existente en r14+rsi*4 y el registro edi. Vemos en cada uno de ellos.
En edi=0x49.

[0x557d73c8a97c]> px@r14
- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E 0123456789ABCDE
0x7f501222e010 4100 0000 4100 0000 4100 0000 4100 00 A...A...A...A..

Compara 0x49 con 0x41. 0x49 en ascii es una «I» que puede corresponder al formato de la flag «INS{}». Por tanto ya encontramos la parte del código que nos interesa para resolver el reto.
Flag:
INS{y0ur_a_r3a1_h4rdc0r3_r3v3rs3r}

Función beginer_reverse desensamblada

[0x5631bdca86a0]> pd 300
            ;-- beginer_reverse::main::h80fa15281f646bc1:
            0x5631bdca86a0      55             push rbp
            0x5631bdca86a1      4157           push r15
            0x5631bdca86a3      4156           push r14
            0x5631bdca86a5      4155           push r13
            0x5631bdca86a7      4154           push r12
            0x5631bdca86a9      53             push rbx
            0x5631bdca86aa      4881ec880000.  sub rsp, 0x88
            0x5631bdca86b1      bf88000000     mov edi, 0x88           ; 136
            0x5631bdca86b6      be04000000     mov esi, 4
            0x5631bdca86bb      e890070000     call sym.__rust_alloc
            0x5631bdca86c0      4885c0         test rax, rax
        ,=< 0x5631bdca86c3      0f84d5030000   je 0x5631bdca8a9e
        |   0x5631bdca86c9      0f280530a904.  movaps xmm0, xmmword map.home_naivenom_ctf_beginner_reverse.r ; [0x5631bdcf3000:16]=-1
        |   0x5631bdca86d0      0f1100         movups xmmword [rax], xmm0
        |   0x5631bdca86d3      0f280536a904.  movaps xmm0, xmmword [0x5631bdcf3010] ; [0x5631bdcf3010:16]=-1
        |   0x5631bdca86da      0f114010       movups xmmword [rax + 0x10], xmm0
        |   0x5631bdca86de      0f28053ba904.  movaps xmm0, xmmword [0x5631bdcf3020] ; [0x5631bdcf3020:16]=-1
        |   0x5631bdca86e5      0f114020       movups xmmword [rax + 0x20], xmm0
        |   0x5631bdca86e9      0f280540a904.  movaps xmm0, xmmword [0x5631bdcf3030] ; [0x5631bdcf3030:16]=-1
        |   0x5631bdca86f0      0f114030       movups xmmword [rax + 0x30], xmm0
        |   0x5631bdca86f4      0f280545a904.  movaps xmm0, xmmword [0x5631bdcf3040] ; [0x5631bdcf3040:16]=-1
        |   0x5631bdca86fb      0f114040       movups xmmword [rax + 0x40], xmm0
        |   0x5631bdca86ff      0f28054aa904.  movaps xmm0, xmmword [0x5631bdcf3050] ; [0x5631bdcf3050:16]=-1
        |   0x5631bdca8706      0f114050       movups xmmword [rax + 0x50], xmm0
        |   0x5631bdca870a      0f28054fa904.  movaps xmm0, xmmword [0x5631bdcf3060] ; [0x5631bdcf3060:16]=-1
        |   0x5631bdca8711      0f114060       movups xmmword [rax + 0x60], xmm0
        |   0x5631bdca8715      0f280554a904.  movaps xmm0, xmmword [0x5631bdcf3070] ; [0x5631bdcf3070:16]=-1
        |   0x5631bdca871c      0f114070       movups xmmword [rax + 0x70], xmm0
        |   0x5631bdca8720      48b9e2010000.  movabs rcx, 0x1de000001e2 ; 2052994367970
        |   0x5631bdca872a      488988800000.  mov qword [rax + 0x80], rcx
        |   0x5631bdca8731      4889442440     mov qword [rsp + 0x40], rax
        |   0x5631bdca8736      0f280543a904.  movaps xmm0, xmmword [0x5631bdcf3080] ; [0x5631bdcf3080:16]=-1
        |   0x5631bdca873d      0f11442448     movups xmmword [rsp + 0x48], xmm0
        |   0x5631bdca8742      48c744240801.  mov qword [rsp + 8], 1
        |   0x5631bdca874b      0f57c0         xorps xmm0, xmm0
        |   0x5631bdca874e      0f11442410     movups xmmword [rsp + 0x10], xmm0
        |   0x5631bdca8753      e8d89f0000     call sym.std::io::stdio::stdin::hcd3fd1740d5196a7
        |   0x5631bdca8758      48890424       mov qword [rsp], rax
        |   0x5631bdca875c      488d7c2458     lea rdi, [rsp + 0x58]   ; 'X' ; 88
        |   0x5631bdca8761      4889e6         mov rsi, rsp
        |   0x5631bdca8764      488d542408     lea rdx, [rsp + 8]      ; 8
        |   0x5631bdca8769      e802a10000     call sym.std::io::stdio::Stdin::read_line::h85c3421ca914511e
        |   0x5631bdca876e      48837c245801   cmp qword [rsp + 0x58], 1 ; [0x58:8]=-1 ; 'X' ; 1
       ,==< 0x5631bdca8774      0f8435030000   je 0x5631bdca8aaf
       ||   0x5631bdca877a      488b0424       mov rax, qword [rsp]
       ||   0x5631bdca877e      f04881280100.  lock sub qword [rax], 1
      ,===< 0x5631bdca8786      7508           jne 0x5631bdca8790
      |||   0x5631bdca8788      4889e7         mov rdi, rsp
      |||   0x5631bdca878b      e830060000     call sym._alloc::sync::Arc_T__::drop_slow::h82dbb96617da66a0
      `---> 0x5631bdca8790      4c8b6c2408     mov r13, qword [rsp + 8] ; [0x8:8]=-1 ; 8
       ||   0x5631bdca8795      488b442418     mov rax, qword [rsp + 0x18] ; [0x18:8]=-1 ; 24
       ||   0x5631bdca879a      4885c0         test rax, rax
      ,===< 0x5631bdca879d      7420           je 0x5631bdca87bf
      |||   0x5631bdca879f      4a8d0c28       lea rcx, [rax + r13]
      |||   0x5631bdca87a3      0fb651ff       movzx edx, byte [rcx - 1]
      |||   0x5631bdca87a7      41b801000000   mov r8d, 1
      |||   0x5631bdca87ad      84d2           test dl, dl
      |||   0x5631bdca87af      7815           js 0x5631bdca87c6
      |||   0x5631bdca87b1      4c29c0         sub rax, r8
      |||   0x5631bdca87b4      4889442418     mov qword [rsp + 0x18], rax
      |||   0x5631bdca87b9      4a8d0c28       lea rcx, [rax + r13]
      |||   0x5631bdca87bd      eb7f           jmp 0x5631bdca883e
      `---> 0x5631bdca87bf      31c0           xor eax, eax
       ||   0x5631bdca87c1      4c89e9         mov rcx, r13
       ||   0x5631bdca87c4      eb78           jmp 0x5631bdca883e
       ||   0x5631bdca87c6      488d71ff       lea rsi, [rcx - 1]
       ||   0x5631bdca87ca      4939f5         cmp r13, rsi
       ||   0x5631bdca87cd      743a           je 0x5631bdca8809
       ||   0x5631bdca87cf      0fb671fe       movzx esi, byte [rcx - 2]
       ||   0x5631bdca87d3      89f3           mov ebx, esi
       ||   0x5631bdca87d5      80e3c0         and bl, 0xc0
       ||   0x5631bdca87d8      80fb80         cmp bl, 0x80            ; 128
       ||   0x5631bdca87db      7530           jne 0x5631bdca880d
       ||   0x5631bdca87dd      488d79fe       lea rdi, [rcx - 2]
       ||   0x5631bdca87e1      4939fd         cmp r13, rdi
       ||   0x5631bdca87e4      742c           je 0x5631bdca8812
       ||   0x5631bdca87e6      0fb679fd       movzx edi, byte [rcx - 3]
       ||   0x5631bdca87ea      89fb           mov ebx, edi
       ||   0x5631bdca87ec      80e3c0         and bl, 0xc0
       ||   0x5631bdca87ef      80fb80         cmp bl, 0x80            ; 128
       ||   0x5631bdca87f2      7522           jne 0x5631bdca8816
       ||   0x5631bdca87f4      488d69fd       lea rbp, [rcx - 3]
       ||   0x5631bdca87f8      4939ed         cmp r13, rbp
       ||   0x5631bdca87fb      741e           je 0x5631bdca881b
       ||   0x5631bdca87fd      0fb669fc       movzx ebp, byte [rcx - 4]
       ||   0x5631bdca8801      83e507         and ebp, 7
       ||   0x5631bdca8804      c1e506         shl ebp, 6
       ||   0x5631bdca8807      eb14           jmp 0x5631bdca881d
       ||   0x5631bdca8809      31f6           xor esi, esi
       ||   0x5631bdca880b      eb1d           jmp 0x5631bdca882a
       ||   0x5631bdca880d      83e61f         and esi, 0x1f
       ||   0x5631bdca8810      eb18           jmp 0x5631bdca882a
       ||   0x5631bdca8812      31ff           xor edi, edi
       ||   0x5631bdca8814      eb0c           jmp 0x5631bdca8822
       ||   0x5631bdca8816      83e70f         and edi, 0xf
       ||   0x5631bdca8819      eb07           jmp 0x5631bdca8822
       ||   0x5631bdca881b      31ed           xor ebp, ebp
       ||   0x5631bdca881d      83e73f         and edi, 0x3f
       ||   0x5631bdca8820      09ef           or edi, ebp
       ||   0x5631bdca8822      c1e706         shl edi, 6
       ||   0x5631bdca8825      83e63f         and esi, 0x3f
       ||   0x5631bdca8828      09fe           or esi, edi
       ||   0x5631bdca882a      c1e606         shl esi, 6
       ||   0x5631bdca882d      83e23f         and edx, 0x3f
       ||   0x5631bdca8830      09f2           or edx, esi
       ||   0x5631bdca8832      81fa00001100   cmp edx, 0x110000
       ||   0x5631bdca8838      0f8517020000   jne 0x5631bdca8a55
       ||   0x5631bdca883e      48c744242004.  mov qword [rsp + 0x20], 4
       ||   0x5631bdca8847      0f57c0         xorps xmm0, xmm0
       ||   0x5631bdca884a      0f11442428     movups xmmword [rsp + 0x28], xmm0
       ||   0x5631bdca884f      4885c0         test rax, rax
       ||   0x5631bdca8852      0f84bd000000   je 0x5631bdca8915
       ||   0x5631bdca8858      4c29e9         sub rcx, r13
       ||   0x5631bdca885b      31f6           xor esi, esi
       ||   0x5631bdca885d      41be04000000   mov r14d, 4
       ||   0x5631bdca8863      bf04000000     mov edi, 4
       ||   0x5631bdca8868      31ed           xor ebp, ebp
       ||   0x5631bdca886a      48894c2438     mov qword [rsp + 0x38], rcx
       ||   0x5631bdca886f      90             nop
       ||   0x5631bdca8870      450fb6642d00   movzx r12d, byte [r13 + rbp]
       ||   0x5631bdca8876      4889f3         mov rbx, rsi
       ||   0x5631bdca8879      4839f5         cmp rbp, rsi
       ||   0x5631bdca887c      757f           jne 0x5631bdca88fd
       ||   0x5631bdca887e      4883c301       add rbx, 1
       ||   0x5631bdca8882      0f8200020000   jb 0x5631bdca8a88
       ||   0x5631bdca8888      488d0436       lea rax, [rsi + rsi]
       ||   0x5631bdca888c      4839c3         cmp rbx, rax
       ||   0x5631bdca888f      480f42d8       cmovb rbx, rax
       ||   0x5631bdca8893      4889d8         mov rax, rbx
       ||   0x5631bdca8896      ba04000000     mov edx, 4
       ||   0x5631bdca889b      48f7e2         mul rdx
       ||   0x5631bdca889e      0f80e4010000   jo 0x5631bdca8a88
       ||   0x5631bdca88a4      4989c7         mov r15, rax
       ||   0x5631bdca88a7      4885f6         test rsi, rsi
       ||   0x5631bdca88aa      7423           je 0x5631bdca88cf
       ||   0x5631bdca88ac      48c1e602       shl rsi, 2
       ||   0x5631bdca88b0      ba04000000     mov edx, 4
       ||   0x5631bdca88b5      4c89f9         mov rcx, r15
       ||   0x5631bdca88b8      e8b3050000     call sym.__rust_realloc
       ||   0x5631bdca88bd      4989c6         mov r14, rax
       ||   0x5631bdca88c0      4885c0         test rax, rax
       ||   0x5631bdca88c3      488b4c2438     mov rcx, qword [rsp + 0x38] ; [0x38:8]=-1 ; '8' ; 56
       ||   0x5631bdca88c8      7523           jne 0x5631bdca88ed
       ||   0x5631bdca88ca      e9c0010000     jmp 0x5631bdca8a8f
       ||   0x5631bdca88cf      be04000000     mov esi, 4
       ||   0x5631bdca88d4      4c89ff         mov rdi, r15
       ||   0x5631bdca88d7      e874050000     call sym.__rust_alloc
       ||   0x5631bdca88dc      4989c6         mov r14, rax
       ||   0x5631bdca88df      4885c0         test rax, rax
       ||   0x5631bdca88e2      488b4c2438     mov rcx, qword [rsp + 0x38] ; [0x38:8]=-1 ; '8' ; 56
       ||   0x5631bdca88e7      0f84a2010000   je 0x5631bdca8a8f
       ||   0x5631bdca88ed      4c89742420     mov qword [rsp + 0x20], r14
       ||   0x5631bdca88f2      48895c2428     mov qword [rsp + 0x28], rbx
       ||   0x5631bdca88f7      4c89f7         mov rdi, r14
       ||   0x5631bdca88fa      4889de         mov rsi, rbx
       ||   0x5631bdca88fd      458924ae       mov dword [r14 + rbp*4], r12d
       ||   0x5631bdca8901      4883c501       add rbp, 1
       ||   0x5631bdca8905      48896c2430     mov qword [rsp + 0x30], rbp
       ||   0x5631bdca890a      4839e9         cmp rcx, rbp
       ||   0x5631bdca890d      0f855dffffff   jne 0x5631bdca8870
       ||   0x5631bdca8913      eb0a           jmp 0x5631bdca891f
       ||   0x5631bdca8915      41be04000000   mov r14d, 4
       ||   0x5631bdca891b      31db           xor ebx, ebx
       ||   0x5631bdca891d      31ed           xor ebp, ebp
       ||   0x5631bdca891f      488d04ad0000.  lea rax, [rbp*4]
       ||   0x5631bdca8927      31c9           xor ecx, ecx
       ||   0x5631bdca8929      0f1f80000000.  nop dword [rax]
       ||   0x5631bdca8930      4839c8         cmp rax, rcx
       ||   0x5631bdca8933      742d           je 0x5631bdca8962
       ||   0x5631bdca8935      418b140e       mov edx, dword [r14 + rcx]
       ||   0x5631bdca8939      83c2e0         add edx, 0xffffffffffffffe0
       ||   0x5631bdca893c      4883c104       add rcx, 4
       ||   0x5631bdca8940      83fa5f         cmp edx, 0x5f           ; '_' ; 95
       ||   0x5631bdca8943      72eb           jb 0x5631bdca8930
       ||   0x5631bdca8945      488d3d44a704.  lea rdi, [0x5631bdcf3090] ; "an error occuredSubmit this and get you'r points!\n"
       ||   0x5631bdca894c      488d15bde505.  lea rdx, str.src_main.rsError_reading_input: ; 0x5631bdd06f10
       ||   0x5631bdca8953      be10000000     mov esi, 0x10           ; 16
       ||   0x5631bdca8958      e833020000     call sym.std::panicking::begin_panic::h770c088eb8f42530
       ||   0x5631bdca895d      e92b010000     jmp 0x5631bdca8a8d
       ||   0x5631bdca8962      4c8b7c2440     mov r15, qword [rsp + 0x40] ; [0x40:8]=-1 ; '@' ; 64
       ||   0x5631bdca8967      4c8b442450     mov r8, qword [rsp + 0x50] ; [0x50:8]=-1 ; 'P' ; 80
       ||   0x5631bdca896c      4c39c5         cmp rbp, r8
       ||   0x5631bdca896f      490f47e8       cmova rbp, r8
       ||   0x5631bdca8973      4885ed         test rbp, rbp
       ||   0x5631bdca8976      7437           je 0x5631bdca89af
       ||   0x5631bdca8978      31d2           xor edx, edx
       ||   0x5631bdca897a      31f6           xor esi, esi
       ||   0x5631bdca897c      31c9           xor ecx, ecx
       ||   0x5631bdca897e      6690           nop
       ||   0x5631bdca8980      4939d6         cmp r14, rdx
       ||   0x5631bdca8983      7423           je 0x5631bdca89a8
       ||   0x5631bdca8985      418b3cb7       mov edi, dword [r15 + rsi*4]
       ||   0x5631bdca8989      c1ff02         sar edi, 2
       ||   0x5631bdca898c      83f70a         xor edi, 0xa
       ||   0x5631bdca898f      31c0           xor eax, eax
       ||   0x5631bdca8991      413b3cb6       cmp edi, dword [r14 + rsi*4]
       ||   0x5631bdca8995      488d7601       lea rsi, [rsi + 1]      ; 1
       ||   0x5631bdca8999      0f94c0         sete al
       ||   0x5631bdca899c      4801c1         add rcx, rax            ; '#'
       ||   0x5631bdca899f      4883c2fc       add rdx, 0xfffffffffffffffc
       ||   0x5631bdca89a3      4839ee         cmp rsi, rbp
       ||   0x5631bdca89a6      72d8           jb 0x5631bdca8980
       ||   0x5631bdca89a8      4c39c1         cmp rcx, r8
       ||   0x5631bdca89ab      7409           je 0x5631bdca89b6
       ||   0x5631bdca89ad      eb47           jmp 0x5631bdca89f6
       ||   0x5631bdca89af      31c9           xor ecx, ecx
       ||   0x5631bdca89b1      4c39c1         cmp rcx, r8
       ||   0x5631bdca89b4      7540           jne 0x5631bdca89f6
       ||   0x5631bdca89b6      488d0543e505.  lea rax, [0x5631bdd06f00] ; section..data.rel.ro
       ||   0x5631bdca89bd      4889442458     mov qword [rsp + 0x58], rax
       ||   0x5631bdca89c2      48c744246001.  mov qword [rsp + 0x60], 1
       ||   0x5631bdca89cb      48c744246800.  mov qword [rsp + 0x68], 0
       ||   0x5631bdca89d4      488d05eda604.  lea rax, [0x5631bdcf30c8]
       ||   0x5631bdca89db      4889442478     mov qword [rsp + 0x78], rax
       ||   0x5631bdca89e0      48c784248000.  mov qword [rsp + 0x80], 0
       ||   0x5631bdca89ec      488d7c2458     lea rdi, [rsp + 0x58]   ; 'X' ; 88
       ||   0x5631bdca89f1      e88aa30000     call sym.std::io::stdio::_print::h77f73d11755d3bb8
       ||   0x5631bdca89f6      4885db         test rbx, rbx
       ||   0x5631bdca89f9      7414           je 0x5631bdca8a0f
       ||   0x5631bdca89fb      48c1e302       shl rbx, 2
       ||   0x5631bdca89ff      ba04000000     mov edx, 4
       ||   0x5631bdca8a04      4c89f7         mov rdi, r14
       ||   0x5631bdca8a07      4889de         mov rsi, rbx
       ||   0x5631bdca8a0a      e851040000     call sym.__rust_dealloc
       ||   0x5631bdca8a0f      488b742410     mov rsi, qword [rsp + 0x10] ; [0x10:8]=-1 ; 16
       ||   0x5631bdca8a14      4885f6         test rsi, rsi
       ||   0x5631bdca8a17      740f           je 0x5631bdca8a28
       ||   0x5631bdca8a19      488b7c2408     mov rdi, qword [rsp + 8] ; [0x8:8]=-1 ; 8
       ||   0x5631bdca8a1e      ba01000000     mov edx, 1
       ||   0x5631bdca8a23      e838040000     call sym.__rust_dealloc
       ||   0x5631bdca8a28      488b742448     mov rsi, qword [rsp + 0x48] ; [0x48:8]=-1 ; 'H' ; 72
       ||   0x5631bdca8a2d      4885f6         test rsi, rsi
       ||   0x5631bdca8a30      7411           je 0x5631bdca8a43
       ||   0x5631bdca8a32      48c1e602       shl rsi, 2
       ||   0x5631bdca8a36      ba04000000     mov edx, 4
       ||   0x5631bdca8a3b      4c89ff         mov rdi, r15
       ||   0x5631bdca8a3e      e81d040000     call sym.__rust_dealloc
       ||   0x5631bdca8a43      4881c4880000.  add rsp, 0x88
       ||   0x5631bdca8a4a      5b             pop rbx
       ||   0x5631bdca8a4b      415c           pop r12
       ||   0x5631bdca8a4d      415d           pop r13
       ||   0x5631bdca8a4f      415e           pop r14
       ||   0x5631bdca8a51      415f           pop r15
       ||   0x5631bdca8a53      5d             pop rbp
       ||   0x5631bdca8a54      c3             ret

Un saludo, @naivenom.