Доступ к комнате доступен только для аккаунтов с премиальной подпиской.
Комната предполагает написание ряда скриптов на python, но предпочтение отдано практике на Go.
[Easy] Base64
Дан файл с закодированными 50 раз данными в base64. Требуется восстановить исходный текст. Скрипт предлагается написать на bash.
#!/bin/bashdata=`cat Downloads/b64.txt`echo-ne"Complete: 0%\r"for i in{1..50}dodata=`echo$data|base64 --decode`echo-ne"Complete: $((i *2))%\r"doneecho-e"\nFlag: \033[1;33m$data\033[0m"
Поскольку процесс далеко не мгновенный, добавлено отображение прогресса в виде счётчика (9).
[Medium] Gotta Catch em All
Необходимо подключиться к определенному порту на сервере, выполнить полученную арифметическую операцию над числом и перейти к следующему порту.
Формат задания: операция, число, порт. Пример задания: add 900 3212, что означает необходимо прибавить к числу значение 900 и далее перейти к порту 3212. Повторять до тех пор, пока не будет получена команда STOP или встретится порт 9765. Каждый порт доступен только 4 секунды, после чего происходит переход к следующему. Чтобы начать с самого начала, необходимо дождаться активации порта 1337. По адресу http://<machines_ip>:3010 указан текущий активный порт.
packagemainimport("flag""fmt""github.com/charmbracelet/huh/spinner""github.com/charmbracelet/lipgloss""io""net/http""net/url""os""strconv""strings""time")// settings
vartargetUrl,proxystringvarinitialPortint// data
varportintvarresultfloat64=0const(startPort=1337endPort=9765)varstyleNone=lipgloss.Style{}funcinit(){flag.StringVar(&targetUrl,"url","","address of target server")flag.IntVar(&initialPort,"port",3010,"initial port")flag.StringVar(&proxy,"proxy","","address of proxy")flag.Parse()iftargetUrl==""{fmt.Println("No arguments defined")flag.PrintDefaults()os.Exit(0)}ifproxy!=""{// os.Setenv("HTTP_PROXY", "socks5://...:1080")
proxyUrl,_:=url.Parse(proxy)http.DefaultTransport=&http.Transport{Proxy:http.ProxyURL(proxyUrl)}}}funcmain(){_=spinner.New().Type(spinner.Points).Style(styleNone).Title(" Awaiting appropriate port...").TitleStyle(styleNone).Action(awaitStart).Run()ifport!=startPort{// Пользователь нажал ctrl+c, выход
os.Exit(0)}for{varres*http.Responseportwait:=func(){for{varerrerrorres,err=http.Get(targetUrl+":"+strconv.Itoa(port))iferr==nil{break}time.Sleep(2*time.Second)}}_=spinner.New().Type(spinner.Line).Style(styleNone).Title(fmt.Sprintf(" awaiting port %d...",port)).TitleStyle(styleNone).Action(portwait).Run()body,_:=io.ReadAll(res.Body)_=res.Body.Close()data:=string(body)varopstringvarvalfloat64_,_=fmt.Sscanf(data,"%s%f%d",&op,&val,&port)fmt.Println(">",op,val)switchop{case"multiply":result=val*resultcase"minus":result=result-valcase"add":result=result+valcase"divide":result=result/valcase"STOP":break}ifport==endPort{break}}fmt.Println("result:",result)}funcawaitStart(){rhost:=targetUrl+":"+strconv.Itoa(initialPort)for{client:=http.Client{Timeout:5*time.Second,}res,err:=client.Get(rhost)iferr!=nil{fmt.Println("Can't connect to",rhost)panic(err)}body,_:=io.ReadAll(res.Body)_=res.Body.Close()str:=string(body)i:=strings.Index(str,"onPort")+8iflen(str)<i{panic("Responce too short, no port data")}_,_=fmt.Sscanf(str[i:],"%d",&port)ifport==startPort{break}else{time.Sleep(time.Second*4)}}}
[Hard] Encrypted Server Chit Chat
Необходимо подключиться по UDP к порту 4000, после чего послать сообщение hello для получения последующих инструкций. Общий смысл в том, что необходимо расшифровать полученные данные. Данные зашифрованы с помощью AES-GCM, часть получаемые данных может быть подделана.
Стоит отметить, что передаваемый в данных вектор исполнения (инициализации, IV) так же нередко называется nonce, как в используемой в коде библиотеке. Смысл у данных терминов несколько разный, но принцип работы одинаков.
packagemainimport("bufio""crypto/aes""crypto/cipher"sha256"crypto/sha256""encoding/hex""errors""flag""fmt""net""os""strconv""strings")// settings
varrhoststringconstport=4000funcinit(){flag.StringVar(&rhost,"rhost","","address of target server")flag.Parse()ifrhost==""{fmt.Println("No arguments defined")flag.PrintDefaults()os.Exit(0)}}funcmain(){varconnnet.Connvarerrerrorifconn,err=net.Dial("udp",rhost+":"+strconv.Itoa(port));err!=nil{panic(err)}fmt.Println(" --- Conversation ---")fmt.Println("\033[34;2m> hello\u001B[0m")if_,err=fmt.Fprint(conn,"hello");err!=nil{panic(err)}constBufSize=512reader:=bufio.NewReader(conn)buf:=make([]byte,BufSize)varreadintifread,err=reader.Read(buf);err!=nil||read>BufSize{panic(err)}varstrstring=string(buf[:read])iffmt.Println("<",str);err!=nil{panic(err)}if!strings.Contains(str,"connected"){panic(errors.New("abnormal welcome message"))}fmt.Println("\u001B[34;2m> ready\u001B[0m")if_,err=fmt.Fprint(conn,"ready");err!=nil{panic(err)}if_,err=reader.Read(buf);err!=nil{panic(err)}str=string(buf)fmt.Println("<",str)data:=strings.Split(str,"")iflen(data)!=27{panic(errors.New("abnormal response"))}iflen(data[14])!=32{panic(errors.New("non SHA256 checksum"))}varkey,ivstringvarchecksum[32]bytekey=strings.Split(data[0],":")[1]iv=strings.Split(data[1],":")[1]copy(checksum[:],[]byte(data[14]))fmt.Println("\n --- Data ---")fmt.Printf("key: %s [%s]\niv: %s\nchecksum: %s\n\n",key,aesType(len(key)),iv,hex.EncodeToString(checksum[:]))fmt.Println(" --- Processing ---")for{if_,err=fmt.Fprint(conn,"final");err!=nil{panic(err)}ifread,err=reader.Read(buf);err!=nil{panic(err)}ciphertext:=string(buf[:read])//fmt.Print("ciphertext:\n", hex.Dump([]byte(ciphertext)))
if_,err=fmt.Fprint(conn,"final");err!=nil{panic(err)}ifread,err=reader.Read(buf);err!=nil{panic(err)}tag:=string(buf[:read])//fmt.Print("tag:\n", hex.Dump([]byte(tag)))
block,_:=aes.NewCipher([]byte(key))gcm,_:=cipher.NewGCM(block)ifgcm.NonceSize()!=len(iv){fmt.Print("error: iv have wrong length\n")continue}ct:=ciphertext+tagpt,err:=gcm.Open(nil,[]byte(iv),[]byte(ct),nil)iferr!=nil{fmt.Println("fail:",err)continue}ifchecksum==sha256.Sum256(pt){fmt.Printf("\033[32;1m%s\033[0m <-- flag!\n",string(pt))break}else{fmt.Printf("\033[31;1m%s\033[0m\n",string(pt))}}}funcaesType(lenint)string{switchlen{case16:{return"AES-128"}case24:{return"AES-192"}case32:{return"AES-256"}}return"unknown"}