PDA

Просмотр полной версии : [Python plugin for OllyDbg]


0x0c0de
02.07.2008, 19:48
Сабж. Плаг позволяет писать скрипты на питоне под ольгу.
Нашла 2 плага 2007 года под 2.4 питон, но увидеть воочию их работу мне так и не удалось. У меня стоял 2.5, а потому решила переписать под него. Проверила некоторые функции и написала небольшую либу, чтобы упростить работу.
Понятное дело, что вам для теста требуется отладчик OllyDbg+Python 2.5+знание питона (у меня питон, который устанавливался с immunity dbg, отдельно не качала). В папке system32 обязательно должна быть либа Python25.dll
Для тех, кто принципиально не заглядывает в readme

[Install]
1.Файл ODBG_pyth.py и ollylib.py положите в папку \Python25\Lib
2.Файл _ODBG_pyth.pyd положите в папку \Python25\DLLs
3.Либу Python_Int.dll в директорию с плагинами OllyDbg
Интерпретатор должен быть нормально настроен, чтобы все либы находились в вышеуказанных директориях и нормально работали.
Запускать скрипт командой меню OllyDbgPython plugin -> Run script. И выбираем скрипт. Чтобы проверить работу плагина - воспользуйтесь примерами из папки example. *В этот момент в отладчик должно быть что-то загружено.



В ollylib - те функции, которые я проверила.
качаем, кому интересно

http://0x0c0de.net/plugin_python.rar

Пишем, что хотелось бы увидеть. Для каких функций требуются примеры. Багрепорты и пожелания лучше в осеку пишите, ибо там я в последнее время бываю чаще, чем на форуме.

Набор апишек у ольги немаленький, потому за несколько дней кодеса обработать, проверить на работоспособность и привести в норм вид все просто нереально.

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

Видео по настройке и запуск примера
http://0x0c0de.net/Ollypy.rar

#-------Добавлено 4.07.2008------------------------
Перезалито. Добавлены новые функции в ollylib.py. В плагине и разделяемой библиотеке отключила прилинковку msvcp80, так что теперь не нужно доп либ никаких.

#----Добавлено 6.07.2008---------------
1. Добавлена функция Attach_by_name(имя_процесса_в_памя ти)
2. Добавлена функция dump_mem(имя_файла_для_дампа,ад ес_начала_региона, размер_региона)
3. Добавлен еще один пример использования

И еще некоторые мелкие исправления
*Иногда примеры нужно модифицировать (в зависимости от базового адреса загрузки загруженной под отладку проги)

Nice try!

#------Добавлено 7.07.2008-----------------

1. Все перезалито. Перекроила все примеры. Добавила доку по ollylib, которую вы можете лицезреть ниже

#----------Добавлено 9.07.2008-----------

1. Снова апдейт. Добавлены новые функции. Смотрим последний пост

#----------Добавлено 10.07.2008---------

Добавлена справка. немного модифицированы примеры

#----------Добавлено 11.07.2008----------------

Перезалито, теперь более полную информацию можно получить в ollylib.py. Там есть прототипы функций... Добавлены новые примеры и функции. Смотрим последний пост

0x0c0de
07.07.2008, 21:51
[Описание плагина]

Делаю небольшое описание функций либы ollylib.py.

[Скриптинг]

1. Начало работы

Любой скрипт нужно начинать с подключении ollylib.py. Делается это так


from ollylib import*


Таким образом вы сможете использовать в вашем скрипте api OllyDbg.

2. Получение значений всех регистров
Для этих целей я написала функцию GReg.
Вызывать так


GReg(имя_регистра)


Например (и сразу вывод в лог значения):


