views:

399

answers:

3

I'm debugging a C++ Win32 application and I'd like to call an arbitrary Win32 API from the context of that process, as though the program had run this line of code:

DestroyWindow(0x00021c0e);

But entering that into the Immediate Window gives:

CXX0017: Error: symbol "DestroyWindow" not found

Edit: Using the full name of the function, {,,user32.dll}_NtUserDestroyWindow@4, I can get the Immediate Window to understand which function I mean and display the function's address:

{,,user32.dll}_NtUserDestroyWindow@4
0x76600454 _NtUserDestroyWindow@4

but when I try to call it, this happens:

{,,user32.dll}_NtUserDestroyWindow@4(0x00021c0e);
CXX0004: Error: syntax error

Is it even possible to call a C function from the Immediate Window like this, or am I barking up the wrong tree?

+1  A: 

I believe the problem is that the C++ EE is having problems resolving the context of DestroyWindow. Try the following

{,,user32}DestroyWindow(0x00021c0e);

I'm not sure if the method invocation syntax supports this style of qualification (only used it for casting in the past). But it's worth a shot.

EDIT You may or may not need to add a ! after the closing }. It's been awhile since I've used this syntax and I often confuse it with the equivalent windbg one.

JaredPar
Thanks for the suggestion, but I've already tried that and it doesn't work. And I've tried decorating it as `_DestroyWindow@4` etc. as well, all the way up to the fully qualified `{,,user32.dll}_DestroyWindow@4`, with no joy.
RichieHindle
@RichieHindle, disapointing :(
JaredPar
@JaredPar: +1 for helping to improve the situation - see my edited question. I can now get it to understand which function I mean, but I still can't make it call it.
RichieHindle
@Richie, thanks! +1'd your answer as well. Wow, by the way.
JaredPar
@JaredPar: Thanks... I'm slightly embarrassed that I didn't figure out how to get the right function name sooner, given that I wrote a blog article on exactly that problem earlier this year: http://entrian.com/blog/setting-a-visual-studio-breakpoint-on-a-win32-api-function-in-user32dll/ 8-)
RichieHindle
+1  A: 

I figured out a workaround, but I'd still prefer to get the Immediate Window to work.

The workaround is:

  • get the address of the function, as shown in the question
  • use the Disassembly window to go to that address, and put a breakpoint there
  • do something to the application to make it call DestroyWindow
  • step back up the call stack to the caller of DestroyWindow, which looks like this:

    6D096A9D push ecx
    6D096A9E call dword ptr ds:[6D0BB4B8h]

  • put a breakpoint on the push ecx instruction, and clear the one on DestroyWindow

  • hit Continue, and again do something to the application to make it call that code
  • note down the value of ecx
  • change the value of ecx in the debugger to the desired value and step over the push/call
  • restore the value of ecx and use Set Next Statement to go back to the push, then Continue

It's longwinded, but it works. It assumes you can make the application call the appropriate API at will.

RichieHindle
+3  A: 

Once you have the function address (as you've done in the updated question), you can try casting it to a function pointer and calling it:

(*(BOOL (*)(HWND))0x76600454)((HWND)0x00021c0e)

The first part of that casts the address to BOOL (*)(HWND), which is a pointer to a function taking an HWND parameter and returning BOOL. Then, the function pointer is dereferenced and called. Make sure to get the parameters correct, otherwise bad things will happen. On 64-bit systems, and HWND might be 64 bits, so you might not be able to get away with passing the parameter as an int.

Edit: See the comments for the full story.

Adam Rosenfield
Thanks for the idea, but... That gives me `CXX0004: Error: syntax error`. Replacing the Windows types (`BOOL` and `HWND`) with primitive types (`int` in both cases) improves things, but I then get `CXX0014: Error: missing operand`. (I'm in a 32-bit process, BTW.)
RichieHindle
The VS debugger's really bad at parsing function pointer types, apparently. Try creating a typedef for it. Put `typedef BOOL (*DESTROYWINDOW)(HWND);` in your code, then write `(*(DESTROYWINDOW)0x76600454)((void*)0x00021c0e)` in the debugger.
Adam Rosenfield
@Adam: Yay! (but a qualified one). By adding your `typedef` to my code, *and* actually using the `typedef` in the code so that the compiler doesn't throw the definition away, *and* breaking the execution of the process within the compilation unit where I used the `typedef`, I can now call DestroyWindow from the immediate window. Thanks! It's a shame to have to jump through these hoops to do it, but at least it's possible.
RichieHindle
This is absolutely terrible. I just had the same experience. This is a huge Visual Studio fail.
jeffamaphone
Anyone know how to do it using .call in NTSD?
jeffamaphone