Replace or change the API call (GetOpenFileName, GetSaveFileName) in a foreign application

I have an old application that calls GetOpenFileNameA and GetSaveFileNameA. Both calls are erroneous. Application crash! I used OllyDbg and the Monitor API to read the size stored in the OPENFILENAME structure. The size of the structure is 76 bytes (testing using Windows 7 x64). I get an access violation exception when GetOpenFileNameA or GetSaveFileNameA is called. I assume that at runtime the window is trying to read 88 bytes instead of 76 bytes. Look at this: http://dotnetbutchering.blogspot.de/2007/10/vc-60-getting-0xc0000005-access.html and this is http://www.asmcommunity.net/board/index.php?topic=5768.15

I did some research, and doing this, I found the following behavior: When starting Microsoft Spy ++, the application does not crash! I went through the debugger and I saw that the access violation exception is still happening, but somehow the exception is being swallowed. The app works great! I can upload and save files.

I have the following ideas. What do you think of them?

  • write sth. like Loader.exe, which does the same as Spy ++. Swallowing an access violation exception when calling both APIs.

  • Use DLL Injection and API Hooking. I could connect GetOpenFileName and GetSaveFileName using a special implementation in a custom DLL. My implementation will correct the structure and pass the corrected structure to the original API calls.

  • Use SetWindowsHook to connect a message box?!?!?!

  • Replace the binary. Is it possible to fix this problem with the size of the structure by fixing it with the HEX editor?

Which one will work? Do you have an idea how I can fix this?

I can not get the source code of this old application. I have to fix this using existing binaries. My solution should work at least on Windows XP and Windows 7 (x86, x64)

The PEiD tool shows me the following information about an old application: Link: 2.55 MS Visual C ++ 4.0

+4
source share
2 answers

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 // (_WIN32_WINNT >= 0x0500) 

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 .

+1
source

(1) Will there be a clean hack that can be difficult to do (what aspect of Spy ++ behavior does it do? Or do you want to rethink the full Syp ++?), And even if you do, how can you be sure that the application will to work correctly (for all input data) after a "swallowed exception"? The internal state of the program may be undefined and later lead to other problems.

(2) Assuming you have no sources, so you cannot fix it in the usual way, this IMHO seems to work best for the problem.

(3) I do not see how this can help you.

(4) Perhaps, but a lot of work. Suppose there is some data about the stack, and then by OPENFILENAMEA one of them (the OPENFILENAMEA structure), you move the offsets of the others, so you have to β€œfix” the links to them.

+1
source

Source: https://habr.com/ru/post/1414156/


All Articles