PDA

Просмотр полной версии : Брут


taha
26.02.2007, 12:39
Брут паролей

Сегодня я поведаю о том, как узнать пароль, не зная алгоритма генерации, вобщем о бруте. Скажу сразу, дело это долгое и весьма рисковое. Помните один из главных принципов - чем меньше изменений мы вносим в логику программы, тем лучше. Вдеь мы будем менять логику программы, внедрять свой код.

[iNtr0]

Перебор паролей происходит по средствам внедрения генератора и определения нескольких состояний полученной системы - правильный пароль, неправильный. Определяем куда поподает управление при правильном пароле и при неправильном. Если пароль правильный, то тормозимся и вызываем отладчик, а если нет, меняем (генерируем новый) и проверяем его и тд., получается, маленький такой, конечный автомат.

[scripts]

Эта часть статьи написана по принципу 'зацените изврат'. Брут через скрипты для Olly не самое быстрое занятие, но если вам так же как и мне нравится смотреть на бегущие буквы, то это для Вас. Долгое потому, что код сначала интерпритируется плагом OllyScript затем в игру вступает сама Olly и только потом прога. Так что мы успеваем и буквы увидеть.

Начнём пожалуй. Сперва мне понадобилась программа с простейшим способом проверки. И я написал эти скромные строки.

invoke func_prov,offset str_pass,offset brutpass
test eax,eax
je @F
invoke MessageBox,0,0,0,0
@@:
push 0
call ExitProcess


Где func_prov - функция, осуществлющая проверку, тупо, через cmp reg1,reg2. Она возвращает 0 если пароль неправильный, и 1 если правилный. Если мы выполняем перебор через скрипт, то внедрять в программу ничего не нужно, просто поставим бряки... Как бы это сказать?! Ну вот из чего состоит простейший автомат?... Сначала идёт проверка состояния, потом передача управления на нужный код (переход). Проверка состояния (switch в switch-технологии, извините за тавтологию =)) происходит с помощью

invoke func_prov,offset str_pass,offset brutpass
test eax,eax
je @F


У нас два состояния 0 и 1. Если 0, то управление передаётся на

push 0
call ExitProcess


если 1, то на

invoke MessageBox,0,0,0,0

Откроем прорамму в Olly.

00401000 PUSH prog.00403006
00401005 PUSH prog.00403000 ; ASCII "ACBCA"
0040100A CALL <prog.func_prov>
0040100F TEST EAX,EAX
00401011 JE SHORT prog.00401021
00401013 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00401015 PUSH 0 ; |Title = NULL
00401017 PUSH 0 ; |Text = NULL
00401019 PUSH 0 ; |hOwner = NULL
0040101B CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
00401020 PUSH 0 ; /ExitCode = 0
00401022 CALL <JMP.&kernel32.ExitProcess> ; \ExitProcess


Мы поставим бряки на 00401020 и 00401013. Если сработает бряк по адресу 00401020, то сгенерированный пароль не подходит, если по адресу 00401013, то всё круто можно выходить (из скрипта).

Мной был написан следующий скрипт (не буду вдаваться в особенности генерации и несовершенности OllyScript, имхо не для этого он был написан).

// Name: Bruter 0.1
// Author: taha
// Date: 18/02/07

//-- .data ---------------------------------

var ot
mov ot,41
var do
mov do,43

//_ address ___________________
var start_addr
mov start_addr,00401000
var bad_addr
mov bad_addr,00401020
var good_addr
mov good_addr,00401013

//__ string _________________
var str_addr
mov str_addr,00403006

var y
var count

//__ backUp _____
var b_eax
var b_ebx
var b_ecx
var b_edx
var b_esi
var b_edi
var b_esp
var b_ebp

//-- .code ---------------------------------

bphws bad_addr,"x"
bphws good_addr,"x"

mov b_eax,eax
mov b_ebx,ebx
mov b_edx,edx
mov b_ecx,ecx
mov b_edi,edi
mov b_esi,esi
mov b_esp,esp
mov b_ebp,ebp

mov count,str_addr
mov y,str_addr
mov [str_addr],41

genstr:
cmp [y],do
je gen_ra
inc [y]
jmp gen_ex
gen_ra:
fill y,1,ot
cmp y,str_addr
je add_s
mov eax,y
dec eax
mov ecx,[eax]
and ecx,FF
cmp ecx,do
je y_dec
inc [eax]
jmp gen_ex
y_dec:
dec y
jmp gen_ra
add_s:
fill count,1,ot
inc count
fill count,1,ot
gen_ex:
mov y,count

run
cmp good_addr,eip
je good

mov eax,b_eax
mov ebx,b_ebx
mov ecx,b_ecx
mov edx,b_edx
mov edi,b_edi
mov esi,b_esi
mov esp,b_esp
mov ebp,b_ebp

mov eip,start_addr
jmp genstr

good:
BPHWC good_addr
BPHWC bad_addr
msg "Всё гуд"
ret


Просто указываете адреса куда нужно попасть, а куда нет, адрес начала проверки и адрес буффера. Изначально строка, буффер, должна состоять из одного символа "A". Да, и не забудте указать с какого по какой символ.

var ot
mov ot,41
var do
mov do,43


Запускаем скрипт и...

00403000 41 43 42 43 41 00 41 43 42 43 41 00 00 00 00 00 ACBCA.ACBCA.....


Heppy end!

[aSm]

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

start:
invoke func_prov,offset str_pass,offset brutpass
test eax,eax
je @F
invoke MessageBox,0,0,0,0
int 3
@@:
jmp Brute
push 0
call ExitProcess


Как видите, если пароль неверный, то происходит переход на наш код генерации, оттуда опять на start, а если верный то тормозится по int 3 и мы читаем пасс =)). Внедрять куда-либо мне было лень.

[полиморфы]

Я о простейших видах полиморфизма. Просто расшифровка какой-либо функции. Здесь тоже всё просто, но есть одна маленькая неприятность. Я пробовал брутить крямис ProTeuS'a. И прога упала при ключе 0BBh (187). Стек был забит всякой гадостью. Попробовал проанализировать код на котором она упала. Это был просто push [...]. Значит при предыдущих ключах вся область стека забилась мусором. Для того чтобы понять о чём я собствено сейчас пишу попробуйте испольнить следующие строки

xor eax,eax
dec eax
mov esp,eax


А теперь попробуйте чтонить пропушить. Тото)). Большая неприятность. НО можно прогу перезапустить и начать брут с следующего ключа. Склоко раз предётся перезапускаться неизвестно...

[ps]
Врядли вам это пригодится. ИМХО брутить алго, смыс которого в расхоривании имени, нерационально. А если прога для собственного пользования, то проще перебить переход.