 |

13.08.2023, 16:00
|
|
Новичок
Регистрация: 11.05.2023
Сообщений: 0
С нами:
1585741
Репутация:
0
|
|
Всем привет!
Сегодня рассмотрим задание "Абсолютная безопасность" из раздела криптографии на Antichat.
Итак, приступим!
Ищем вектор
Нам дается IP'шник, и три подсказки: - Возможно проверка на утечку флага является "узким местом"?
- Вы не любите кошек? Да вы просто не умеете их готовить!
- Я думаю стоит накапливать зашифрованные флаги.
Откроем IP. Видим, что он обнаружил контент, который не может обработать браузер.
Поэтому смотрим на вторую подсказку и запускаем netcat (для винды - ncat) и подключаемся:
Код:
ncat 62.173.140.174 11000
Для взаимодействия у нас есть две команды: "request" и "exit". Если с "exit" все ясно, то с "request" нет. Для этого смотрим вверх и видим кусок кода, который используется при отправке request'а.
Python:
Код:
async
def
gen_enc_flag
(
)
:
rand_bytes
=
urandom
(
23
)
enc
=
bytes
(
i
^
j
for
i
,
j
in
zip
(
flag
,
rand_bytes
)
)
for
i
in
range
(
23
)
:
assert
enc
[
i
]
!=
flag
[
i
]
,
"leak detected"
return
enc
.
hex
(
)
Я в коде не силен, поэтому просто загрузил код в ChatGPT
За его ответ судить не берусь, но общее понимание появилось.
Сначала функция генерирует 23 рандомных байта, далее она делает XOR байта первого символа флага с первым сгенерированным байтом, потом тоже самое со вторым и.т.д.
После XOR'ов всех символов флага программа проверяет на равенство каждый байт зашифрованного флага и изначального. Если таковой есть, то печатает "Leaked some plaintext".
Получается, что в каждом зашифрованном флаге на своем месте нет ни одного символа от изначального.
Т.е если флаг - Antichat{eto_ne_flag}, то первый байт (43 для "C") нам никогда не встретится. Тоже самое и для остальных символов.
Сбор флагов
Тут мы обращаемся к третьей подсказке "Я думаю, стоит накапливать зашифрованные флаги". Осталось определиться с количеством собираемых флагов. Слышал, что 5000 достаточно, но я определил для себя - 30000. Так сказать, наверняка .
Ясно дело, что вручную это ооочень долго, поэтому автоматизируем, используя pynput для ввода с клавиатуры.
Сам код:
Python:
Код:
import
time
import
pynput
from
pynput
.
keyboard
import
Key
,
Controller
keyboard
=
Controller
(
)
# Create the controller
i
=
0
time
.
sleep
(
10
)
while
i
<
30000
:
keyboard
.
type
(
'request'
)
time
.
sleep
(
0.1
)
keyboard
.
press
(
Key
.
enter
)
time
.
sleep
(
0.1
)
i
+=
1
Перед тем, как запускать, идем обратно в netcat, останавливаем и опять запускаем, но уже с записью в файл:
Код:
ncat 62.173.140.174 11000 -o dump.txt
Запускаем скрипт и переходим в окно netcat'а.
Ждем. Сборка 30000 шифрованных флагов у меня заняла ≈ 1.5-2 часа.
По окончании сбора флагов получаем файл. Теперь нам надо почистить файл от лишнего, оставив только флаги. Открываем VSCode и удаляем ненужное. Я не стал это автоматизировать, т.к делается это за две минуты простой заменой.
Наш дамп до:
После:
Находим флаг
Теперь создаем второй скрипт для нахождения флага:
Python:
Код:
start
=
0
end
=
2
two_bytes
=
[
]
text
=
''
hex_numbers
=
[
'00'
,
'01'
,
'02'
,
'03'
,
'04'
,
'05'
,
'06'
,
'07'
,
'08'
,
'09'
,
'0a'
,
'0b'
,
'0c'
,
'0d'
,
'0e'
,
'0f'
,
'10'
,
'11'
,
'12'
,
'13'
,
'14'
,
'15'
,
'16'
,
'17'
,
'18'
,
'19'
,
'1a'
,
'1b'
,
'1c'
,
'1d'
,
'1e'
,
'1f'
,
'20'
,
'21'
,
'22'
,
'23'
,
'24'
,
'25'
,
'26'
,
'27'
,
'28'
,
'29'
,
'2a'
,
'2b'
,
'2c'
,
'2d'
,
'2e'
,
'2f'
,
'30'
,
'31'
,
'32'
,
'33'
,
'34'
,
'35'
,
'36'
,
'37'
,
'38'
,
'39'
,
'3a'
,
'3b'
,
'3c'
,
'3d'
,
'3e'
,
'3f'
,
'40'
,
'41'
,
'42'
,
'43'
,
'44'
,
'45'
,
'46'
,
'47'
,
'48'
,
'49'
,
'4a'
,
'4b'
,
'4c'
,
'4d'
,
'4e'
,
'4f'
,
'50'
,
'51'
,
'52'
,
'53'
,
'54'
,
'55'
,
'56'
,
'57'
,
'58'
,
'59'
,
'5a'
,
'5b'
,
'5c'
,
'5d'
,
'5e'
,
'5f'
,
'60'
,
'61'
,
'62'
,
'63'
,
'64'
,
'65'
,
'66'
,
'67'
,
'68'
,
'69'
,
'6a'
,
'6b'
,
'6c'
,
'6d'
,
'6e'
,
'6f'
,
'70'
,
'71'
,
'72'
,
'73'
,
'74'
,
'75'
,
'76'
,
'77'
,
'78'
,
'79'
,
'7a'
,
'7b'
,
'7c'
,
'7d'
,
'7e'
,
'7f'
,
'80'
,
'81'
,
'82'
,
'83'
,
'84'
,
'85'
,
'86'
,
'87'
,
'88'
,
'89'
,
'8a'
,
'8b'
,
'8c'
,
'8d'
,
'8e'
,
'8f'
,
'90'
,
'91'
,
'92'
,
'93'
,
'94'
,
'95'
,
'96'
,
'97'
,
'98'
,
'99'
,
'9a'
,
'9b'
,
'9c'
,
'9d'
,
'9e'
,
'9f'
,
'a0'
,
'a1'
,
'a2'
,
'a3'
,
'a4'
,
'a5'
,
'a6'
,
'a7'
,
'a8'
,
'a9'
,
'aa'
,
'ab'
,
'ac'
,
'ad'
,
'ae'
,
'af'
,
'b0'
,
'b1'
,
'b2'
,
'b3'
,
'b4'
,
'b5'
,
'b6'
,
'b7'
,
'b8'
,
'b9'
,
'ba'
,
'bb'
,
'bc'
,
'bd'
,
'be'
,
'bf'
,
'c0'
,
'c1'
,
'c2'
,
'c3'
,
'c4'
,
'c5'
,
'c6'
,
'c7'
,
'c8'
,
'c9'
,
'ca'
,
'cb'
,
'cc'
,
'cd'
,
'ce'
,
'cf'
,
'd0'
,
'd1'
,
'd2'
,
'd3'
,
'd4'
,
'd5'
,
'd6'
,
'd7'
,
'd8'
,
'd9'
,
'da'
,
'db'
,
'dc'
,
'dd'
,
'de'
,
'df'
,
'e0'
,
'e1'
,
'e2'
,
'e3'
,
'e4'
,
'e5'
,
'e6'
,
'e7'
,
'e8'
,
'e9'
,
'ea'
,
'eb'
,
'ec'
,
'ed'
,
'ee'
,
'ef'
,
'f0'
,
'f1'
,
'f2'
,
'f3'
,
'f4'
,
'f5'
,
'f6'
,
'f7'
,
'f8'
,
'f9'
,
'fa'
,
'fb'
,
'fc'
,
'fd'
,
'fe'
,
'ff'
,
]
remove
=
"{}'"
for
i
in
range
(
23
)
:
with
open
(
'C:/Users/event/Desktop/dump.txt'
,
'r'
)
as
f
:
for
line
in
f
:
first_two
=
line
[
start
:
end
]
two_bytes
.
append
(
first_two
)
data
=
set
(
hex_numbers
)
-
set
(
two_bytes
)
clear_data
=
''
.
join
(
[
char
for
char
in
data
if
char
not
in
remove
]
)
bytes_object
=
bytes
.
fromhex
(
clear_data
)
text
=
""
.
join
(
[
text
,
bytes_object
.
decode
(
"utf-8"
)
]
)
start
+=
2
end
+=
2
two_bytes
=
[
]
print
(
text
)
Здесь мы объявляем массив всех hex-символов (hex_numbers).
Далее достаем все hex-значения символов из дампа и находим единственное неиспользованное. Его перегоняем в ASCII и добавляем в text.
Запускаем, получаем флаг, сдаем.
Спасибо за прочтение!
Есть критика или пожелание - пишите!)
|
|
|

