← Back to list

Writeup Crackity | TFC CTF 2021 | Catégorie reverse

December 3, 2021

Unknown 2 | GrabCon CTF 2021

Fichier(s)

Nécessaires

Flag

TFCCTF{j4v4_0bfusc4t10n_1s_pr3tty_n0t_pr3tty}

Solution détaillée

La solution n’est pas très longue mais elle permet d’introduire le reverse de fichier .jar avec un exemple assez basique.

Nous avons donc un fichier java à reverse pour trouver le Flag. J’ai d’abord essayé d’exécuter le fichier mais il semble cassé, et je ne peux le lancer.

root@DESKTOP-HNQJECB: /c
➜   java crackity.jar
Error: Could not find or load main class crackity.jar
Caused by: java.lang.ClassNotFoundException: crackity.jar

Ouvrons donc avec jd-gui le fichier pour comprendre comment fonctionne le code :

Alt text

Aïe … C’est laid ; Le code est obfusqué. J’ai donc cherché ce qu’il y avait de lisible et j’ai d’abord trouver ceci :

public static final String f4x82c624da = ("Nr" + (Math.log(3.0d) / 4.0d));

public static String IlLLIILIlIILLIllIIILLIlLILlLILLLLLIILIIlLIIIILlIlLlllLIIlLLllLlIlLLIIIIIlIllLlILILLLIILlLILIIllllLIlIlLLllIIILIllIllIllIlIIIIILlLILLLIIIILIILlLlIIIlLILlILllIlllIlLlILllllLlILIlllIlIlLILIlILILIlLLLIIlIlLlLlLlIIIlLILILIILLILLLLILIlLlILILLLIIILILIlLILllLIllILLLLlILlllLlIIlIILlLlILLlIllILlILIIlLlLLlIILllIIILlIIIlLlLlllLlLIIIILlIIILlLIlILLlILLLLLlIILIlLlllIIllLIILIILlLLlLLLllLLlLLLIIlIlllllIlLIILlIlLLLIlIllLLllILlLIILLlILLlLLIIlllIILIIllIlIlILlLILLILILIIIILlLIIlllllLlILIIIIlIlllILlIILLllLlLIIlIIIlILI(String paramString) {
   char[] arrayOfChar = new char[paramString.length()];
   for (byte b = 0; b < paramString.length(); b++)
     arrayOfChar[b] = (char)(paramString.charAt(b) - IlLLI.charAt(b % IlLLI.length()));
   return new String(arrayOfChar);
 }

La fonction prend en paramètre une string. Allons donc chercher plus loin dans le code. Nous reviendrons sur ce code juste après.

Après quelques secondes :