eax = GReg("Eax")
Log("eax is %X" % int(str(eax)))
esp = GReg("eSp")
Log("esp is %X" % int(str(esp)))
ebp = GReg("ebp")
Log("ebp is %X" % int(str(ebp)))
esi = GReg("esi")
Log("esi is %X" % int(str(esi)))
edi = GReg("edi")
Log("edi is %X" % int(str(edi)))
eip = GReg("eip")
Log("eip is %X" % int(str(eip)))
ss = GReg("ss")
Log("ss is %X" % int(str(ss)))
ds = GReg("ds")
Log("ds is %X" % int(str(ds)))
efl = GReg("efl")
Log("efl is %X" % int(str(efl)))


и так далее ....
Полностью пример в Get_Regs.py

Функции вывода подробнее смотреть в п.4

3. Анализ текущего модуля

AnalyseCurrentModule()

Не знаю, нужно ли это было здесь, но все равно. Пример в файле Analyse.py

4.Результат работы скрипта – информационные функции


Log(”message”) – запись в лог
Flashmes(“message”)
msg(адрес,”message”)
Err(“message”) – вывод сообщения об ошибке
Info(“message”)


Пример работы в файле Inf_func.py

5. Получение адреса библиотечной функции
Пример:


addr_ = Getfuncaddr("kernel32.LoadLibraryA")


и вывод в лог


Info("LoadLibraryA address %X" %int(addr_))


6. Ассемблирование команды


Asm(“команда”,адрес)


Пример:


Asm("sub eax,eax",0x0401000)


Теперь по адресу 0x0401000 инструкция sub eax,eax

7. Постановка хардварного бряка


Sethardbp(address,size,type)


Варианты типа бряка (последний аргумент)


HB_CODE бряк на исполнение
HB_ACCESS бряк на доступ
HB_WRITE бряк на запись


Пример постановки бряка на библиотечную функцию


laddr = Getfuncaddr("kernel32.LoadLibraryA")
Sethardbp(long(laddr),4,HB_CODE)



Вся работа с бряками в файле breaks.py

8. Удаление хардварного бряка

Удалить хардварный бряк можно двумя способами. Используя функцию


Deletehardbp(index)


или


Deletehardbpbyaddr(адрес)


В первом случае указываете значение от 0 до 3 – номер бряка. Во втором – адрес, по которому поставлен бряк.

9. Исполнение программы

Функция Run () – эквивалент F9
Функция StepF8() – F8
Функция StepF7() - F7
Функция RunRet() – Ctrl+F9

Пример в файле ex.py

10. Атач к процессу

Можно осуществить двумя способами. Если вам известен ProcessId, то воспользуйтесь функцией


Attach(pid)


Если же вам известно имя процесса в памяти, то


Attachbyname(procname)


Пример в файле Attach.py

11. Постановка мемори-бряков

Функция


Setmembp(type,addr,size)


Варианты первого параметра


MEMBP_READ мемори-бряк на чтение
MEMBP_WRITE мемори-бряк на запись


12.Выбор и загрузка файла в отладчик

Сначала вызов диалога открытия файла


Browsefile(title,buf,ext,mode)


title – заголовок окна
buf – буфер для имени
ext – расширение файла

Пример


buf = ""
Browsefile("Test browse",buf,".exe",0)


Если вы выберете какой-то файл – в переменной buf будет путь к этому файлу

Затем нужно вызвать функцию


Runfile(path)


Производная от OpenEXEfile из Олиного апи=)
В нашем случае


Runfile(buf)


Пример в файле open.py

13. Приостановка процесса


Suspend()


14. Восстановление всех нитей процесса


Restoreallthrd()


15. То, же, что 14, только для 1 треда


Runthread(thread_id)



16. Дамп региона в файл


Dumpreg(file_name,base,size)


file_name – имя файла
base – адрес начала региона
size – размер региона

Чтобы получить адрес начала региона воспользуйтесь функцией


Findmem(адрес_принадлежащий_ре гиону)


Функция возвращает структуру


typedef struct t_memory { // Memory block descriptor
ulong base; // Base address of memory block
ulong size; // Size of block
ulong type; // Service information, TY_xxx
ulong owner; // Address of owner of the memory
ulong initaccess; // Initial read/write access
ulong access; // Actual status and read/write access

ulong threadid; // Block belongs to this thread or 0
char sect[SHORTLEN]; // Name of module section
char *copy; // Copy used in CPU window or NULL
ulong reserved[8]; // Reserved for plugin compatibility
} t_memory;



