Типа предисловия

Не так давно на небезызвестном www.xakep.ru была устроена очередная развлекуха под названием Головоломка для хакера №7: КОНКУРС. Цель оного действа - побуждение ксакепов к решению некоторых задач, требующих некоторой работы мозгов и получение за это некоторой денежной суммы, а также всяческих почестей и уважения в глазах соксакеповцев. Однако, такая безусловно нужная и полезная идея не нашла поддержки в народных массах. Далее будут изложены некоторые мои соображения по поводу задач (точнее их решения), прочитав которые даже самый ксакеповский ксакеп будет способен хоть что-то решить. Сразу хочу сказать что все нижеизложенное всего лишь мое humble opinion, и вся неконструктивная критика идет на /dev/null, все остальное можно вываливать на ксакеповский "форум". Крики типа "а чего ты такой умный, а 10 9 8 7 ... пункты не решил?" идут вместе с критикой.

It starts (c)

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

10

Quote: В основе smurf-атаки - отправка пакетов на широковешательные адреса. Как отличить широковещательный адрес от "нешироковещательного"?

Тут я начал понимать задумку автора. Если такой вопрос будет первым, и его увидит какой-нибудь нормальный человек, то читать задания дальше просто не будет. Respect автору.

Netmask address = 255.255.255.0
Some address = 1.1.0.255

Не буду вдаваться в подробности, благо поисковиками умеют пользоваться все. Отличить широковещательный адрес очень просто - достаточно взять адрес, который нужно проверить и наложить на него маску подсети. Если в результирующем "адресе" все биты = 1, значит это broadcast. В данном примере...

host | mask = 00000001 00000001 00000000 11111111 | 11111111 11111111 11111111 00000000 = 11111111 11111111 11111111 11111111 = broadcast.

9

Quote: Известно, что функция crypt(variabla,"salt") из *никсовой библиотеки crypt возвращает значение "saeNMv4rNf6.E". Найдите variabla

It's DES, baby. Функция возвращает хеш-образ последовательности символов, salt это двухсимвольная константа, которая позволяет получить (теоретически) 4096 различных хеш образов на каждую символьную последовательность. Да, чуть не забыл... макс. длина последовательности - 8 байт. Прямой реверс этой функции невозможен, однако в связи с ее популярностью существует довольно много брутфорсеров, например crack или John the Ripper. Воспользуемся вторым... Для работы понадобится файл похожий на /etc/passwd с одним абстрактным пользователем и нашей строкой "saeNMv4rNf6.E" в качестве хеша от пароля. После всех мучений должно получиться что variabla = "magazine".

8

Quote: Реверс для начинающих. Определите "серийник" для sample1.exe

Reverse? Who said reverse? Назвать это творение "crackme" язык просто не поворачивается. Для нахождения процедуры обработки нажатия на "Ok" можно обойтись вообще без отладчика (любители могут заняться bpx GetDlgItemTextA & bpx GetWindowTextA). Предположим, что найти обработчик сможет каждый и глянем что же там интересного. Могу заранее расстроить - ничего.

