[Bug 46019] Adobe Digital Editions 4.5.9 installer fails, reports ' Adobe Digital Editions 4.5 is already running' ( invalid module handle passed to 'FreeLibrary()', causing code dll unmapped as data dll)

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Oct 20 06:28:17 CDT 2018


https://bugs.winehq.org/show_bug.cgi?id=46019

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |focht at gmx.net
           Keywords|                            |Installer
          Component|-unknown                    |kernel32
            Summary|Adobe Digital Editions      |Adobe Digital Editions
                   |4.5.9 doesn't install:      |4.5.9 installer fails,
                   |claims ``Adobe Digital      |reports 'Adobe Digital
                   |Editions 4.5 is already     |Editions 4.5 is already
                   |running``, then             |running' (invalid module
                   |aborts/crashes              |handle passed to
                   |                            |'FreeLibrary()', causing
                   |                            |code dll unmapped as data
                   |                            |dll)

--- Comment #4 from Anastasius Focht <focht at gmx.net> ---
Hello folks,

confirming.

--- snip ---
$ wine ./ADE_4.5_Installer.exe 
wine: Unhandled page fault on read access to 0x00000000 at address 0x10001559
(thread 0009), starting debugger...
Unhandled exception: page fault on read access to 0x00000000 in 32-bit code
(0x10001559).
Register dump:
 CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b
 EIP:10001559 ESP:0033fcf8 EBP:004072f0 EFLAGS:00010a06(  R- --O I   - -P- )
 EAX:00000000 EBX:00000000 ECX:0043a020 EDX:00000000
 ESI:00149918 EDI:00422ec0
...
Backtrace:
=>0 0x10001559 in system (+0x1559) (0x004072f0)
0x10001559: testl    %eax,0x0(%eax)
Modules:
Module    Address            Debug info    Name (109 modules)
PE      400000-  43a000    Deferred        ade_4.5_installer
PE    10000000-10006000    Export          system
ELF    7ac00000-7ac86000    Deferred        riched20<elf>
  \-PE    7ac10000-7ac86000    \               riched20
ELF    7b400000-7b7ed000    Deferred        kernel32<elf>
  \-PE    7b420000-7b7ed000    \               kernel32
ELF    7bc00000-7bd00000    Deferred        ntdll<elf>
  \-PE    7bc10000-7bd00000    \               ntdll
ELF    7c000000-7c004000    Deferred        <wine-loader>
...
Threads:
process  tid      prio (all id:s are in hex)
00000008 (D) Z:\home\focht\Downloads\ADE_4.5_Installer.exe
    00000029    0
    00000009    0 <==
--- snip ---

The installer is NSIS based, and as Louis already mentioned you can unpack it
using 7zip. Listing of content:

--- snip ---
$ 7z l ADE_4.5_Installer.exe 

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.utf8,Utf16=on,HugeFiles=on,64 bits,8 CPUs
Intel(R) Core(TM) i7-4700HQ CPU @ 2.40GHz (306C3),ASM,AES-NI)

Scanning the drive for archives:
1 file, 8906168 bytes (8698 KiB)

Listing archive: ADE_4.5_Installer.exe