OllyDbg Plugin API v1.10


*взято из PluginSDK OllyDbg (так как не у всех читающих он есть)

В этой структуре нам надо 2 поля base и size…

Пример в файле dump.py

0x0c0de
07.07.2008, 21:53
17. Запись в память


Writemem(addr,buf,size)


addr – адрес
buf – откуда копируем байты
size – размер буфера

18. Дизассемблирование команды


Disassm(addr,type)


Первый параметр – адрес, по которому нужно дизассемблировать команду
Второй параметр – тип дизасма


DISASM_SIZE получение длины команды
DISASM_ALL полное дизассемблирование


Функция возвращает структуру t_disasm


typedef struct t_disasm { // Results of disassembling
ulong ip; // (*) Instrucion pointer
char dump[TEXTLEN]; // Hexadecimal dump of the command
char result[TEXTLEN]; // Disassembled command
char comment[TEXTLEN]; // Brief comment
char opinfo[3][TEXTLEN]; // Comments to command's operands
int cmdtype; // (*) One of C_xxx
int memtype; // (*) Type of addressed variable in memory

int nprefix; // (*) Number of prefixes
int indexed; // Address contains register(s)
ulong jmpconst; // (*) Constant jump address
ulong jmptable; // (*) Possible address of switch table
ulong adrconst; // (*) Constant part of address
ulong immconst; // (*) Immediate constant
int zeroconst; // (*) Whether contains zero constant
int fixupoffset; // (*) Possible offset of 32-bit fixups

int fixupsize; // (*) Possible total size of fixups or 0
ulong jmpaddr; // Destination of jump/call/return
int condition; // 0xFF:unconditional, 0:false, 1:true
int error; // (*) Error while disassembling command
int warnings; // (*) Combination of DAW_xxx
int optype[3]; // Type of operand (extended set DEC_xxx)
int opsize[3]; // Size of operand, bytes

int opgood[3]; // Whether address and data valid
ulong opaddr[3]; // Address if memory, index if register
ulong opdata[3]; // Actual value (only integer operands)
t_operand op[3]; // Full description of operand
ulong regdata[8]; // Registers after command is executed
int regstatus[8]; // Status of registers, one of RST_xxx
ulong addrdata; // Traced memory address

int addrstatus; // Status of addrdata, one of RST_xxx
ulong regstack[NREGSTACK]; // Stack tracing buffer
int rststatus[NREGSTACK]; // Status of stack items
int nregstack; // Number of items in stack trace buffer
ulong reserved[29]; // Reserved for plugin compatibility
} t_disasm;



OllyDbg Plugin API v1.10


Интересное поле - текстовое представление команды – result
Небольшой пример в файле disasm_test.py

19. Ввод числа

Для этих целей существует функция


Getlng(title,size)


title – заголовок откна ввода
size – размер вводмого значения в байтах (1,2,4)

Возвращаемое значение функции – введенное число

Пример в файле example_input.py

20.Постановка темпового бряка


Tempbp(addr,type)


Адрес, тип.

21.Обычные бряки


Setbp(addr,type,cmd)


Повторюсь. Примеры использования в breaks.py

0x0c0de
07.07.2008, 21:55
22. Получение информации о модуле


Findmod(addr)


Адрес, принадлежащий модулю в качестве параметра. Функция возвращает структуру t_module . Опять привожу ее здесь, но не полностью (все тот же Plugin SDK OllyDbg). Только часто используемые поля


