FCSC 2020 - infiltrate (reverse)

Reverse - infiltrate

The following quote was given as mission

Des agents ont réussi à exfiltrer un fichier en utilisant la LED du disque dur durant une copie de disque. Ils nous ont fourni l’image de la capture

And the file started with the following picture.

Extracting the hidden file

Quickly looking at the pixel just by zooming on the picture I only saw black and white pixel. No gray ones, meaning that there was only two values (255, 255, 255 for white and (0, 0, 0) for black.

We can quickly check it out with the python lib PIL

from PIL import Image

set([ pix for pix in list(Image.open("./infiltrate.png", "r").getdata())])

This will output : {(0, 0, 0), (255, 255, 255)}, confirming they are only two possible values.

Knowing this we can assume that (0, 0, 0) is a binary 0 value and (255, 255, 255 if a 1. We can script something to retrieve the whole data.

from struct import pack
from PIL import Image

str_data = ""
bytes_data = b""

# fetching all 0 and 1
for pix in list(Image.open("./infiltrate.png", "r").getdata()):
    if pix == (0,0,0):
        str_data += "0"
    else:
        str_data += "1"

# splitting bits in bytes
for x in [str_data[i:i+8] for i in range(0, len(str_data), 8)]:
    bytes_data += pack("B", int(x, 2))

open("out", "wb").write(bytes_data)

We now have another file, we can check which kind of file this is.

λ ackira ~/nextcloud/CTF/FCSC2020/reverse/infiltrate » file out
out: data
λ ackira ~/nextcloud/CTF/FCSC2020/reverse/infiltrate » binwalk out

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
16            0x10            ELF, 64-bit LSB shared object, AMD x86-64, version 1 (SYSV)
1249          0x4E1           Ubiquiti firmware header, third party, ~CRC32: 0x0, version: "SSL_1.0.0"

An ELF file is inside the out file starting from the 16th bytes, we can extract it with dd

dd if=out of=elf bs=1 skip=16

And then check it dependencies

linux-vdso.so.1 (0x00007ffd87365000)
libcrypto.so.1.0.0 => /usr/lib/libcrypto.so.1.0.0 (0x00007f51c3c29000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f51c3a63000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f51c3a5e000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f51c40cf000)

libcrypto.so.1.0.0 please no :(

We can also check it symbols and start it to see how it behave


 λ ackira ~/nextcloud/CTF/FCSC2020/reverse/infiltrate » nm elf | grep T
000000000000089a T doit
0000000000000ae4 T _fini
0000000000200f88 d _GLOBAL_OFFSET_TABLE_
00000000000006e8 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000000ae0 T __libc_csu_fini
0000000000000a70 T __libc_csu_init
00000000000009f5 T main
0000000000000790 T _start
0000000000201010 D __TMC_END__
 
 λ ackira ~/nextcloud/CTF/FCSC2020/reverse/infiltrate » ./elf
Hello! Entrez la clé
help
Mauvaise clé !

It’s seems to have only two functions main as usual and doit. It want a key and we have to find it.

Let’s run ltrace to see which functions it uses from the libcrypto

λ ackira ~/nextcloud/CTF/FCSC2020/reverse/infiltrate » ltrace ./elf
puts("Hello! Entrez la cl\303\251 "Hello! Entrez la clé
)                                                = 23
fgets(hello
"hello\n", 7, 0x7f88471587e0)                                                 = 0x7ffe7e1fcc80
strlen("hello\n")                                                                   = 6
SHA1(0x7ffe7e1fcc80, 6, 0x7ffe7e1fcc50, 6)                                          = 0x7ffe7e1fcc50
puts("Mauvaise cl\303\251 !"Mauvaise clé !
)                                                       = 16
putchar(10, 0x55b30abb02a0, 0, 0x7f8847089567
)                                      = 10
+++ exited (status 0) +++

The SHA1 function is called, certainly with our input. Lets disassemble the doit function and check how the comparison is done.

Nothing is done in main after reading the disassembly of this function


000000000000089a <doit>:
 89a:   55                      push   rbp
 89b:   48 89 e5                mov    rbp,rsp
 89e:   48 83 ec 40             sub    rsp,0x40
 8a2:   48 89 7d c8             mov    QWORD PTR [rbp-0x38],rdi
 8a6:   64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
 8ad:   00 00
 8af:   48 89 45 f8             mov    QWORD PTR [rbp-0x8],rax
 8b3:   31 c0                   xor    eax,eax
 8b5:   48 8b 45 c8             mov    rax,QWORD PTR [rbp-0x38]
 8b9:   48 89 c7                mov    rdi,rax
 8bc:   e8 8f fe ff ff          call   750 <strlen@plt>
 8c1:   48 89 c1                mov    rcx,rax
 8c4:   48 8d 55 e0             lea    rdx,[rbp-0x20]
 8c8:   48 8b 45 c8             mov    rax,QWORD PTR [rbp-0x38]
 8cc:   48 89 ce                mov    rsi,rcx
 8cf:   48 89 c7                mov    rdi,rax
 8d2:   e8 89 fe ff ff          call   760 <SHA1@plt>
 8d7:   c7 45 dc 00 00 00 00    mov    DWORD PTR [rbp-0x24],0x0
 8de:   c7 45 d8 00 00 00 00    mov    DWORD PTR [rbp-0x28],0x0
 8e5:   e9 be 00 00 00          jmp    9a8 <doit+0x10e>
 8ea:   0f b6 45 e0             movzx  eax,BYTE PTR [rbp-0x20]
 8ee:   3c 58                   cmp    al,0x58
 8f0:   0f 85 aa 00 00 00       jne    9a0 <doit+0x106>
 8f6:   0f b6 45 e1             movzx  eax,BYTE PTR [rbp-0x1f]
 8fa:   3c 23                   cmp    al,0x23
 8fc:   0f 85 9e 00 00 00       jne    9a0 <doit+0x106>
 902:   0f b6 45 ea             movzx  eax,BYTE PTR [rbp-0x16]
 906:   3c a3                   cmp    al,0xa3
 908:   0f 85 92 00 00 00       jne    9a0 <doit+0x106>
 90e:   0f b6 45 e2             movzx  eax,BYTE PTR [rbp-0x1e]
 912:   3c db                   cmp    al,0xdb
 914:   0f 85 86 00 00 00       jne    9a0 <doit+0x106>
 91a:   0f b6 45 e3             movzx  eax,BYTE PTR [rbp-0x1d]
 91e:   3c 97                   cmp    al,0x97
 920:   75 7e                   jne    9a0 <doit+0x106>
 922:   0f b6 45 e6             movzx  eax,BYTE PTR [rbp-0x1a]
 926:   3c c4                   cmp    al,0xc4
 928:   75 76                   jne    9a0 <doit+0x106>
 92a:   0f b6 45 e4             movzx  eax,BYTE PTR [rbp-0x1c]
 92e:   3c 68                   cmp    al,0x68
 930:   75 6e                   jne    9a0 <doit+0x106>
 932:   0f b6 45 e5             movzx  eax,BYTE PTR [rbp-0x1b]
 936:   3c 01                   cmp    al,0x1
 938:   75 66                   jne    9a0 <doit+0x106>
 93a:   0f b6 45 f2             movzx  eax,BYTE PTR [rbp-0xe]
 93e:   3c 26                   cmp    al,0x26
 940:   75 5e                   jne    9a0 <doit+0x106>
 942:   0f b6 45 e7             movzx  eax,BYTE PTR [rbp-0x19]
 946:   3c a0                   cmp    al,0xa0
 948:   75 56                   jne    9a0 <doit+0x106>
 94a:   0f b6 45 e8             movzx  eax,BYTE PTR [rbp-0x18]
 94e:   3c e2                   cmp    al,0xe2
 950:   75 4e                   jne    9a0 <doit+0x106>
 952:   0f b6 45 e9             movzx  eax,BYTE PTR [rbp-0x17]
 956:   3c d7                   cmp    al,0xd7
 958:   75 46                   jne    9a0 <doit+0x106>
 95a:   0f b6 45 f3             movzx  eax,BYTE PTR [rbp-0xd]
 95e:   3c 12                   cmp    al,0x12
 960:   75 3e                   jne    9a0 <doit+0x106>
 962:   0f b6 45 eb             movzx  eax,BYTE PTR [rbp-0x15]
 966:   3c 30                   cmp    al,0x30
 968:   75 36                   jne    9a0 <doit+0x106>
 96a:   0f b6 45 ec             movzx  eax,BYTE PTR [rbp-0x14]
 96e:   3c b2                   cmp    al,0xb2
 970:   75 2e                   jne    9a0 <doit+0x106>
 972:   0f b6 45 ed             movzx  eax,BYTE PTR [rbp-0x13]
 976:   3c bb                   cmp    al,0xbb
 978:   75 26                   jne    9a0 <doit+0x106>
 97a:   0f b6 45 ef             movzx  eax,BYTE PTR [rbp-0x11]
 97e:   3c fe                   cmp    al,0xfe
 980:   75 1e                   jne    9a0 <doit+0x106>
 982:   0f b6 45 f0             movzx  eax,BYTE PTR [rbp-0x10]
 986:   3c 27                   cmp    al,0x27
 988:   75 16                   jne    9a0 <doit+0x106>
 98a:   0f b6 45 ee             movzx  eax,BYTE PTR [rbp-0x12]
 98e:   3c 82                   cmp    al,0x82
 990:   75 0e                   jne    9a0 <doit+0x106>
 992:   0f b6 45 f1             movzx  eax,BYTE PTR [rbp-0xf]
 996:   3c cc                   cmp    al,0xcc
 998:   75 06                   jne    9a0 <doit+0x106>
 99a:   83 45 dc 01             add    DWORD PTR [rbp-0x24],0x1
 99e:   eb 04                   jmp    9a4 <doit+0x10a>
 9a0:   83 6d dc 01             sub    DWORD PTR [rbp-0x24],0x1
 9a4:   83 45 d8 01             add    DWORD PTR [rbp-0x28],0x1
 9a8:   83 7d d8 13             cmp    DWORD PTR [rbp-0x28],0x13
 9ac:   0f 8e 38 ff ff ff       jle    8ea <doit+0x50>
 9b2:   83 7d dc 14             cmp    DWORD PTR [rbp-0x24],0x14
 9b6:   75 1a                   jne    9d2 <doit+0x138>
 9b8:   48 8b 45 c8             mov    rax,QWORD PTR [rbp-0x38]
 9bc:   48 89 c6                mov    rsi,rax
 9bf:   48 8d 3d 2e 01 00 00    lea    rdi,[rip+0x12e]        # af4 <_IO_stdin_used+0x4>
 9c6:   b8 00 00 00 00          mov    eax,0x0
 9cb:   e8 40 fd ff ff          call   710 <printf@plt>
 9d0:   eb 0c                   jmp    9de <doit+0x144>
 9d2:   48 8d 3d 38 01 00 00    lea    rdi,[rip+0x138]        # b11 <_IO_stdin_used+0x21>
 9d9:   e8 42 fd ff ff          call   720 <puts@plt>
 9de:   90                      nop
 9df:   48 8b 45 f8             mov    rax,QWORD PTR [rbp-0x8]
 9e3:   64 48 33 04 25 28 00    xor    rax,QWORD PTR fs:0x28
 9ea:   00 00
 9ec:   74 05                   je     9f3 <doit+0x159>
 9ee:   e8 7d fd ff ff          call   770 <__stack_chk_fail@plt>
 9f3:   c9                      leave
 9f4:   c3                      ret

So after some debugging we found that our string is sha1 hashed and the result is stored at [rbp-0x20]. Then this value is compared byte per byte to hardcoded value.

Let’s use vim to extract these value and put it in the right order (as in the original disassembly they are not checked in the order, yes I didn’t check it and found a wrong hash aha).

8ea:   0f b6 45 e0             movzx  eax,BYTE PTR [rbp-0x20]
8ee:   3c 58                   cmp    al,0x58
8f6:   0f b6 45 e1             movzx  eax,BYTE PTR [rbp-0x1f]
8fa:   3c 23                   cmp    al,0x23
90e:   0f b6 45 e2             movzx  eax,BYTE PTR [rbp-0x1e]
912:   3c db                   cmp    al,0xdb
91a:   0f b6 45 e3             movzx  eax,BYTE PTR [rbp-0x1d]
91e:   3c 97                   cmp    al,0x97
92a:   0f b6 45 e4             movzx  eax,BYTE PTR [rbp-0x1c]
92e:   3c 68                   cmp    al,0x68
932:   0f b6 45 e5             movzx  eax,BYTE PTR [rbp-0x1b]
936:   3c 01                   cmp    al,0x1
922:   0f b6 45 e6             movzx  eax,BYTE PTR [rbp-0x1a]
926:   3c c4                   cmp    al,0xc4
942:   0f b6 45 e7             movzx  eax,BYTE PTR [rbp-0x19]
946:   3c a0                   cmp    al,0xa0
94a:   0f b6 45 e8             movzx  eax,BYTE PTR [rbp-0x18]
94e:   3c e2                   cmp    al,0xe2
952:   0f b6 45 e9             movzx  eax,BYTE PTR [rbp-0x17]
956:   3c d7                   cmp    al,0xd7
902:   0f b6 45 ea             movzx  eax,BYTE PTR [rbp-0x16]
906:   3c a3                   cmp    al,0xa3
962:   0f b6 45 eb             movzx  eax,BYTE PTR [rbp-0x15]
966:   3c 30                   cmp    al,0x30
96a:   0f b6 45 ec             movzx  eax,BYTE PTR [rbp-0x14]
96e:   3c b2                   cmp    al,0xb2
972:   0f b6 45 ed             movzx  eax,BYTE PTR [rbp-0x13]
976:   3c bb                   cmp    al,0xbb
98a:   0f b6 45 ee             movzx  eax,BYTE PTR [rbp-0x12]
98e:   3c 82                   cmp    al,0x82
97a:   0f b6 45 ef             movzx  eax,BYTE PTR [rbp-0x11]
97e:   3c fe                   cmp    al,0xfe
982:   0f b6 45 f0             movzx  eax,BYTE PTR [rbp-0x10]
986:   3c 27                   cmp    al,0x27
992:   0f b6 45 f1             movzx  eax,BYTE PTR [rbp-0xf]
996:   3c cc                   cmp    al,0xcc
93a:   0f b6 45 f2             movzx  eax,BYTE PTR [rbp-0xe]
93e:   3c 26                   cmp    al,0x26
95a:   0f b6 45 f3             movzx  eax,BYTE PTR [rbp-0xd]
95e:   3c 12                   cmp    al,0x12

If we extract each byte we found the following hash : 5823db976801c4a0e2d7a330b2bb82fe27cc2612

We can check if it is present in known rainbow tables online with hash-buster ( but is also present in crackstation)

$ python ~/tools/crypto/Hash-Buster/hash.py -s 5823db976801c4a0e2d7a330b2bb82fe27cc2612
_  _ ____ ____ _  _    ___  _  _ ____ ___ ____ ____
|__| |__| [__  |__|    |__] |  | [__   |  |___ |__/
|  | |  | ___] |  |    |__] |__| ___]  |  |___ |  \  v3.0

[!] Hash function : SHA1
401445

The flag is : FCSC{401445}