Проблемы с моей DLL в Windows 8 x64 (хотя в Win7x64 - работает!)

Тема в разделе "WASM.BEGINNERS", создана пользователем f2065, 31 дек 2011.

  1. f2065

    f2065 Eugene

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Адрес:
    Russia,Moscow
    Почему-то у меня не работает DLL под Windows 8 x64.
    regsvr32 выдаёт ошибку:

    The module test64.dll failed to load.
    Make sure the binary is stored at the specified path or debug it to check for problems with the binary or dependent .DLL files.
    Invalid access to memory location.

    В гугле решения найти не удалось (только вот понятно что это ошибка error 998 - но почему непонятно).

    В Windows XP 64bit и в Windows 7 64bit - кладу свою test64.dll в C:\Windows\System32, и в CMD-консоле запускаю
    C:\>regsvr32 test64.dll
    Всё отлично, контрольные MessageBoxы вылезают, всё работает. Единственное есть багофича с наследованием у консоли - консоль должна быть открыта через Win+R или проводник, если же она запущена из-под 32-битного файлового менеджера - то 64-битную DLL не позволяет регистрировать в windows\system32, только в пользовательских папках с явным указанием пути.

    Ну а проблема то собственно с Windows 8 x64. Там моя test64.dll не работает вообще никак и ни из каких папок. И в C:\Windows\System32, и просто в несистемных папках, и пути в regsvr32 указывал, и UAC вырублен полностью, я админ, и пробовал написать .cmd и запускать его Run as Adminstrator… В любом случае итог один - Invalid access to memory location. И ни одного моего контрольного MessageBox не вылезает - т.е. DLL тупо не открывается вообще - DllEntryPoint не вызывается.

    Другие варианты запуска (через реестр) тоже не работают. Собственно, с этого и началось разбирательство. Есть моя программка (COM-сервер расширения оболочки) которая работает во всех 64битных виндах (xp, 7, 2008), но вот в Win8 обнаружил что не работает. В процессе чего набросал такой вот простейший пример test64.dll - и убедился что в Win8 он тоже не работает…

    Есть идеи в чём у меня тут ошибка то ?

    Код (Text):
    1. ; build in FASM v.1.69.35
    2. ; X:\ASM\FASM\FASM.EXE test64dll.asm test64.dll
    3.  
    4. format PE64 GUI 4.0 DLL
    5. entry DllEntryPoint
    6.  
    7. include 'X:\ASM\FASM\INCLUDE\WIN64A.INC'
    8.  
    9. section '.idata' import data readable writeable
    10. library user32,'USER32.DLL'
    11. import user32,MessageBoxA,'MessageBoxA'
    12.  
    13. section '.text' code readable executable
    14.  
    15. proc DllEntryPoint .hinstDLL,.fdwReason,.lpvReserved
    16.     invoke  MessageBoxA, 0, t_DllEntryPoint, t_test64, MB_OK
    17.     mov rax, 1
    18.     ret
    19. endp
    20.  
    21. proc DllCanUnloadNow
    22.     invoke  MessageBoxA, 0, t_DllCanUnloadNow, t_test64, MB_OK
    23.     mov rax, 0
    24.     ret
    25. endp
    26.  
    27. proc DllGetClassObject, rclsid,riid,ppv
    28.     mov [rclsid], rcx
    29.     mov [riid], rdx
    30.     mov [ppv], r8
    31.     push    rdi
    32.     sub rsp, 8 ; stack align
    33.     invoke  MessageBoxA, 0, t_DllGetClassObject, t_test64, MB_OK
    34.     mov rdi, [ppv]
    35.     mov qword [rdi], 0
    36.     mov rax, 0x80040111 ; CLASS_E_CLASSNOTAVAILABLE
    37.     add rsp, 8
    38.     pop rdi
    39.     ret
    40. endp
    41.  
    42. proc DllRegisterServer
    43.     invoke  MessageBoxA, 0, t_DllRegisterServer, t_test64, MB_OK
    44.     mov rax, 0
    45.     ret
    46. endp
    47.  
    48. proc DllUnregisterServer
    49.     invoke  MessageBoxA, 0, t_DllUnregisterServer, t_test64, MB_OK
    50.     mov rax, 0
    51.     ret
    52. endp
    53.  
    54. section '.bss' data readable writeable
    55. t_test64 db 'test64.dll',0
    56. t_DllEntryPoint db 'DllEntryPoint',0
    57. t_DllCanUnloadNow db 'DllCanUnloadNow',0
    58. t_DllGetClassObject db 'DllGetClassObject',0
    59. t_DllRegisterServer db 'DllRegisterServer',0
    60. t_DllUnregisterServer db 'DllUnregisterServer',0
    61.  
    62. section '.edata' export data readable
    63. export 'test64.DLL',\
    64.     DllEntryPoint,'DllEntryPoint',\
    65.     DllCanUnloadNow,'DllCanUnloadNow',\
    66.     DllGetClassObject,'DllGetClassObject',\
    67.     DllRegisterServer,'DllRegisterServer',\
    68.     DllUnregisterServer,'DllUnregisterServer'
    69.  
    70. section '.reloc' fixups data discardable
    Дизассемблировал DllEntryPoint:
    Код (Text):
    1. Section 2. (virtual address 00002000)
    2. Virtual size : 00000155
    3. Section size in file : 00000200
    4. Offset to raw data for section : 00000600
    5. Flags 60000020 : Text Executable Readable
    6. Alignment : default
    7. Exported entry 1. DllEntryPoint
    8.  
    9. Segment type: Pure code
    10. Segment permissions: Read/Execute
    11. _text segment para public 'CODE' use64
    12. assume cs:_text
    13. org 402000h
    14. assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
    15.  
    16. ; Attributes: bp-based frame
    17.  
    18. ; BOOL __stdcall DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
    19. public DllEntryPoint
    20. DllEntryPoint proc near
    21. push rbp
    22. mov rbp, rsp
    23. sub rsp, 20h
    24. mov rcx, 0 ; hWnd
    25. mov rdx, offset Text ; "DllEntryPoint"
    26. mov r8, offset Caption ; "test64.dll"
    27. mov r9, 0 ; uType
    28. call cs:MessageBoxA
    29. add rsp, 20h
    30. mov rax, 1
    31. leave
    32. retn
    33. DllEntryPoint endp
     
  2. f2065

    f2065 Eugene

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Адрес:
    Russia,Moscow
    Никто что ли под win8 ещё не пишет dll ? Уже ведь несколько месяцев как win8-бета выложена…

    Вобщем, методом тыка и анализа других немногочисленных примеров - удалил строчку section '.reloc'…
    И в Win8 заработало!

    Но зато сломалось в WinXP64 (LoadLibrary failed - Attempt to access invalid address) и Win7x64 (Invalid access to memory location).

    Далее обнаружил что проблема касается не только win8x64, а вообще обоих Win8 - в 32битной точно такая же ошибка (разумеется там я написал 32битную DLL).

    Может теперь какие-нибудь идеи будут ?
    Что надо явным образом написать в '.reloc' чтобы работало и в WinXP/Win7 и в Win8 ?

    Собрал эту же DLL в MASM x64 v10 - она работает и в xp64, и в win8x64…
    Проблема у FASM…
     
  3. f2065

    f2065 Eugene

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Адрес:
    Russia,Moscow
    Проблема решена.
    Если кому интересно - у FASM (даже вот в том дистрибутиве что на оф.сайте на сегодня есть) кривые примеры .dll в \examples.
    Причём это я уже 3 раз сталкиваюсь с проблемами которые как потом обнаруживаю - из-за ошибок в примерах и в инклюдах у FASM…

    Секции .reloc вообще не должно быть.
    В конце секции .text (для dll) надо вставить две строчки:
    data fixups
    end data
    и теперь dll работает как в winxp/win7, так и в win8.
    причём всё это актуально и для 32битной винды и для 64битной.
     
  4. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    Это вы методом тыка нашли?
    А принцип объяснить можете?
    Почему это секции релоков быть не должно и при этом сами же тычете релоки в секцию кода? О_О
     
  5. f2065

    f2065 Eugene

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Адрес:
    Russia,Moscow
    Когда стало ясно что проблема в FASM - в гугле и на оф.форуме нашёл много обсуждений. На оф.форуме по ссылкам можно найти и высказывание самого автора FASM что можно вот сделать так… Ну и - работает! Я уже тщательно проверил на реальной сложной DLL, на всех виндах - XP32, 2003r2-32, XP64, 7-32, 7-64, 2008r2-64, 8-32, 8-64 - всё работает - проблема решена.

    Неа, я во внутренностях .exe разбираюсь плохо. :dntknw: Но по вышеуказанной ссылке про это много страниц обсуждений…
     
  6. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    /*решил не влазить в дискуссию*/
     
  7. f2065

    f2065 Eugene

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Адрес:
    Russia,Moscow
    Для желающих всё-же разобраться с причинами…
    Сейчас проверил в Windows 8.
    Вот в том исходнике что в первом сообщении - дописал в конце «dd ?» - не работает… Попробовал также «dq 0» или «dq ?» - тоже не работает.

    а удаляю строчку «section '.reloc'…» вообще, и пишу перед section '.bss' :
    Код (Text):
    1. endp
    2.  
    3. data    fixups
    4. end     data
    5.  
    6. section '.bss' data readable writeable
    И оно работает в Windows 8… Ну и в других виндах тоже.

    Вообще на оф.форуме фасма тоже видел такой совет что в секцию писать dd или dd 2000 dup… Но мне не помогло, а к тому же там упомянуто что вот в последних версиях фасма это не работает, а в предыдущих работало.

    кстати секция .reloc не пустая, там два адреса… смотрел при помощи PEBrowse.
    Посмотрел на 64-битные dll от winrar и 7zip - у них секции .reloc есть, но в Win8 работают нормально… Вероятно какая-то совокупность других параметров заголовка вместе с .reloc в FASM приводит к тому что в win8 проблема.

    вот в аттаче test64dll_v2.rar три варианта скомпилировал: c fixup в text (работает везде), и с reloc-секцией (не работает в win8) - один по дефолту другой секция раздута до 0x2000 (но всё это не помогло).

    Код (Text):
    1. ; build in FASM v.1.69.35
    2. ; X:\ASM\FASM\FASM.EXE test64dll.asm test64.dll
    3.  
    4. format PE64 GUI 4.0 DLL
    5. entry DllEntryPoint
    6.  
    7. include 'X:\ASM\FASM\INCLUDE\WIN64A.INC'
    8.  
    9. section '.idata' import data readable writeable
    10. library user32,'USER32.DLL'
    11. import user32,MessageBoxA,'MessageBoxA'
    12.  
    13. section '.text' code readable executable
    14.  
    15. proc DllEntryPoint .hinstDLL,.fdwReason,.lpvReserved
    16.     lea rax, [t_DllEntryPoint_p_a]
    17.     cmp rdx, DLL_PROCESS_ATTACH
    18.     je  .m0
    19.     lea rax, [t_DllEntryPoint_p_d]
    20.     cmp rdx, DLL_PROCESS_DETACH
    21.     je  .m0
    22.     lea rax, [t_DllEntryPoint_t_a]
    23.     cmp rdx, DLL_THREAD_ATTACH
    24.     je  .m0
    25.     lea rax, [t_DllEntryPoint_t_d]
    26.     cmp rdx, DLL_THREAD_DETACH
    27.     je  .m0
    28.     lea rax, [t_DllEntryPoint_unknow]
    29. .m0:    mov rdx, rax
    30.     call    msgbox
    31.     mov rax, 1
    32.     ret
    33. endp
    34.  
    35. proc DllCanUnloadNow
    36.     lea rdx, [t_DllCanUnloadNow]
    37.     call    msgbox
    38.     xor rax, rax
    39.     ret
    40. endp
    41.  
    42. proc DllGetClassObject, rclsid,riid,ppv
    43.     mov [rclsid], rcx
    44.     mov [riid], rdx
    45.     mov [ppv], r8
    46.     lea rdx, [t_DllGetClassObject]
    47.     call    msgbox
    48.     mov rax, [ppv]
    49.     mov qword [rax], 0
    50.     mov rax, 0x80040111 ; CLASS_E_CLASSNOTAVAILABLE
    51.     ret
    52. endp
    53.  
    54. proc DllRegisterServer
    55.     lea rdx, [t_DllRegisterServer]
    56.     call    msgbox
    57.     xor rax, rax
    58.     ret
    59. endp
    60.  
    61. proc DllUnregisterServer
    62.     lea rdx, [t_DllUnregisterServer]
    63.     call    msgbox
    64.     invoke  MessageBoxA, 0, t_DllUnregisterServer, t_test64, MB_OK
    65.     xor rax, rax
    66.     ret
    67. endp
    68.  
    69. msgbox: sub rsp, 0x28
    70.     xor r9, r9 ; MB_OK
    71.     lea r8, [t_test64]
    72.     xor rcx, rcx
    73.     call    [MessageBoxA]
    74.     add rsp, 0x28
    75.     retn
    76.  
    77. ;data    fixups
    78. ;end     data
    79.  
    80. section '.bss' data readable writeable
    81. include 'build_datetime.inc'
    82. t_test64 db 'test64.dll ', build_datetime, 0
    83. t_DllEntryPoint_p_a db 'DllEntryPoint_process_attach',0
    84. t_DllEntryPoint_p_d db 'DllEntryPoint_process_detach',0
    85. t_DllEntryPoint_t_a db 'DllEntryPoint_thread_attach',0
    86. t_DllEntryPoint_t_d db 'DllEntryPoint_thread_detach',0
    87. t_DllEntryPoint_unknow db 'DllEntryPoint_unknow',0
    88. t_DllCanUnloadNow db 'DllCanUnloadNow',0
    89. t_DllGetClassObject db 'DllGetClassObject',0
    90. t_DllRegisterServer db 'DllRegisterServer',0
    91. t_DllUnregisterServer db 'DllUnregisterServer',0
    92.  
    93. section '.edata' export data readable
    94. export 'test64.dll',\
    95.     DllEntryPoint,'DllEntryPoint',\
    96.     DllCanUnloadNow,'DllCanUnloadNow',\
    97.     DllGetClassObject,'DllGetClassObject',\
    98.     DllRegisterServer,'DllRegisterServer',\
    99.     DllUnregisterServer,'DllUnregisterServer'
    100.  
    101. section '.reloc' fixups data discardable
    102. ;dq 0
    103. ;dq 0x2000 dup 0
     
  8. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    f2065
    Здесь неважно, что именно дописывать. Важно, чтобы хотя бы виртуальный размер секции был ненулевым. В противном случае Windows откажется грузить образ. И это не баг fasm, и ошибок в примерах fasm тоже нет. Все когда-либо предлагаемые решения (от добавления dd ? до переноса директории релоков в общую с чем-нибудь секцию) относятся именно к этой проблеме.

    Но конкретно в Вашем случае (доселе невиданная) проблема явно в чём-то другом. Вполне вероятно, что здесь как раз таки баг fasm'а. Была бы у меня восьмёрка, я бы обязательно потестировал. Вопрос имеет смысл запостить на форуме fasm с явным указанием на то, что пустых секций в образе нет.