On trouve ce type de string :

 public static final String IlLLIILIlIILLIllIIILLIlLILlLILLLLLIILIIlLIIIILlIlLlllLIIlLLllLlIlLLIIIIIlIllLlILILLLIILlLILIIllllLIlIlLLllIIILIllIllIllIlIIIIILlLILLLIIIILIILlLlIIIlLILlILllIlllIlLlILllllLlILIlllIlIlLILIlILILIlLLLIIlIlLlLlLlIIIlLILILIILLILLLLILIlLlILILLLIIILILIlLILllLIllILLLLlILlllLlIIlIILlLlILLlIllILlILIIlLlLLlIILllIIILlIIIlLlLlllLlLIIIILlIIILlLIlILLlILLLLLlIILIlLlllIIllLIILIILlLLlLLLllLLlLLLIIlIlllllIlLIILlIlLLLIlIllLLllILlLIILLlILLlLLIIlllIILIIllIlIlILlLILLILILIIIILlLIIlllllLlILIIIIlIlllILlIILLllLlLIIlIIIlILI = „«{`›zg£}k…nswši–y†…wƒ¼|‘€¡˜¢«¨¥‚“›¦¨jy–ט;

Le padding du nom obfusqué de la fonction faisait qu’on ne les voyait pas tous de suite.

Un nouveau petit souci ce pose. On ne peut pas les récupérer en les copiant collant. Surement qu’il y a une sorte de sanitizing lors de la copie dans jd-gui .

Je vais donc utiliser un autre outil pour récupérer les strings et les placer dans un fichier texte :

Jdax

Il présente les mêmes fonctionnalités que l’autre outils de décompilation.

Maintenant que nous le pouvons, récupérons les strings chiffrés :

allstring = [
'„«{`›zg£}k…nswši–y†…wƒ¼|‘€¡˜¢«¨¥‚“›¦¨jy–ט',
'¤Úšai›«m©…nŒ€id”ldŒ‘ì’”hŠªŸdz¢{a°¥¡—…¦˜Éz',
'„¿…ƒ§¤ˆ—š‚}™udˆ™››ŽmŽ™µd`Ž–wª~„±¨¥~ˆxƒi¡¥Àۅ',
'¢¸sq†}¯ i©d–b“œ¬£•k¨f~à_¥–¤¨h§¤°‘Ÿf«¢©g©Âë­',
'„Å—†ª°‰xiœ†e|œh•v†£›‚Ùt„¨|¤žŸ › œsf¢bcl‡ƒšÃ`',
'»Ý…š„„¬ª~—™¢t¤¡že®­†¯Ö{~eš¢l…c®e¤¤¨ry}lwȸs',
'š¶•u†‘…Žœˆgš¦˜j~‚„Šx„褗…¨œz–•gx«¦©y†ˆz­ž¼Èe',
'¹¥’¨|¨¨¤mš‡§b|j˜¬ƒ¬j£âd_›ig}j…y«œ¦¬dj¯w‡£Ê¡',
'“Üf–„¬§‹†i‡ghiƒŽ—ª˜¸gu—ˆzd~­Š|‹°„¥ˆ¡‡ßŸ',
'´ç‚•…¢xŠn§¨~~w«ªƒ¬ˆ«•Ùwy–¢jmš•r®€Š~Ša†Žvgµ¥£',
'…ârg‡£eh§€¤¯˜zhŠ†˜y‰h³Ä†a¦kd §•¤ŸŠdŠo}†¡w“È‚',
'¶¨~¤›px¢ƒ|¢g™ª±`di¬©»¿†’ƒ|‚f„w}h«¡¬`¤™ŒŸæy',
'¤Úšai›«m©…nŒ€id”ldŒ‘ì’”hŠªŸdz¢{a°¥¡—…¦˜Éz',
'»Ë¡~t~i‹§‰š…t†z…§ªƒ~ƒÜx šlhfg}uy…œŽ…––˜‹ž±Õ',
'’Åe¡¤™‚}{q†¦šm`cmf®¤¨€…j›¦†fƒa®‚ˆ‹}€¬œd–²ã¤',
'³Å†|“«¢œ¯©ƒŠ|y¤£ubŸŠn”Õg«£m‰¥fw©Œ¨°†¨¡ªh¹Àb',
'„«{e©Š•wf{˜sr¢šc›«‹¯à|œi¯h„Ž“wkpw€„ŠÀٜ',
'µÈf›”‰™†ŽfˆœsŸ¦¡edp™x›Øa‡“¯š}m{az‡¨nu®kx€Üˆ',
'¥³ae–o{‚ƒ€c™}…‰¢¦~kz©»Æha¦‰¢x€u”yzž‰Š§–€|nß',
'¥Ü˜~~z‰xk‰¤§¦|˜o€šžªe‘Ë¡› ‡Š¯¢i€‡dŒ™{ŠÁçš'
]

Enfin, nous allons utiliser python pour inverser le chiffrement.

La première chose importante que nous voyons tous de suite est qu’une string n’est pas obfusqué :

String f4x82c624da = ("Nr" + (Math.log(3.0d) / 4.0d));

Je l’ai exécuté en local et j’ai obtenu : "Nr0.27465307216702745"

Nous semblons avoir la clef maintenant . Analysons brièvement l’algorithme :

  • Création d’une string
