Found an interesting inconsistency with GetProcAddress between wine and native. On windows GetProcAddress of that's say "LoadLibraryA" exported from kernel32 always returns the same address, no matter which process it's called from.
On wine it's different. That's say there are two programs app1.exe & app2.exe. app1.exe calls app2.exe (CreateProcess, etc.). Here is what I'm getting: app1.exe: GetProcAddress(mKernel32, "LoadLibraryA") returns 0x404FCBCC app2.exe: GetProcAddress(mKernel32, "LoadLibraryA") returns 0x404FFBCC
I have tested this with more then two programs. All consecutive apps return same number as app2.exe. When any of this programs are ran under winedbg they all return same address as app2.exe.
Running separate program doesn't change this behavior for parent-child processes. Both programs started in parallel will return the same address as app1.exe.
What's more interesting, is that GetModuleHandleA("Kernel32") always returns the same handle.
Is there are any reason why this is happening? Any ways to fix this?
Unfortunately there are some programs that depend on address returned from GetProcAddress being the same in parent and child processes.
Vitaliy Margolen wrote:
app1.exe: GetProcAddress(mKernel32, "LoadLibraryA") returns 0x404FCBCC app2.exe: GetProcAddress(mKernel32, "LoadLibraryA") returns 0x404FFBCC
Is there are any reason why this is happening? Any ways to fix this?
Under Windows 98, you will always get the same address for the same export from a dll, however that's not garanteed under Windows NT (or Wine).
The problem is that mmap does not garantee that any specific area of memory will be available, so we can't always load a library at the same address.
You could "fix" it for a specific dll by reserving a memory area using the wine-preloader, but that would be a hack.
Unfortunately there are some programs that depend on address returned from GetProcAddress being the same in parent and child processes.
Which program depends upon that behaviour? It's possible that some old Windows 98 copy protections schemes depend upon it, but they should work if you change the version to win2k.
Mike
Mike McCormack wrote:
Is there are any reason why this is happening? Any ways to fix this?
Under Windows 98, you will always get the same address for the same export from a dll, however that's not garanteed under Windows NT (or Wine).
Yes it is. NTDLL and KERNEL32 are both mapped to always the same address on >=NT4 (in NT3 only NTDLL was at a fixed address however).
Felix
Felix Nawothnig wrote:
Yes it is. NTDLL and KERNEL32 are both mapped to always the same address on >=NT4 (in NT3 only NTDLL was at a fixed address however).
KERNEL32 and NTDLL are special cases because they are loaded first when the address space is empty, and since the NT kernel has no address space randomization they will consistently end up at the same address.
As far as I know, there's no *garantee* of that, it just happens to be that way. If you know otherwise, please point me to the relevant documentation. :)
Mike
Mike McCormack wrote:
Yes it is. NTDLL and KERNEL32 are both mapped to always the same address on >=NT4 (in NT3 only NTDLL was at a fixed address however).
KERNEL32 and NTDLL are special cases because they are loaded first when the address space is empty, and since the NT kernel has no address space randomization they will consistently end up at the same address.
As far as I know, there's no *garantee* of that, it just happens to be that way. If you know otherwise, please point me to the relevant documentation. :)
http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c5767/ says:
When creating a process, the loader on Win 2000, Win XP and Win 2003 checks if kernel32.dll and user32.dll (their names are hardcoded into the loader) are mapped at their preferred bases; if not, a hard error is raised. In WinNT 4 ole32.dll was also checked. In WinNT 3.51 and lower such checks were not present, so kernel32.dll and user32.dll could be anywhere. Anyway, the only module that is always at its base is ntdll.dll. The loader doesn't check it, but if ntdll.dll is not at its base, the process just can't be created.
It's a common technique to rely on the fact that exports from kernel32 reside at the same address to use CreateRemoteThread calling LoadLibrary for remote code injection (this is not what Vitaliy's App is doing here but the assertions are the same).
Felix
I have an application failing to communicate at 19200, but working at 57600. I've got about 40k of logs of DCB dumps for a case it fails (19200 baud) and the case it succeeds (57600 baud). If anyone wants I can post them here.
But...
Any particular reason why GetCommState doesn't first zero the passed structure, or set the size with sizeof()?
If an app fails to zero its supplied DCB structure for a Get, and Windows *does* then code might work for Windows and fail for Wine? I don't have a windows box to test this though.
It also strikes me that ignored DCB elements from a Set operation should be stored in a map associated with the underlying ports so the values can be retrieved on the next Get call and the 'Set' will appear to have succeeded, don't know if anyone would like to comment on that.
-biff.
___________________________________________________________ Yahoo! Messenger - NEW crystal clear PC to PC calling worldwide with voicemail http://uk.messenger.yahoo.com
"biffer" == biffer os bifferos@yahoo.co.uk writes:
biffer> I have an application failing to communicate at 19200, but biffer> working at 57600. I've got about 40k of logs of DCB dumps for a biffer> case it fails (19200 baud) and the case it succeeds (57600 biffer> baud). If anyone wants I can post them here.
biffer> But...
biffer> Any particular reason why GetCommState doesn't first zero the biffer> passed structure, or set the size with sizeof()?
biffer> If an app fails to zero its supplied DCB structure for a Get, biffer> and Windows *does* then code might work for Windows and fail for biffer> Wine? I don't have a windows box to test this though.
biffer> It also strikes me that ignored DCB elements from a Set biffer> operation should be stored in a map associated with the biffer> underlying ports so the values can be retrieved on the next Get biffer> call and the 'Set' will appear to have succeeded, don't know if biffer> anyone would like to comment on that.
What happens if you correct what you suspect an error? Does the application succeed?
--- Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de wrote:
"biffer" == biffer os bifferos@yahoo.co.uk
writes:
biffer> I have an application failing to
communicate at 19200, but biffer> working at 57600. I've got about 40k of logs of DCB dumps for a biffer> case it fails (19200 baud) and the case it succeeds (57600 biffer> baud). If anyone wants I can post them here.
biffer> But... biffer> Any particular reason why GetCommState
doesn't first zero the biffer> passed structure, or set the size with sizeof()?
biffer> If an app fails to zero its supplied DCB
structure for a Get, biffer> and Windows *does* then code might work for Windows and fail for biffer> Wine? I don't have a windows box to test this though.
biffer> It also strikes me that ignored DCB
elements from a Set biffer> operation should be stored in a map associated with the biffer> underlying ports so the values can be retrieved on the next Get biffer> call and the 'Set' will appear to have succeeded, don't know if biffer> anyone would like to comment on that.
What happens if you correct what you suspect an error? Does the application succeed?
No such luck :-(
I did something like this:
comm.c: ------8<---------------8<---------------8<--------- DCB g_dcb; int g_dcb_set = 0;
BOOL WINAPI SetCommState() { memcpy( &g_dcb, lpdcb, sizeof( DCB ) ); g_dcb_set = 1;
----- wine stuff ----- }
BOOL WINAPI GetCommState( { if (g_dcb_set) { memcpy( lpdcb, &g_dcb, sizeof( DCB ) ); } else { memset( lpdcb, 0, sizeof( DCB ) ); }
---- wine stuff ----- }
------8<---------------8<---------------8<---------
.. but I'm really fishing here.
In fact this isn't a big deal, because choosing the correct baud rate makes it work, but I was just curious. On the face of it, it seemed an odd way to implement the two functions, but if it works for the majority like it is all well and good.
cheers,
-biff.
___________________________________________________________ Yahoo! Messenger - NEW crystal clear PC to PC calling worldwide with voicemail http://uk.messenger.yahoo.com
http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c5767/ says:
When creating a process, the loader on Win 2000, Win XP and Win 2003 checks if kernel32.dll and user32.dll (their names are hardcoded into the loader) are mapped at their preferred bases; if not, a hard error is raised. In WinNT 4 ole32.dll was also checked. In WinNT 3.51 and lower such checks were not present, so kernel32.dll and user32.dll could be anywhere. Anyway, the only module that is always at its base is ntdll.dll. The loader doesn't check it, but if ntdll.dll is not at its base, the process just can't be created.
It's a common technique to rely on the fact that exports from kernel32 reside at the same address to use CreateRemoteThread calling LoadLibrary for remote code injection (this is not what Vitaliy's App is doing here but the assertions are the same).
OK, fair enough.
It's hard to implement that in Wine, because dlls are loaded using dlopen() and there's no way to specify which address to load the dll at.
You might be able to do it by staticly linking ntdll, kernel32 and user32 with wine-pthread/wine-kthread, and fixing the binary's address in memory, though that would probably be quite a bit of work.
Mike
Mike McCormack wrote:
You might be able to do it by staticly linking ntdll, kernel32 and user32 with wine-pthread/wine-kthread, and fixing the binary's address in memory, though that would probably be quite a bit of work.
Mike
This is not a bad Idea for other stuff as well one thing that comes to mined is winlib (self contained package). Though I admit I am not that brave. What would you do? a configure switch with alternate make targets. Could you think of a way that would get accepted into the tree and be regularly tested for?
Free Life Boaz
On Sunday 07 August 2005 10:13, Mike McCormack wrote:
http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c5767 /
says:
When creating a process, the loader on Win 2000, Win XP and Win 2003 checks if kernel32.dll and user32.dll (their names are hardcoded into the loader) are mapped at their preferred bases; if not, a hard error is raised. In WinNT 4 ole32.dll was also checked. In WinNT 3.51 and lower such checks were not present, so kernel32.dll and user32.dll could be anywhere. Anyway, the only module that is always at its base is ntdll.dll. The loader doesn't check it, but if ntdll.dll is not at its base, the process just can't be created.
It's a common technique to rely on the fact that exports from kernel32 reside at the same address to use CreateRemoteThread calling LoadLibrary for remote code injection (this is not what Vitaliy's App is doing here but the assertions are the same).
OK, fair enough.
It's hard to implement that in Wine, because dlls are loaded using dlopen() and there's no way to specify which address to load the dll at.
I would say that the only relatively sane way to do it is to re-implement dlopen to support such functionality. The ELF tables that dlopen needs are documented. It doesn't seem like a trivial task to reimplement it, but it should be doable. Last time I checked, ELF tables are at least manageable to deal with given a rainy afternoon: http://hrabia.ibib.waw.pl/~winnie/qtbeheader.html
Kuba
Kuba Ober wrote:
On Sunday 07 August 2005 10:13, Mike McCormack wrote:
http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c5767 /
says:
When creating a process, the loader on Win 2000, Win XP and Win 2003 checks if kernel32.dll and user32.dll (their names are hardcoded into the loader) are mapped at their preferred bases; if not, a hard error is raised. In WinNT 4 ole32.dll was also checked. In WinNT 3.51 and lower such checks were not present, so kernel32.dll and user32.dll could be anywhere. Anyway, the only module that is always at its base is ntdll.dll. The loader doesn't check it, but if ntdll.dll is not at its base, the process just can't be created.
It's a common technique to rely on the fact that exports from kernel32 reside at the same address to use CreateRemoteThread calling LoadLibrary for remote code injection (this is not what Vitaliy's App is doing here but the assertions are the same).
OK, fair enough.
It's hard to implement that in Wine, because dlls are loaded using dlopen() and there's no way to specify which address to load the dll at.
I would say that the only relatively sane way to do it is to re-implement dlopen to support such functionality. The ELF tables that dlopen needs are documented. It doesn't seem like a trivial task to reimplement it, but it should be doable. Last time I checked, ELF tables are at least manageable to deal with given a rainy afternoon: http://hrabia.ibib.waw.pl/~winnie/qtbeheader.html
Kuba
Hello.
There is also other way to do it. Wine could create the jump table (I don't know if it's good name in English) that would look like: jmp <func1> jmp <func2> ... where func1 is what dlsym returns and GetProcAddress could return address to this jump instruction. This table could be mmaped in fixed place.
Jacek
It's a common technique to rely on the fact that exports from kernel32 reside at the same address to use CreateRemoteThread calling LoadLibrary for remote code injection (this is not what Vitaliy's App is doing here but the assertions are the same).
It's hard to implement that in Wine, because dlls are loaded using dlopen() and there's no way to specify which address to load the dll at.
I would say that the only relatively sane way to do it is to re-implement dlopen to support such functionality. The ELF tables that dlopen needs are documented. It doesn't seem like a trivial task to reimplement it, but it should be doable. Last time I checked, ELF tables are at least manageable to deal with given a rainy afternoon: http://hrabia.ibib.waw.pl/~winnie/qtbeheader.html
There is also other way to do it. Wine could create the jump table (I don't know if it's good name in English) that would look like: jmp <func1> jmp <func2> ... where func1 is what dlsym returns and GetProcAddress could return address to this jump instruction. This table could be mmaped in fixed place.
That's clever too! I didn't think of it. Now the question is if the copy protection guys didn't think of doing checksumming of the actual functions in question, or if they won't eventually. That'd firmly lock their products to Windows, unless their checksumming was insecure. Then code could be fabricated to match the signature while doing the jump that one needs. One hopes they don't read wine-devel ;)
Kuba
It's a common technique to rely on the fact that exports from kernel32 reside at the same address to use CreateRemoteThread calling LoadLibrary for remote code injection (this is not what Vitaliy's App is doing here but the assertions are the same).
It's hard to implement that in Wine, because dlls are loaded using dlopen() and there's no way to specify which address to load the dll at.
I would say that the only relatively sane way to do it is to re-implement dlopen to support such functionality. The ELF tables that dlopen needs are documented. It doesn't seem like a trivial task to reimplement it, but it should be doable. Last time I checked, ELF tables are at least manageable to deal with given a rainy afternoon: http://hrabia.ibib.waw.pl/~winnie/qtbeheader.html
There is also other way to do it. Wine could create the jump table (I don't know if it's good name in English) that would look like: jmp <func1> jmp <func2> ... where func1 is what dlsym returns and GetProcAddress could return address to this jump instruction. This table could be mmaped in fixed place.
That's clever too! I didn't think of it. Now the question is if the copy protection guys didn't think of doing checksumming of the actual functions in question, or if they won't eventually. That'd firmly lock their products to Windows, unless their checksumming was insecure. Then code could be fabricated to match the signature while doing the jump that one needs. One hopes they don't read wine-devel ;)
Well they actually took care of that. They don't really use GetProcAddress. At least safedisc doesn't. They pretty much implemented their own GetProcAddress that does work on wine. I don't know details of it but it suffers form the same problem :-(
Something tells me that their GetProcAddress will not work with such a jump table.
Vitaliy
Saturday, August 6, 2005, 11:24:05 PM, Mike McCormack wrote:
app1.exe: GetProcAddress(mKernel32, "LoadLibraryA") returns 0x404FCBCC app2.exe: GetProcAddress(mKernel32, "LoadLibraryA") returns 0x404FFBCC
Is there are any reason why this is happening? Any ways to fix this?
Under Windows 98, you will always get the same address for the same export from a dll, however that's not garanteed under Windows NT (or Wine).
The problem is that mmap does not garantee that any specific area of memory will be available, so we can't always load a library at the same address.
You could "fix" it for a specific dll by reserving a memory area using the wine-preloader, but that would be a hack.
I think you missing the point. I'm not talking about separate runs of wine. I'm talking about one instance with parent & child processes. I would assume that each dll that has been loaded when parent started will have the same entry points for the child process as well. Because kernel32 is not unloadeble it's exports should always be in the same place guaranteed until the next reboot.
Unfortunately there are some programs that depend on address returned from GetProcAddress being the same in parent and child processes.
Which program depends upon that behaviour? It's possible that some old Windows 98 copy protections schemes depend upon it, but they should work if you change the version to win2k.
For now it's all safedisc protected games.
Vitaliy
Vitaliy Margolen wrote:
You could "fix" it for a specific dll by reserving a memory area using the wine-preloader, but that would be a hack.
I think you missing the point. I'm not talking about separate runs of wine. I'm talking about one instance with parent & child processes. I would assume that each dll that has been loaded when parent started will have the same entry points for the child process as well. Because kernel32 is not unloadeble it's exports should always be in the same place guaranteed until the next reboot.
The child and parent processes are seperate runs of Wine. Each process loads and initializes each dll it uses on its own. The kernel makes no guarantees that a .so loaded in one process will be loaded at the same address in other processes.
Thinking about it more, even if we reserved an area of memory using wine-preloader, we can't force dlopen to use it :/
Mike