Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей.
Здесь обсуждаются безопасность, программирование, технологии и многое другое.
Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Расширение функциональности OllyDbg |

09.04.2007, 16:19
|
|
Постоянный
Регистрация: 20.08.2006
Сообщений: 327
Провел на форуме: 2472378
Репутация:
1077
|
|
Расширение функциональности OllyDbg
Расширение функциональности OllyDbg
[ intro ]
Итак, начнём. Наверное каждый кто исследовал сложную/большую программу, сталкивался с проблемой запоминания адресов, подсчёта некоторых констант. Для сохранения адресов и коментариев к некоторым кускам кода, многие пользуються обычным Блокнотом (как и я). Что ни говори, без него уже никуда. Тут возникает проблема его вызова. Как то лень постоянно открывать Пуск > etc. Многие возразят: ‘А разве, Win+R > notepad, не достаточно быстро?’. Да это быстро/удобно, но всё равно не совсем то. Хорошо бы создать дополнительное меню “tools” в OllyDbg, где бы и находились итемы часто используемых прог. Блокнот, Калькулятор etc. Но без хирургического вмешательства этого не достичь. Придется OllyDbg “лечь под нож”.
На данную статью меня вдохновила статья из второго номера журнала ARTeam и отсутсвие подобных на великом и могучем.
[ tools ]
Для этого нам понадобятся:
Restorator 2005 – редактор ресурсов
Shadow - я выбрал эту модификацию OllyDbg (по вкусу)
MASM – компилятор
[Правка ресурсов]
Windows-программа, помимо исполняемого кода, содержит ресурсы: иконки, диалоги, битмапы, музыку. Только ресурсы не преобразовываются как исполняемый код. И для исправления ресурсов намного удобнее использовать специальные программы. Для этого я выбрал Restorator.
Открываем Shadow.exe в Restorator 2005. Перед нами папки ресурсов: диалоги, картинки, меню. Нам естественно нужна папка Menu. Заходим в неё. Выбираем MAINMENU.
Я решил засунуть “tools” между “Options”и “Windows”. Поэтому пишем следующее:
Код:
POPUP "&Tools"
{
MENUITEM "&Calc", 4001
MENUITEM "&Notepad", 4002
}
Естественно между POPUP "Op&tions" {…} и POPUP "&Window" {…}.
4001d – 0FA1h – это ID пункта, будет отсылаться вместе с сообщением. Именно этот ID даёт программе понять, что от неё хотят (точнее понять какой пункт выбран).
Теперь закрываем редактор, попутно разрешая сохранить изменеия и бэкап.
Открываем Shadow.exe !
Так... Меню создали. Теперь нужно сделать так, чтобы OllyDbg обрабатывала сообщения этих итемов.
[Цикл сообщений]
Когда пользователь выбирает пункт меню, Windows отсылает программе сообщение WM_COMMAND, которое обрабатывается в цикле сообщений. Каждый, кто программировал под Windows, писал следующие строки:
Код:
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK
.IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
GetMessage пеpедает указатель на MSG стpуктуpу Windows. Эта стpуктуpа будет заполнена инфоpмацией о сообщении, котоpые Winsows хотят послать окну этого модуля. Если возвращается false, то это сигнал, что пора завершаться. TranslateMessage переводит код нажатой клавиши в ASCII-сомвол. И теперь самое интересное – DispatchMessage. Эта API передаёт управление функции обработки сообщений (WndProc). Тоесть эта функция поможет нам найти “WndProc”, в которой содержится обработчик сообщения WM_COMMAND.
Итак отрываем файл Shadow.exe в другой Olly[Dbg|ICE|Shadow]. Мы попадём на EP.
Код:
00401000 > $ /EB 10 JMP SHORT Shadow.00401012
00401002 |66 DB 66 ; CHAR 'f'
00401003 |62 DB 62 ; CHAR 'b'
00401004 |3A DB 3A ; CHAR ':'
00401005 |43 DB 43 ; CHAR 'C'
00401006 |2B DB 2B ; CHAR '+'
Запускаем программу (F9) и закрываем все лишнии окна (такие как CPU, хэндлеры, логи, карта памяти), в отлаживаемой программе. Оставивь нужно только основное окно. Мы ведь не хотим рыться в сообщениях чужих окон. Теперь перейдём в DispatchMessage. Для этого жмём Ctrl-G и вводим “DispatchMessageA”. Ставим break “F2” в начале функции и запускаем программу. Останавливаемся. Снимаем бряк. Переходим на карту памяти Alt-M и ставим break на секцию кода. Теперь вам понятна логика действий? Сейчас мы внутри DispatchMessage, которая передаёт управление “WndProc”. Соответсвенно первое попадание в секцию кода – это попадание на “WndProc”. F9 и мы попадём сюда:
Код:
004323D4 /$ 55 PUSH EBP
004323D5 |. 8BEC MOV EBP,ESP
004323D7 |. 81C4 04F0FFFF ADD ESP,-0FFC
004323DD |. 50 PUSH EAX
004323DE |. 81C4 30FDFFFF ADD ESP,-2D0
004323E4 |. 53 PUSH EBX
004323E5 |. 56 PUSH ESI
004323E6 |. 57 PUSH EDI
004323E7 |. 8B5D 10 MOV EBX,[ARG.3]
004323EA |. 8B45 0C MOV EAX,[ARG.2]
004323ED |. 3D 11010000 CMP EAX,111 ; Switch (cases 1..478)
004323F2 |. 7F 61 JG SHORT Shadow.00432455
004323F4 |. 0F84 1E140000 JE Shadow.00433818
И вот уже невооружонным глазом видно где проверка WM_COMMAND.
004323ED |. CMP EAX,111 ; Switch (cases 1..478)
WM_COMMAND equ 111h
Идём по F8 до строки по адресу 004323ED. Далее в меню выбираем “Go to”.
Дальше, естественно, “Case 111 (WM_COMMAND)”. И мы здесь:
Код:
00433818 |> \8BCB MOV ECX,EBX ; Case 111 (WM_COMMAND) of switch 004323ED
0043381A |. C1E9 10 SHR ECX,10
0043381D |. 66:85C9 TEST CX,CX
00433820 |. 0F85 EC090000 JNZ Shadow.00434212
00433826 |. 8BC3 MOV EAX,EBX
Помещаем сюда бряк и выбираем, добавленный нами, пункт в “tools”. Например “calc”. Идём по F8 вот до этого места:
Код:
00433A1A |. /E9 77070000 JMP Shadow.00434196
00433A1F |> |81EA C7090000 SUB EDX,9C7
00433A25 |. |0F84 37070000 JE Shadow.00434162
00433A2B |. |4A DEC EDX
00433A2C |. |0F84 4E070000 JE Shadow.00434180
00433A32 |. |E9 5F070000 JMP Shadow.00434196
00433A37 |> |33C0 XOR EAX,EAX ; Case 7D1 of switch 0043382F
00433A39 |. |83C9 FF OR ECX,FFFFFFFF
JMP Shadow.00434196 – это переход в случаее если обработка полученного сообщения не предусмотренно.
Теперь нам следует подыскать свободное место в программе (для внедрения некоторого кода). Как всегда место нашлось в оверлее.
Код:
004AF670 00 DB 00
004AF671 00 DB 00
004AF672 00 DB 00
004AF673 00 DB 00
004AF674 00 DB 00
004AF675 00 DB 00
004AF676 00 DB 00
004AF677 00 DB 00
004AF678 00 DB 00
004AF679 00 DB 00
004AF67A 00 DB 00
004AF67B 00 DB 00
004AF67C 00 DB 00
004AF67D 00 DB 00
004AF67E 00 DB 00
И что же мы туда будем внедрять? Нет! Не обработку данного сообщения, хотя это частично так. Это было бы слишком жирно. Мы напишем dll, Функцию из которой, будем вызывать с этого участка.
Код:
004AF670 > \60 PUSHAD
004AF671 . 68 97EC5000 PUSH Shadow_-.0050EC97 ; /ProcNameOrOrdinal = "f_menu"
004AF676 . 68 8DEC5000 PUSH Shadow_-.0050EC8D ; |/FileName = "tools.dll"
004AF67B . E8 B8FAFFFF CALL <JMP.&KERNEL32.LoadLibraryA> ; |\LoadLibraryA
004AF680 . 50 PUSH EAX ; |hModule
004AF681 . E8 0AFAFFFF CALL <JMP.&KERNEL32.GetProcAddress> ; \GetProcAddress
004AF686 . FFD0 CALL EAX
004AF688 . 61 POPAD
Теперь JMP Shadow.00434196 меняем на JMP Shadow.004AF670, а в конец этого кода добавляем
Код:
004AF689 .^ E9 084BF8FF JMP Shadow_-.00434196
Отлично! Так же не забудьте записать где-нибудь имена библиотеки и функции.
Заметка:
-------------------------------
CALL <JMP.&KERNEL32.LoadLibraryA> и CALL <JMP.&KERNEL32.GetProcAddress> - не тупо вбиты как “call LoadLibraryA”, “call GetProcAddress”. А как “CALL 004AF138”, “CALL 004AF090”.
Код:
004AF138 $- FF25 B4D35000 JMP DWORD PTR DS:[<&KERNEL32.LoadLibrary>; kernel32.LoadLibraryA
…
004AF090 $- FF25 44D35000 JMP DWORD PTR DS:[<&KERNEL32.GetProcAddr>; kernel32.GetProcAddress
Это сделанно для того, чтобы файл мог запускаться на других системах, где адресс API может быть другим.
--------------------------------
Теперь сохраним пропатченный файл. Для этого в меню выбираем “Copy to executable” > “All modifications” > “Copy all”. В открывшемся окне выбираем “Save file” и сохраняем.
[Пишем dll]
Начнём со скелета DLL.
Код:
.386
.model flat, stdcall
option casemap:none
include D:\masm32\include\windows.inc
include D:\masm32\include\user32.inc
include D:\masm32\include\kernel32.inc
includelib D:\masm32\lib\user32.lib
includelib D:\masm32\lib\kernel32.lib
.code
DLLEntry proc hInstDLL:DWORD, reason:DWORD, unused:DWORD
.if reason == DLL_PROCESS_ATTACH
mov eax,TRUE
.endif
Ret
DLLEntry Endp
f_menu proc
RET
f_menu EndP
end DLLEntry
Теперь о том как получить сообщение. Когда шли по F8, думаю вы заметили, что оно храниться в edx. Но когда выполняются LoadLibraryA, GetProcAddress регистр edx засерается. Не забываейте, что мы сохранили в стеке все регистры, командой PUSHAD. PUSHAD заносит в стек все регистры от eax до edi

Соответсвенно ESP+14h – это содержимое edx. Только когда управление попадёт в нашу функцию, в стек войдёт ещё и адрес возврата. Тогда edx будет по ESP+18h.

В итоге у меня получился следующий файл
Код:
.386
.model flat, stdcall
option casemap:none
include D:\masm32\include\windows.inc
include D:\masm32\include\user32.inc
include D:\masm32\include\kernel32.inc
includelib D:\masm32\lib\user32.lib
includelib D:\masm32\lib\kernel32.lib
.data
p_calc db "\calc.exe",0
p_notepad db "\notepad.exe",0
.data?
pi PROCESS_INFORMATION <>
startinfo STARTUPINFO <>
buffer db 50 dup(?)
.code
DLLEntry proc hInstDLL:DWORD, reason:DWORD, unused:DWORD
.if reason == DLL_PROCESS_ATTACH
mov eax,TRUE
.endif
Ret
DLLEntry Endp
f_menu proc
mov eax,[esp+18h]
cmp eax,5D9h
jne @F
invoke GetSystemDirectory, addr buffer, sizeof buffer
invoke lstrcat,addr buffer,addr p_calc
invoke CreateProcess, addr buffer, NULL, NULL, NULL,\
FALSE, NORMAL_PRIORITY_CLASS,\
NULL, NULL, addr startinfo, addr pi
RET
@@:
cmp eax,5DAh
jne @F
invoke GetWindowsDirectory, addr buffer, sizeof buffer
invoke lstrcat,addr buffer,addr p_notepad
invoke CreateProcess, addr buffer, NULL, NULL, NULL,\
FALSE, NORMAL_PRIORITY_CLASS,\
NULL, NULL, addr startinfo, addr pi
@@:
RET
f_menu EndP
end DLLEntry
Компилим! Запускаем нашу Shadow.exe. Выбираем пункт и... Всё работает! Теперь блокнот\калькулятор можно вызвать из меню.
[Заключение]
Теперь можно смело расширять возможности любой проги. Менять настройки под себя.
Удобно! +)
PS. Нужно будет добавить кнопку соединения с инт0рнетом))))
|
|
|
|
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|