13.08.2023, 22:17
|
|
Постоянный
Регистрация: 28.05.2022
Сообщений: 800
С нами:
2086530
Репутация:
0
|
|
[QUOTE]
Kevgen сказал(а):
Всем привет!
Сегодня рассмотрим задание "Абсолютная безопасность" из криптографии от Antichat.
Итак, приступим!
Ищем вектор
Нам дается IP'шник, и три подсказки: - Возможно проверка на утечку флага является "узким местом"?
- Вы не любите кошек? Да вы просто не умеете их готовить!
- Я думаю стоит накапливать зашифрованные флаги.
Откроем IP. Видим, что он обнаружил контент, который не может обработать браузер.
Поэтому смотрим на вторую подсказку и запускаем netcat (для винды - ncat) и подключаемся:
Код:
ncat 62.173.140.174 11000
Для взаимодействия у нас есть две команды: "request" и "exit". Если с "exit" все ясно, то с "request" нет. Для этого смотрим вверх и видим кусок кода, который используется при отправке request'а.
Python:
Код:
async
def
gen_enc_flag
(
)
:
rand_bytes
=
urandom
(
23
)
enc
=
bytes
(
i
^
j
for
i
,
j
in
zip
(
flag
,
rand_bytes
)
)
for
i
in
range
(
23
)
:
assert
enc
[
i
]
!=
flag
[
i
]
,
"leak detected"
return
enc
.
hex
(
)
Я в коде не силен, поэтому просто загрузил код в ChatGPT
За его ответ судить не берусь, но общее понимание появилось.
Сначала функция генерирует 23 рандомных байта, далее она делает XOR байта первого символа флага с первым сгенерированным байтом, потом тоже самое со вторым и.т.д.
После XOR'ов всех символов флага программа проверяет на равенство каждый байт зашифрованного флага и изначального. Если таковой есть, то печатает "Leaked some plaintext".
Получается, что в каждом зашифрованном флаге на своем месте нет ни одного символа от изначального.
Т.е если флаг - Antichat{eto_ne_flag}, то первый байт (43 для "C") нам никогда не встретится. Тоже самое и для остальных символов.
Сбор флагов
Тут мы обращаемся к третьей подсказке "Я думаю стоит накапливать зашифрованные флаги".
Осталось определиться с количеством собираемых флагов. Слышал, что 5000 достаточно, но я определил для себя - 30000. Так сказать, наверняка .
Ясно дело, что вручную это ооочень долго, поэтому автоматизируем, используя pynput для ввода с клавиатуры.
Сам код:
Python:
Код:
import
time
import
pynput
from
pynput
.
keyboard
import
Key
,
Controller
keyboard
=
Controller
(
)
# Create the controller
i
=
0
time
.
sleep
(
10
)
while
i
>
hashes.txt
;
sleep
0.1
;
done
2к флагов достаточно.
Решалка:
Python:
Код:
with
open
(
'hashes.txt'
,
'r'
)
as
file
:
hashes
=
file
.
readlines
(
)
list1
=
[
]
flag
=
[
]
symbols
=
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}!$@%^&*()"
for
i
in
range
(
len
(
hashes
)
)
:
hashes
[
i
]
=
bytes
.
fromhex
(
hashes
[
i
]
)
for
x
in
range
(
23
)
:
for
a
in
symbols
:
for
i
in
range
(
len
(
hashes
)
)
:
if
hashes
[
i
]
[
int
(
x
)
]
==
ord
(
a
)
:
if
a
in
list1
:
list1
.
remove
(
a
)
break
else
:
if
a
not
in
list1
:
list1
.
append
(
a
)
flag
+=
list1
print
(
''
.
join
(
flag
)
)
|
|
|