--
Path = ADE_4.5_Installer.exe
Type = PE
Physical Size = 8906168
CPU = x86
Characteristics = Executable 32-bit NoRelocs NoLineNums NoLocalSyms
Created = 2016-12-11 23:50:45
Headers Size = 1024
Checksum = 8971119
Name = DigitalEditions.exe
Image Size = 237568
Section Alignment = 4096
File Alignment = 512
Code Size = 24576
Initialized Data Size = 118784
Uninitialized Data Size = 1024
Linker Version = 6.0
OS Version = 4.0
Image Version = 6.0
Subsystem Version = 4.0
Subsystem = Windows GUI
DLL Characteristics = Relocated NX-Compatible NoSEH TerminalServerAware
Stack Reserve = 1048576
Stack Commit = 4096
Heap Reserve = 1048576
Heap Commit = 4096
Image Base = 4194304
Comment = FileVersion: 4.5.9.0
FileVersion: 1.0
ProductVersion: 4.5.9.0
CompanyName: Adobe Systems Incorporated
Debugger: 0
FileDescription: Adobe Digital Editions 4.5.9
InternalName: Adobe Digital Editions 4.5.9
LegalCopyright: © 2006-2018 Adobe Systems Incorporated and its licensors. All
rights reserved.
LegalTrademarks: Adobe® Digital Editions
OriginalFilename: DigitalEditions.exe
ProductName: Adobe Digital Editions 4.5.9
----
Path = [0]
Size = 8826272
Packed Size = 8826272
Virtual Size = 8826272
Offset = 72192
--
Path = [0]
Type = Nsis
Physical Size = 8826269
Tail Size = 3
Method = LZMA:23
Solid = +
Headers Size = 1466291
Embedded Stub Size = 0
SubType = NSIS-3 BadCmd=11

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
                    .....        11264      8826265  $PLUGINSDIR/System.dll
                    .....        14848               $PLUGINSDIR/UAC.dll
2018-09-25 08:53:26 .....      2037784               DigitalEditions.exe
2018-09-25 08:53:20 .....       220184               ADEAutoUpdater_450.exe
2018-09-25 08:55:18 .....     10306072               rmsdk_wrapper.dll
2018-09-25 08:54:40 .....       246296               migration.exe
2018-09-25 08:54:38 .....       306712               log4net.dll
...
2018-09-25 08:13:58 .....        95297               $DOCUMENTS/My Digital
Editions/welcome.epub
2018-09-25 08:13:58 .....          902               $DOCUMENTS/My Digital
Editions/Manifest/welcome.epub.xml
2018-09-25 08:13:58 .....       162633               $DOCUMENTS/My Digital
Editions/welcome.epub
2018-09-25 08:13:58 .....                            $DOCUMENTS/My Digital
Editions/Manifest/welcome.epub.xml
------------------- ----- ------------ ------------  ------------------------
2018-09-25 08:55:48           25075078      8826265  86 files
--- snip ---

Trace log:

