My attempt to open a file on a remote machine looks like this:
#include <Windows.h>
#include <cwchar>
void main() {
HANDLE h = CreateFileW (
L"\\\\10.10.10.10\\c$\\windows\\system32\\calc.exe",
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
0,
nullptr);
if (h == INVALID_HANDLE_VALUE) {
std::wprintf(L"Error: %u\n", GetLastError());
} else {
CloseHandle(h);
}
}
The problem is: it fails and GetLastError ()
returns 1326 (the username or password is invalid).
What I've tried:
NetUseAdd
for IPC$ and C$ with local administrator credentials (both connect successfully)WNetAddConnection2
for IPC$ and C$ with local administrator credentials (both connect successfully)According to the event log of the remote machine, CreateFile
attempts to work with the credentials of the user that started the process.
What should I do to make CreateFile
use the provided credentials?
Yes, I try to connect to the C$ share and it can be done from Explorer.
Short answer: LogonUser
+ ImpersonateLoggedOnUser
.
TL;DR
Most of Windows API that are capable of working with remote machines, usually can be made working mounting IPC$
share using either WNetAddConnection*
family or NetUseAdd
. There are exceptions though.
One of them is CreateFile
. This function ignores established IPC$
connections as well as any established connections to shares. You need to use LogonUser
+ ImpersonateLoggedOnUser
pair.
I should point out that the description of LogonUser
on the MS's site can be misleading. It's correct in saying that "you cannot use LogonUser to log on to a remote computer". What it actually can do is to prepare network credentials for future connections to the remote computer. Actual logon will be happening during later API calls (CreateFile
in this case).