17.08.2023, 18:52
|
|
Новичок
Регистрация: 02.03.2017
Сообщений: 0
С нами:
4841507
Репутация:
0
|
|
обоим спасибо!
|
|
|

19.08.2023, 00:05
|
|
Новичок
Регистрация: 07.02.2023
Сообщений: 0
С нами:
1719376
Репутация:
0
|
|
Сорян, что вмешиваюсь. Спасибо за райтап, но вот сборы ответов мне не удалось собрать ни первым, ни вторым способом, потэтому я написал свой скрипт [S]с блэкджеком и...[/S] Пришлось совмещать алгоритмы, зато в одном месте все и сразу =)
Может быть кому-то пригодится.
Python:
Код:
from
pwn
import
*
io
=
remote
(
'62.173.140.174'
,
11000
)
hashes
=
[
]
io
.
recvuntil
(
b'$ '
)
print
(
"Getting hashes..."
)
count
=
5000
for
i
in
range
(
count
)
:
io
.
sendline
(
b'request'
)
io
.
recvuntil
(
b'$ '
)
if
io
.
recv
(
4
)
==
b'[-] '
:
continue
hashes
.
append
(
io
.
recv
(
46
)
.
decode
(
'ascii'
)
)
io
.
recvline
(
)
io
.
close
(
)
#print(f"Hashes we got: {hashes}")
print
(
"Decoding hashes..."
)
list1
=
[
]
flag
=
[
]
symbols
=
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}!$@%^&*()"
for
i
in
range
(
len
(
hashes
)
)
:
hashes
[
i
]
=
bytes
.
fromhex
(
hashes
[
i
]
)
for
x
in
range
(
23
)
:
for
a
in
symbols
:
for
i
in
range
(
len
(
hashes
)
)
:
if
hashes
[
i
]
[
int
(
x
)
]
==
ord
(
a
)
:
if
a
in
list1
:
list1
.
remove
(
a
)
break
else
:
if
a
not
in
list1
:
list1
.
append
(
a
)
flag
+=
list1
print
(
''
.
join
(
flag
)
)
|
|
|
|
 |
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|