how to run following mailslots program in VC++ - c++

//writing to mailslot
#include <windows.h>
#include <stdio.h>
LPTSTR SlotName = TEXT("\\\\.\\mailslot\\sample_mailslot");
BOOL WriteSlot(HANDLE hSlot, LPTSTR lpszMessage)
{
BOOL fResult;
DWORD cbWritten;
fResult = WriteFile(hSlot,
lpszMessage,
(DWORD) (lstrlen(lpszMessage)+1)*sizeof(TCHAR),
&cbWritten,
(LPOVERLAPPED) NULL);
if (!fResult)
{
printf("WriteFile failed with %d.\n", GetLastError());
return FALSE;
}
printf("Slot written to successfully.\n");
return TRUE;
}
int main()
{
HANDLE hFile;
hFile = CreateFile(SlotName,
GENERIC_WRITE,
FILE_SHARE_READ,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile failed with %d.\n", GetLastError());
return FALSE;
}
WriteSlot(hFile, TEXT("Message one for mailslot."));
WriteSlot(hFile, TEXT("Message two for mailslot."));
Sleep(5000);
WriteSlot(hFile, TEXT("Message three for mailslot."));
CloseHandle(hFile);
return TRUE;
}
//reading from mailslot
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
HANDLE hSlot;
LPTSTR SlotName = TEXT("\\\\.\\mailslot\\sample_mailslot");
BOOL ReadSlot()
{
DWORD cbMessage, cMessage, cbRead;
BOOL fResult;
LPTSTR lpszBuffer;
TCHAR achID[80];
DWORD cAllMessages;
HANDLE hEvent;
OVERLAPPED ov;
cbMessage = cMessage = cbRead = 0;
hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("ExampleSlot"));
if( NULL == hEvent )
return FALSE;
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = hEvent;
fResult = GetMailslotInfo( hSlot, // mailslot handle
(LPDWORD) NULL, // no maximum message size
&cbMessage, // size of next message
&cMessage, // number of messages
(LPDWORD) NULL); // no read time-out
if (!fResult)
{
printf("GetMailslotInfo failed with %d.\n", GetLastError());
return FALSE;
}
if (cbMessage == MAILSLOT_NO_MESSAGE)
{
printf("Waiting for a message...\n");
return TRUE;
}
cAllMessages = cMessage;
while (cMessage != 0) // retrieve all messages
{
// Create a message-number string.
StringCchPrintf((LPTSTR) achID,
80,
TEXT("\nMessage #%d of %d\n"),
cAllMessages - cMessage + 1,
cAllMessages);
// Allocate memory for the message.
lpszBuffer = (LPTSTR) GlobalAlloc(GPTR,
lstrlen((LPTSTR) achID)*sizeof(TCHAR) + cbMessage);
if( NULL == lpszBuffer )
return FALSE;
lpszBuffer[0] = '\0';
fResult = ReadFile(hSlot,
lpszBuffer,
cbMessage,
&cbRead,
&ov);
if (!fResult)
{
printf("ReadFile failed with %d.\n", GetLastError());
GlobalFree((HGLOBAL) lpszBuffer);
return FALSE;
}
// Concatenate the message and the message-number string.
StringCbCat(lpszBuffer,
lstrlen((LPTSTR) achID)*sizeof(TCHAR)+cbMessage,
(LPTSTR) achID);
// Display the message.
_tprintf(TEXT("Contents of the mailslot: %s\n"), lpszBuffer);
GlobalFree((HGLOBAL) lpszBuffer);
fResult = GetMailslotInfo(hSlot, // mailslot handle
(LPDWORD) NULL, // no maximum message size
&cbMessage, // size of next message
&cMessage, // number of messages
(LPDWORD) NULL); // no read time-out
if (!fResult)
{
printf("GetMailslotInfo failed (%d)\n", GetLastError());
return FALSE;
}
}
CloseHandle(hEvent);
return TRUE;
}
BOOL WINAPI MakeSlot(LPTSTR lpszSlotName)
{
hSlot = CreateMailslot(lpszSlotName,
0, // no maximum message size
MAILSLOT_WAIT_FOREVER, // no time-out for operations
(LPSECURITY_ATTRIBUTES) NULL); // default security
if (hSlot == INVALID_HANDLE_VALUE)
{
printf("CreateMailslot failed with %d\n", GetLastError());
return FALSE;
}
return TRUE;
}
void main()
{
MakeSlot(SlotName);
while(TRUE)
{
ReadSlot();
Sleep(3000);
}
}

Go through the Visual Studio C++ Guided Tour on MSDN or watch this introductory video explaining how to create a basic Win32 application in C++. They should be enough of a starting point. From there on just browse the MSDN library to advance your knowledge or search for issues you encounter.

Related

Find starting offset of a partition

