
В данной статье рассмотрим решения 3-х заданий с сайта pwnable.kr.
- PWN;
- криптография (Crypto);
- cетевые технологии (Network);
- реверс (Reverse Engineering);
- стеганография (Stegano);
- поиск и эксплуатация WEB-уязвимостей.
Вдобавок к этому я поделюсь своим опытом в компьютерной криминалистике, анализе малвари и прошивок, атаках на беспроводные сети и локальные вычислительные сети, проведении пентестов и написании эксплоитов.
Чтобы вы могли узнавать о новых статьях, программном обеспечении и другой информации, я создал канал в Telegram и группу для обсуждения любых вопросов в области ИиКБ. Также ваши личные просьбы, вопросы, предложения и рекомендации рассмотрю лично и отвечу всем.
Вся информация представлена исключительно в образовательных целях. Автор этого документа не несёт никакой ответственности за любой ущерб, причиненный кому-либо в результате использования знаний и методов, полученных в результате изучения данного документа.
Решение задания coin1
Нажимаем на иконку с подписью coin1, и нам предоставляют адрес и порт для подключения.

После подключения нам предлагают сыграть в игру и предоставляют правила игры. А также нам дают на прохождение 60 секунд, поэтому придется все автоматизировать.

По правилам игры нам дают N монет, каждая весом 10, кроме одной — ее вес 9. Нам дают количество шансов(раундов) C для одной игры. На каждом раунде мы посылаем индексы монет, и нам вовращают и суммарный вес. Таким образом, применяя бинарный поиск, мы найдем нужную монету.
Напишем код. Для начала установим соединение с сервером, примем и распарсим числа N и C.
from pwn import * r = remote('pwnable.kr', 9007) r.recv() s = r.recv() print(s) n = int(s.split(' ')[0][2:]) c = int(s.split('=')[2].split('\n')[0]) print(n, c)

Отлично. Теперь напишем часть, для прохождения одного уровня. Для этого нам понадобится массив значений от 1 до N+1 и цикл из С шагов, на каждой итерации которого будет отправлять половину массива. Если возвращенный в ответе вес будет делиться на 10 без остатка, то наша монета в другой части массива. Таким образом, мы снова разделим другую половину и проделаем то же самое с ней, и т.д. пока не будет обнаружена та самая монета.
mas = range(1,n+1) for i in range(c): s = "" if len(mas)==1: mas.append(mas[0]) for j in mas[:len(mas)/2]: s += (str(j)+" ") print(s) r.send(s+"\n") nr = r.recv() print(nr) if int(nr) % 10: mas = mas[:len(mas)/2] else: mas = mas[len(mas)/2:] r.send(str(mas[0])+"\n") print(r.recv())

Теперь добавим это решение в цикл для прохождения всех уровней.
from pwn import * r = remote('pwnable.kr', 9007) r.recv() for level in range(1, 101): s = r.recvline() n = int(s.split(' ')[0][2:]) c = int(s.split('=')[2].split('\n')[0]) mas = range(1,n+1) for i in range(c): s = "" if len(mas)==1: mas.append(mas[0]) for j in mas[:len(mas)/2]: s += (str(j)+" ") r.send(s+"\n") nr = r.recv() if int(nr) % 10: mas = mas[:len(mas)/2] else: mas = mas[len(mas)/2:] r.send(str(mas[0])+"\n") r.recvline() if level%5==0: print("Check "+str(level)+"/100") print(r.recv())

Сдаем флаг и получаем очки.
Решение задания blackjack
Нажимаем на первую иконку с подписью coin1, и нам предоставляют адрес и порт для подключения. Еще сообщают, что нужно выиграть миллион.

После подключения нам предлагают сыграть в игру и спрашивают о готовности.

После нашего ответа, выходим в меню, начать игру, узнать правила или выйти из игры.

Начинаем новую игру.

Такие задания часто встречаются в CTF и о них полезно знать. Скорее всего отсутствует обработчик отрицательных чисел. Таким образом если ввести -999500 и проиграть, то из нашего банка вычтут отрицаельное число, то есть прибавлено положительное (500 — (-500) = 500 + 500 = 1000). Введем -1000000.


Сдаем флаг и получаем еще одно очко.
Решение задания lotto
Нажимаем на первую иконку с подписью lotto, и нам говорят, что нужно подключиться по SSH с паролем guest.

При подключении мы видим соответствующий баннер.

Давайте узнаем, какие файлы есть на сервере, а также какие мы имеем права.

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> unsigned char submit[6]; void play(){ int i; printf("Submit your 6 lotto bytes : "); fflush(stdout); int r; r = read(0, submit, 6); printf("Lotto Start!\n"); //sleep(1); // generate lotto numbers int fd = open("/dev/urandom", O_RDONLY); if(fd==-1){ printf("error. tell admin\n"); exit(-1); } unsigned char lotto[6]; if(read(fd, lotto, 6) != 6){ printf("error2. tell admin\n"); exit(-1); } for(i=0; i<6; i++){ lotto[i] = (lotto[i] % 45) + 1; // 1 ~ 45 } close(fd); // calculate lotto score int match = 0, j = 0; for(i=0; i<6; i++){ for(j=0; j<6; j++){ if(lotto[i] == submit[j]){ match++; } } } // win! if(match == 6){ system("/bin/cat flag"); } else{ printf("bad luck...\n"); } } void help(){ printf("- nLotto Rule -\n"); printf("nlotto is consisted with 6 random natural numbers less than 46\n"); printf("your goal is to match lotto numbers as many as you can\n"); printf("if you win lottery for *1st place*, you will get reward\n"); printf("for more details, follow the link below\n"); printf("http://www.nlotto.co.kr/counsel.do?method=playerGuide#buying_guide01\n\n"); printf("mathematical chance to win this game is known to be 1/8145060.\n"); } int main(int argc, char* argv[]){ // menu unsigned int menu; while(1){ printf("- Select Menu -\n"); printf("1. Play Lotto\n"); printf("2. Help\n"); printf("3. Exit\n"); scanf("%d", &menu); switch(menu){ case 1: play(); break; case 2: help(); break; case 3: printf("bye\n"); return 0; default: printf("invalid menu\n"); break; } } return 0; }
В функции main() нет ничего интересного. Интереспредставляет функция play(), разобрав которую мы поймем логику работы программы. Сперва мы вводим 6 значений, потом программа псевдослучайно генерирует еще 6 в диапазоне (1-45), после чего эти две последовательности сравниваются. Флаг получаем приналичии 6 совпадений. Но проверка выполнена неправильно. Таким образом в цикле каждый символ введенной последовательности сравнивается с каждым символом сгенерированной.

Таким образом будем вводить 6 одинаковых символов каждый раз, пока не получим флаг. Я вводил !!!!!!, и на 7 раз получил флаг.

Сдаем флаг и получаем два очка. До встречи в следующих статьях!
Мы в телеграм канале: канал в Telegram.
ссылка на оригинал статьи https://habr.com/ru/post/461641/
Добавить комментарий