typedef struct t_module { // Executable module descriptor
ulong base; // Base address of module
ulong size; // Size occupied by module
ulong type; // Service information, TY_xxx
ulong codebase; // Base address of module code block
ulong codesize; // Size of module code block

ulong resbase; // Base address of resources
ulong ressize; // Size of resources
t_stringtable *stringtable; // Pointers to string resources or NULL
int nstringtable; // Actual number of used stringtable
int maxstringtable; // Actual number of allocated stringtable
ulong entry; // Address of <ModuleEntryPoint> or NULL
ulong database; // Base address of module data block

ulong idatatable; // Base address of import data table
ulong idatabase; // Base address of import data block
ulong edatatable; // Base address of export data table
ulong edatasize; // Size of export data table
ulong reloctable; // Base address of relocation table
ulong relocsize; // Size of relocation table
char name[SHORTLEN]; // Short name of the module

char path[MAXPATH]; // Full name of the module
int nsect; // Number of sections in the module
IMAGE_SECTION_HEADER *sect; // Copy of section headers from file
ulong headersize; // Total size of headers in executable
ulong fixupbase; // Base of image in executable file
int nfixup; // Number of fixups in executable
t_fixup *fixup; // Extracted fixups or NULL
…..

} t_module;

OllyDbg Plugin API v1.10



Пример использования в файле modul.py

23.Получение ид текущей нити


Getcputhrdid()


24. Получение информации о треде


Findthrd(id)


Возвращает структуру t_thread, которую я уже не привожу здесь. Смотрим пример в файле
thrd.py

25. Получение имени треда


Decodethrdname(buf, tid,mode)


Буфер для хранения имени, ид треда, режим. Пример в thrd.py

26. Обнаружение VmWare
Обнаружение VmWare.


IsVmWare()


Возвращает 0, если мы не под варей и 1 в противном случае

Пример в файле vmWarecheck.py.

27. Ввод строки пользователем

Функция


Gettxt(title,text,letter,type,ind)


Пример в файле get_text.py

28. Поиск команды “вперед” от текущей инструкции


Disasmin(addr,str)


Где первый параметр адрес, с которого надо начинать поиск. Второй – текстовое представление инструкции. Например вам нужна инструкция push ebp. Тогда вы пишите в качестве аргумента "PUSH EBP". Заглавными. Возвращаемое значение - адрес инструкции, если она найдена и 0, если не найдена.
Пример можно посмотреть в файле disasm_test.py

29. Поиск команды “назад” от текущей инструкции



Disasmback(addr,str)


Где первый параметр адрес, с которого надо начинать поиск. Второй – текстовое представление инструкции. Возвращаемое значение - адрес инструкции, если она найдена и 0, если не найдена.
Пример можно посмотреть в файле disasm_test.py

30. Поиск команда по опкоду "вперед"


Disasminbyopcode(addr,str)


То, же, что и 28, только поиск по опкоду. Например вы хотите найти инструкцию с опкодом 33 C0. Тогда в качестве второго аргумента вы пишите "33C0". без пробелов заглавными. Первым аргументом - адрес, с которого следует начинать поиск. Пример там же, где и 28,29

31. Поиск команда по опкоду "назад"


Disasmbackbyopcode(addr,str)


То, же, что и 29, только по опкоду. Описание такое же, как и в 30 и пример там же.

0x0c0de
11.07.2008, 20:13
32. Получение информации об инструкции


asmfindmodel(model)


В качестве параметра функция принимает структуру t_asmmodel
Вы вводите инструкцию в окно ввода, функция заполняет структуру t_asmmodel информацией об этой команде.

Напомню, что структура имеет вид


typedef struct t_asmmodel { // Model to search for assembler command
char code[MAXCMDSIZE]; // Binary code
char mask[MAXCMDSIZE]; // Mask for binary code (0: bit ignored)
int length; // Length of code, bytes (0: empty)
int jmpsize; // Offset size if relative jump
int jmpoffset; // Offset relative to IP
int jmppos; // Position of jump offset in command

} t_asmmodel;


Эта функция нужна для использования Findallcmds

33. Поиск команды

Findallcmds(pd,model,origin,title)


Первый параметр - структура t_dump
Второй параметр - заполненная структура t_asmmodel (см. п. 32)
Третий параметр - адрес, которого следует начинать поиск
Четвертый параметр - заголовок окна

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