Suppose I have a usb drive with two partition e:, f:. How do I know from which offset the partition e: or f: starts so that I can write raw data starting from that offset. I could not find any function that would provide me the offset in c++. In Dos I could easily get this with wmic partition get Index, Name, StartingOffset.
To get the StartingOffset of partitions in a Physical Drive(such as \\\\.\\PhysicalDrive1), you could use IOCTL_DISK_GET_DRIVE_LAYOUT_EX to get PARTITION_INFORMATION_EX arrays for each partition:
#include <windows.h>
#include <stdio.h>
#define wszDrive L"\\\\.\\PhysicalDrive1"
int wmain(int argc, wchar_t* argv[])
{
HANDLE hDevice = INVALID_HANDLE_VALUE; // handle to the drive to be examined
BOOL bResult = FALSE; // results flag
DWORD junk = 0; // discard results
DWORD error;
DWORD szNewLayout = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + sizeof(PARTITION_INFORMATION_EX) * 4 * 25;
hDevice = CreateFileW(wszDrive, // drive to open
GENERIC_READ, // no access to the drive
FILE_SHARE_READ,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
0); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
error = GetLastError();
printf("CreateFileW error: %d\n", error);
return -1;
}
DRIVE_LAYOUT_INFORMATION_EX* pdg = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(szNewLayout);
if (pdg == NULL)
{
error = GetLastError();
printf("malloc error: %d\n", error);
CloseHandle(hDevice);
return -1;
}
ZeroMemory(pdg, szNewLayout);
bResult = DeviceIoControl(hDevice, // device to be queried
IOCTL_DISK_GET_DRIVE_LAYOUT_EX, // operation to perform
NULL, 0, // no input buffer
pdg, szNewLayout,// sizeof(*pdg)*2, // output buffer
&junk, // # bytes returned
(LPOVERLAPPED)NULL); // synchronous I/O
if (!bResult)
{
error = GetLastError();
printf("DeviceIoControl error: %d\n", error);
free(pdg);
CloseHandle(hDevice);
return -1;
}
for (int i = 0; i < pdg->PartitionCount; i++) {
printf("partition %d: %lld\n", i, pdg->PartitionEntry[i].StartingOffset.QuadPart);
}
free(pdg);
CloseHandle(hDevice);
return 0;
}
To get the StartingOffset of a specified partition(such as \\\\.\\E:), you could use IOCTL_DISK_GET_PARTITION_INFO_EX:
#include <windows.h>
#include <stdio.h>
#define wszDrive L"\\\\.\\E:"
int wmain(int argc, wchar_t* argv[])
{
HANDLE hDevice = INVALID_HANDLE_VALUE; // handle to the drive to be examined
BOOL bResult = FALSE; // results flag
DWORD junk = 0; // discard results
DWORD error;
PARTITION_INFORMATION_EX piex;
ZeroMemory(&piex, sizeof(PARTITION_INFORMATION_EX));
hDevice = CreateFileW(wszDrive, // drive to open
GENERIC_READ, // no access to the drive
FILE_SHARE_READ,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
0); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
error = GetLastError();
printf("CreateFileW error: %d\n", error);
return -1;
}
bResult = DeviceIoControl(hDevice,
IOCTL_DISK_GET_PARTITION_INFO_EX,
NULL, 0,
&piex, sizeof(PARTITION_INFORMATION_EX),
&junk,
(LPOVERLAPPED)NULL);
if (!bResult)
{
error = GetLastError();
printf("DeviceIoControl error: %d\n", error);
CloseHandle(hDevice);
return -1;
}
wprintf(L"%s StartingOffset: %lld\n", wszDrive, piex.StartingOffset.QuadPart);
CloseHandle(hDevice);
return 0;
}

Broken pipe when reading from a pipe of a child process launched as a different user

