ECSC2019 - Am I Computable?

description: Nous avons récupéré cet exécutable amicomputable qui n’a pas l’air de fonctionner avec le fichier fourni file.dat.

Pouvez-vous nous donner la sortie affichée ?

category: reverse - 461

ecsc_amicomputable.png

An ELF64 file and a data file are attached to the description.

If we try to launch the elf file, the program it processing something but we can’t see the end of it…

Let try to understand what it is doing (IDA pseudocode decompilation)…

[...]
# stream is the file.dat
while ( v5 < v8 )
{
	bzero(&s, 0x400uLL);
	v4 = fread(&s, 1uLL, 0x400uLL, stream);
	memcpy(&v11[v5], &s, v4);
	v5 += v4;
}
v9 = (unsigned __int64)v8 >> 1;
ptr = malloc(2LL * v9);
if ( !ptr )
	return 3LL;
for ( i = 0; i < v9; ++i )
	ptr[i] = ((unsigned __int8)v11[2 * i] << 8) + (unsigned __int8)v11[2 * i + 1];
sub_DB9((__int64)ptr, v9);
for ( j = 0; j < v9; ++j )
{
	v11[2 * j] = ptr[j] >> 8;
	v11[2 * j + 1] = ptr[j];
}
sub_CB0((__int64)v11, v8);
[...]

The program concatenate 2 consecutive octets and add it to ptr. let’s see what is the sub_DB9 function:

__int64 __fastcall sub_DB9(__int64 a1, unsigned int a2)
{
	__int64 result; // rax
	__int16 v3; // ST1C_2
	unsigned int i; // [rsp+10h] [rbp-Ch]
	unsigned int j; // [rsp+14h] [rbp-8h]

	result = a2;
	for ( i = a2; i; --i )
	{
		for ( j = 0; ; ++j )
		{
			result = i - 1;
			if ( j >= (unsigned int)result )
			  break;
			if ( *(_WORD *)(2LL * j + a1) > *(_WORD *)(2LL * (j + 1) + a1) )
			{
				v3 = *(_WORD *)(2LL * j + a1);
				*(_WORD *)(2LL * j + a1) = *(_WORD *)(2LL * (j + 1) + a1);
				*(_WORD *)(2LL * (j + 1) + a1) = v3;
			}
		}
	}
	return result;
}

When i was trying to recode the function in python I understood that this function is actually sorting the ptr table. In fact, the algorithm is taking a lot of time and that’s why we can’t see the end of the program…

Okay, back to the main function, the ptr table in given to sub_CB0:

unsigned __int64 __fastcall sub_CB0(__int64 a1, unsigned int a2)
{
  char v3; // [rsp+10h] [rbp-80h]
	char v4; // [rsp+70h] [rbp-20h]
	unsigned __int64 v5; // [rsp+88h] [rbp-8h]

	v5 = __readfsqword(0x28u);
	sub_E82(&v3);
	sub_ED1((__int64)&v3, a1, a2);
	sub_1018((__int64)&v4, (__int64)&v3);
	printf("ECSC{", &v3);
	sub_D66((__int64)&v4);
	puts("}");
	return __readfsqword(0x28u) ^ v5;
}

In sub_E82 we can notice some constants: ecsc_amicomputable_constants.png

Google it to determine that it is simply a md5 hashing algorithm.

To conclude, the program is concatenating consecutive octets, sorting this table and calculating the md5 of this file. I coded it in python:

import hashlib

f = open('file.dat', 'rb')
content = f.read()
f.close()

ptr = []

for i in range(len(content)/2):
	ptr.append( ( ord(content[i*2]) << 8) + ord(content[(i*2) + 1]) )

ptr.sort()

content = list(content)
for i in range(len(content)/2):
	content[2*i] = chr( (ptr[i] >> 8)&0xff )
	content[(2*i) + 1] = chr(ptr[i]&0xff)

content = ''.join(content)

print "ECSC{" + hashlib.md5(content).hexdigest() + "}"
# python script.py 
ECSC{5d12758be6f2a971153c5599339f77b0}

Great ! File is ECSC{5d12758be6f2a971153c5599339f77b0}