diff --git a/tasks/jojo1/readme.md b/tasks/jojo1/readme.md new file mode 100644 index 0000000..6f977d4 --- /dev/null +++ b/tasks/jojo1/readme.md @@ -0,0 +1,104 @@ +Для начала, посмотрим что происходит на странице. Для этого, зайдем в исходный код. На странице выполняется скрипт, который сначала открывает WebSocket. Чтобы узнать что это, загуглим. Это соединение с сервером, которое обменивается текстовыми данными. Все что есть в скрипте помимо этого является оберткой над этим соединением, по типу добавления сообщения в страницу. Так что дальше исследовать страницу мало пользы, можно исследовать соединение. +Погуглив, можно узнать что общение по вебсокетам доступно в python3, что мы и будем использовать. Программа дальше отрывает соединение, отправляет 'init' и печатает все ответы от сервера. +``` +import websocket as ws +c=ws.create_connection('wss://jojo1.ctfmay.sch9.ru/ws/') +c.send('b') +while(1): + print(c.recv()) +``` +Вывод: +> photo 3 + +Следующий запрос соединение воспримет как попытку угадать фразу. Так как у ДжоДжо изначально 4 ХП, то можно узнать 4 идущие подряд фразы. Дальше, можно воспользоваться данным в условии словарем глаголов, для всех глаголов заменить их номерами и посмотреть на результат. Пример: +Фразы: +> Я хочу выйти чтобы рвать, а потом родиться и, будучи победителем, приказать оставить тебе, ДжоДжо, так сильно пытающийся велеть!!! +> Я хочу определять чтобы попадать, а потом грозить и, будучи победителем, приказать решиться тебе, ДжоДжо, так сильно пытающийся мыть!!! +> Я хочу утверждать чтобы хранить, а потом согласиться и, будучи победителем, приказать хотеться тебе, ДжоДжо, так сильно пытающийся смеяться!!! +> Я хочу обращаться чтобы совершить, а потом возражать и, будучи победителем, приказать меняться тебе, ДжоДжо, так сильно пытающийся сравнивать!!! +> Я хочу понравиться чтобы следовать, а потом нравиться и, будучи победителем, приказать сметь тебе, ДжоДжо, так сильно пытающийся миновать!!! +Номера в 0-нумерации: +41, 924, 260, 514, 210, 565 +100, 204, 727, 514, 637, 905 +159, 483, 195, 514, 65, 246 +218, 762, 662, 514, 492, 586 +277, 42, 130, 514, 919, 926 + +Можно заметить, что номер первого глагола изменяется на одинаковое число каждый раз, возвращаясь в 0 если увеличивается до 999, т.е. "ходит по кругу из чисел от 1 до 999" (), то же верно и для остальных номеров. Можно ещё несколько раз позапускать соединение чтобы убедиться что это всегда так и что номер (?????) глагола - всегда 514. Теперь, с помощью этого замечания попробуем угадать одну фразу. Кроме того, попробуем автоматически генерировать ответ, т.к. в дальнейшем это придется сделать 1000 раз. +``` +import websocket as ws #подключаем библиотеку +a=open('glags.txt','r').read().split('\n')[:-1] #Загружаем файл, записываем в массив + + +c=ws.create_connection('wss://jojo1.ctfmay.sch9.ru/ws/') #Начинаем соединение +c.send('init') #Посылаем 'init' в соединение +print('recieve:',c.recv()) #Выводим на экран ответ (photo 3) +c.send('b') #Посылаем что-то чтобы узнать первую фразу +s=c.recv() #Считываем фразу из соединения +print('recieve:',s) #Выводим её на экран +print('recieve:',c.recv()) #Считываем оставшиеся фразы +print('recieve:',c.recv()) # +print('recieve:',c.recv()) # +print('recieve:',c.recv()) # +words=[s[s.find('хочу')+5:s.find('чтобы')-1], #Вытаскиваем из фразы только 5 глаголов, которые изменяются... + s[s.find('чтобы')+6:s.find('а потом')-2], # ...и записываем их в массив + s[s.find('а потом')+8:s.find('и, будучи')-1], # + s[s.find('и, будучи')+33:s.find('тебе,')-1], # + s[s.find('пытающийся')+11:s.find('!!!')]] # +print('words in phrase:',words) #Выводим на экран массив слов +oidx=[a.index(words[i]) for i in range(5)] #Записываем индексы слов в массиве a (словаре) в массив +print('indexes in dictionary:',oidx) #И выводим этот массив +c.send('b') #Повторяем операцию для следующей фразы +s=c.recv() +print('recieve:',s) +print('recieve:',c.recv()) +print('recieve:',c.recv()) +print('recieve:',c.recv()) +print('recieve:',c.recv()) +words=[s[s.find('хочу')+5:s.find('чтобы')-1], + s[s.find('чтобы')+6:s.find('а потом')-2], + s[s.find('а потом')+8:s.find('и, будучи')-1], + s[s.find('и, будучи')+33:s.find('тебе,')-1], + s[s.find('пытающийся')+11:s.find('!!!')]] +print('words in phrase:',words) +idx=[a.index(words[i]) for i in range(5)] +print('indexes in dictionary:',idx) +d=[(idx[i]-oidx[i])%len(a) for i in range(5)] #Cчитаем изменение номера для каждого глагола +print('differences:',d) #Выводим его на экран +for i in range(5): #Угадываем глаголы третьей фразы + idx[i]+=d[i] #Пересчитываем массив idx + idx[i]%=len(a) + words[i]=a[idx[i]] #Выбираем нужные глаголы +c.send(f'Я хочу { words[0] } чтобы \ #Выводим угаданную фразу +{ words[1] }, а потом { words[2] } и, будучи \ # +победителем, приказать { words[3] } тебе, ДжоДжо\ # +, так сильно пытающийся { words[4] }!!!') # + +while(1): + print(c.recv()) #Выводим остаток ответов от сервера. +``` +Видим, что на этот раз вывод другой и ХП снялись уже не у ДжоДжо, поэтому продолжаем отгадывать фразы таким же образом. Начальный код остается таким же, но после выбора нужных глаголов код будет: +``` +for i in range(1000): #Повторяем столько раз, сколько ХП у противника + c.send(f'Я хочу { words[0] } чтобы \ #Отправляем сгенерированную фразу +{ words[1] }, а потом { words[2] } и, будучи \ +победителем, приказать { words[3] } тебе, ДжоДжо\ +, так сильно пытающийся { words[4] }!!!') + s=c.recv() #Выводим ответ от сервера + print('recieve:',s) + print('recieve:',c.recv()) + print('recieve:',c.recv()) + print('recieve:',c.recv()) + print('words in phrase:',words) + print('idxs:',idx) + for i in range(5): #Пересчитываем массивы + idx[i]+=d[i] + idx[i]%=len(a) + words[i]=a[idx[i]] +c.send('h') #Выводим что-то чтобы получить ответ от сервера +while(1): + print(c.recv()) #Выводим остаток ответов от сервера. + +``` +Таким образом, получаем флаг. +Флаг: `ctf{guess_reverse_jusddf}` \ No newline at end of file