char[] cArr = new char[str.length()];
  • Loop sur la longeur de la string d’entrée
for (int i = 0; i < str.length(); i++) { }
  • Ajout d’une lettre dans la string cArr
 cArr[i] = (char) (str.charAt(i) - f4x82c624da.charAt(i % f4x82c624da.length()));

Cette lettre en question est la résultante de la soustraction entre l’index de lettre de la string chiffré avec l’index de la lettre de la clé trouvée plus haut.

Grâce à ceci, on peut écrire ce petit script python :

bigstr = "Nr0.27465307216702745"

def rev(input_):
  final = ""
  for i in range(len(input_)):
    a = ord(input_[i])
    b = ord(bigstr[i%len(bigstr)])
    final += chr(a - b)
  return final

allstring = [
'„«{`›zg£}k…nswši–y†…wƒ¼|‘€¡˜¢«¨¥‚“›¦¨jy–ט',
'¤Úšai›«m©…nŒ€id”ldŒ‘ì’”hŠªŸdz¢{a°¥¡—…¦˜Éz',
'„¿…ƒ§¤ˆ—š‚}™udˆ™››ŽmŽ™µd`Ž–wª~„±¨¥~ˆxƒi¡¥Àۅ',
'¢¸sq†}¯ i©d–b“œ¬£•k¨f~à_¥–¤¨h§¤°‘Ÿf«¢©g©Âë­',
'„Å—†ª°‰xiœ†e|œh•v†£›‚Ùt„¨|¤žŸ › œsf¢bcl‡ƒšÃ`',
'»Ý…š„„¬ª~—™¢t¤¡že®­†¯Ö{~eš¢l…c®e¤¤¨ry}lwȸs',
'š¶•u†‘…Žœˆgš¦˜j~‚„Šx„褗…¨œz–•gx«¦©y†ˆz­ž¼Èe',
'¹¥’¨|¨¨¤mš‡§b|j˜¬ƒ¬j£âd_›ig}j…y«œ¦¬dj¯w‡£Ê¡',
'“Üf–„¬§‹†i‡ghiƒŽ—ª˜¸gu—ˆzd~­Š|‹°„¥ˆ¡‡ßŸ',
'´ç‚•…¢xŠn§¨~~w«ªƒ¬ˆ«•Ùwy–¢jmš•r®€Š~Ša†Žvgµ¥£',
'…ârg‡£eh§€¤¯˜zhŠ†˜y‰h³Ä†a¦kd §•¤ŸŠdŠo}†¡w“È‚',
'¶¨~¤›px¢ƒ|¢g™ª±`di¬©»¿†’ƒ|‚f„w}h«¡¬`¤™ŒŸæy',
'¤Úšai›«m©…nŒ€id”ldŒ‘ì’”hŠªŸdz¢{a°¥¡—…¦˜Éz',
'»Ë¡~t~i‹§‰š…t†z…§ªƒ~ƒÜx šlhfg}uy…œŽ…––˜‹ž±Õ',
'’Åe¡¤™‚}{q†¦šm`cmf®¤¨€…j›¦†fƒa®‚ˆ‹}€¬œd–²ã¤',
'³Å†|“«¢œ¯©ƒŠ|y¤£ubŸŠn”Õg«£m‰¥fw©Œ¨°†¨¡ªh¹Àb',
'„«{e©Š•wf{˜sr¢šc›«‹¯à|œi¯h„Ž“wkpw€„ŠÀٜ',
'µÈf›”‰™†ŽfˆœsŸ¦¡edp™x›Øa‡“¯š}m{az‡¨nu®kx€Üˆ',
'¥³ae–o{‚ƒ€c™}…‰¢¦~kz©»Æha¦‰¢x€u”yzž‰Š§–€|nß',
'¥Ü˜~~z‰xk‰¤§¦|˜o€šžªe‘Ë¡› ‡Š¯¢i€‡dŒ™{ŠÁçš'
]

for string in allstring:
  print(rev(string))

Celui-ci nous donne le flag une fois exécuté !!!

Alt text