Using IOCTL_MOUNTMGR_QUERY_POINTS - c++

I am not able to know how to use the IOCTL_MOUNTMGR_QUERY_POINTS .
I have searched the internet and found some sample code to try with.
but i am not sure whether its correct or not....
can you please let me know how to use the IOCTL_MOUNTMGR_QUERY_POINTS to get the drive letter
Thank you for your time
below is my source coode
HANDLE hUsbDevice = CreateFile( pDetData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
UCHAR Bytes[10000];
PMOUNTMGR_MOUNT_POINTS pMntPoints = (PMOUNTMGR_MOUNT_POINTS) Bytes;
MOUNTMGR_MOUNT_POINT mntPoint, *pmnt;
DWORD bytesReturned;
if (hUsbDevice == INVALID_HANDLE_VALUE) {
qDebug()<<"CreateFile failed with error: %d\n"<<GetLastError();
}
else {
qDebug ()<<"VALID DEVICE";
BOOL status = DeviceIoControl( hUsbDevice,
IOCTL_MOUNTMGR_QUERY_POINTS,
&mntPoint,
sizeof(MOUNTMGR_MOUNT_POINT),
pMntPoints,
10000,
&bytesReturned,
NULL);
wprintf(L"\tBOOL VALUE : %d\n", status);
qDebug ()<<pMntPoints->MountPoints;
}

OK! Here is a code example, but written without any error control to make it shorter:
#include <windows.h>
#include <C:\WinDDK\7600.16385.1\inc\ddk\mountmgr.h>
#include <tchar.h>
#include <stdio.h>
#pragma comment(lib, "Crypt32.lib")
int main()
{
TCHAR chDrive = 'N', szUniqueId[128];
TCHAR szDeviceName[7] = _T("\\\\.\\");
HANDLE hDevice, hMountMgr;
BYTE byBuffer[1024];
PMOUNTDEV_NAME pMountDevName;
DWORD cbBytesReturned, dwInBuffer, dwOutBuffer, ccb;
PMOUNTMGR_MOUNT_POINT pMountPoint;
BOOL bSuccess;
PBYTE pbyInBuffer, pbyOutBuffer;
LPTSTR pszLogicalDrives, pszDriveRoot;
// MOUNTMGR_DOS_DEVICE_NAME is defined as L"\\\\.\\MountPointManager"
hMountMgr = CreateFile (MOUNTMGR_DOS_DEVICE_NAME,
0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hMountMgr == INVALID_HANDLE_VALUE)
return 1;
cbBytesReturned = GetLogicalDriveStrings (0, NULL);
pszLogicalDrives = (LPTSTR) LocalAlloc (LMEM_ZEROINIT,
cbBytesReturned*sizeof(TCHAR));
cbBytesReturned = GetLogicalDriveStrings (cbBytesReturned,
pszLogicalDrives);
for (pszDriveRoot = pszLogicalDrives; *pszDriveRoot != TEXT('\0');
pszDriveRoot += lstrlen(pszDriveRoot) + 1) {
szDeviceName[4] = pszDriveRoot[0];
szDeviceName[5] = _T(':');
szDeviceName[6] = _T('\0');
//lstrcpy (&szDeviceName[4], TEXT("\\??\\USBSTOR\\DISK&VEN_SANDISK&PROD_CRUZER&REV_8.01\\1740030578903736&0"));
hDevice = CreateFile (szDeviceName, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
return 1;
bSuccess = DeviceIoControl (hDevice,
IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
NULL, 0,
(LPVOID)byBuffer, sizeof(byBuffer),
&cbBytesReturned,
(LPOVERLAPPED) NULL);
pMountDevName = (PMOUNTDEV_NAME) byBuffer;
_tprintf (TEXT("\n%.*ls\n"), pMountDevName->NameLength/sizeof(WCHAR),
pMountDevName->Name);
bSuccess = CloseHandle (hDevice);
dwInBuffer = pMountDevName->NameLength + sizeof(MOUNTMGR_MOUNT_POINT);
pbyInBuffer = (PBYTE) LocalAlloc (LMEM_ZEROINIT, dwInBuffer);
pMountPoint = (PMOUNTMGR_MOUNT_POINT) pbyInBuffer;
pMountPoint->DeviceNameLength = pMountDevName->NameLength;
pMountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
CopyMemory (pbyInBuffer + sizeof(MOUNTMGR_MOUNT_POINT),
pMountDevName->Name, pMountDevName->NameLength);
dwOutBuffer = 1024 + sizeof(MOUNTMGR_MOUNT_POINTS);
pbyOutBuffer = (PBYTE) LocalAlloc (LMEM_ZEROINIT, dwOutBuffer);
bSuccess = DeviceIoControl (hMountMgr,
IOCTL_MOUNTMGR_QUERY_POINTS,
pbyInBuffer, dwInBuffer,
(LPVOID)pbyOutBuffer, dwOutBuffer,
&cbBytesReturned,
(LPOVERLAPPED) NULL);
if (bSuccess) {
ULONG i;
PMOUNTMGR_MOUNT_POINTS pMountPoints = (PMOUNTMGR_MOUNT_POINTS) pbyOutBuffer;
for (i=0; i<pMountPoints->NumberOfMountPoints; i++) {
_tprintf (TEXT("#%i:\n"), i);
_tprintf (TEXT(" Device=%.*ls\n"),
pMountPoints->MountPoints[i].DeviceNameLength/sizeof(WCHAR),
pbyOutBuffer + pMountPoints->MountPoints[i].DeviceNameOffset);
_tprintf (TEXT(" SymbolicLink=%.*ls\n"),
pMountPoints->MountPoints[i].SymbolicLinkNameLength/sizeof(WCHAR),
pbyOutBuffer + pMountPoints->MountPoints[i].SymbolicLinkNameOffset);
ccb = sizeof(szUniqueId)/sizeof(szUniqueId[0]);
if (CryptBinaryToString (pbyOutBuffer + pMountPoints->MountPoints[i].UniqueIdOffset,
pMountPoints->MountPoints[i].UniqueIdLength,
CRYPT_STRING_BASE64,
szUniqueId, &ccb))
_tprintf (TEXT(" UniqueId=%s\n"), szUniqueId);
else
_tprintf (TEXT(" UniqueId=%.*ls\n"),
pMountPoints->MountPoints[i].UniqueIdLength/sizeof(WCHAR),
pbyOutBuffer + pMountPoints->MountPoints[i].UniqueIdOffset);
}
}
pbyInBuffer = (PBYTE) LocalFree (pbyInBuffer);
pbyOutBuffer = (PBYTE) LocalFree (pbyOutBuffer);
}
pszLogicalDrives = (LPTSTR) LocalFree (pszLogicalDrives);
bSuccess = CloseHandle (hMountMgr);
return 0;
}
if produce on my computer the output like
\Device\HarddiskVolume3
#0:
Device=\Device\HarddiskVolume3
SymbolicLink=\DosDevices\C:
UniqueId=O5TWlQAAwBRIAAAA
#1:
Device=\Device\HarddiskVolume3
SymbolicLink=\??\Volume{12703dc4-bf56-11db-8c6c-806e6f6e6963}
UniqueId=O5TWlQAAwBRIAAAA
...
\Device\CdRom2
#0:
Device=\Device\CdRom2
SymbolicLink=\DosDevices\L:
UniqueId=\??\USBSTOR#CdRom&Ven_HL-DT-ST&Prod_DVDRAM_GE20LU11&Rev_CL01#0010101640008B615&0#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
#1:
Device=\Device\CdRom2
SymbolicLink=\??\Volume{2c5f6a93-2b50-11df-aa6a-005056c00008}
UniqueId=\??\USBSTOR#CdRom&Ven_HL-DT-ST&Prod_DVDRAM_GE20LU11&Rev_CL01#0010101640008B615&0#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
\Device\HarddiskVolume8
#0:
Device=\Device\HarddiskVolume8
SymbolicLink=\DosDevices\N:
UniqueId=_??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer&Rev_8.01#1740030578903736&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
#1:
Device=\Device\HarddiskVolume8
SymbolicLink=\??\Volume{ae08a3c8-71cf-11de-bc1d-005056c00008}
UniqueId=_??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer&Rev_8.01#1740030578903736&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}

Related

WriteFile and ReadFile on child process's stdio (using overlapped named pipe)

I want to read asynchronously from a child process's stdin, so I create an IOCP loop that listens for when ReadFile() is done. But ReadFile() is never done, it always returns ERROR_IO_PENDING, and WriteFile() always returns ERROR_IO_PENDING.
Node.js can asynchronously read from a child process:
const child_process = require("child_process")
var p = child_process.spawn("gcc")
p.stdout.on('data', data=>console.log(String(data)))
p.stderr.on('data', data=>console.log(String(data)))
How to do this in the Win32 API?
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <wchar.h>
#pragma comment (lib, "User32.lib")
static HANDLE iocp = INVALID_HANDLE_VALUE;
typedef struct PROCESS {
OVERLAPPED ol;
HANDLE hProcess,
stdin_read, stdin_write,
stdout_read, stdout_write,
stderr_read, stderr_write;
char buf[100];
} PROCESS, *PPROCESS, *LPROCESS;
DWORD WINAPI Worker(LPVOID param);
BOOL create_pipe(HANDLE* pserver_pipe, HANDLE* pclient_pipe, PROCESS* p) {
static __int64 counter=0;
HANDLE server_pipe, client_pipe;
int err;
WCHAR name[64];
for (;;) {
swprintf(name, sizeof(name), L"\\\\?\\pipe\\child\\%Id.%p", counter, p);
server_pipe = CreateNamedPipeW(
name,
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1,
65536,
65536,
0,
NULL);
if (server_pipe != INVALID_HANDLE_VALUE)
break;
err = GetLastError();
if (err != ERROR_PIPE_BUSY && err != ERROR_ACCESS_DENIED) {
return FALSE;
}
counter++;
}
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof sa;
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = 1;
client_pipe = CreateFileW(name,
GENERIC_READ|WRITE_DAC,
0,
&sa,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
if (client_pipe==INVALID_HANDLE_VALUE){
return FALSE;
}
if (CreateIoCompletionPort(client_pipe, iocp, (ULONG_PTR)p, 0)==NULL){
return FALSE;
}
if (CreateIoCompletionPort(server_pipe, iocp, (ULONG_PTR)p, 0)==NULL){
return FALSE;
}
*pclient_pipe = client_pipe;
*pserver_pipe = server_pipe;
return TRUE;
}
int wmain()
{
iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
assert(iocp);
PROCESS child_process{};
assert(create_pipe(&child_process.stdout_write, &child_process.stdout_read, &child_process));
assert(create_pipe(&child_process.stderr_write, &child_process.stderr_read, &child_process));
assert(create_pipe(&child_process.stdin_write, &child_process.stdin_read, &child_process));
HANDLE hThread = CreateThread(NULL, 0, Worker, iocp, 0, NULL);
assert(hThread);
WCHAR szCmdline[]=L"cmd";
PROCESS_INFORMATION piProcInfo{};
STARTUPINFOW siStartInfo{.cb = sizeof(STARTUPINFO),
.dwFlags=STARTF_USESTDHANDLES,
.hStdInput=child_process.stdin_read,
.hStdOutput=child_process.stdout_write,
.hStdError=child_process.stderr_write};
assert(CreateProcessW(NULL, szCmdline, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo));
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
// CloseHandle(child_process.stdout_write);
// CloseHandle(child_process.stdin_read);
ReadFile(child_process.stdout_read, child_process.buf, sizeof(child_process.buf), NULL, &child_process.ol);
int err = GetLastError();
if (err!=ERROR_IO_PENDING){
printf("Error in ReadFile %d\n", err);
}else{
puts("ReadFile is pending...\n");
}
char buf[100];
DWORD dwIn;
for(;;){
ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE), buf, sizeof buf, &dwIn, NULL);
if (dwIn<=0)
break;
WriteFile(child_process.stdin_write, buf, dwIn, NULL, &child_process.ol);
err = GetLastError();
if (err!=ERROR_IO_PENDING){
printf("Error in WriteFile %d\n", err);
}else{
puts("WriteFile is pending...\n");
}
}
PostQueuedCompletionStatus(iocp, 0, 0, 0);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(iocp);
}
DWORD WINAPI Worker(LPVOID param) {
DWORD dwIoSize = 0;
LPOVERLAPPED ol;
PROCESS* ctx;
for(;;){
BOOL bSuccess = GetQueuedCompletionStatus((HANDLE)param, &dwIoSize,
(PDWORD_PTR)&ctx,
&ol,
INFINITE);
if (ctx == NULL) {
printf("ctx is NULL, maybe you call PostQueuedCompletionStatus? err=%d\n", GetLastError());
break;
}
if (bSuccess==FALSE || dwIoSize == 0) {
printf("GetQueuedCompletionStatus does not success(maybe EOF reached?) err=%d\n", GetLastError());
break;
}
WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), ctx->buf, dwIoSize, NULL, NULL);
ReadFile(ctx->stdout_read, ctx->buf, sizeof(ctx->buf), NULL, &ctx->ol);
}
return 0;
}
After search on Github, it's quite easy.
Create a Named Pipe for current process(read), and create a File for child process(write).
Github links:
https://github.com/parasol-framework/parasol/blob/c5ad64188c7496e3ff54eb75fd03c9e3124fe08b/src/core/microsoft/processes.c
https://github.com/dinamsky/malware-botnets/blob/4cd142d10f971cb93c334b6f48c12c85bcc8f63a/Phatbot-stoney/Phatbot-stoney/cmdshell.cpp
https://github.com/grimjoey/jlstudio/blob/e5d2d81f0a94d2020f2e912e43a487d9cb6f7c33/src/jls/process.cpp
https://github.com/Ai-Thinker-Open/Ai-Thinker-Open_ESP32-S2_SDK/blob/7d75213674b4572f90c68162ad6fe9b16dae65ad/tools/windows/tool_setup/cmdlinerunner/cmdlinerunner.c
https://github.com/LeonColt/skripsi/blob/141af593ec65cd7adaedf7a90fc4cd7cde5cc602/Maschinen/RedirectIOChildProcess.cpp
redirect stdout and stderr
#include <windows.h>
#include <assert.h>
#include <stdio.h>
struct Stdio;
typedef void (*Callback)(struct Stdio* self, DWORD len);
struct Stdio {
OVERLAPPED ol;
HANDLE pipe;
BYTE buf[100];
Callback callback;
};
typedef struct CTX {
struct Stdio Stdout, Stderr, Stdin;
} CTX, *LCTX, *LPCTX;
HANDLE Hstdout=INVALID_HANDLE_VALUE;
HANDLE Hstderr=INVALID_HANDLE_VALUE;
DWORD WINAPI Worker(LPVOID iocp){
struct Stdio *stdio;
OVERLAPPED *ol;
DWORD dwIoSize;
for(;;){
if (!GetQueuedCompletionStatus(iocp, &dwIoSize, (PDWORD_PTR)&stdio, &ol, INFINITE) || dwIoSize==0 || ol==NULL || stdio==NULL){
switch (GetLastError()){
case ERROR_BROKEN_PIPE:
puts("the process has been exited, exit thread...");
break;
default:
printf("error = %d, exit thread\n", GetLastError());
}
break;
}
stdio->callback(stdio, dwIoSize);
}
return 0;
}
void OnStdoutRead(struct Stdio *self, DWORD len){
WriteConsoleA(Hstdout, self->buf, len, NULL, NULL);
ReadFile(self->pipe, self->buf, sizeof(self->buf), NULL, &self->ol);
}
void OnStderrRead(struct Stdio *self, DWORD len){
WriteConsoleA(Hstderr, self->buf, len, NULL, NULL);
ReadFile(self->pipe, self->buf, sizeof(self->buf), NULL, &self->ol);
}
int wmain(){
assert(Hstdout = GetStdHandle(STD_OUTPUT_HANDLE));
assert(Hstderr = GetStdHandle(STD_ERROR_HANDLE));
HANDLE Pstdout, Pstderr; // child process's
CTX ctx{.Stdout=Stdio{.callback=OnStdoutRead}, .Stderr=Stdio{.callback=OnStderrRead}};
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
HANDLE hThread = CreateThread(NULL, 0, Worker, iocp, 0, NULL); // Worker thread
SECURITY_ATTRIBUTES sa{.nLength=sizeof(SECURITY_ATTRIBUTES), .bInheritHandle=TRUE};
const WCHAR* pipe_name1 = L"\\\\.\\Pipe\\child-1";
assert((ctx.Stdout.pipe = CreateNamedPipeW(
pipe_name1,
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE,
1,
4096,
4096,
5000,
NULL))!=INVALID_HANDLE_VALUE);
assert(INVALID_HANDLE_VALUE != (Pstdout = CreateFileW(
pipe_name1,
GENERIC_WRITE,
0,
&sa,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL)));
const WCHAR *pipe_name2 = L"\\\\.\\Pipe\\child-2";
assert((ctx.Stderr.pipe = CreateNamedPipeW(
pipe_name2,
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE,
1,
4096,
4096,
5000,
NULL))!=INVALID_HANDLE_VALUE);
assert((Pstderr = CreateFileW(
pipe_name2,
GENERIC_WRITE,
0,
&sa,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL))!=INVALID_HANDLE_VALUE);
STARTUPINFOW si{.cb = sizeof(si),
.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW,
.wShowWindow = SW_HIDE,
.hStdInput = GetStdHandle(STD_INPUT_HANDLE), // use current stdin
.hStdOutput = Pstdout,
.hStdError = Pstderr};
WCHAR cmd[] = L"powershell"; // or cmd, py, bash...
PROCESS_INFORMATION pInfo{};
assert(CreateProcessW(
NULL, cmd, NULL, NULL,
TRUE, 0, NULL, NULL,
&si, &pInfo));
assert(CloseHandle(Pstdout)); // we don't need this
assert(CloseHandle(Pstderr)); // we don't need this
assert(CreateIoCompletionPort(ctx.Stdout.pipe, iocp, (ULONG_PTR)&ctx.Stdout, 0));
assert(CreateIoCompletionPort(ctx.Stderr.pipe, iocp, (ULONG_PTR)&ctx.Stderr, 0));
ReadFile(ctx.Stdout.pipe, ctx.Stdout.buf, sizeof(ctx.Stdout.buf), NULL, &ctx.Stdout.ol);
ReadFile(ctx.Stderr.pipe, ctx.Stdout.buf, sizeof(ctx.Stderr.buf), NULL, &ctx.Stderr.ol);
WaitForSingleObject(pInfo.hProcess, INFINITE); // wait for process exit
PostQueuedCompletionStatus(iocp, 0, 0, NULL); // tell IOCP Worker exit
WaitForSingleObject(hThread, INFINITE); // wait for thread exit
assert(CloseHandle(hThread));
assert(CloseHandle(ctx.Stderr.pipe));
assert(CloseHandle(ctx.Stdout.pipe));
assert(CloseHandle(pInfo.hProcess));
assert(CloseHandle(iocp));
assert(CloseHandle(Hstderr));
puts("exit main function..."); // !!important: before close stdout
assert(CloseHandle(Hstdout));
}
Redirect stdin, stdout, stderr
#include <windows.h>
#include <assert.h>
#include <stdio.h>
static HANDLE Hstdout, Hstderr, Hstdin, HstopEvent;
struct Stdio;
typedef void (*Callback)(struct Stdio* self, DWORD len);
struct Stdio {
OVERLAPPED ol;
HANDLE pipe;
BYTE buf[100];
Callback callback;
};
typedef struct CTX {
struct Stdio Stdout, Stderr, Stdin;
} CTX, *LCTX, *LPCTX;
DWORD WINAPI Worker(LPVOID iocp){
struct Stdio *stdio;
OVERLAPPED *ol;
DWORD dwIoSize;
for(;;){
if (!GetQueuedCompletionStatus(iocp, &dwIoSize, (PDWORD_PTR)&stdio, &ol, INFINITE) || dwIoSize==0 || ol==NULL || stdio==NULL){
switch (GetLastError()){
case ERROR_BROKEN_PIPE:
SetEvent(HstopEvent);
puts("the process has been exited, exit thread...");
break;
default:
printf("error = %d, exit thread\n", GetLastError());
}
break;
}
stdio->callback(stdio, dwIoSize);
}
return 0;
}
void OnStdoutRead(struct Stdio *self, DWORD len){
WriteConsoleA(Hstdout, self->buf, len, NULL, NULL);
ReadFile(self->pipe, self->buf, sizeof(self->buf), NULL, &self->ol);
}
void OnStderrRead(struct Stdio *self, DWORD len){
WriteConsoleA(Hstderr, self->buf, len, NULL, NULL);
ReadFile(self->pipe, self->buf, sizeof(self->buf), NULL, &self->ol);
}
void OnStdinWriteComplete(struct Stdio *self, DWORD len){
printf("[%u bytes write to stdin]\n", len);
}
int wmain(){
assert((Hstdout = GetStdHandle(STD_OUTPUT_HANDLE))!=INVALID_HANDLE_VALUE);
assert((Hstderr = GetStdHandle(STD_ERROR_HANDLE))!=INVALID_HANDLE_VALUE);
assert((Hstdin = GetStdHandle(STD_INPUT_HANDLE))!=INVALID_HANDLE_VALUE);
assert((HstopEvent=CreateEventW(NULL, FALSE, FALSE, NULL))!=INVALID_HANDLE_VALUE);
CTX ctx{.Stdout=Stdio{.callback=OnStdoutRead}, .Stderr=Stdio{.callback=OnStderrRead}, .Stdin=Stdio{.callback=OnStdinWriteComplete}};
STARTUPINFOW si{.cb = sizeof(si), .dwFlags = STARTF_USESTDHANDLES};
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
HANDLE hThread = CreateThread(NULL, 0, Worker, iocp, 0, NULL); // Worker thread
SECURITY_ATTRIBUTES sa{.nLength=sizeof(SECURITY_ATTRIBUTES), .bInheritHandle=TRUE};
const WCHAR* pipe_name1 = L"\\\\.\\Pipe\\child-1";
assert((ctx.Stdout.pipe = CreateNamedPipeW(
pipe_name1,
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE,
1,
4096,
4096,
5000,
NULL))!=INVALID_HANDLE_VALUE);
assert((si.hStdOutput = CreateFileW(
pipe_name1,
GENERIC_WRITE,
0,
&sa,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL))!=INVALID_HANDLE_VALUE);
const WCHAR *pipe_name2 = L"\\\\.\\Pipe\\child-2";
assert((ctx.Stderr.pipe = CreateNamedPipeW(
pipe_name2,
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE,
1,
4096,
4096,
5000,
NULL))!=INVALID_HANDLE_VALUE);
assert((si.hStdError = CreateFileW(
pipe_name2,
GENERIC_WRITE,
0,
&sa,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL))!=INVALID_HANDLE_VALUE);
const WCHAR *pipe_name3 = L"\\\\.\\Pipe\\child-3";
assert((ctx.Stdin.pipe = CreateNamedPipeW(
pipe_name3,
PIPE_ACCESS_OUTBOUND,
PIPE_TYPE_BYTE,
1,
4096,
4096,
5000,
NULL))!=INVALID_HANDLE_VALUE);
assert((si.hStdInput = CreateFileW(
pipe_name3,
GENERIC_READ,
0,
&sa,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL))!=INVALID_HANDLE_VALUE);
WCHAR cmd[] = L"powershell"; // or cmd, py, bash...
PROCESS_INFORMATION pInfo{};
assert(CreateProcessW(
NULL, cmd, NULL, NULL,
TRUE, 0, NULL, NULL,
&si, &pInfo));
assert(CloseHandle(si.hStdError)); // we don't need this
assert(CloseHandle(si.hStdInput)); // we don't need this
assert(CloseHandle(si.hStdOutput)); // we don't need this
assert(CreateIoCompletionPort(ctx.Stdout.pipe, iocp, (ULONG_PTR)&ctx.Stdout, 0));
assert(CreateIoCompletionPort(ctx.Stderr.pipe, iocp, (ULONG_PTR)&ctx.Stderr, 0));
ReadFile(ctx.Stdout.pipe, ctx.Stdout.buf, sizeof(ctx.Stdout.buf), NULL, &ctx.Stdout.ol);
ReadFile(ctx.Stderr.pipe, ctx.Stdout.buf, sizeof(ctx.Stderr.buf), NULL, &ctx.Stderr.ol);
DWORD dwIoSize;
for(;;){
CHAR buf[100];
ReadConsoleA(Hstdin, buf, sizeof(buf), &dwIoSize, NULL);
if (WaitForSingleObject(HstopEvent, 0)==WAIT_OBJECT_0)
break;
WriteFile(ctx.Stdin.pipe, buf, dwIoSize, NULL, &ctx.Stdin.ol);
if (WaitForSingleObject(HstopEvent, 0)==WAIT_OBJECT_0)
break;
}
PostQueuedCompletionStatus(iocp, 0, 0, NULL); // tell IOCP Worker exit
WaitForSingleObject(hThread, INFINITE); // wait for thread exit
assert(CloseHandle(hThread));
assert(CloseHandle(ctx.Stderr.pipe));
assert(CloseHandle(ctx.Stdout.pipe));
assert(CloseHandle(pInfo.hProcess));
assert(CloseHandle(iocp));
assert(CloseHandle(Hstderr));
assert(CloseHandle(HstopEvent));
puts("exit main function..."); // !!important: before close stdout
assert(CloseHandle(Hstdout));
}

