Solution de erdnaxe pour Aaarg

intro reverse linux x86/x64

11 novembre 2023

Analyse préliminaire

On commence par analyser le type du fichier :

$ file aaarg
aaarg: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=f5b07c01242cc5987bed7730c2762ae0491b5ddc, stripped

aaarg est donc un fichier exécutable ELF x86-64, strippé donc sans symboles de débogage.

On tente d’afficher les chaînes de caractères du binaire :

$ strings aaarg
/lib64/ld-linux-x86-64.so.2
libc.so.6
[...] Rien d'intéressant

Le flag ne semble pas être en clair dans le programme, on passe donc à de l’analyse statique.

Analyse statique

On importe et analyse le binaire aaarg dans Ghidra. Dans la liste des fonctions reconnues de Ghidra, on trouve la fonction entry qui est le point d’entrée habituel pour un tel binaire. Dedans on trouve un appel à la fonction __libc_start_main qui prend en premier argument une fonction main. On renomme donc FUN_00401190 en main et on l’annote. On obtient :

long main(int argc,char **argv)

{
  long lVar1;
  ulong uVar2;
  char *local_10;

  lVar1 = 1;
  if (1 < argc) {
    uVar2 = strtoul(argv[1],&local_10,10);
    lVar1 = 1;
    if ((*local_10 == '\0') && (lVar1 = 2, uVar2 == (long)-argc)) {
      uVar2 = 0;
      do {
        putc((int)(char)(&DAT_00402010)[uVar2],stdout);
        uVar2 = uVar2 + 4;
      } while (uVar2 < 0x116);
      putc(10,stdout);
      lVar1 = 0;
    }
  }
  return lVar1;
}

Par la lecture de ce programme, on en déduit que pour arriver aux appels à putc, il faut que :

  • le programme prenne au moins 1 argument ;
  • cet argument est un entier en écriture décimale (strtoul(argv[1],&local_10,10)) ;
  • cet entier doit être égal à -argc.

Il ne faut pas oublier que argc compte également le nom du programme. On trouve alors le flag :

$ ./aaarg -2
FCSC{f9a38adace9dda3a9ae53e7aec180c5a73dbb7c364fe137fc6721d7997c54e8d}
$ ./aaarg -3 test
FCSC{f9a38adace9dda3a9ae53e7aec180c5a73dbb7c364fe137fc6721d7997c54e8d}
$ ./aaarg -4 test test
FCSC{f9a38adace9dda3a9ae53e7aec180c5a73dbb7c364fe137fc6721d7997c54e8d}

Il est également possible de retrouver le flag en allant inspecter DAT_00402010. On se rend compte que cette chaîne de caractères contient des zero-width joiner \xE2\x80\x8D, cela explique pourquoi strings ne trouve pas directement le flag.