Неинтересное начало поскипано...
CODE:00450275                 call    @TControl@GetText ; TControl::GetText
CODE:0045027A                 mov     eax, [ebp+Serial_txt]
CODE:0045027D                 call    @StrToInt
CODE:00450282                 mov     [ebp+Serial_num], eax
CODE:00450285                 xor     eax, eax
CODE:00450287                 pop     edx
CODE:00450288                 pop     ecx
CODE:00450289                 pop     ecx
CODE:0045028A                 mov     fs:[eax], edx
CODE:0045028D                 jmp     short Code_start
CODE:0045028F ; ---------------------------------------------------------------------------
CODE:0045028F 
CODE:0045028F loc_45028F:                             ; DATA XREF: sub_450238+29
CODE:0045028F                 jmp     loc_403980
CODE:00450294 ; ---------------------------------------------------------------------------
CODE:00450294                 call    sub_403CE8
CODE:00450299 
CODE:00450299 Code_start:                             ; CODE XREF: sub_450238+55
CODE:00450299                                         ; DATA XREF: sub_450238+61 ...
CODE:00450299                 mov     [ebp+Code_start_ofs], offset Code_start
CODE:004502A0                 mov     eax, offset Code_end
CODE:004502A5                 sub     eax, offset Code_start
CODE:004502AA                 mov     [ebp+Code_lengh], eax
CODE:004502AD                 xor     ebx, ebx
CODE:004502AF                 mov     eax, [ebp+Code_lengh]
CODE:004502B2                 test    eax, eax
CODE:004502B4                 jl      short Code_zero_lengh
CODE:004502B6                 inc     eax
CODE:004502B7                 xor     edx, edx
CODE:004502B9 
CODE:004502B9 Calculate:                              ; CODE XREF: sub_450238+8C
CODE:004502B9                 mov     ecx, [ebp+Code_start_ofs]
CODE:004502BC                 movzx   ecx, byte ptr [ecx+edx]
CODE:004502C0                 add     ebx, ecx
CODE:004502C2                 inc     edx
CODE:004502C3                 dec     eax
CODE:004502C4                 jnz     short Calculate
CODE:004502C6 
CODE:004502C6 Code_zero_lengh:                        ; CODE XREF: sub_450238+7C
CODE:004502C6                 mov     eax, [ebp+Serial_num]
CODE:004502C9                 xor     eax, 0Ah
CODE:004502CC                 cmp     ebx, eax
CODE:004502CE                 jnz     short Code_end
CODE:004502D0                 lea     edx, [ebp+var_14]
CODE:004502D3                 mov     eax, ebx
CODE:004502D5                 call    @Sysutils@IntToStr$qqri ; Sysutils::IntToStr(int)
CODE:004502DA                 mov     edx, [ebp+var_14]
CODE:004502DD                 mov     eax, ds:dword_452C1C
CODE:004502E2                 call    @Controls@TControl@SetText$qqrx17System@AnsiString ; Controls::TControl::SetText(System::AnsiString)
CODE:004502E7                 mov     eax, ds:dword_452C1C
CODE:004502EC                 call    sub_44B824
CODE:004502F1                 mov     eax, ds:off_451EF4
CODE:004502F6                 mov     eax, [eax]
CODE:004502F8                 call    @TCustomForm@Show ; TCustomForm::Show
CODE:004502FD 
CODE:004502FD Code_end:                               ; CODE XREF: sub_450238+96
CODE:004502FD                                         ; DATA XREF: sub_450238+68
CODE:004502FD                 xor     eax, eax
CODE:004502FF                 pop     edx
CODE:00450300                 pop     ecx
CODE:00450301                 pop     ecx
CODE:00450302                 mov     fs:[eax], edx
CODE:00450305                 push    offset loc_450322
Не менее неинтересный конец тоже...
Serial из строкового представления преобразуется в число. По умолчанию считается, что система счисления - десятичная. Далее начинаем считать "правильный" serial number. Делается это в цикле Calculate (004502B9 - 004502C4) путем накапливания суммы всех байт начиная с адреса 00450299 и заканчивая 004502FD (Code_start и Code_end соответственно). Полученная сумма сравнивается с Serial xor 0xA. При совпадении - решается что Serial правильный.
serial xor 0xA = magic =>
serial xor 0xA xor 0xA = magic xor 0xA => 
serial = magic xor 0xA
Детский сад. Счастливые обладатели softice могут запустить sample1.exe, написать "addr sample1" и "bpx 4502CC". После чего ввести что угодно в поле серийника и давануть "Ok". В вылетевшем айсе делается "? ebx ^ 0A" и серийник готов - 12868.

7

Quote: 7. Для прохождения пятого уровня NG Security Game не обязательно знать логины и пароли, находящиеся в таблице. Однако, существует способ узнать их. Определите, сколько именно логинов и паролей в таблице и перечислите их.

