Авторские статьи Брут

Discussion in 'Статьи' started by taha, 26 Feb 2007.

  1. taha

    taha Elder - Старейшина

    Joined:
    20 Aug 2006
    Messages:
    399
    Likes Received:
    330
    Reputations:
    251
    Брут паролей

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

    [iNtr0]

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

    [scripts]

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

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

    Code:
    	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-технологии, извините за тавтологию =)) происходит с помощью

    Code:
    	invoke func_prov,offset str_pass,offset brutpass
    	test eax,eax
    	je @F
    
    У нас два состояния 0 и 1. Если 0, то управление передаётся на

    Code:
    	push 0
    	call ExitProcess
    
    если 1, то на

    Code:
    	invoke MessageBox,0,0,0,0
    Откроем прорамму в Olly.

    Code:
    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, имхо не для этого он был написан).

    Code:
    //   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". Да, и не забудте указать с какого по какой символ.

    Code:
    	var ot
    	mov ot,41
    	var do
    	mov do,43
    
    Запускаем скрипт и...

    Code:
    00403000  41 43 42 43 41 00 41 43 42 43 41 00 00 00 00 00  ACBCA.ACBCA.....
    
    Heppy end!

    [aSm]

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

    Code:
    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 [...]. Значит при предыдущих ключах вся область стека забилась мусором. Для того чтобы понять о чём я собствено сейчас пишу попробуйте испольнить следующие строки

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

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