четверг, 29 октября 2015 г.

The 2015 FlareOn Challenge part 1

Попался на глаза интересный челлендж http://www.flare-on.com/
Хоть он и закончился. Решил пройти.
Первое задание.
Дано
файл: i_am_happy_you_are_to_playing_the_flareon_challenge.exe
размер: 1546 байт
Не упакован.

При запуске просит ввести пароль.

Let's start out easy
Enter the password>

На неправильный пароль выдаетYou are failure

Посмотрим что внутри:

Начало простое, инициализируем консоль, выводим сообщение, и ждем ввода пользователя:
Введенные данные сохраняются в переменную byte_402158

push    ebp
mov     ebp, esp
sub     esp, 10h
mov     [ebp+var_10], eax
push    0FFFFFFF6h      ; nStdHandle
call    GetStdHandle
mov     [ebp+var_C], eax
push    0FFFFFFF5h      ; nStdHandle
call    GetStdHandle
mov     [ebp+hFile], eax
push    0               ; lpOverlapped
lea     eax, [ebp+NumberOfBytesWritten]
push    eax             ; lpNumberOfBytesWritten
push    2Ah             ; nNumberOfBytesToWrite
push    offset aLetSStartOutEa ; "Let's start out easy\r\nEnter the passw"...
push    [ebp+hFile]     ; hFile
call    WriteFile
push    0               ; lpOverlapped
lea     eax, [ebp+NumberOfBytesWritten]
push    eax             ; lpNumberOfBytesRead
push    32h             ; nNumberOfBytesToRead
push    offset byte_402158 ; lpBuffer
push    [ebp+var_C]     ; hFile
call    ReadFile
xor     ecx, ecx

И вот собственно весь алгоритм валидации:

loc_40104D:

mov     al, byte_402158[ecx]
xor     al, 7Dh
cmp     al, byte_402140[ecx]
jnz     short loc_40107B
inc     ecx
cmp     ecx, 18h
jl      short loc_40104D


Цикл xor-ит введенные данные, числом 0x7D, и сравнивает со статическим буфером.
Посмотрим, что там в буфере:
0x1F, 0x08, 0x13, 0x13, 0x04, 0x22, 0x0E, 0x11,
0x4D, 0x0D, 0x18, 0x3D, 0x1B, 0x11, 0x1C, 0x0F,
0x18, 0x50, 0x12, 0x13, 0x53, 0x1E, 0x12, 0x10

На С++ это задание можно представить так:
#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::vector<char> secret = {
        0x1F, 0x08, 0x13, 0x13, 0x04, 0x22, 0x0E, 0x11,
        0x4D, 0x0D, 0x18, 0x3D, 0x1B, 0x11, 0x1C, 0x0F,
        0x18, 0x50, 0x12, 0x13, 0x53, 0x1E, 0x12, 0x10
    };
    std::string success{ "You are success" };
    std::string failure{ "You are failure" };

    std::cout << "Let's start out easy" << std::endl;
    std::cout << "  Enter the password>";
    std::string pass;
    std::cin >> pass;
    
    for (int i = 0; i < 24; ++i)
    {
        if (secret[i] != (pass[i] ^ 0x7D))
        {
            std::cout << failure << std::endl;
            return 0;
        }

    }
    std::cout << success << std::endl;

    return 0;
}

Решение:
Пропустим исходный буфер через xor:

buf = [ 0x1F, 0x08, 0x13, 0x13, 0x04, 0x22, 0x0E, 0x11,
        0x4D, 0x0D, 0x18, 0x3D, 0x1B, 0x11, 0x1C, 0x0F,
        0x18, 0x50, 0x12, 0x13, 0x53, 0x1E, 0x12, 0x10]

for ch in buf:
print(chr(ch^0x7D), end='')
print()

bunny_sl0pe@flare-on.com

Вероятно, нужно было отправить сюда e-main, и в ответ пришло бы 2-е задание, но так как челлендж уже закончился, все задания скачиваются одним архивом.

Первое задание было оооочень простым, посмотрим что со втором (я уже глянул, там тоже все просто, но немного посложнее), продолжение следует... 

Код на GitHub