К величайшему сожалению автор забыл оставить ссылку на творение человечества под названием NG Security Game. Возможно оное творение упоминалось в каком-либо выпуске "хацкера", но не все же его читают... Ужасно огорчившись переходим к следующему пункту.

6 & 5

Quote: Немного теории. Автор одной из статей про DNS-spoofing пишет: "мне достаточно нескольких минут, чтобы определить все DNS-сервера, используемые любым IRCd, и я - не единственный человек, кто может сделать это". Опишите, кто эти "избранные" и как выглядит способ, о котором говорит автор?

Quote: Немного дикой практики. Опишите атаку, позволяющую заблокировать получение почты через POP3 из любого ящика на mail.ru (при этом остальные ящики должны работать нормально). Hint: создатели системы уверены, что это не бага, а фича.

Не интересно. Копание на форуме в поисках ответа на 5-й вопрос или игра в гадалку для ответа на 6-й (способов этих туева хуча).

4

Quote: Почувствуйте себя Касперским :) Напишите ядро программы (все, кроме базы сигнатур), проверяющей содержимое почтового ящика через POP3, находящей (по сигнатуре) в ящике зараженные вирусами письма и удаляющей их.

"Пойди туда, не знаю куда... напиши то, не знаю что...". Задача задана весьма абстрактно (или это называется свобода выражения?). Не определены ни язык, на котором это предстоит написать, ни платформа... В таком случае пойдем самым легким путем:

#!/usr/bin/perl -w

use Mail::POP3Client;

$user = "someone";
$password = "who cares?";
$host = "pop3.host.domain.com";

printf("POP3 mail checker\n");

$pop = new Mail::POP3Client( USER     => $user,
                             PASSWORD => $password,
                             HOST     => $host );

open(SIGN, "sign") || die "could not open signature file\n";

@sign = ;

print "Found " . $pop->Count() . " messages in the mailbox...\n";

for( $i = 1; $i <= $pop->Count(); $i++ ) {
    foreach( $pop->HeadAndBody( $i ) ) {
        /^(From|Subject):\s+/i && print $_, "\n";
        for ($j = 0; $j < @sign; $j++) {
            chomp $sign[ $j ];
            if (/$sign[ $j ]/) {
                print "signature matched: \"$sign[ $j ]\", deleting message\n";
                $pop->Delete( $i );
            }
        }
    }
}
$pop->Close();        
Прямолинейно, примитивно и очень просто. Тем не менее это чудо техники работает и исправно ищет и удалят из ящика те самые зараженные файлы. Комментировать тут собственно нечего... все желающие идут и читают умные книжки про perl.

3

Quote: Создание remote shell exploit. На хосте 195.209.178.41, порт 4050, находится самописный дырявый "сервис". Исходник и бинарник - не дадим :) OS - Linux, kernel 2.2.

Требует слишком долгого сидения в онлайне (пока это невозможно). В условии ясно сказано, что опять намечается игра в гадалку (это также означает, уязвимость скорее всего - элементарное переполнение при вводе чего-то-там-слишком-длинного). "Rest for now" (c). Возможно поковыряюсь (если будет возможность и желающие что-то послушать по этому поводу).

2

Quote: Опять RE, но под win32. Из бинарника sample1.exe восстановите исходный код программы (Delphi 6).

I asked, WHO THE HELL SAID "REVERSING"? Возвращаемся к нашим баранам... точнее барану (это не автору). Немного непонятно чего хочет автор. Абсолютно точно восстановить код невозможно, это знают даже вышеупомянутые бараны. Имена переменных (как и некоторые другие вкусности) для нас безвозвратно потеряны. Возможно это своего рода проверка "а можешь ли ты, уважаемый ксакеп реализовать такой подсчет правильного серийника?". Напомню, что серийник считается как сумма байт куска кода программы. Еще можно понять задачу "получить программу, которая ведет себя так же как и sample1.exe, и показать ее исходник". После пояснения (желательно автором) я к этому пункту обязательно вернусь.