--- snip ---
$ WINEDEBUG=+seh,+relay wine ./ADE_4.5_Installer.exe >>log.txt 2>&1
...
002a:Call KERNEL32.GetModuleHandleA(00409800
"C:\\users\\focht\\Temp\\nso7084.tmp\\System.dll") ret=00402030
002a:Ret  KERNEL32.GetModuleHandleA() retval=00000000 ret=00402030
002a:Call KERNEL32.LoadLibraryExA(00409800
"C:\\users\\focht\\Temp\\nso7084.tmp\\System.dll",00000000,00000008)
ret=00402040
002a:Call PE DLL (proc=0x1000270b,module=0x10000000
L"System.dll",reason=PROCESS_ATTACH,res=(nil))
002a:Call KERNEL32.VirtualProtect(1000404c,00000004,00000040,1000403c)
ret=1000272f
002a:Ret  KERNEL32.VirtualProtect() retval=00000001 ret=1000272f
002a:Ret  PE DLL (proc=0x1000270b,module=0x10000000
L"System.dll",reason=PROCESS_ATTACH,res=(nil)) retval=1
002a:Ret  KERNEL32.LoadLibraryExA() retval=10000000 ret=00402040
002a:Call KERNEL32.GetProcAddress(10000000,00409400 "Call") ret=0040204f
002a:Ret  KERNEL32.GetProcAddress() retval=100016bd ret=0040204f
...
002a:Call KERNEL32.FreeLibrary(100016bd) ret=004020ba
002a:Ret  KERNEL32.FreeLibrary() retval=00000001 ret=004020ba 
...
002a:Call KERNEL32.GetModuleHandleA(00409800
"C:\\users\\focht\\Temp\\nso7084.tmp\\UAC.dll") ret=00402030
002a:Ret  KERNEL32.GetModuleHandleA() retval=00000000 ret=00402030
002a:Call KERNEL32.LoadLibraryExA(00409800
"C:\\users\\focht\\Temp\\nso7084.tmp\\UAC.dll",00000000,00000008) ret=00402040 
002a:Call PE DLL (proc=0x10002854,module=0x10000000
L"UAC.dll",reason=PROCESS_ATTACH,res=(nil))
002a:Ret  PE DLL (proc=0x10002854,module=0x10000000
L"UAC.dll",reason=PROCESS_ATTACH,res=(nil)) retval=1
002a:Ret  KERNEL32.LoadLibraryExA() retval=10000000 ret=00402040
002a:Call KERNEL32.GetProcAddress(10000000,00409400 "_") ret=0040204f
002a:Ret  KERNEL32.GetProcAddress() retval=10002017 ret=0040204f 
...
002a:Ret  PE DLL (proc=0x7d117d20,module=0x7d100000
L"secur32.dll",reason=PROCESS_ATTACH,res=(nil)) retval=1
002a:Ret  KERNEL32.LoadLibraryA() retval=7d100000 ret=1000188d
002a:Call KERNEL32.GetProcAddress(7d100000,10001224 "GetUserNameExA")
ret=10001895
002a:Ret  KERNEL32.GetProcAddress() retval=7d1033e4 ret=10001895
002a:Call KERNEL32.GetProcAddress(7e690000,1000123c "CreateProcessWithLogonW")
ret=100018a2
002a:Ret  KERNEL32.GetProcAddress() retval=7e6a0534 ret=100018a2
002a:Call KERNEL32.GetProcAddress(7dc60000,10001254 "SHGetValueA") ret=100018af
002a:Ret  KERNEL32.GetProcAddress() retval=7dc6c1f8 ret=100018af
002a:Call KERNEL32.CreateEventA(00000000,00000000,00000000,00000000)
ret=100020c2
002a:Ret  KERNEL32.CreateEventA() retval=00000060 ret=100020c2
002a:Call KERNEL32.CreateEventA(00000000,00000000,00000000,00000000)
ret=100020d1
002a:Ret  KERNEL32.CreateEventA() retval=00000064 ret=100020d1
002a:Call
KERNEL32.CreateFileMappingA(ffffffff,00000000,08000004,00000000,00002804,00000000)
ret=100020f1
002a:Ret  KERNEL32.CreateFileMappingA() retval=00000068 ret=100020f1
002a:Call KERNEL32.MapViewOfFile(00000068,000f001f,00000000,00000000,00000000)
ret=10002109
002a:Ret  KERNEL32.MapViewOfFile() retval=00390000 ret=10002109
002a:Call
KERNEL32.CreateThread(00000000,00000001,10001cd8,00000000,00000000,00000000)
ret=10002137
002a:Ret  KERNEL32.CreateThread() retval=0000006c ret=10002137
002a:Call KERNEL32.WaitForSingleObject(00000064,ffffffff) ret=10002156 
002a:Call KERNEL32.WaitForSingleObject(00000064,ffffffff) ret=10002156
...
002b:Call PE DLL (proc=0x1000270b,module=0x10000000
L"System.dll",reason=THREAD_ATTACH,res=(nil))
002b:Call user32.UnhookWindowsHookEx(00000000) ret=1000271a
002b:Ret  user32.UnhookWindowsHookEx() retval=00000000 ret=1000271a
002b:Call KERNEL32.CloseHandle(00000000) ret=100027bf
002b:Ret  KERNEL32.CloseHandle() retval=00000000 ret=100027bf
002b:trace:seh:raise_exception code=c0000005 flags=0 addr=0x100027d6
ip=100027d6 tid=002b
002b:trace:seh:raise_exception  info[0]=00000000
002b:trace:seh:raise_exception  info[1]=00000000
002b:trace:seh:raise_exception  eax=1000270b ebx=7bce2000 ecx=00000000
edx=c0000001 esi=00fbeb68 edi=7bce2000
002b:trace:seh:raise_exception  ebp=00fbeb68 esp=00fbeb48 cs=0023 ds=002b
es=002b fs=0063 gs=006b flags=00010283
002b:trace:seh:call_stack_handlers calling handler at 0x7bca53e0 code=c0000005
flags=0
002b:trace:seh:__regs_RtlUnwind code=c0000005 flags=2
002b:trace:seh:__regs_RtlUnwind eax=00000000 ebx=7bca5270 ecx=00fbeaf0
edx=00fbebec esi=00fbebec edi=7bca5270
002b:trace:seh:__regs_RtlUnwind ebp=00fbe6a8 esp=00fbe688 eip=7bca52cd cs=0023
ds=002b fs=0063 gs=006b flags=00000206
002b:trace:seh:__regs_RtlUnwind calling handler at 0x7bc816b0 code=c0000005
flags=2
002b:trace:seh:__regs_RtlUnwind handler at 0x7bc816b0 returned 1
002b:exception c0000005 in PE entry point
(proc=0x1000270b,module=0x10000000,reason=THREAD_ATTACH,res=(nil)) 
...
002a:Call KERNEL32.GetModuleHandleA(00409800
"C:\\users\\focht\\Temp\\nso7084.tmp\\System.dll") ret=00402030
002a:Ret  KERNEL32.GetModuleHandleA() retval=10000000 ret=00402030
002a:Call KERNEL32.GetProcAddress(10000000,00409400 "Call") ret=0040204f
002a:Ret  KERNEL32.GetProcAddress() retval=00000000 ret=0040204f
...
002a:Call KERNEL32.lstrcpynA(0040a000,004226c0 "Adobe Digital Editions 4.5 is
already running. Please close Adobe Digital Editions 4.5 and try
again.",00000400) ret=00405f0a
002a:Ret  KERNEL32.lstrcpynA() retval=0040a000 ret=00405f0a
002a:Call user32.MessageBoxIndirectA(00409230) ret=0040574e
--- snip ---

Another example of Adobe living up to its standards, producing garbage code.
Disassembly of installer app code:

--- snip ---
00402029  PUSH ESI
0040202A  CALL DWORD PTR DS:[<&KERNEL32.GetModuleHandleA>]
00402030  MOV EDI,EAX
00402032  CMP EDI,EBX
00402034  JNE SHORT 00402046
00402036  PUSH 8
00402038  PUSH EBX
00402039  PUSH ESI
0040203A  CALL DWORD PTR DS:[<&KERNEL32.LoadLibraryExA>]
00402040  MOV EDI,EAX
00402042  CMP EDI,EBX
00402044  JE SHORT 004020BF
00402046  PUSH DWORD PTR SS:[EBP+8]
00402049  PUSH EDI
0040204A  CALL <JMP.&KERNEL32.GetProcAddress> ; get API entry
0040204F  MOV ESI,EAX
00402051  CMP ESI,EBX
00402053  JE SHORT 00402092
00402055  CMP DWORD PTR SS:[EBP-20],EBX
00402058  MOV DWORD PTR SS:[EBP-4],EBX
0040205B  JE SHORT 00402074
0040205D  PUSH DWORD PTR SS:[EBP-20]
00402060  CALL 00401423
00402065  CALL ESI
00402067  TEST EAX,EAX
00402069  JZ SHORT 0040209C
0040206B  MOV DWORD PTR SS:[EBP-4],1
00402072  JMP SHORT 0040209C
00402074  PUSH OFFSET 00409000          ; callback1
00402079  PUSH OFFSET 0040A804          ; callback2
0040207E  PUSH OFFSET 00424000          ; callback3
00402083  PUSH 400
00402088  PUSH DWORD PTR SS:[EBP-8]
0040208B  CALL ESI                      ; call API entry
0040208D  ADD ESP,14
00402090  JMP SHORT 0040209C
00402092  PUSH DWORD PTR SS:[EBP+8]
00402095  PUSH -9
00402097  CALL 00405110
0040209C  CMP DWORD PTR SS:[EBP-1C],EBX
0040209F  JNE 0040295E
004020A5  PUSH EDI
004020A6  CALL 00403817
004020AB  TEST EAX,EAX
004020AD  JZ 0040295E
004020B3  PUSH EDI                      ; function clobbered EDI lowbits
004020B4  CALL DWORD PTR DS:[<&KERNEL32.FreeLibrary>]
004020BA  JMP 0040295E
--- snip ---

The helper library clobbers EDI in the API entry point.
Register EDI is supposed to hold the module handle but neither caller nor
callee saves it across the entry point call.

--- snip ---
002a:Call KERNEL32.FreeLibrary(100016bd) ret=004020ba
002a:Ret  KERNEL32.FreeLibrary() retval=00000001 ret=004020ba 
--- snip ---

Wine happily unmaps the library because it thinks it's a data dll (low bits set
due to clobber). Later, the app loads another helper lib 'UAC.dll' which gets
mapped to 0x10000000 (re-occupies the same load address as former
'system.dll').
'UAC.dll' creates a thread, causing OS loader notifications to be sent to all
dll entry points, including the one that was mistakenly unmapped as data dll.
Since the module data from 'system.dll' is still in loader module list, the old
dll entry point from 'system.dll' is called. 'UAC.dll' code is now mapped in
this place, causing exception.