typedef struct t_dump { // Current status of dump window
t_table table; // Treat dump window as custom table
int dimmed; // Draw in lowcolor if nonzero
ulong threadid; // Use decoding and registers if not 0
int dumptype; // Current dump type, DU_xxx+count+size
SPECFUNC *specdump; // Decoder of DU_SPEC dump types
int menutype; // Standard menus, MT_xxx

int itemwidth; // Length of displayed item, characters
int showstackframes; // Show stack frames in address dump
int showstacklocals; // Show names of locals in stack
int showsource; // Show source as comment in disassembler
char filename[MAXPATH]; // Name of displayed or backup file
ulong base; // Start of memory block or file
ulong size; // Size of memory block or file

ulong addr; // Address of first displayed byte
ulong lastaddr; // Address of last displayed byte + 1
ulong sel0; // Address of first selected byte
ulong sel1; // Last selected byte (not included!)
ulong startsel; // Start of last selection
int captured; // Mouse is captured by dump
ulong reladdr; // Addresses relative to this
char relname[SHORTLEN]; // Symbol for relative zero address base

char *filecopy; // Copy of the file or NULL
char *backup; // Old backup of memory/file or NULL
int runtraceoffset; // Offset back in run trace
ulong reserved[8]; // Reserved for the future extentions
} t_dump;



OllyDbg Plugin API v1.10


Достаточно заполнить поля base и size (эту информацию можно получить с помощью функции из ollylib Findmod)
Пример в файле find_cmds.py

34. Преобразование виртуального адреса в смещение в исполняемом файле


Searchfileoffset(pmod,addr)


Пример использования в файле find_file_offset.py

35. Ввод 64-битного MMX числа


GetMmx(title,data,mode)



GetMmxXY(title,data,mode)



Вторая функция тож самое, что и первая, ток можно координаты указать окна
Пример в файле get_mmx.py
Добавила прототипы функций в либу ollylib.py. Так что теперь удобней. Это лучшая справка =)

0x0c0de
16.07.2008, 10:24
Справку перезалила отдельно от основного архива, сделала скрины, обновила набор функций. За прототипами go to ollylib.py. Сам плаг тоже перезалила

download

http://0x0c0de.net/Plugin_Python.chm

0x0c0de
19.07.2008, 19:45
Полезное дополнение. 4 новых функции.

Первая фукция


Getnumberofmods()


Возвращает количество модулей, загруженных в АП отлаживаемого процесса. Возвращаемое значение типа int.

Далее функция, напрямую зависящая от предыдущей


Getmodule(number)


Принимает номер модуля в качестве параметра (номер просто для того, чтобы можно было пробежаться по всему списку модулей и найти нужный).
Возвращаемое значение - структура mod_info [я еще в нормальный вид не до конца привела - вот руки дойдут и будут вам, товарищи, все поля]


typedef struct mod_info {
ulong base;
ulong size;
...
ulong code_begin;
ulong code_size;
ulong resource;
....
ulong Entry;
ulong data_addr;
ulong imp;
....
....
char path[256];
};


Здесь, думаю все понятно. Пример использования этого всего в файле get_modules.py

Далее две аналогичные функции, только для блоков памяти


Getnumberofblocks()


Возвращает число выделенных блоков


Getmemoryblock(number)


Получает номер блока [цель номера - та же, что и в предыдущем случае]
Возвращаемое значение - структура mem_blocks
Структура mem_blocks



typedef struct mem_blocks {
ulong addr;
ulong size;
}mem_blocks;



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

nerezus
19.07.2008, 21:44
Все, что ты делаешь, это конечно круто, но:
http://www.python.org/dev/peps/pep-0008/
Naming Conventions

0x0c0de
19.07.2008, 22:12
>>http://www.python.org/dev/peps/pep-0008/
>>Naming Conventions

Оо, спасибо. не видела этого. Дельно, исправлю имеющиеся косяки в ближайшее время.