1

Quote: Reverse Engeneering. Дана игра "Тетрис" под Linux, ELF-файл. Для тех, кто хочет в нее поиграть - кнопки управления - a,s,d,f, пробел ;) Остальным - задача пропатчить ее так, чтобы в игре была менюшка с пунктами "сохранить игру" и "загрузить игру".

ELF is magic (c). Единственное более-менее интересное задание (или все-таки менее?). К сожалению формулировка тоже не лишена некоторых неточностей. Например:

При желании еще можно придумать пару вопросов. Поступим так же как и в пункте 4, то есть пойдем простейшим путем. Это означает, что: По большому счету вид менюшки не принципиален, более важна технология. А точнее ответ на вопрос "каким образом добавить мой код в ELF файл, да еще сделать это так, чтобы этот код время от времени работал". Рассмотрим наш файл чуть более внимательно, с точки зрения ELF формата. Все кто первый раз о таком слышат - бегом читать документацию (/usr/include/elf.h).
$ readelf -l tetris

Elf file type is EXEC (Executable file)
Entry point 0x80489c0
There are 6 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x000c0 0x000c0 R E 0x4
  INTERP         0x0000f4 0x080480f4 0x080480f4 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x01ac2 0x01ac2 R E 0x1000
  LOAD           0x001ac4 0x0804aac4 0x0804aac4 0x00144 0x00544 RW  0x1000
  DYNAMIC        0x001b60 0x0804ab60 0x0804ab60 0x000a8 0x000a8 RW  0x4
  NOTE           0x000108 0x08048108 0x08048108 0x00020 0x00020 R   0x4

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.got .rel.bss .rel.plt .init .plt .text .fini .rodata 
   03     .data .eh_frame .ctors .dtors .got .dynamic .bss 
   04     .dynamic 
   05     .note.ABI-tag 
Забавно. Шестой сегмент типа NOTE содержит пачку магических чисел и 3 буквы "G", "N" и "U" идущие подряд. Похоже на что-то, правда? Никакой информации необходимой для работы программы там не содержится. План действий: дописать нужный нам код в конец файла, поправить шестой сегмент. В сегменте необходимо исправить: offset должен быть равен смещению нашего кода в файле (т.е. original file length), тип LOAD (мы же хотим чтобы нас загрузили), VirtAddr&PhysAddr - куда-нибудь ниже адреса с которого начнет грузиться программа. Лирическое Отступление: все ELF файлы cлинкованные ld c установками по умолчанию начинают грузиться с адреса 0x8048000, FileSiz&MemSiz должны быть равны размеру нашего кода, флаги R W E (что означает Read, Write, Execute). So? Let's rock.. Для совершения вышеописанных манипуляций с файлом можно воспользоваться чем угодно. Я решил написать простенькую программу.
#include 
#include 
#include 
#include 
#include 

int main()
{
	Elf32_Ehdr *pELF;
	Elf32_Phdr *note, *code;
	
	char file[100000], our_code[100000];

	int fd = open("tetris", O_RDONLY);
	int size = read(fd, file, sizeof(file));
	
	int fd1 = open("_code_", O_RDONLY);
	int our_size = read(fd1, our_code, sizeof(our_code)); 

	pELF = (Elf32_Ehdr *)file;
	printf("entry point is at 0x%x\n", pELF->e_entry);
	
	note = (Elf32_Phdr *)((int)file + sizeof(Elf32_Phdr) * 5 + pELF->e_phoff);
	code = (Elf32_Phdr *)((int)file + sizeof(Elf32_Phdr) * 2 + pELF->e_phoff);
	
	if (code->p_type != PT_LOAD) {
		return 1;
	}
	
	if (note->p_type == PT_NOTE) {	
		printf("found note...\n");
		note->p_type = PT_LOAD;
		code->p_flags |=