[Python plugin for OllyDbg]

Discussion in 'Реверсинг' started by 0x0c0de, 2 Jul 2008.

  1. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    Сабж. Плаг позволяет писать скрипты на питоне под ольгу.
    Нашла 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. Там есть прототипы функций... Добавлены новые примеры и функции. Смотрим последний пост
     
    #1 0x0c0de, 2 Jul 2008
    Last edited: 11 Jul 2008
    6 people like this.
  2. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    [Описание плагина]

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

    [Скриптинг]

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

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

    Code:
     
    from ollylib import*
    
    Таким образом вы сможете использовать в вашем скрипте api OllyDbg.

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

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

    Code:
    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.Результат работы скрипта – информационные функции

    Code:
    Log(”message”) – запись в лог
    Flashmes(“message”)  
    msg(адрес,”message”)
    Err(“message”) – вывод сообщения об ошибке 
    Info(“message”) 
    
    Пример работы в файле Inf_func.py

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

    Code:
    addr_ = Getfuncaddr("kernel32.LoadLibraryA")
    
    и вывод в лог

    Code:
    Info("LoadLibraryA address %X" %int(addr_))
    
    6. Ассемблирование команды

    Code:
    Asm(“команда”,адрес)
    
    Пример:

    Code:
    Asm("sub eax,eax",0x0401000) 
    
    Теперь по адресу 0x0401000 инструкция sub eax,eax

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

    Code:
    Sethardbp(address,size,type)
    
    Варианты типа бряка (последний аргумент)

    Code:
    HB_CODE  бряк на исполнение      
    HB_ACCESS  бряк на доступ     
    HB_WRITE                    бряк на запись
     
    Пример постановки бряка на библиотечную функцию

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

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

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

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

    Code:
    Deletehardbp(index)
    
    или

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

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

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

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

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

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

    Code:
    Attach(pid)
    
    Если же вам известно имя процесса в памяти, то

    Code:
    Attachbyname(procname) 
    
    Пример в файле Attach.py

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

    Функция

    Code:
    Setmembp(type,addr,size)
    
    Варианты первого параметра

    Code:
    MEMBP_READ               мемори-бряк на чтение
    MEMBP_WRITE              мемори-бряк на запись
    
    12.Выбор и загрузка файла в отладчик

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

    Code:
    Browsefile(title,buf,ext,mode)
    
    title – заголовок окна
    buf – буфер для имени
    ext – расширение файла

    Пример

    Code:
    buf = ""
    Browsefile("Test browse",buf,".exe",0)
    
    Если вы выберете какой-то файл – в переменной buf будет путь к этому файлу

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

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

    Code:
    Runfile(buf)
    
    Пример в файле open.py

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

    Code:
     
    Suspend()
    
    14. Восстановление всех нитей процесса

    Code:
    Restoreallthrd()
    
    15. То, же, что 14, только для 1 треда

    Code:
    Runthread(thread_id)
    

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

    Code:
    Dumpreg(file_name,base,size)
    
    file_name – имя файла
    base – адрес начала региона
    size – размер региона

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

    Code:
    Findmem(адрес_принадлежащий_региону)
    
    Функция возвращает структуру

    Code:
    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
     
    #2 0x0c0de, 7 Jul 2008
    Last edited: 10 Jul 2008
    4 people like this.
  3. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    17. Запись в память

    Code:
    Writemem(addr,buf,size)
    
    addr – адрес
    buf – откуда копируем байты
    size – размер буфера

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

    Code:
    Disassm(addr,type)
     
    Первый параметр – адрес, по которому нужно дизассемблировать команду
    Второй параметр – тип дизасма

    Code:
    DISASM_SIZE    получение длины команды
    DISASM_ALL полное дизассемблирование     
    
    Функция возвращает структуру t_disasm

    Code:
    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. Ввод числа

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

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

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

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

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

    Code:
     
    Tempbp(addr,type)
    
    Адрес, тип.

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

    Code:
    Setbp(addr,type,cmd)
    
    Повторюсь. Примеры использования в breaks.py
     
    #3 0x0c0de, 7 Jul 2008
    Last edited: 7 Jul 2008
    1 person likes this.
  4. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    22. Получение информации о модуле

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

    Code:
    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.Получение ид текущей нити

    Code:
    Getcputhrdid()
    
    24. Получение информации о треде

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

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

    Code:
    Decodethrdname(buf, tid,mode)
    
    Буфер для хранения имени, ид треда, режим. Пример в thrd.py

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

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

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

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

    Функция

    Code:
     
     Gettxt(title,text,letter,type,ind)
    
    Пример в файле get_text.py

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

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

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


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

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

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

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

    Code:
     
    Disasmbackbyopcode(addr,str)
    
    То, же, что и 29, только по опкоду. Описание такое же, как и в 30 и пример там же.
     
    #4 0x0c0de, 7 Jul 2008
    Last edited: 9 Jul 2008
  5. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    32. Получение информации об инструкции

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

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

    Code:
    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. Поиск команды
    Code:
    Findallcmds(pd,model,origin,title)
    
    Первый параметр - структура t_dump
    Второй параметр - заполненная структура t_asmmodel (см. п. 32)
    Третий параметр - адрес, которого следует начинать поиск
    Четвертый параметр - заголовок окна

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

    Code:
    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. Преобразование виртуального адреса в смещение в исполняемом файле

    Code:
    Searchfileoffset(pmod,addr)
    
    Пример использования в файле find_file_offset.py

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

    Code:
    GetMmx(title,data,mode)
    
    Code:
    GetMmxXY(title,data,mode)
    

    Вторая функция тож самое, что и первая, ток можно координаты указать окна
    Пример в файле get_mmx.py
    Добавила прототипы функций в либу ollylib.py. Так что теперь удобней. Это лучшая справка =)
     
    #5 0x0c0de, 11 Jul 2008
    Last edited: 20 Jul 2008
  6. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    Справку перезалила отдельно от основного архива, сделала скрины, обновила набор функций. За прототипами go to ollylib.py. Сам плаг тоже перезалила

    download

    http://0x0c0de.net/Plugin_Python.chm
     
    2 people like this.
  7. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    Полезное дополнение. 4 новых функции.

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

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

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

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

    Code:
    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

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

    Code:
    Getnumberofblocks()
    
    Возвращает число выделенных блоков

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

    Code:
    
    typedef struct mem_blocks {
    ulong addr; 
    ulong size; 
    }mem_blocks;
    
    
    Пример этих функций было лень впихивать в отдельный скрипт, а потому там же, что и в предыдущем случае
    Все перезалито.
     
    #7 0x0c0de, 19 Jul 2008
    Last edited: 19 Jul 2008
  8. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    Все, что ты делаешь, это конечно круто, но:
    http://www.python.org/dev/peps/pep-0008/
    Naming Conventions
     
    1 person likes this.
  9. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    >>http://www.python.org/dev/peps/pep-0008/
    >>Naming Conventions

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