I'm trying to launch a child executable to run as the logged in user(written in golang) from a windows service running as SYSTEM. I am using the CreateProcessAsUser method to start the process. I've observed that the child process actually starts, but i'm unable to read the stdout of it. I've followed the steps described in https://learn.microsoft.com/en-us/windows/win32/procthread/creating-a-child-process-with-redirected-input-and-output to redirect the stdin and stdout of the child.
I have also set the permissions on the pipe to the Everyone SID, but still getting the same issue.
The parent process's code is as follows (after further edits based on suggestions in the comments)
#include "test.h"
#include <windows.h>
#include <winbase.h>
#include <userenv.h>
#include <tchar.h>
#include <wtsapi32.h>
#include <strsafe.h>
#include <processthreadsapi.h>
#define BUFSIZE 4096
#define PROC_THREAD_ATTRIBUTE_HANDLE_LIST ( 2 | 0x00020000)
typedef struct _STARTUPINFOEXA {
STARTUPINFOA StartupInfo;
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList;
} STARTUPINFOEXA, *LPSTARTUPINFOEXA;
void ReadAndHandleOutput(HANDLE hPipeRead, FILE* fp)
{
CHAR lpBuffer[BUFSIZE];
DWORD nBytesRead;
DWORD bytesAvailable;
DWORD bytesLeftInMsg;
do
{
if (!PeekNamedPipe(hPipeRead, lpBuffer, sizeof(lpBuffer), &nBytesRead, &bytesAvailable, &bytesLeftInMsg))
{
if (GetLastError() == ERROR_BROKEN_PIPE) {
fprintf(fp, "Broken Pipe \n");
fflush(fp);
break; // pipe done - normal exit path.
}
else {
fprintf(fp, "ReadFileError %d\n", GetLastError()); // Something bad happened.
fflush(fp);
}
}
} while(bytesLeftInMsg > 0);
fprintf(fp, "GOT OUTPUT, %s -- %d -- %d -- %d\n", lpBuffer, nBytesRead, bytesAvailable, bytesLeftInMsg);
fflush(fp);
}
bool LaunchProcess(char *process_path)
{
FILE *fp = fopen("C:\\test.log", "a");
DWORD SessionId = WTSGetActiveConsoleSessionId();
if (SessionId == -1) { // no-one logged in
fprintf(fp, "Session ID is -1\n");
fclose(fp);
return false;
}
HANDLE hToken;
BOOL ok = WTSQueryUserToken(SessionId, &hToken);
if (!ok) {
fprintf(fp, "Unable to get the token for session id %d\n", SessionId);
fclose(fp);
return false;
}
void *environment = NULL;
ok = CreateEnvironmentBlock(&environment, hToken, TRUE);
if (!ok)
{
fprintf(fp, "Unable to create environment with session ID %d\n", SessionId);
CloseHandle(hToken);
fclose(fp);
return false;
}
HANDLE hServerPipe = CreateNamedPipe("\\\\.\\Pipe\\test-pipe.em", PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_READMODE_BYTE, 1, 0, 0, 0, 0);
HANDLE hClientPipe;
if (hServerPipe != INVALID_HANDLE_VALUE)
{
static SECURITY_ATTRIBUTES sa = { sizeof(sa), 0, TRUE };
hClientPipe = CreateFile("\\\\.\\Pipe\\test-pipe.em", FILE_GENERIC_READ|FILE_GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
if (hClientPipe == INVALID_HANDLE_VALUE)
{
fprintf(fp, "Error creating client handle %d", GetLastError());
CloseHandle(hServerPipe);
return false;
}
} else {
fprintf(fp, "Error creating server handle %d", GetLastError());
return false;
}
STARTUPINFOEXA si = { { sizeof(si) } };
PROCESS_INFORMATION pi;
si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
si.StartupInfo.hStdInput = si.StartupInfo.hStdOutput = si.StartupInfo.hStdError = hClientPipe;
DWORD dwCreationFlags = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
BOOL fInit = FALSE;
SIZE_T Size;
if (!InitializeProcThreadAttributeList(0, 1, 0, &Size) && GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
InitializeProcThreadAttributeList(si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)alloca(Size), 1, 0, &Size))
{
fInit = TRUE;
if (UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &si.StartupInfo.hStdError, sizeof(HANDLE), 0, 0)) {
dwCreationFlags |= EXTENDED_STARTUPINFO_PRESENT;
}
}
fprintf(fp, "calling the process %s\n", process_path);
fflush(fp);
ok = CreateProcessAsUser(hToken, NULL, process_path, NULL, NULL, TRUE, dwCreationFlags, environment, NULL, &si.StartupInfo, &pi);
fprintf(fp, "Running process %s and %d with PID %d\n", process_path, ok, pi.dwProcessId);
fflush(fp);
if (!ok) {
wchar_t buf[BUFSIZE];
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buf, (sizeof(buf) / sizeof(wchar_t)), NULL);
fprintf(fp, "Failed to create processes as user - %d, %d, %S, %s\n", SessionId, GetLastError(), buf, process_path);
fclose(fp);
return false;
} else {
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
// Close pipe handles (do not continue to modify the parent).
// You need to make sure that no handles to the write end of the
// output pipe are maintained in this process or else the pipe will
// not close when the child process exits and the ReadFile will hang.
if (!CloseHandle(si.StartupInfo.hStdError)) {
fprintf(fp, "CloseHandle - outputwrite Error %d\n", GetLastError());
fclose(fp);
return false;
}
ReadAndHandleOutput(hServerPipe, fp);
CloseHandle(hServerPipe);
fclose(fp);
return true;
Cleanup:
fprintf(fp, "Something went wrong");
fclose(fp);
return false;
}
The child process's code is as follows
package main
import (
"fmt"
"os"
"time"
)
func main() {
os.Stdout.Write([]byte("Hello from the GO side..."))
f, err := os.OpenFile("C:\\log.text", os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
panic(err)
}
defer f.Close()
var output = fmt.Sprintf("I'm running as %d launched by %d", os.Getpid(), os.Getppid())
if _, err = f.WriteString(output); err != nil {
panic(err)
}
os.Stdout.Close()
}
I'm able to see the current PID and the parent's PID(the service) in the log.text file, However I keep getting a pipe broken error on the parent side.
Any pointers are appreciated

ManualMap inject a DLL from Resources in C++