Wine's FreeLibrary() code should be more robust to handle the case of
braindamaged/broken apps better.

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/kernel32/module.c#l1080

--- snip ---
1080 /***********************************************************************
1081  *           FreeLibrary   (KERNEL32.@)
1082  *
1083  * Free a dll loaded into the process address space.
1084  *
1085  * PARAMS
1086  *  hLibModule [I] Handle to the dll returned by LoadLibraryA().
1087  *
1088  * RETURNS
1089  *  Success: TRUE. The dll is removed if it is not still in use.
1090  *  Failure: FALSE. Use GetLastError() to determine the cause.
1091  */
1092 BOOL WINAPI DECLSPEC_HOTPATCH FreeLibrary(HINSTANCE hLibModule)
1093 {
1094     BOOL                retv = FALSE;
1095     NTSTATUS            nts;
1096 
1097     if (!hLibModule)
1098     {
1099         SetLastError( ERROR_INVALID_HANDLE );
1100         return FALSE;
1101     }
1102 
1103     if ((ULONG_PTR)hLibModule & 3) /* this is a datafile module */
1104     {
1105         if ((ULONG_PTR)hLibModule & 1)
1106         {
1107             struct exclusive_datafile *file;
1108             ULONG_PTR magic;
1109 
1110             LdrLockLoaderLock( 0, NULL, &magic );
1111             LIST_FOR_EACH_ENTRY( file, &exclusive_datafile_list, struct
exclusive_datafile, entry )
1112             {
1113                 if (file->module != hLibModule) continue;
1114                 TRACE( "closing %p for module %p\n", file->file,
file->module );
1115                 CloseHandle( file->file );
1116                 list_remove( &file->entry );
1117                 HeapFree( GetProcessHeap(), 0, file );
1118                 break;
1119             }
1120             LdrUnlockLoaderLock( 0, magic );
1121         }
1122         return UnmapViewOfFile( (void *)((ULONG_PTR)hLibModule & ~3) );
1123     }
1124 
1125     if ((nts = LdrUnloadDll( hLibModule )) == STATUS_SUCCESS) retv = TRUE;
1126     else SetLastError( RtlNtStatusToDosError( nts ) );
1127 
1128     return retv;
1129 }
--- snip ---

Before trying to unmap a dll as datafile you should check if there is a PE
header present, i.e.:

--- snip ---
if( !RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~3))) -> error out
...
--- snip ---

Even dlls, loaded via 'LoadLibraryEx( ... LOAD_LIBRARY_AS_DATAFILE)' still need
a PE header - although with only very few members required valid. Most of the
PE structure would be useless anyway since data dlls are handled completely
differently.

$ sha1sum ADE_4.5_Installer.exe 
cf271d4f749bdf0b6cfc6114f5536dfb6381fe70  ADE_4.5_Installer.exe

$ du -sh ADE_4.5_Installer.exe 
8.5M    ADE_4.5_Installer.exe

$ wine --version
wine-3.18-114-g417e94f199

Regards

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.


More information about the wine-bugs mailing list