Modèles de script
Certains défis exigent que vous interagissiez avec eux de manière interactive, voire programmative. Comme les communications avec les défis sont sécurisées grâce à SSL/TLS (pour que personne n'interfère avec votre trafic), vous aurez besoin des bonnes incantations. Les petits modèles de scripts suivants devraient vous aider à le faire sans trop de tracas. N'hésitez pas à consulter la référence de ces outils au besoin (RTFM comme on dit dans le jargon).
En ligne de commande
ncat
(apt install ncat
) possède une option --ssl
. Cet outil peut être pratique pour expérimenter manuellement ce que le serveur raconte.
$ ncat --ssl jffi24-nathaniel.chals.hackin.ca 443
- Ne pas oublier le numéro de port, ce sera 443 sauf instruction contraire.
- Adaptez le nom du serveur en fonction du challenge.
Même si ncat
est interactif, c'est toutefois peu pratique de programmer avec.
socat
(apt install socat
) est plus sophistiqué et permet plus facilement la communication bidirectionnelle.
Pour l'équivalant interactif, on peut faire
$ socat SSL:jffi24-nathaniel.chals.hackin.ca:443 -
Si l'on veut "brancher" les entrées-sorties sur un programme, on peut faire
$ socat SSL:jffi24-nathaniel.chals.hackin.ca:443 EXEC:./mon_programme
Pour le programme, stdin
et stdout
sont correctement rédigés de et vers le serveur. stderr
reste affiché sur la console. Merci socat!
Pour des constructions plus sophistiquées, il est plus simple et plus débogable de programmer la communication SSL/TLS directement dans le langage. Des bibliothèques existent pour la plupart des langages.
Python3 (pwntools)
#!/usr/bin/env python3
#
# https://docs.pwntools.com/en/stable/index.html
#
# tl;dr, pour installer les outils:
#
# python3 -mvenv /tmp/venv-pwntools
# . /tmp/venv-pwntools/bin/activate
# pip install pwntools
# python mon-script.py
#
from pwn import *
io = remote('chals.hackin.ca', 443, ssl=True, sni='lechall.chals.hackin.ca')
#io.recvline() # lire 1 ligne
#io.recvuntil(b'hello') # lire jusqu'à la première occurence de b'world'
#io.sendline(b'world') # envoyer b'world\n'
#io.send(b'world') # envoyer b'world'
# plus encore... rtfm
# une connexion directe au socket
io.interactive()
Python3 (pure)
#!/usr/bin/env python3
#
# Une implémentation pure Python3 pour une connexion TCP sous TLS.
# On recommande fortement l'utilisation de la suite d'outils pwntools. :)
#
import contextlib
import socket
import ssl
@contextlib.contextmanager
def connexion(nom):
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
try:
with socket.create_connection(('chals.hackin.ca', 443)) as sk:
with ctx.wrap_socket(sk, server_hostname=nom) as ssk:
yield ssk
finally:
pass
# indiquer le nom de l'hôte pour le chall
with connexion('lechall.chals.hackin.ca') as io:
# on tente de lire au maximum 4096 octets (et au moins 1)
t = io.recv(4096)
print(t)
#io.send(b'Hello world!')
Ruby
#!/usr/bin/env ruby
#
# Une implémentation pure Ruby pour une connexion TCP sous TLS.
# On recommande fortement l'utilisation de la suite d'outils pwntools. :)
#
require 'openssl'
require 'socket'
def connexion(nom)
ctx = OpenSSL::SSL::SSLContext.new
sk = TCPSocket.new 'chals.hackin.ca', 443
ssk = OpenSSL::SSL::SSLSocket.new sk, ctx
ssk.hostname = nom
ssk.sync_close = true
ssk.connect
return ssk
end
io = connexion('lechall.chals.hackin.ca')
t = io.sysread 4096
puts t
#io.syswrite 'Hello world!'