https://bugs.winehq.org/show_bug.cgi?id=56362
Bug ID: 56362 Summary: Using CreateRemoteThread on x86 child from an x86_64 parent fails if a lpParameter is specified. Product: Wine Version: 9.3 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: kernel32 Assignee: wine-bugs@winehq.org Reporter: admin@sewer56.dev Distribution: ---
Created attachment 76098 --> https://bugs.winehq.org/attachment.cgi?id=76098 Reproduction source code.
[ testcase source download ]
Using CreateRemoteThread on x86 child from an x86_64 parent fails if a lpParameter is specified.
Full code reproduction in attachment.
----------- Attachment Info:
test-AMD64.sh : Build & test 64-bit host and 64-bit client test-x86.sh : Build & test 32-bit host and 32-bit client test-AMD64-to-x86-target.sh : Build & test 64-bit host and 32-bit client
test_target.c : Dummy program, does nothing except sleep. call-into-suspended-process.c : Test program that simulates calling CreateRemoteThread into suspended processes.
-----------
Truth table:
| x86 to x86 | AMD64 | AMD64 w/ x86 test_target | Windows 11 | OK | OK | OK | Wine (git) | OK | OK | FAIL |
The test program fails with:
`[FAIL] CreateRemoteThread(process = 0000000000000048, start_address = 0000000000350000, parameter = &dummy) = 0000000000000000`.
----------- Extra Notes:
Tested on x86_64 Archlinux using latest git version of Wine (reports as 'wine-9.3').
When running on Windows, this succeeds `WriteProcessMemory succeeded, but 0 bytes were written`.
I encountered this bug while writing a DLL Injection library. I validate my code against Wine when I publish my libraries.
Please note, that I don't normally program in C (I don't even have an IDE set up for this). I just write minimal reproductions in C when filing bugs to try make life easier for Wine developers.
https://bugs.winehq.org/show_bug.cgi?id=56362
Eric Pouech eric.pouech@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |eric.pouech@gmail.com
--- Comment #1 from Eric Pouech eric.pouech@gmail.com --- This works with Wine in "new" WOW64 mode (which more closely mimics Windows WOW implementation) but fails in the "old" WOW64 mode.
In old wow64 mode, a 32bit process lives in a 32bit address space, whereas in new wow64 mode, a 32bit process lives in a 64bit address space (even if the 32bit pieces of the process only accesses the (lower)32bit address space).
In your code, &dummy is an address from parent's address space, which happens to not fit in a 32bit value. If you truncate &dummy to 32bit ``` (void*)(ULONG_PTR)(ULONG)(ULONG_PTR)&dummy ``` your tests work even in old wow64 mode.
I strongly suggest that you use the Wine's "new" WOW64 for testing injection features, otherwise you'll face more issues than just this one.
(and to come back to what you're trying to do, the &dummy has no meaning in child address space. So, unless you want to pass an integer value, you likely want to virtual alloc that memory in child, initialize it from parent, and pass its address in CreateRemoteThread)
https://bugs.winehq.org/show_bug.cgi?id=56362
--- Comment #2 from admin@sewer56.dev ---
In your code, &dummy is an address from parent's address space, which happens to not fit in a 32bit value. If you truncate &dummy to 32bit
(void*)(ULONG_PTR)(ULONG)(ULONG_PTR)&dummy
your tests work even in old wow64 mode.
Thank you for your response. I wasn't aware of the new mode, but seems that things work just fine over there, thanks.
I was admittedly in quite a rush while writing the original issue report [and all of last week], so I didn't notice the actual core issue was incorrect use of the API (invalid address in child process space). I probably should have caught and noted it in the report.
To give some more context, I forked an existing library and started validating it against Wine while patching up some things. One of the things I saw some test code do was pass an invalid parameter to the target (which goes unused in called method). Running that led to the aforementioned error; it didn't click to me at the time that lpParameter had a value that was out of range for the child.
By all accounts, I simply saw Windows blindly accepted it, Wine didn't, so I reported the discrepancy. That's how I got here anyway.
I imagine this is probably good to close for when the new `WOW64` mode becomes the default.
https://bugs.winehq.org/show_bug.cgi?id=56362
admin@sewer56.dev changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|Using CreateRemoteThread on |Using CreateRemoteThread on |x86 child from an x86_64 |x86 child from an x86_64 |parent fails if a |parent fails if invalid |lpParameter is specified. |lpParameter is specified.
https://bugs.winehq.org/show_bug.cgi?id=56362
--- Comment #3 from Eric Pouech eric.pouech@gmail.com --- I think I'm gonna close this bug now as wontfix as: - it works fine in new WOW mode - yes it doesn't work in old WOW mode, but there's nothing that can be done in that mode to make CreateRemoteThread work reliably.
https://bugs.winehq.org/show_bug.cgi?id=56362
--- Comment #4 from admin@sewer56.dev --- Sounds good to me. Wouldn't want for people to invest in fixing code that'll be deprecated.
https://bugs.winehq.org/show_bug.cgi?id=56362
Eric Pouech eric.pouech@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution|--- |WONTFIX
--- Comment #5 from Eric Pouech eric.pouech@gmail.com --- as per #3
https://bugs.winehq.org/show_bug.cgi?id=56362
--- Comment #6 from Austin English austinenglish@gmail.com --- Closing.
https://bugs.winehq.org/show_bug.cgi?id=56362
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #7 from Austin English austinenglish@gmail.com --- Actually closing.