1

I'm trying to invoke win32 api with windbg,

> .call kernel32!ExitProcess(0)
                              ^ Symbol not a function in '.call kernel32!ExitProcess(0)'

windbg should support this, any idea?

daisy
  • 22,498
  • 29
  • 129
  • 265

1 Answers1

4

One reason might be that the debugger cannot find the method:

0:004> x kernel32!Exit*
00007ffc`12e9b0c0 KERNEL32!ExitVDM (<no parameter info>)
00007ffc`12e7d620 KERNEL32!ExitProcessImplementation (<no parameter info>)

You certainly don't have private symbols for kernel32!ExitProcess(). If you don't have the private symbols, then you need to have a function in your own code (for which you have private symbols) that you can pass as the prototype:

.call /s SameSignatureAsExitProcess kernel32!ExitProcess(0)

So what I would suggest is: get the LLD extension, compile yourself some methods like

Header file:

#pragma once
#include <Windows.h>
class Call
{
public:
    static void v();
    static void vi(int);
    static void vui(unsigned int);
    static void vl(long);
    static void vul(unsigned long);
};

Cpp file:

#include "Call.h"

void Call::v(){}
void Call::vi(int) {}
void Call::vui(unsigned int) {}
void Call::vl(long) {}
void Call::vul(unsigned long) {}

and then use it

0:000> .load ...\lld
0:000> !injectdll ...\Calls\x64\Debug\Calls.dll
ModLoad: 00007ffc`11270000 00007ffc`1129e000   C:\Windows\System32\IMM32.DLL
ModLoad: 00007ffc`070a0000 00007ffc`070c5000   ...\Calls\x64\Debug\Calls.dll
ModLoad: 00007ffb`f9000000 00007ffb`f91c2000   C:\Windows\System32\ucrtbased.dll
ModLoad: 00007ffc`07070000 00007ffc`07092000   C:\Windows\System32\VCRUNTIME140D.dll
ModLoad: 00007ffc`0d800000 00007ffc`0d89c000   C:\Windows\system32\uxtheme.dll
ntdll!NtTerminateThread+0x14:
00007ffc`138f01c4 c3              ret

0:004> ld Calls
*** WARNING: Unable to verify checksum for ...\Calls\x64\Debug\Calls.dll
Symbols loaded for Calls

0:004> x Calls!Call::*
00007ffc`070b1710 Calls!Call::vui (unsigned int)
00007ffc`070b1760 Calls!Call::vul (unsigned long)
00007ffc`070b1670 Calls!Call::vi (int)
00007ffc`070b1620 Calls!Call::v (void)
00007ffc`070b16c0 Calls!Call::vl (long)

0:004> .call /s Calls!Call::v kernelbase!TerminateProcess()
Thread is set up for call, 'g' will execute.
WARNING: This can have serious side-effects,
including deadlocks and corruption of the debuggee.

While this looks much better (no error message), it still does not work - the process does not terminate. I currently can't figure out why. Maybe it's still helpful for someone.

What works for me is

static void t(); // .h
void Call::t() // .cpp
{
    ExitProcess(0);
}

and then

0:007> .call Calls!Call::t()
Thread is set up for call, 'g' will execute.
WARNING: This can have serious side-effects,
including deadlocks and corruption of the debuggee.
0:007> p
Calls!Call::t+0x2a:
00007ffc`0709166a 33c9            xor     ecx,ecx
0:007> p
ntdll!NtTerminateProcess+0x14:
00007ffc`138efce4 c3              ret

but that's not very convenient, if you don't know in advance what method you want to call.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • 2
    TerminateProcess takes two parameters but you passed none. – Raymond Chen May 18 '19 at 22:42
  • @RaymondChen: good point. Don't know why I thought it does not need parameters. Do you know why ExitProcess() is not in the list of symbols of kernel32? – Thomas Weller May 19 '19 at 11:55
  • 2
    It's there, but you loaded a symbol file that gives the function's internal name (ExitProcessImpl) so the debugger uses that instead. If you hadn't loaded a symbol file, then the debugger would have used exports and would have found the function under it's exported name. – Raymond Chen May 19 '19 at 19:50
  • @RaymondChen: awesome, thanks. I'll try to use ExitProcessImplementation() with the same signature and update the answer if that works – Thomas Weller May 20 '19 at 13:18