How to exclude remote Windows MailSlot access for universal well-known LOCAL SIDs?

I try to windows Mailslots for interprocess communication but I'd like to refuse any remote communication.
I set well-known LOCAL sid for my mailslot BUT I still could write to mailslot from another computer in my domain
SID_IDENTIFIER_AUTHORITY sid_auth_local = SECURITY_LOCAL_SID_AUTHORITY;
if (AllocateAndInitializeSid(&sid_auth_local, 1,
SECURITY_LOCAL_LOGON_RID, 0, 0, 0, 0, 0, 0, 0, &localSid))
client:
if ((mailslot = CreateFileA("\\\\MYDOMAIN\\mailslot\\MYSLOT", GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
I've attached client server example.
What is wrong here? Is there the way to exclude remote connection through mailslots?
Thx.
server example:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <accctrl.h>
#include <aclapi.h>
int main(void)
{
char buffer[4];
DWORD readBytes;
DWORD res;
HANDLE mailslot;
PSID localSid = NULL;
PACL acl = NULL;
SECURITY_ATTRIBUTES *p_sa = NULL;
SECURITY_DESCRIPTOR sd;
EXPLICIT_ACCESS_A ea;
SECURITY_ATTRIBUTES sa;
SID_IDENTIFIER_AUTHORITY sid_auth_local = SECURITY_LOCAL_SID_AUTHORITY;
if (AllocateAndInitializeSid(&sid_auth_local, 1,
SECURITY_LOCAL_LOGON_RID, 0, 0, 0, 0, 0, 0, 0, &localSid)) //SECURITY_LOCAL_LOGON_RID
{
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance = NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = (LPSTR)localSid;
if (SetEntriesInAclA(1, &ea, NULL, &acl) == ERROR_SUCCESS &&
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) &&
SetSecurityDescriptorDacl(&sd, TRUE, acl, FALSE))
{
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
p_sa = &sa;
}
}
if ((mailslot = CreateMailslot(L"\\\\.\\mailslot\\MYSLOT", 2048, MAILSLOT_WAIT_FOREVER, p_sa)) == INVALID_HANDLE_VALUE)
{
printf("Failed to create a MailSlot %d\n", GetLastError());
return 0;
}
if (localSid) FreeSid(localSid);
if (acl) LocalFree(acl);
while ((res = ReadFile(mailslot, buffer, 4, &readBytes, NULL)) != 0)
{
printf("Received %d bytes %s\n", readBytes, buffer);
}
CloseHandle(mailslot);
return 0;
}
client example:
#include <windows.h>
#include <stdio.h>
void main(int argc, char *argv[])
{
HANDLE mailslot;
DWORD writtenBytes;
if ((mailslot = CreateFileA("\\\\MYDOMAIN\\mailslot\\MYSLOT", GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
{
printf("CreateFile failed with error %d\n", GetLastError());
return;
}
if (WriteFile(mailslot, "Hi\n", 3, &writtenBytes, NULL) == 0)
{
printf("WriteFile failed with error %d\n", GetLastError());
return;
}
printf("Wrote %d bytes\n", writtenBytes);
CloseHandle(mailslot);
}

How to Load PE Files for Process Hollowing?

The target is notepad.exe
The code to insert is a PE file called Hello.
PE FILE:
Error:
error occurred --> if (IDH->e_magic== IMAGE_DOS_SIGNATURE
error content is "Exception through: read access violation. IDH was 0xC4."
The following is the whole code.
#include <Windows.h>
#include <TlHelp32.h>
#include <stdio.h>
#include <tchar.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <tchar.h>
#include <locale.h>
#define FILE_PATH ("C:/Windows/System32/notepad.exe")
#define PE_FILE_PATH ("C:/Users/code1/Desktop/Hello.exe")
typedef LONG(WINAPI* NtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);
void ProcHollowing(LPSTR szFilePath, PVOID ); //pFile);
PVOID pFile();
int main(){
ProcHollowing((LPSTR)(FILE_PATH), pFile());
return 0;
}
PVOID pFile() { //PE파일의 DATA 추출 부분 (.text 추출)
HANDLE hFile = CreateFile((LPCWSTR)PE_FILE_PATH, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0);
if (hFile == INVALID_HANDLE_VALUE) {
printf("Fail: Hello.exe 파일이 없습니다.");
}
return hFile;
}
void ProcHollowing(LPSTR szFilePath /*TargetProc*/, PVOID pFile/*PE Data*/) {
PIMAGE_DOS_HEADER IDH;/*PE 구조의 첫 시작부분 DOS 헤더*/
PIMAGE_NT_HEADERS INH;/*PE헤더*/
PIMAGE_SECTION_HEADER ISH; //섹션 헤더
PROCESS_INFORMATION PI; //프로세스 정보
STARTUPINFOA SI; //생성시 프로세스에 대한 윈도우 스테이션, 데스크탑, 표준 핸들 및 주 창의 모양을 지정하는 구조체.
PCONTEXT CTX;
PDWORD dwImageBase; //생성된 프로세스의 Image Base 주소
NtUnmapViewOfSection NewNtUnmapViewOfSection;
LPVOID pImageBase;
int Count;
IDH = PIMAGE_DOS_HEADER(pFile);
if (IDH->e_magic== IMAGE_DOS_SIGNATURE/*PE 파일이 맞는지 시그니처를 통해 확인한다.*/) { //IMAGE_DOS_SIGNATURE는 4D5A 즉 MZ
_tprintf(TEXT("SUCCESS: This is PE File\n"));
INH = PIMAGE_NT_HEADERS(DWORD(pFile) + IDH->e_lfanew); // Dos header의 끝부분 + 시작 부분으로 PE Header를 구하는 것.
if (INH->Signature == IMAGE_NT_SIGNATURE/*시그니처 확인하여 PE포멧 파일인지 구분*/) {
_tprintf(TEXT("SUCCESS: PE FILE Check\n"));
RtlZeroMemory(&SI, sizeof(SI)); // SI의 크기만큼 0으로 채워준다는 의미. 즉, 초기화
RtlZeroMemory(&PI, sizeof(PI));
bool bResult = CreateProcessA(szFilePath/*실행할 모듈의 이름 notepad.exe*/, NULL, NULL, NULL,
FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI); // 정상 프로세스를 생성. SUSPENDED 상태.
if (bResult) {//프로세스가 잘 생성되면
_tprintf(TEXT("SUCCESS: CreateProcessA\n"));
CTX = PCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE)); //CTX 가상 메모리 할당.
CTX->ContextFlags = CONTEXT_FULL; //Context 구조에서 초기화해야하는 부분을 나타내는 값.
if (GetThreadContext(PI.hThread, LPCONTEXT(CTX))/*프로세스 정보 획득*/) {
ReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&dwImageBase), 4, NULL); /*Image Base 주소 구하기*/
//ebx에는 PEB 주소가 들어가 있고 PEB+8에는 Image Base 주소가 들어가있다.
//PEB(Process Environment Block)에는 해당 프로세스에 대한 정보가 들어가있음.
_tprintf(TEXT("SUCCESS: Get Image Base Address\n"));
if (DWORD(dwImageBase) == INH->OptionalHeader.ImageBase) { //Image Base와 PE Header의 OPTIONAL HEADER의 Image Base가 같으면
NewNtUnmapViewOfSection = NtUnmapViewOfSection(GetProcAddress(GetModuleHandleA("ntdll.dll"),
"NtUnmapViewOfSection")); //메모리 할당해지 핸들이랑 주소
_tprintf(TEXT("SUCCESS: Unmap\n"));
NewNtUnmapViewOfSection(PI.hProcess, PVOID(dwImageBase)); //정상 프로세스의 메모리 할당 해지
}
else {
_tprintf(TEXT("FAIL: Unmap\n"));
}
pImageBase = VirtualAllocEx(PI.hProcess, LPVOID(INH->OptionalHeader.ImageBase), //재할당
INH->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);
/*악성코드 데이터 삽입 부분 같은데 여기부분 이해 잘 안됨.*/
if (pImageBase) { //재할당 완료 되면
_tprintf(TEXT("SUCCESS: Reassignment\n"));
WriteProcessMemory(PI.hProcess, pImageBase, pFile,/*pFile, 즉 데이터를 넣어주는 부분같음.*/
INH->OptionalHeader.SizeOfHeaders, NULL);//악성코드 삽입(?) 헤더를 바꿔주는 거같음.
for (Count = 0; Count < INH->FileHeader.NumberOfSections; Count++) {
ISH = PIMAGE_SECTION_HEADER(DWORD(pFile) + IDH->e_lfanew + 248 + (Count * 40));
WriteProcessMemory(PI.hProcess,
LPVOID(DWORD(pImageBase) + ISH->VirtualAddress),
LPVOID(DWORD(pFile) + ISH->PointerToRawData),
ISH->SizeOfRawData, NULL);
}
WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8),// 메모리 쓰기. Image Base
LPVOID(&INH->OptionalHeader.ImageBase),
4, NULL);
CTX->Eax = DWORD(pImageBase) + INH->OptionalHeader.AddressOfEntryPoint; //AddressOfEntryPoint는 PE파일이 메모리에
//로드된 후 맨 처음 실행되어야 하는 코드의 주소가 포함되어 있음.
//Eax는 Original Entry Point(OEP)가 들어가 있음. 즉, 실행 프로그램의 실제 시작 위치
SetThreadContext(PI.hThread, LPCONTEXT(CTX)); //프로세스 정보 변경
ResumeThread(PI.hThread); //프로세스 재실행
}
else {
_tprintf(TEXT("FAIL: Reassignment\n"));
}
}
else {
_tprintf(TEXT("FAIL: Get Image Base Address\n"));
}
}
else {
_tprintf(TEXT("FAIL: CreateProcessA\n"));
}
}
else {
_tprintf(TEXT("FAIL: PE FILE Check\n"));
}
VirtualFree(pFile, 0, MEM_RELEASE);
}
else { //PE파일이 아니면
_tprintf(TEXT("FAIL: This is not PE File\n"));
}
}
There are too many things to fix for excution
I will not upload the modified code because there are some parts that were not implemented..
First,
PVOID pFile(){ // hFile is a HANDLE but ret type is PVOID... hmmm
...
//HANDLE hFile = CreateFile((LPCWSTR)PE_FILE_PATH, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, 0); // <-- GENREIC_WRITE? and CREATE_ALWAYS?
HANDLE hFile = CreateFile($file_name, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
...
You should read MSDN Docs CreateFile
You create a file handle, but there is no reading method (like API ReadFile)
^ This is the cause of the error.
...
if (DWORD(dwImageBase) == INH->OptionalHeader.ImageBase) {
NewNtUnmapViewOfSection = NtUnmapViewOfSection(GetProcAddress(GetModuleHandleA("ntdll.dll"),
"NtUnmapViewOfSection"));
NewNtUnmapViewOfSection(PI.hProcess, PVOID(dwImageBase));
...
...
WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8),
LPVOID(&INH->OptionalHeader.ImageBase),
4, NULL);
...
STUDY ASRL!
...
CTX->Eax = DWORD(pImageBase) + INH->OptionalHeader.AddressOfEntryPoint;
SetThreadContext(PI.hThread, LPCONTEXT(CTX));
ResumeThread(PI.hThread);
...
You ResumeThread before write the Dos Header, Dos Stub, PE Header in child process Memory
you have to fix entire codeㅠㅠ :(

INVALID_FUNCTION error when writing to HID file

I am writing a program to send data to an HID device. I followed the following page from Microsoft's documentation: Finding and Opening a HID Collection and I get the file handle successfully, but when I try to write using WriteFile, I get an INVALID_FUNCTION error (1). I have sent the same data to the device through a Hyperterminal and it worked, so I'm sure that the information I am sending is correct.
Here is my code:
HANDLE m_hCommPort;
GUID guid = GUID_DEVINTERFACE_USB_DEVICE;
HDEVINFO hinfo;
DWORD index = 0;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
SP_DEVINFO_DATA deviceInfoData;
BOOL result;
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL;
DWORD requiredSize;
DWORD deviceIndex = 0;
hinfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
result = SetupDiEnumDeviceInterfaces(hinfo, NULL, &guid, deviceIndex, &deviceInterfaceData);
while (result == TRUE) {
deviceInfoData.cbSize = sizeof(deviceInfoData);
SetupDiGetDeviceInterfaceDetail(hinfo, &deviceInterfaceData, NULL, 0, &requiredSize, &deviceInfoData);
deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);
deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
SetupDiGetDeviceInterfaceDetail(hinfo, &deviceInterfaceData, deviceInterfaceDetailData, requiredSize, NULL, &deviceInfoData);
Trace(TEXT(deviceInterfaceDetailData->DevicePath));
if (_tcsstr(deviceInterfaceDetailData->DevicePath, "vid_0c2e&pid_0be7")) {
Trace(TEXT(deviceInterfaceDetailData->DevicePath));
break;
}
result = SetupDiEnumDeviceInterfaces(hinfo, NULL, &guid, ++deviceIndex, &deviceInterfaceData);
}
if (result == FALSE) {
ErrorExit("SetupDiEnumDeviceInterfaces ");
}
else if(deviceInterfaceDetailData != NULL){
m_hCommPort = CreateFile(deviceInterfaceDetailData->DevicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (m_hCommPort == INVALID_HANDLE_VALUE) {
ErrorExit("CreateFile");
}
else {
DWORD bytesWritten;
char scanCommand[] = { 22,77,13,'I','M','G','S','N','P','1','B' };
DWORD size = sizeof(scanCommand);
BOOL fileWritten = WriteFile(m_hCommPort, scanCommand, size, &bytesWritten, NULL);
if (fileWritten == TRUE) {
Trace(TEXT("Wrote %d files to device"), bytesWritten);
}
else {
ErrorExit("Error writing to file");
}
}
}
Can someone help me to understand why I am getting this error please?

How to get services and characteristics from bluetooth LE device

I'm writing desktop app in Windows 8.1, and I need to get services from paired device using BluetoothGATTGetServices function. To make it I need to get handle to the device, that I've done and get handle using CreateFile function. But when I try to get service function return error: HRESULT_FROM_WIN32(ERROR_NOT_SUPORTED). Does anyone know how to fix it or tell what I'm doing wrong.
My device I'm trying to get services is iPhone 5s.
Here is code example:
HRESULT WinBluetoothDeviceProvider::GetBleHandle(OUT HANDLE* hBluetooth, WinBluetoothDevice* blDev)
{
GUID bthGuid;
CLSIDFromString(TEXT(BLE_INTERFACE_GUID), &bthGuid); // BLE_INTERFACE_GUID this is GUID of my Device Interface GUID
//#define BLE_INTERFACE_GUID "{00f40965-e89d-4487-9890-87c3abb211f4}"
HRESULT result = S_OK;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA devInfoData;
HANDLE hBle;
hDevInfo = SetupDiGetClassDevs(&bthGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE)
return E_FAIL;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
SP_DEVICE_INTERFACE_DATA devInterfData = { 0 };
devInterfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
DWORD DataT;
LPTSTR buffer = NULL;
DWORD buffersize = 0;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &bthGuid, i, &devInterfData); i++)
{
DWORD d = GetLastError();
DWORD size = 0;
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfData, NULL, 0, &size, 0))
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
{
result = S_OK;
break;
}
PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, size);
pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfData, pInterfaceDetailData, size, &size, &devInfoData))
{
result = E_FAIL;
break;
}
hBle = CreateFile(pInterfaceDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
USHORT serviceBuffActual;
PBTH_LE_GATT_SERVICE servicesBuff = new _BTH_LE_GATT_SERVICE;
HRESULT result = S_OK;
result = BluetoothGATTGetServices(hBle,
0, NULL, &serviceBuffActual, BLUETOOTH_GATT_FLAG_NONE);
// this function always retunr ERROR_NOT_SUPPORTED
LocalFree(pInterfaceDetailData);
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return result;
}
Try https://gist.github.com/programmarchy/c9d02e22d58bfab3f8bb#file-gistfile1-cpp-L110-L117, without FILE_ATTRIBUTE_NORMAL
hComm = CreateFile(
pInterfaceDetailData->DevicePath,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);