I am learning C++ and I need help figuring out how to inject a DLL with ManualMap Injection from the C++ Projects resources.
I have a source for this in C#, but I am not sure how to convert it, and I don't want to try to convert about 5000 lines of code.
Here is a undetected DLL Injection using ManualMapping it's undetected by many GameGuard's for injecting DLL's into games.
#include <stdio.h>
#include <Windows.h>
#include <tlhelp32.h> /* PROCESSENTRY32 */
#include <conio.h> /* _getch() */
#include <shlwapi.h> /* StrStrI */
#pragma comment(lib, "shlwapi.lib") /* unresolved external symbol __imp__StrStrIW#8 */
typedef HMODULE (WINAPI *pLoadLibraryA)(LPCSTR);
typedef FARPROC (WINAPI *pGetProcAddress)(HMODULE,LPCSTR);
typedef BOOL (WINAPI *PDLL_MAIN)(HMODULE,DWORD,PVOID);
typedef struct _MANUAL_INJECT
{
PVOID ImageBase;
PIMAGE_NT_HEADERS NtHeaders;
PIMAGE_BASE_RELOCATION BaseRelocation;
PIMAGE_IMPORT_DESCRIPTOR ImportDirectory;
pLoadLibraryA fnLoadLibraryA;
pGetProcAddress fnGetProcAddress;
}MANUAL_INJECT,*PMANUAL_INJECT;
DWORD WINAPI LoadDll(PVOID p)
{
PMANUAL_INJECT ManualInject;
HMODULE hModule;
DWORD i,Function,count,delta;
PDWORD ptr;
PWORD list;
PIMAGE_BASE_RELOCATION pIBR;
PIMAGE_IMPORT_DESCRIPTOR pIID;
PIMAGE_IMPORT_BY_NAME pIBN;
PIMAGE_THUNK_DATA FirstThunk,OrigFirstThunk;
PDLL_MAIN EntryPoint;
ManualInject=(PMANUAL_INJECT)p;
pIBR=ManualInject->BaseRelocation;
delta=(DWORD)((LPBYTE)ManualInject->ImageBase-ManualInject->NtHeaders->OptionalHeader.ImageBase); // Calculate the delta
// Relocate the image
while(pIBR->VirtualAddress)
{
if(pIBR->SizeOfBlock>=sizeof(IMAGE_BASE_RELOCATION))
{
count=(pIBR->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/sizeof(WORD);
list=(PWORD)(pIBR+1);
for(i=0;i<count;i++)
{
if(list[i])
{
ptr=(PDWORD)((LPBYTE)ManualInject->ImageBase+(pIBR->VirtualAddress+(list[i] & 0xFFF)));
*ptr+=delta;
}
}
}
pIBR=(PIMAGE_BASE_RELOCATION)((LPBYTE)pIBR+pIBR->SizeOfBlock);
}
pIID=ManualInject->ImportDirectory;
// Resolve DLL imports
while(pIID->Characteristics)
{
OrigFirstThunk=(PIMAGE_THUNK_DATA)((LPBYTE)ManualInject->ImageBase+pIID->OriginalFirstThunk);
FirstThunk=(PIMAGE_THUNK_DATA)((LPBYTE)ManualInject->ImageBase+pIID->FirstThunk);
hModule=ManualInject->fnLoadLibraryA((LPCSTR)ManualInject->ImageBase+pIID->Name);
if(!hModule)
{
return FALSE;
}
while(OrigFirstThunk->u1.AddressOfData)
{
if(OrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
// Import by ordinal
Function=(DWORD)ManualInject->fnGetProcAddress(hModule,(LPCSTR)(OrigFirstThunk->u1.Ordinal & 0xFFFF));
if(!Function)
{
return FALSE;
}
FirstThunk->u1.Function=Function;
}
else
{
// Import by name
pIBN=(PIMAGE_IMPORT_BY_NAME)((LPBYTE)ManualInject->ImageBase+OrigFirstThunk->u1.AddressOfData);
Function=(DWORD)ManualInject->fnGetProcAddress(hModule,(LPCSTR)pIBN->Name);
if(!Function)
{
return FALSE;
}
FirstThunk->u1.Function=Function;
}
OrigFirstThunk++;
FirstThunk++;
}
pIID++;
}
if(ManualInject->NtHeaders->OptionalHeader.AddressOfEntryPoint)
{
EntryPoint=(PDLL_MAIN)((LPBYTE)ManualInject->ImageBase+ManualInject->NtHeaders->OptionalHeader.AddressOfEntryPoint);
return EntryPoint((HMODULE)ManualInject->ImageBase,DLL_PROCESS_ATTACH,NULL); // Call the entry point
}
return TRUE;
}
DWORD WINAPI LoadDllEnd()
{
return 0;
}
DWORD GetTargetThreadIDFromProcName(const char * ProcName)
{
PROCESSENTRY32 pe;
HANDLE thSnapShot;
BOOL retval, ProcFound = false;
thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (thSnapShot == INVALID_HANDLE_VALUE)
{
//MessageBox(NULL, "Error: Unable to create toolhelp snapshot!", "2MLoader", MB_OK);
printf("Error: Unable to create toolhelp snapshot!");
return false;
}
pe.dwSize = sizeof(PROCESSENTRY32);
retval = Process32First(thSnapShot, &pe);
while (retval)
{
if (StrStrI(pe.szExeFile, ProcName))
{
return pe.th32ProcessID;
}
retval = Process32Next(thSnapShot, &pe);
}
return 0;
}
void GetGamePath(char* buff) {
HKEY hKey = 0;
char path[255] = { 0 };
char filename[255] = { 0 };
DWORD dwType = 0;
DWORD dwBufSize = 255;
GetFullPathName("Game.exe", MAX_PATH, buff, NULL);
//If file exists, then just exit.
if (FILE *file = fopen(buff, "r")) {
fclose(file);
return;
}
if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\SomeGame\\Game", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS)
{
bool failed = false;
dwType = REG_SZ;
if (RegQueryValueEx(hKey, "PATH", 0, &dwType, (BYTE*)&path, &dwBufSize) != ERROR_SUCCESS)
failed = true;
if (RegQueryValueEx(hKey, "FILENAME", 0, &dwType, (BYTE*)&filename, &dwBufSize) != ERROR_SUCCESS)
failed = true;
RegCloseKey(hKey);
sprintf(buff, "%s%s", path, filename);
if (failed) {
GetFullPathName("Game.exe", MAX_PATH, buff, NULL);
}
}
}
int wmain(int argc,wchar_t* argv[])
{
PIMAGE_DOS_HEADER pIDH;
PIMAGE_NT_HEADERS pINH;
PIMAGE_SECTION_HEADER pISH;
HANDLE hProcess,hThread,hFile,hToken;
PVOID /*buffer,*/image,mem;
DWORD i,FileSize,ProcessId,ExitCode,read;
TOKEN_PRIVILEGES tp;
MANUAL_INJECT ManualInject;
if(OpenProcessToken((HANDLE)-1,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
{
tp.PrivilegeCount=1;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
tp.Privileges[0].Luid.LowPart=20;
tp.Privileges[0].Luid.HighPart=0;
AdjustTokenPrivileges(hToken,FALSE,&tp,0,NULL,NULL);
CloseHandle(hToken);
}
printf("\nOpening the DLL.\n");
/*
hFile=CreateFile("AO.dll",GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL); // Open the DLL
if(hFile==INVALID_HANDLE_VALUE)
{
printf("\nError: Unable to open the DLL (%d)\n",GetLastError());
return -1;
}
FileSize=GetFileSize(hFile,NULL);
buffer=VirtualAlloc(NULL,FileSize,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
if(!buffer)
{
printf("\nError: Unable to allocate memory for DLL data (%d)\n",GetLastError());
CloseHandle(hFile);
return -1;
}
// Read the DLL
if(!ReadFile(hFile,buffer,FileSize,&read,NULL))
{
printf("\nError: Unable to read the DLL (%d)\n",GetLastError());
VirtualFree(buffer,0,MEM_RELEASE);
CloseHandle(hFile);
return -1;
}
CloseHandle(hFile);
*/
MODULE hModule = GetModuleHandle(NULL); // get the handle to the current module (the executable file)
HRSRC hResource = FindResource(hModule, MAKEINTRESOURCE(RESOURCE_ID), RESOURCE_TYPE); // substitute RESOURCE_ID and RESOURCE_TYPE.
HGLOBAL hMemory = LoadResource(hModule, hResource);
DWORD dwSize = SizeofResource(hModule, hResource);
LPVOID lpAddress = LockResource(hMemory);
unsigned char *buffer = new char[dwSize];
memcpy(buffer, lpAddress, dwSize);
pIDH=(PIMAGE_DOS_HEADER)buffer;
if(pIDH->e_magic!=IMAGE_DOS_SIGNATURE)
{
printf("\nError: Invalid executable image.\n");
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
pINH=(PIMAGE_NT_HEADERS)((LPBYTE)buffer+pIDH->e_lfanew);
if(pINH->Signature!=IMAGE_NT_SIGNATURE)
{
printf("\nError: Invalid PE header.\n");
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
if(!(pINH->FileHeader.Characteristics & IMAGE_FILE_DLL))
{
printf("\nError: The image is not DLL.\n");
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
// Retrieve process ID
ProcessId = 0;
char buf[MAX_PATH] = { 0 };
//Game.exe not started, attempt to start Game.exe (same path as this tool).
if (ProcessId == 0) {
// Gets the exe's full path name.
GetGamePath(buf);
printf("GamePath: ");
printf(buf);
printf("\n");
LPCTSTR lpApplicationName = buf; /* The program to be executed */
STARTUPINFO lpStartupInfo;
PROCESS_INFORMATION lpProcessInfo;
memset(&lpStartupInfo, 0, sizeof(lpStartupInfo));
memset(&lpProcessInfo, 0, sizeof(lpProcessInfo));
/* Create the process */
if (!CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &lpStartupInfo, &lpProcessInfo)) {
printf("Uh-Oh! CreateProcess() failed to start program %s\n", lpApplicationName);
_getch();
return 0;
} else {
WaitForSingleObject(lpProcessInfo.hProcess, 2000);
CloseHandle(lpProcessInfo.hThread);
CloseHandle(lpProcessInfo.hProcess);
ProcessId = lpProcessInfo.dwProcessId;
}
}
printf("Game.exe ProcessId = %d\n", ProcessId);
printf("\nOpening target process.\n");
hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessId);
if(!hProcess)
{
printf("\nError: Unable to open target process (%d)\n",GetLastError());
VirtualFree(buffer,0,MEM_RELEASE);
CloseHandle(hProcess);
return -1;
}
printf("\nAllocating memory for the DLL.\n");
image=VirtualAllocEx(hProcess,NULL,pINH->OptionalHeader.SizeOfImage,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); // Allocate memory for the DLL
if(!image)
{
printf("\nError: Unable to allocate memory for the DLL (%d)\n",GetLastError());
VirtualFree(buffer,0,MEM_RELEASE);
CloseHandle(hProcess);
return -1;
}
// Copy the header to target process
printf("\nCopying headers into target process.\n");
if(!WriteProcessMemory(hProcess,image,buffer,pINH->OptionalHeader.SizeOfHeaders,NULL))
{
printf("\nError: Unable to copy headers to target process (%d)\n",GetLastError());
VirtualFreeEx(hProcess,image,0,MEM_RELEASE);
CloseHandle(hProcess);
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
pISH=(PIMAGE_SECTION_HEADER)(pINH+1);
// Copy the DLL to target process
printf("\nCopying sections to target process.\n");
for(i=0;i<pINH->FileHeader.NumberOfSections;i++)
{
WriteProcessMemory(hProcess,(PVOID)((LPBYTE)image+pISH[i].VirtualAddress),(PVOID)((LPBYTE)buffer+pISH[i].PointerToRawData),pISH[i].SizeOfRawData,NULL);
}
printf("\nAllocating memory for the loader code.\n");
mem=VirtualAllocEx(hProcess,NULL,4096,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); // Allocate memory for the loader code
if(!mem)
{
printf("\nError: Unable to allocate memory for the loader code (%d)\n",GetLastError());
VirtualFreeEx(hProcess,image,0,MEM_RELEASE);
CloseHandle(hProcess);
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
printf("\nLoader code allocated at %#x\n",mem);
memset(&ManualInject,0,sizeof(MANUAL_INJECT));
ManualInject.ImageBase=image;
ManualInject.NtHeaders=(PIMAGE_NT_HEADERS)((LPBYTE)image+pIDH->e_lfanew);
ManualInject.BaseRelocation=(PIMAGE_BASE_RELOCATION)((LPBYTE)image+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
ManualInject.ImportDirectory=(PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)image+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
ManualInject.fnLoadLibraryA=LoadLibraryA;
ManualInject.fnGetProcAddress=GetProcAddress;
printf("\nWriting loader code to target process.\n");
WriteProcessMemory(hProcess,mem,&ManualInject,sizeof(MANUAL_INJECT),NULL); // Write the loader information to target process
WriteProcessMemory(hProcess,(PVOID)((PMANUAL_INJECT)mem+1),LoadDll,(DWORD)LoadDllEnd-(DWORD)LoadDll,NULL); // Write the loader code to target process
printf("\nExecuting loader code.\n");
hThread=CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)((PMANUAL_INJECT)mem+1),mem,0,NULL); // Create a remote thread to execute the loader code
if(!hThread)
{
printf("\nError: Unable to execute loader code (%d)\n",GetLastError());
VirtualFreeEx(hProcess,mem,0,MEM_RELEASE);
VirtualFreeEx(hProcess,image,0,MEM_RELEASE);
CloseHandle(hProcess);
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
WaitForSingleObject(hThread,INFINITE);
GetExitCodeThread(hThread,&ExitCode);
if(!ExitCode)
{
VirtualFreeEx(hProcess,mem,0,MEM_RELEASE);
VirtualFreeEx(hProcess,image,0,MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
CloseHandle(hThread);
VirtualFreeEx(hProcess,mem,0,MEM_RELEASE);
CloseHandle(hProcess);
printf("\nDLL injected at %#x\n",image);
if(pINH->OptionalHeader.AddressOfEntryPoint)
{
printf("\nDLL entry point: %#x\n",(PVOID)((LPBYTE)image+pINH->OptionalHeader.AddressOfEntryPoint));
}
VirtualFree(buffer,0,MEM_RELEASE);
return 0;
}

Wow64GetThreadContext returning same values for WOW64_CONTEXT structure members

I am compiling to 64-bit and calling the functions on a 32-bit(Wow64) processes thread. No errors are being returned for any functions.
But for some reason the CPU register members in the WOW64_CONTEXTstruct passed to Wow64GetThreadContext are always the same values each and every time the function is called. Even though I initialize every member in the struct to 0, WOW64_CONTEXT wow64ctxt = {0}.
As far as I know I am doing everything correctly but I always get the same values for each member in WOW64_CONTEXT.
Here's my code:
#define _WIN32_WINNT _WIN32_IE_WIN8
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
int main()
{
DWORD dwPid = 0;
BOOL found = FALSE;
BOOL wow64 = FALSE;
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
HANDLE hSnapshot = INVALID_HANDLE_VALUE;
THREADENTRY32 th32;
WOW64_CONTEXT wow64ctxt = {0};
printf("PID: ");
scanf("%lu", &dwPid);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if(hProcess == NULL)
{
printf("Error getting handle to process: %lu\n", GetLastError());
return 1;
}
if(!IsWow64Process(hProcess, &wow64))
{
printf("Error determining bitness of process: %lu\n", GetLastError());
return 1;
}
if(!wow64)
{
printf("Error, not a 32-bit process... closing program\n");
return 1;
}
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwPid);
if(hSnapshot == INVALID_HANDLE_VALUE)
{
printf("Error getting thread snapshot: %lu\n", GetLastError());
return 1;
}
th32.dwSize = sizeof(THREADENTRY32);
if(!Thread32First(hSnapshot, &th32))
{
printf("Error Thread32First: %lu\n", GetLastError());
return 1;
}
while(Thread32Next(hSnapshot, &th32))
{
if(th32.th32OwnerProcessID == dwPid)
{
found = TRUE;
break;
}
}
if(!found)
{
printf("Thread could not be found\n");
return 1;
}
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, th32.th32ThreadID);
if(hThread == NULL)
{
printf("Error getting a handle to thread %lu: %lu\n", th32.th32ThreadID, GetLastError());
return 1;
}
if(Wow64SuspendThread(hThread) == -1)
{
printf("Error suspending thread: %lu\n", GetLastError());
return 1;
}
wow64ctxt.ContextFlags = WOW64_CONTEXT_FULL;
if(!Wow64GetThreadContext(hThread, &wow64ctxt))
{
printf("Error getting thread context: %lu\n", GetLastError());
}
ResumeThread(hThread);
printf("EAX: %lu\n", wow64ctxt.Eax);
printf("EBP: %lu\n", wow64ctxt.Ebp);
printf("EIP: %lu\n", wow64ctxt.Eip);
return 0;
}

How to determine if an account belongs to Administrators group programmatically?

My Windows has several accounts like "test1", "test2" and "test3" that belong to the Administrators group. I am developing an application program and I want that program to know if itself is run under an account that belong to the Administrators group by designing a boolean function: isCurrentUserAdminMember(), the isCurrentUserAdminMember() funtion should only return TRUE if the process is run by "test1", "test2", "test3" or the built-in Administrator account no matter whether the process is elevated.
I found some code in http://www.codeproject.com/Articles/320748/Haephrati-Elevating-during-runtime as below, but it seems only to check if the current process is elevated as an Administrator. I don't care if the process is elevated, I just want to know if the start account of the process is a member of Administrators group. And I hope the determination itself is not privilege required. Is that possible? thanks.
BOOL IsAppRunningAsAdminMode()
{
BOOL fIsRunAsAdmin = FALSE;
DWORD dwError = ERROR_SUCCESS;
PSID pAdministratorsGroup = NULL;
// Allocate and initialize a SID of the administrators group.
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
if (!AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&pAdministratorsGroup))
{
dwError = GetLastError();
goto Cleanup;
}
// Determine whether the SID of administrators group is enabled in
// the primary access token of the process.
if (!CheckTokenMembership(NULL, pAdministratorsGroup, &fIsRunAsAdmin))
{
dwError = GetLastError();
goto Cleanup;
}
Cleanup:
// Centralized cleanup for all allocated resources.
if (pAdministratorsGroup)
{
FreeSid(pAdministratorsGroup);
pAdministratorsGroup = NULL;
}
// Throw the error if something failed in the function.
if (ERROR_SUCCESS != dwError)
{
throw dwError;
}
return fIsRunAsAdmin;
}
At last, we achieved the goal to check the Administrators group membership as the code below, however it is USELESS as the answer and comment said, just leave here for reference in case anybody needs it for other use.
// PermTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdio.h"
#include "iostream"
using namespace std;
#include "windows.h"
#include <lm.h>
#pragma comment(lib, "netapi32.lib")
BOOL IsUserInGroup(const wchar_t* groupe)
{
BOOL result = FALSE;
SID_NAME_USE snu;
WCHAR szDomain[256];
DWORD dwSidSize = 0;
DWORD dwSize = sizeof szDomain / sizeof * szDomain;
if ((LookupAccountNameW(NULL, groupe, 0, &dwSidSize, szDomain, &dwSize, &snu) == 0)
&& (ERROR_INSUFFICIENT_BUFFER == GetLastError()))
{
SID* pSid = (SID*)malloc(dwSidSize);
if (LookupAccountNameW(NULL, groupe, pSid, &dwSidSize, szDomain, &dwSize, &snu))
{
BOOL b;
if (CheckTokenMembership(NULL, pSid, &b))
{
if (b == TRUE)
{
result = TRUE;
}
}
else
{
result = FALSE;
}
}
//Si tout vas bien (la presque totalitée des cas), on delete notre pointeur
//avec le bon operateur.
free(pSid);
}
return result;
}
void getUserInfo(WCHAR *domainName, WCHAR *userName)
{
LPUSER_INFO_3 pBuf = NULL;
int j = 0;
DWORD nStatus = NetUserGetInfo(domainName, userName, 3, (LPBYTE *) &pBuf);
LPUSER_INFO_2 pBuf2 = NULL;
pBuf2 = (LPUSER_INFO_2) pBuf;
if (pBuf)
{
wprintf(L"User account name: %s\\%s\n", domainName, pBuf2->usri2_name);
wprintf(L"Privilege level: %d\n\n", pBuf2->usri2_priv);
}
// wprintf(L"\tPassword: %s\n", pBuf2->usri2_password);
// wprintf(L"\tPassword age (seconds): %d\n",
// pBuf2->usri2_password_age);
// wprintf(L"Privilege level: %d\n\n", pBuf2->usri2_priv);
// #define USER_PRIV_GUEST 0
// #define USER_PRIV_USER 1
// #define USER_PRIV_ADMIN 2
// wprintf(L"\tHome directory: %s\n", pBuf2->usri2_home_dir);
// wprintf(L"\tComment: %s\n", pBuf2->usri2_comment);
// wprintf(L"\tFlags (in hex): %x\n", pBuf2->usri2_flags);
// wprintf(L"\tScript path: %s\n", pBuf2->usri2_script_path);
// wprintf(L"\tAuth flags (in hex): %x\n",
// pBuf2->usri2_auth_flags);
// wprintf(L"\tFull name: %s\n", pBuf2->usri2_full_name);
// wprintf(L"\tUser comment: %s\n", pBuf2->usri2_usr_comment);
// wprintf(L"\tParameters: %s\n", pBuf2->usri2_parms);
// wprintf(L"\tWorkstations: %s\n", pBuf2->usri2_workstations);
// wprintf
// (L"\tLast logon (seconds since January 1, 1970 GMT): %d\n",
// pBuf2->usri2_last_logon);
// wprintf
// (L"\tLast logoff (seconds since January 1, 1970 GMT): %d\n",
// pBuf2->usri2_last_logoff);
// wprintf
// (L"\tAccount expires (seconds since January 1, 1970 GMT): %d\n",
// pBuf2->usri2_acct_expires);
// wprintf(L"\tMax storage: %d\n", pBuf2->usri2_max_storage);
// wprintf(L"\tUnits per week: %d\n",
// pBuf2->usri2_units_per_week);
// wprintf(L"\tLogon hours:");
// for (j = 0; j < 21; j++)
// {
// printf(" %x", (BYTE) pBuf2->usri2_logon_hours[j]);
// }
// wprintf(L"\n");
// wprintf(L"\tBad password count: %d\n",
// pBuf2->usri2_bad_pw_count);
// wprintf(L"\tNumber of logons: %d\n",
// pBuf2->usri2_num_logons);
// wprintf(L"\tLogon server: %s\n", pBuf2->usri2_logon_server);
// wprintf(L"\tCountry code: %d\n", pBuf2->usri2_country_code);
// wprintf(L"\tCode page: %d\n", pBuf2->usri2_code_page);
}
#include <comdef.h>
#define MAX_NAME 256
BOOL GetLogonFromToken (HANDLE hToken, _bstr_t& strUser, _bstr_t& strdomain)
{
DWORD dwSize = MAX_NAME;
BOOL bSuccess = FALSE;
DWORD dwLength = 0;
strUser = "";
strdomain = "";
PTOKEN_USER ptu = NULL;
//Verify the parameter passed in is not NULL.
if (NULL == hToken)
goto Cleanup;
if (!GetTokenInformation(
hToken, // handle to the access token
TokenUser, // get information about the token's groups
(LPVOID) ptu, // pointer to PTOKEN_USER buffer
0, // size of buffer
&dwLength // receives required buffer size
))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
goto Cleanup;
ptu = (PTOKEN_USER)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, dwLength);
if (ptu == NULL)
goto Cleanup;
}
if (!GetTokenInformation(
hToken, // handle to the access token
TokenUser, // get information about the token's groups
(LPVOID) ptu, // pointer to PTOKEN_USER buffer
dwLength, // size of buffer
&dwLength // receives required buffer size
))
{
goto Cleanup;
}
SID_NAME_USE SidType;
char lpName[MAX_NAME];
char lpDomain[MAX_NAME];
if( !LookupAccountSidA( NULL , ptu->User.Sid, lpName, &dwSize, lpDomain, &dwSize, &SidType ) )
{
DWORD dwResult = GetLastError();
if( dwResult == ERROR_NONE_MAPPED )
strcpy (lpName, "NONE_MAPPED" );
else
{
printf("LookupAccountSid Error %u\n", GetLastError());
}
}
else
{
// printf( "Current user is %s\\%s\n",
// lpDomain, lpName );
strUser = lpName;
strdomain = lpDomain;
bSuccess = TRUE;
}
Cleanup:
if (ptu != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)ptu);
return bSuccess;
}
HRESULT GetUserFromProcess( _bstr_t& strUser, _bstr_t& strdomain)
{
//HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,procId);
HANDLE hProcess = GetCurrentProcess();
if(hProcess == NULL)
return E_FAIL;
HANDLE hToken = NULL;
if( !OpenProcessToken( hProcess, TOKEN_QUERY, &hToken ) )
{
CloseHandle( hProcess );
return E_FAIL;
}
BOOL bres = GetLogonFromToken (hToken, strUser, strdomain);
CloseHandle( hToken );
CloseHandle( hProcess );
return bres?S_OK:E_FAIL;
}
int _tmain(int argc, _TCHAR* argv[])
{
//cout << IsUserInGroup(L"administrators");
getUserInfo(L"adtest.net", L"Administrator");
getUserInfo(NULL, L"Administrator");
getUserInfo(NULL, L"test");
getUserInfo(NULL, L"test2");
getUserInfo(NULL, L"testnormal");
_bstr_t username;
_bstr_t domain;
GetUserFromProcess(username, domain);
cout << "Current account running this program is: " << endl << domain << "\\" << username << endl;
getchar();
return 0;
}
You can do this by opening your process token (OpenProcessToken, listing the SIDs using GetTokenInformation and comparing each SID to the Administrators SID.
Microsoft have sample code here: Searching for a SID in an Access Token in C++
However, this is rarely a useful thing to do. Even if the user is not a member of the Administrators group, they can still elevate by providing an administrative username and password, so you should not (for example) only offer elevation if the user is in the Administrators group.
bool IsMemberOfGroup(const char *pszGroupName){
bool bFound = false;
HANDLE hToken=INVALID_HANDLE_VALUE;
BOOL bSuccess = OpenProcessToken( GetCurrentProcess(),
TOKEN_QUERY,//|TOKEN_QUERY_SOURCE,
&hToken);
if ( bSuccess )
{
DWORD dwSizeToken=0;
DWORD dwSizeName=0;
DWORD dwSizeReferencedDomainName = 0;
// Get group information:
GetTokenInformation(hToken, TokenGroups, NULL, dwSizeToken, &dwSizeToken);
{
const int MAX_NAME = 256;
char *psName = new char[MAX_NAME];
char *psDomain = new char[MAX_NAME];
char *pBuf = new char[dwSizeToken+10];
TOKEN_GROUPS *pGroupInfo = (TOKEN_GROUPS *)pBuf;
bSuccess = GetTokenInformation(hToken, TokenGroups, pGroupInfo, dwSizeToken, &dwSizeToken);
if ( bSuccess )
{
// find the group name we are looking for
for ( UINT uiGroupNdx = 0; uiGroupNdx < pGroupInfo->GroupCount && !bFound; uiGroupNdx++ )
{
SID_NAME_USE SidType;
dwSizeName = MAX_NAME;
dwSizeReferencedDomainName = MAX_NAME;
bSuccess = LookupAccountSid(NULL, // local system,
pGroupInfo->Groups[uiGroupNdx].Sid,
psName,
&dwSizeName,
psDomain,
&dwSizeReferencedDomainName,
&SidType);
if ( bSuccess )
{
if ( SidTypeGroup == SidType )
{
if ( !lstrcmpi(pszGroupName, psName) )
{
bFound = true;
}
}
}
}
}
delete [] pBuf;
delete [] psName;
delete [] psDomain;
}
CloseHandle(hToken);
}
return bFound;
}