Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   Реверсинг (https://forum.antichat.xyz/forumdisplay.php?f=94)
-   -   Задача для хекеров =) (https://forum.antichat.xyz/showthread.php?t=85225)

VERte][ 18.09.2008 02:53

Задача для хекеров =)
 
(Очень занимательное домашнее задание от препода =) )
Дана несколько запутанная программа. Преподователь вводит пароль, который студент не видит. После этого студент должен ввести свои варианты пароля и добиться вывода строки "You're COOl hacker" Количество попыток ограниченно(2 штуки). Требование: во время угадывания нельзя запускать дебаггеры, виртуальные машины и т.д. Просто для исследования программы можно использовать дизасм и дебаггер, hex редакторы нельзя использовать (препод все равно будет компилить прогу сам). (Решений несколько)
Код программы:
Код:

#include <stdio.h>
#include <stdlib.h>

#define ARRAY_LENGTH 100
int main()
{
        int flag;
        int i,j;
        char a_passwords[2][ARRAY_LENGTH]={"xxx","yyy"};
        char *p_user = NULL;
        char *p_etalon =NULL;

        p_etalon=a_passwords[0];
        p_user=a_passwords[1];
        printf("Etalon password: ");
        fflush(stdout);
        scanf("%s",p_etalon);
        for (i=0; i<10000;i++) //что бы студент не видел, что было введено преподом
        {
                printf("\n");
        }
        a_passwords[1][0]=&p_etalon-&p_user;
        for (j=2;j>0;j--)
        {
                printf("Password: ");
                fflush(stdout);

                scanf("%s",p_user);

            flag=0;
                for (i=0; i<ARRAY_LENGTH;i++)
                {
                        flag=(p_etalon[i]!=p_user[i]);
                        if ((p_etalon[i]==0) || (p_user[i]==0) || flag)
                                break;
                }
                if (flag)
                {
                        printf(p_user);
                        printf(" - wrong pasword!\n");
                }
                else
                {
                        printf("\nYou're COOl hacker!!!\n");
                        exit(0);
                }
        }
        printf("You're looser!!!\n");
        return 0;
}


ProTeuS 18.09.2008 12:22

если отлад4ик можно юзать, то какие-проблемы? препод ввел серийнки. запустил ольку, приатта4ился, нашел код ввода проверки, отттрейсил сравнение, нашел буфер эталонного паса, ввел. все. 1 попытка, 100% результат

VERte][ 18.09.2008 13:53

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

goodkit 18.09.2008 14:28

keylogger поставь ^_^

VERte][ 18.09.2008 15:13

Проблема чисто программая:)

winterfrost 18.09.2008 18:24

Вероятно, один из способов решения, это использовать ошибку форматной строки:
Код:

printf(p_user);
Так-же нет никаких ограничений на длинну ввода в переменные, вероятно, это тоже можо как-то использовать. Например, если во время первого запроса на ввод пароля ввести более 122 символов, то исчезнет ограничение на 2-е попытки угадать пароль

P.S. компилировал gcc на 64-битной системе

upd:
Вобщем, вот мой вариант решения данной задачи =)
Код:

Etalon password: 1234
[...]
Password: <122 симола 'a'>
<122 симола 'a'> - wrong pasword!
Password: %c%c%c

1 - wrong pasword!
Password: 1%c%c%c
1
2 - wrong pasword!
Password: 12%c%c%c
12
3 - wrong pasword!
Password: 123%c%c%c
123
4 - wrong pasword!
Password: 1234%c%c%c
1234
 - wrong pasword!
Password: 1234

You're COOl hacker!!!

Сообщая что пароль не верный, программа выводит следующий верный симол пароля(перед "- wrong pasword!"), таким образом, убрав ограничение на 2-е попытки (122 сивола 'a'), мы посимвольно подбираем верный пароль.

paulzey 18.09.2008 18:50

Особой сложности не имеет. Есть два способа обхода.
1) Системный. Часто все забывают, что типовой системный ввод обладает "историей". Достаточно во время ввода нажать кнопку вверх, последнее введённое значение будет подставлено.

2) Программный. В самом деле, внимательно смотрим на два куска кода.
Цитата:

char a_passwords[2][ARRAY_LENGTH]={"xxx","yyy"};
char *p_user = NULL;
char *p_etalon =NULL;
и
Цитата:

flag=(p_etalon[i]!=p_user[i]);
Соответственно, значением a_passwords[1] можно переписать значение p_user, заставив программу сравнивать пользовательский пароль сам с собой.
Проверим идею - вуа-ля, см. рисунок:
http://img231.imageshack.us/img231/2...le01ik0.th.png
С клавиатуры вводятся (через Alt+Num Цифра) три байта. В моём случае - с кодами 20, 255, 18 (0x12FF14). Путём анализа скомпилированного кода можно узнать значение для конкретного случая.
http://img218.imageshack.us/img218/1...le02yz9.th.png
Желтым выделена область, содержащая эталон пароля, красным - пользовательский, зелёным - ссылочные переменные. Возможно затереть только три байта первой ссылки (нулевой символ с клавиатуры ввести нельзя). Таким образом, просто узнав второй адрес, можно поместить его в кодах позади последовательности, буфер переполнится, значение затрётся, после ста проверок флаг всё равно будет нулевой.
Пример данных, затирающих ссылку.
http://img61.imageshack.us/img61/721...le03ak4.th.png
Видно, что данные ссылок одинаковы. Именно это обстоятельство позволяет осуществить успешную атаку.

VERte][ 18.09.2008 21:57

в добавление, компилироваться все это будет на unix машине

paulzey 19.09.2008 09:59

Тогда придётся активно осваивать gdb. Сейчас, к сожалению, ни одной завалящей консоли под рукой нет, проверить не на чем, как на обед пойду - гляну, что да как.

VERte][ 21.09.2008 20:36

Проанализировав программы с разных компиляторов, пришел к выводу, что решения с затиранием числа попыток ввода и указателей (p_user, p_etalon) очень сильно зависят от компилятора и флагов компиляции. Например у меня на xp pro sp2 с компилером gcc, без оптимайза число попыток непосредственно загружалось в регистр в программе, а указатели находились до массива, так что эти способы не канали (хотя изменяя флаги компиляции можно было прийти к данным решениям). Тем не менее существует (на мой взгляд) достаточно универсальный способ нахождения пароля. Завтра я его выложу (после того как сдам работу преподу, конкуренция блин=) ), кто выложит до меня поставлю +15 (ибо способ достаточно сложен для нахождения), если будет найден ещё один универсальный способ поставлю +20. Дерзайте =)


Время: 15:50