The size of the structure is 76 bytes (testing in Windows 7 x64). I received an access violation exception while GetOpenFileNameA or GetSaveFileNameA is called. I assume that at run time the window is trying to read 88 bytes instead of 76 bytes.
if you look at the OPENFILENAME
struct
, you will notice:
#if (_WIN32_WINNT >= 0x0500) void * pvReserved; DWORD dwReserved; DWORD FlagsEx; #endif
which in a 32-bit program (VC ++ 4 did not support 64-bit targets) translates into a difference of 12 bytes. As long as lStructSize
correctly installed by the caller, this should not be a problem at all. It might be worth using procdump
from Microsoft / Sysinternals to get the exact state minidump (or attach a debugger and investigate). The exception you encounter does not have to be related to the size of the struct
. If so, it is more likely that Microsoft dropped the ball when it comes to backward compatibility of this feature. Obviously, OPENFILENAME::lStructSize
exists for struct
versions and will not happen to ensure that you meet. But then we are talking about a program created using the compiler / linker, starting with Windows 2000.
write sth. like Loader.exe, which does the same as Spy ++. Swallowing an access violation exception when calling both APIs. This is a fair question. If you introduced exception handling at the top level, you could do what you want, but this can cause side effects depending on what exactly caused the exception (that is, what exact memory was overwritten).
Use DLL Injection and API Hooking. I could connect GetOpenFileName and GetSaveFileName with a custom implementation in a custom DLL. my implementation will correct the structure and pass the corrected structure to the original API calls. This is largely due to the first. I think it will be the easiest and safest of all, because in this way you can correct the behavior without undue intrusion. Please read below. Also check out the NInjectLib.
Use SetWindowsHook to connect a message box?!?!?! I do not see how this helps, except to facilitate the injection of the DLL (for 1. and 2.).
Replace the binary. Is it possible to fix this problem of structure size using fix using the HEX editor? This may be the most difficult, depending on whether OPENFILENAME
inside the binary (initialized data) or on the stack or whether it is allocated on the heap (then easy).
One possible hybrid approach for 1. and 2. would be:
- Add a subkey to
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
, named after the executable program (for example, foo.exe
) - Create a
REG_SZ
value named Debugger
inside this newly created section and set the value for the program that I will now try to describe.
This effectively sets up the debugger for this old application, and that means that the debugger we're going to write will receive your application command line as arguments. This is convenient because it is transparent to the end user, and you can customize it to suit your needs.
You will need to write a debugger. This task is not as tantalizing as it seems at first glance, because you can use Win32 helper suggestions for debugging. The bottom line is in the debugger loop. In the general case, you yourself create the target process using CreateProcess
, passing the appropriate flags to debug it. To control execution, use WaitForDebugEvent
and ContinueDebugEvent
. For all practical purposes, you may not need a debugger loop at all, because you can pause the main thread of the target application (pass CREATE_SUSPENDED
to CreateProcess
) and then point the CONTEXT
main thread to your own code at the very beginning, then call ResumeThread(pi.hThread)
. This way you will do this before the main thread starts. However, this can cause problems due to the way kernel32.dll
CreateThread
works (which is related to registering a new thread with the Win32 aka csrss.exe
). Therefore, it may be appropriate instead to patch the IAT target in memory or something similar. After all, you are only interested in two functions.
Check out two articles here and here for a more detailed look at this topic.
I prefer to write my PyDbg
based PyDbg
from PaiMei , but I admittedly have not tried to use such a Python-based debugger in Image File Execution Options
.