как имитировать структуру существующей DLL?

Тема в разделе "WASM.ASSEMBLER", создана пользователем malandrinus, 11 сен 2010.

  1. malandrinus

    malandrinus New Member

    Публикаций:
    0
    Регистрация:
    11 сен 2010
    Сообщения:
    2
    Есть задача пропатчить существующую dll. Для этого добавил в неё дополнительную секцию и теперь хочу дополнить её своим кодом а также врезками в код, существующий в других секциях.
    Для этого пытаюсь сделать следующее. Пишу свою библиотеку и пытаюсь имитировать структуру существующей, т.е. создать тот-же набор секций, находящихся по тем-же виртуальным смещениям, что и секции в исходной библиотеке. По идее это должно упростить последующий перенос фрагментов кода из моей либы в целевую.
    Использую masm32. Это выглядит примерно так (в сокращённом виде):
    Код (Text):
    1. .xmm
    2. .686p
    3. .model flat
    4. OPTION LANGUAGE:STDCALL
    5.  
    6. _text segment public 'CODE' use32
    7.     assume cs:_text
    8.     assume ds:_data
    9.     org 1000h
    10. LibMain proc instance:DWORD,reason:DWORD,unused:DWORD
    11.     ;...
    12.     ret
    13. LibMain endp
    14. _text ends
    15.  
    16. _data segment public 'DATA' use32
    17.     assume cs:_data
    18.     org 600000h
    19.     db 0FFh
    20. _data ends
    21.  
    22. _MyCode segment public 'CODE' use32
    23.     assume cs:_text
    24.     assume ds:_data
    25.     org 60D000h
    26.     nop
    27. _MyCode ends
    28.  
    29. end LibMain
    Т.е. видно, что в секциях я расставил директивы org, и между двумя секциями кода поместил секцию данных. Однако после ассемблирования и линковки получаю совсем не то, что нужно. Видно, что обе секции кода находятся вместе в начале, и после них размещена секция данных, а виртуальные смещения не имеют ничего общего с адресами из директив org.

    Непонятно, как заставить ассемблер/линковшик создать секции именно там, где мне надо.
     
  2. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    вы бредите. так никто не делает.
    пишите на фасме, делайте .bin файл и патчите им дллку
     
  3. s_d_f

    s_d_f New Member

    Публикаций:
    0
    Регистрация:
    15 май 2008
    Сообщения:
    342
    malandrinus
    Директива org, это вроде как рудимент оставшийся от 16-битной версии.
    На самом деле masm не может знать виртуальных аддресов, потому-что ассемблирует объектные модули.
    Линкеру можно явно указать базу, а также выравнивание виртуальных и файловых секций, чего как правило достаточно для эмулирования обычных т.е. не хакерских .dll`eй.
     
  4. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    s_d_f
    сами вы рудимент.
    алсо выравнивание секций != размер секций
     
  5. CyberManiac

    CyberManiac New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2003
    Сообщения:
    2.473
    Адрес:
    Russia
    Шоу только начинается. Полагаю, следующим номером будет вопрос, как впилить в старую dll новые релоки.
     
  6. s_d_f

    s_d_f New Member

    Публикаций:
    0
    Регистрация:
    15 май 2008
    Сообщения:
    342
    A что такой не вежливый.
    Надо-ли вспоминать кто обычно определяет содержимое, а за одно и разме
    р секции.
     
  7. malandrinus

    malandrinus New Member

    Публикаций:
    0
    Регистрация:
    11 сен 2010
    Сообщения:
    2
    GoldFinch,
    Это рабочая метода. Так уже делают (автор не я), и она работает, хотя есть некоторые неудобства.
    Почему именно fasm?
    Где можно почитать о методе, который вы упоминаете?

    CyberManiac,
    Это ко мне? Нет, не спрошу. С такой рутиной как-нибудь сам справлюсь. Меня интересовал конкретный вопрос. Кто-нибудь помнит, о чём он был?
     
  8. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    учите формат PE, асм, инструменты и не топчите моск честным людям %)
    метода кнешно рабочая, но она гуан*.
     
  9. baldr

    baldr New Member

    Публикаций:
    0
    Регистрация:
    29 апр 2010
    Сообщения:
    327
    Идея, в общем-то, простая. В fasm есть директива file, ей можно нарезать исходный файл хоть вдоль, хоть поперёк. Вот пример, иллюстрирующий это.
    Код (Text):
    1. format binary as "dll"
    2. file "%WinDir%\system32\user32.dll": 0, 0x61B14; смещение VS_FIXEDFILEINFO.dwFileVersionLS
    3. dw 3100; апгрейдим с 3099 до 3100
    4. file "%WinDir%\system32\user32.dll": $, 0x61C5E-$; смещение билда в строковой FileVersion
    5. du "3100"
    6. file "%WinDir%\system32\user32.dll": $; остаток файла
    Смещения забиты жёстко, но интерпретатор fasm позволяет разобрать структуру PE и собрать то, что нужно. Ключевые директивы: virtual, file, load и store, причём последняя может упростить патч до
    Код (Text):
    1. file "%WinDir%\system32\user32.dll"; оптом дешевше
    2. store word 3100 at 0x61B14
    3. store qword "3 1 0 0" and 0xFF00FF00FF00FF at 0x61C5E; маска прибъёт пробелы
    Неленивый и IMAGE_OPTIONAL_HEADER.CheckSum может поправить, но это уж кружавчики.
     
  10. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    baldr
    Ленивый тоже может. :)

    Код (Text):
    1. include 'general.inc'
    2. format binary as "dll"
    3.  
    4. IDH.e_lfanew            equ 3Ch
    5. sizeof.Signature        equ 4h
    6. sizeof.FileHeader       equ 14h
    7. IOH.CheckSum            equ 40h
    8.  
    9.  
    10. PEFile: file "%WinDir%\system32\user32.dll"
    11. PESize = $-PEFile
    12.  
    13. load PEHeader dword from PEFile + IDH.e_lfanew
    14. PEHeader = PEFile + PEHeader
    15.  
    16. PEOptionalHeader = PEHeader + sizeof.Signature + sizeof.FileHeader
    17.  
    18. ;set the checksum field to zero
    19. store dword 0 at PEOptionalHeader + IOH.CheckSum
    20.  
    21. newCheckSum = 0
    22. repeat PESize/4
    23.     load buf dword from (%-1)*4
    24.     newCheckSum = (newCheckSum + buf) and 0FFFFFFFFh + (newCheckSum + buf) shr 32
    25. end repeat
    26. newCheckSum = (newCheckSum shr 16) + (newCheckSum and 0FFFFh)
    27. newCheckSum = newCheckSum and 0FFFFh + newCheckSum shr 16 + PESize
    28.  
    29. store dword newCheckSum at PEOptionalHeader + IOH.CheckSum
    30.  
    31. display 'New checksum is: ',h=newCheckSum,10,13
    Модификация display отсюда.
     
  11. s_d_f

    s_d_f New Member

    Публикаций:
    0
    Регистрация:
    15 май 2008
    Сообщения:
    342
    Тебе лиж-бы по холиварить. Свет клином на этом fasm`e сошелся.

    Первая метода, очень хорошая. Хотя конечно те кто не в состоянии сообразить как правильно нарезать файлы без директивы file, могут думать иначе.

    При умелой доработке метода, код для дополнительной секции можно и на C++ писать.
     
  12. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    Это делается например так:
    Код (Text):
    1. """ EXE file path example,
    2.     using pefile library by Ero Carrera (http://code.google.com/p/pefile/)
    3.     and FASM compiler (http://flatassembler.net/)
    4. """
    5.  
    6. import os
    7. import tempfile
    8. import pefile
    9.  
    10. # file to patch
    11. FILE_NAME = 'some.exe'
    12.  
    13. # we can't know patch size before we compile it, so we should define it before
    14. MAX_PATCH_SIZE = 0x100
    15.  
    16. # path to FASM without backslash, like 'c:\fasm'
    17. FASM = '%FASM%'
    18.  
    19. TEMP_FILENAME = tempfile.gettempdir() + '\\patch'
    20.  
    21. pe = pefile.PE(FILE_NAME)
    22. text = pe.sections[0]
    23. textFileSize = text.SizeOfRawData + (0x1FF - (text.SizeOfRawData + 0x1FF) & 0x1FF) # aligned by 0x200
    24. patchRVA = text.VirtualAddress + textFileSize - MAX_PATCH_SIZE
    25.  
    26. k32imp = (entry.imports for entry in pe.DIRECTORY_ENTRY_IMPORT if entry.dll.lower().startswith('kernel32')).next()
    27. def get_imp_va(funcName):
    28.     return hex((imp.address for imp in k32imp if imp.name == funcName).next())
    29.  
    30. open(TEMP_FILENAME + '.asm ', 'w').write('''; THIS CODE WAS GENERATED BY SCRIPT
    31.  
    32. use32
    33.  
    34. label _LoadLibrary dword at ''' + get_imp_va('LoadLibraryA') + '''
    35. label _FindFirstFile dword at ''' + get_imp_va('FindFirstFileA') + '''
    36. label _FindNextFile dword at ''' + get_imp_va('FindNextFileA') + '''
    37. label _OriginalEntryPoint at ''' + hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint + pe.OPTIONAL_HEADER.ImageBase) + '''
    38.  
    39. include "''' + FASM + '''\include\win32a.inc"
    40.  
    41. org ''' + hex(pe.OPTIONAL_HEADER.ImageBase + patchRVA) + '''
    42. align 16
    43.  
    44. ; NewEntryPoint
    45. call LoadPlugins
    46. call _OriginalEntryPoint
    47. ret
    48.  
    49. mask db "*.plgn", 0
    50. align 16
    51.  
    52. proc LoadPlugins uses edi
    53.     local findData:WIN32_FIND_DATA
    54.     lea eax, [findData]
    55.     invoke _FindFirstFile, mask, eax
    56.     mov edi, eax
    57.     test eax, eax
    58.     jnz load_loo
    59.     ret
    60.  
    61. load_loo:
    62.     lea eax, [findData.cFileName]
    63.     invoke _LoadLibrary, eax
    64.    
    65.     lea eax, [findData]
    66.     invoke _FindNextFile, edi, eax
    67.     test eax, eax
    68.     jnz load_loo
    69.     ret
    70. endp
    71. ''')
    72.  
    73. err = os.system(FASM + '\\fasm.exe ' + TEMP_FILENAME + '.asm ' + TEMP_FILENAME + '.bin')
    74. os.remove(TEMP_FILENAME + '.asm')
    75. if err == 0:
    76.     print "\nCompiled OK. Patching."
    77.     pe.set_bytes_at_rva(patchRVA, open(TEMP_FILENAME + '.bin', 'rb').read())
    78.     pe.OPTIONAL_HEADER.AddressOfEntryPoint = patchRVA
    79.     pe.write(FILE_NAME)
    80.    
    81.     os.remove(TEMP_FILENAME + '.bin')
    82.     print "All done."
    83.  
    84. os.system("pause")
    Сделать так же для длл с релоками не проблема.
     
  13. baldr

    baldr New Member

    Публикаций:
    0
    Регистрация:
    29 апр 2010
    Сообщения:
    327
    l_inc,

    Ленивый может и editbin /release сделать. :derisive:

    Я всё не доведу до ума обёртку для display, понимающую синтаксис «display "$=", %#010x:$, 13, 10». Всё-таки привычку думать форматами printf() трудно изжить. :derisive:
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    baldr
    На измену, значит, подбиваете? :)
    То ли я далёк от printf, то ли не очень оно похоже на его формат. В любом случае никогда не сталкивался с необходимостью расширять синтаксис вывода аж настолько. Это ведь не пользовательский вывод, а для себя только.
     
  15. baldr

    baldr New Member

    Публикаций:
    0
    Регистрация:
    29 апр 2010
    Сообщения:
    327
    l_inc,

    То, что до двоеточия — легальная спецификация формата printf, означает вывести шестнаццатирично мелкими буквами с соответствующим префиксом ("0x") в поле шириной 2+8=10 с лидирующими нулями. Ну а $ — известно что. Привычка, я ж говорю. Лет двадцать назад я Фортрановскими форматами думал. :derisive:

    Ох, чую, дадут пинка за оффтоп.
     
  16. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    baldr
    Вообще, я почему-то решил, что в имитацию поведения printf входит также и обработка того, что в кавычках (ну там сохранили переданную строку "$=" директивой db в секции virtual, потом через load распарсили посимвольно и т.д.). Т.е. собственно спецификаторы должны были бы быть в кавычках. В общем, извиняюсь, неправильно понял. А спецификатор %#010x знамо, что делает, разумеется.
    Сим предлагаю оффтоп и завершить.