Difference between GetExtendedUdpTable and netstat result - c++

I used this code to get opened UDP ports and the application that use every port.
DWORD (WINAPI *pGetExtendedUdpTable)(
PVOID pUdpTable,
PDWORD pdwSize,
BOOL bOrder,
ULONG ulAf,
UDP_TABLE_CLASS TableClass,
ULONG Reserved
);
MIB_UDPTABLE_OWNER_PID *pUDPInfo;
MIB_UDPROW_OWNER_PID *owner;
DWORD size;
DWORD dwResult;
HMODULE hLib = LoadLibrary((LPCWSTR)"iphlpapi.dll");
pGetExtendedUdpTable = (DWORD (WINAPI *)(PVOID,PDWORD,BOOL,ULONG,UDP_TABLE_CLASS,ULONG))
GetProcAddress(hLib, "GetExtendedTcpTable");
if ( !pGetExtendedUdpTable )
{
//printf("Could not load iphlpapi.dll. This application is for Windows XP SP2 and up.\n");
return "Could not load iphlpapi.dll. This application is for Windows XP SP2 and up.\n";
}
dwResult = pGetExtendedUdpTable(NULL, &size, false, AF_INET, (UDP_TABLE_CLASS)5, 0);
pUDPInfo = (MIB_UDPTABLE_OWNER_PID*)malloc(size);
dwResult = pGetExtendedUdpTable(pUDPInfo, &size, false, AF_INET, (UDP_TABLE_CLASS)5, 0);
//
if (dwResult != NO_ERROR)
{
printf("Couldn't get our IP table");
return "Couldn't get our IP table";
}
for (DWORD dwLoop = 0; dwLoop < pUDPInfo->dwNumEntries; dwLoop++)
{
owner = &pUDPInfo->table[dwLoop];
ApplicationName = GetNameByPID(owner->dwOwningPid);
OpenedPort = convertInt(ntohs(owner->dwLocalPort));
LocalAdress = convertInt(ntohs(owner->dwLocalAddr));
}
But, I haven't the same result as netstat -ano.In my code, I have port 0 more than 10 times but in netstat command port 0 doesn't exist.

You have UDP everywhere but the function you're querying for is the TCP one (GetExtendedTcpTable).

Related

A process created with CreateProcessAsUserW from a 64 bit process exits immediately with exception code 0xc06d007e on Windows 7 64 bit

I have a C# Application, which is launched from a C++ DLL using CreateProcessAsUserW api. The process is launched successfully, but terminates immediately. It works properly on Windows 10 [both as 32 bit and 64 bit] and 32 bit on Windows 7. I found the following link,
Why is this process crashing as soon as it is launched?
however, process monitor from SysInternals finds no missing dll. [I can attach the saved logs from ProcMon] I also tried passing the path to the application folder, as suggested elsewhere, in the lpCurrentDirectory parameter of the API, but that did not work either.
I followed the guidance in How to get the active user when multiple users are logged on in Windows? to write the code which launches the process,
and the method which launches the process is called from a windows service.To emulate that from the command line, I used the following
How do you run CMD.exe under the Local System Account? [psexec64 -i -s cmd.exe, and then launched the process from cmd.exe]
The method is as follows
//How to get the active user when multiple users are logged on in Windows?
STDMETHODIMP CProcessManager::LaunchProcessAsActiveUser(BSTR processName, LONG* dwProcessId)
{
//char *lpszPath = _com_util::ConvertBSTRToString(processName);
wchar_t* path = (wchar_t*)processName;//CharToWideChar(lpszPath);
DWORD session_id = -1;
DWORD session_count = 0;
WTS_SESSION_INFOA *pSession = NULL;
if (WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
{
//log success
}
else
{
//log error
return S_OK;
}
logger->Log(L"Session Count", session_count);
logger->Log(L"Begin Enumerating Sesions");
for (int i = 0; i < session_count; i++)
{
session_id = pSession[i].SessionId;
logger->Log(L"SessionId", session_id);
WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;
DWORD bytes_returned = 0;
if (::WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE,
session_id,
WTSConnectState,
reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
&bytes_returned))
{
wts_connect_state = *ptr_wts_connect_state;
::WTSFreeMemory(ptr_wts_connect_state);
if (wts_connect_state != WTSActive) continue;
}
else
{
//log error
continue;
}
logger->Log(L"End Enumerating Sesions");
logger->Log(L"Selected Session Id", session_id);
HANDLE hImpersonationToken;
if (!WTSQueryUserToken(session_id, &hImpersonationToken))
{
//log error
logger->Log(L"Exception in WTSQueryUserToken", GetLastError());
continue;
}
//Get real token from impersonation token
DWORD neededSize1 = 0;
HANDLE *realToken = new HANDLE;
if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1))
{
CloseHandle(hImpersonationToken);
hImpersonationToken = *realToken;
}
else
{
//log error
logger->Log(L"Exception in GetTokenInformation", GetLastError());
continue;
}
HANDLE hUserToken;
if (!DuplicateTokenEx(hImpersonationToken,
//0,
//MAXIMUM_ALLOWED,
TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
NULL,
SecurityImpersonation,
TokenPrimary,
&hUserToken))
{
//log error
logger->Log(L"Exception in DuplicateTokenEx", GetLastError());
continue;
}
// Get user name of this process
//LPTSTR pUserName = NULL;
WCHAR* pUserName;
DWORD user_name_len = 0;
if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len))
{
//log username contained in pUserName WCHAR string
// char * lpszUserName = WideCharToChar(pUserName);
logger->Log(pUserName);
//LocalFree(lpszUserName);
}
else
{
logger->Log(L"Exception in WTSQuerySessionInformation", GetLastError());
}
//Free memory
if (pUserName) WTSFreeMemory(pUserName);
ImpersonateLoggedOnUser(hUserToken);
STARTUPINFOW StartupInfo;
StartupInfo.cb = sizeof(STARTUPINFOW);
//GetStartupInfoW(&StartupInfo);
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
//Uncommented by Sagar 20th January 20118 1612
StartupInfo.lpDesktop = CharToWideChar("winsta0\\default");
//to Hide Console Process 03-10-2018
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_SHOW;//SW_HIDE;
PROCESS_INFORMATION processInfo;
SECURITY_ATTRIBUTES Security1;
ZeroMemory(&Security1, sizeof(Security1));
Security1.nLength = sizeof SECURITY_ATTRIBUTES;
SECURITY_ATTRIBUTES Security2;
ZeroMemory(&Security2, sizeof(Security2));
Security2.nLength = sizeof SECURITY_ATTRIBUTES;
void* lpEnvironment = NULL;
// Get all necessary environment variables of logged in user
// to pass them to the new process
BOOL resultEnv = CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE);
if (!resultEnv)
{
//log error
DWORD err = GetLastError();
logger->Log(L"Exception in CreateEnvironmentBlock", err);
continue;
}
WCHAR PP[1024]; //path and parameters
ZeroMemory(PP, 1024 * sizeof WCHAR);
wcscpy_s(PP, path);
wcscat_s(PP, L" ");
//wcscat(PP, args);
// Start the process on behalf of the current user
BOOL result = CreateProcessAsUserW(hUserToken,
PP,
NULL,
&Security1,
&Security2,
FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE/*| CREATE_NO_WINDOW*/,//CREATE_NO_WINDOW to Hide Console Process 03-10-2018
/*lpEnvironment*/NULL,
//"C:\\ProgramData\\some_dir",
NULL,
/*NULL,*/
&StartupInfo,
&processInfo);
if (!result)
{
//log error
//char * lpszPath = WideCharToChar(PP);
logger->Log(L"Failed to create process", PP);
//LocalFree(lpszPath);
DWORD err = GetLastError();
logger->Log(L"GetLastError returned", err);
}
else
{
*dwProcessId = processInfo.dwProcessId;
logger->Log(L"Created Process", *dwProcessId);
//log success
}
DestroyEnvironmentBlock(lpEnvironment);
CloseHandle(hImpersonationToken);
CloseHandle(hUserToken);
CloseHandle(realToken);
RevertToSelf();
}
WTSFreeMemory(pSession);
return S_OK;
}
Procmon screen shots attached below
Please help.
Thanks,
Sagar
[![Pg 1](https://i.stack.imgur.com/CJCrG.png)
[![Pg 2](https://i.stack.imgur.com/uo8Uw.png)
[![Pg 3](https://i.stack.imgur.com/G7g12.png)
[![Pg 4](https://i.stack.imgur.com/6e5w4.png)
[![Pg 5](https://i.stack.imgur.com/8k2b0.png)
I tried the following permutations
Target Process : ATL DLL : Launcher:Result
64 bit 64 bit 64 bit Crashes
64 bit 32 bit 64 bit Crashes
32 bit 32 bit 64 bit Crashes
32 bit 64 bit 64 bit Crashes
32 bit 32 bit 32 bit OK
64 bit 32 bit 32 bit OK
64 bit 64 bit 32 bit OK
32 bit 64 bit 32 bit OK
So it seems that if the launcher process is 64 bit, it always crashes and if it is 32 bit, it always succeeds. What is the difference between a 64 and 32 bit launcher process?
I got the answer on https://social.msdn.microsoft.com/Forums/vstudio/en-US/fb9d15fb-dc9f-488e-92c4-e0bb438442e1/64-bit-dot-net-process-created-with-createprocessasuserw-exits-immediately-with-exception-code?forum=vcgeneral [RLWA32 answered it]
There was a problem with the way in which the process was being launched. His code for launching the process is as follows, and it works fine.
UINT __stdcall RunProgram(LPVOID pv)
{
WCHAR szTarg32[MAX_PATH] = TARGET32_PATH, szTarg64[MAX_PATH] = TARGET64_PATH;
LPWSTR pszProcess = nullptr;
PWTS_SESSION_INFOW pwsi = NULL;
DWORD dwSession = -1, dwCount = 0;
HANDLE hToken = NULL;
LPVOID lpEnvironment = nullptr;
LPWSTR pszPath = nullptr;
UINT ret = 1;
DWORD dwOpcode = reinterpret_cast<DWORD>(pv);
if (dwOpcode == LAUNCH_X86PROCESS)
pszProcess = szTarg32;
else
pszProcess = szTarg64;
if (!WTSEnumerateSessionsW(WTS_CURRENT_SERVER, 0, 1, &pwsi, &dwCount))
{
Report(L"WTSEnumerateSessions failed with %d\n", GetLastError());
return ret;
}
for (DWORD i = 0; i < dwCount; i++)
{
if (pwsi[i].State == WTSActive)
{
dwSession = pwsi[i].SessionId;
break;
}
}
if (dwSession != -1)
{
if (WTSQueryUserToken(dwSession, &hToken))
{
if (CreateEnvironmentBlock(&lpEnvironment, hToken, FALSE))
{
HRESULT hr;
if (SUCCEEDED((hr = SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, hToken, &pszPath))))
{
if (ImpersonateLoggedOnUser(hToken))
{
STARTUPINFOW si = { sizeof si };
PROCESS_INFORMATION pi = {};
if (CreateProcessAsUserW(hToken, pszProcess, nullptr, nullptr, nullptr, FALSE, CREATE_UNICODE_ENVIRONMENT, lpEnvironment, pszPath, &si, &pi))
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
Report(L"CreateProcessAsUser started %s, pid is %d\n", pszProcess, pi.dwProcessId);
ret = 0;
}
else
Report(L"CreateProcessAsUser failed with %d\n", GetLastError());
RevertToSelf();
}
else
Report(L"ImpersonateLoggedOnUser failed with %d\n", GetLastError());
}
else
Report(L"SHGetKnownFolderPath failed with 0x%X\n", hr);
}
else
Report(L"CreateEnvironmentBlock failed with %d\n", GetLastError());
}
else
Report(L"WTSQueryUserToken failed with %d\n", GetLastError());
}
else
Report(L"WTSEnumerateSessions reported no active session\n");
if (pwsi)
WTSFreeMemory(pwsi);
if (hToken)
CloseHandle(hToken);
if (lpEnvironment)
DestroyEnvironmentBlock(lpEnvironment);
if (pszPath)
CoTaskMemFree(pszPath);
return ret;
}

Deleting a Standard TCP IP port using xcvdata not working

Xcvdata() for deleting port.
BOOL DeletePortCus( TCHAR* PortName )
{
HANDLE hPrinter;
PRINTER_DEFAULTS PrinterDefaults;
memset(&PrinterDefaults, 0, sizeof(PrinterDefaults));
PrinterDefaults.pDatatype = NULL;
PrinterDefaults.pDevMode = NULL;
PrinterDefaults.DesiredAccess = SERVER_ACCESS_ADMINISTER;
DWORD needed = 0;
DWORD rslt = 0;
//Port data
PORT_DATA_1 pOutputData ;
DWORD error = 0;
if (!OpenPrinter(L",XcvMonitor Standard TCP/IP Port", &hPrinter, &PrinterDefaults))
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), NULL,(LPTSTR) &lpMsgBuf, 0, NULL );
_tprintf( TEXT("Error in OpenPrinter. Error msg : %s"),lpMsgBuf);
LocalFree( lpMsgBuf );
return FALSE;
}
DWORD xcvresult= 0;
if (
!XcvData(
hPrinter,
TEXT("DeletePort"),
(PBYTE)PortName,
(lstrlen(PortName) +1) * sizeof(TCHAR), //the 1 is for the trailing NULL
( byte * ) &pOutputData,
sizeof(PORT_DATA_1),
&needed,
&xcvresult)
)
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), NULL,(LPTSTR) &lpMsgBuf, 0, NULL );
_tprintf( TEXT("Error in XcvData. Error msg : %s; XcvDataPort status val = %d"), lpMsgBuf, xcvresult);
LocalFree( lpMsgBuf );
return FALSE;
}
ClosePrinter(hPrinter);
return TRUE;
}
The highlight is both the functions (openprinter and xcvdata) succeed. But the port is not getting removed. I am completely at a loss here as I dont have any error to lookup.
Instead of ,XcvMonitor Standard TCP/IP Port I also tried with ,XcvPort <portname>. Still same.
As Samer suggested below, I tried with OpenPrinter2 with no cache option.
PS: I know there's this simple alternative DeletePort(), but it invokes a UI dialog box if it fails, so I don't want to use it.
It seems the issue might be related to specific version of OS which caches printer handles. To get around this you use an alternate call OpenPrinter2 with the PRINTER_OPTION_NO_CACHE. Below is the modified code with the flag set.
HANDLE hPrinter;
PRINTER_DEFAULTS PrinterDefaults;
memset(&PrinterDefaults, 0, sizeof(PrinterDefaults));
PrinterDefaults.pDatatype = NULL;
PrinterDefaults.pDevMode = NULL;
PrinterDefaults.DesiredAccess = SERVER_ACCESS_ADMINISTER;
PRINTER_OPTIONS PrinterOptions;
PrinterOptions.cbSize = sizeof(PrinterOptions);
PrinterOptions.dwFlags = PRINTER_OPTION_NO_CACHE;
DWORD needed = 0;
DWORD rslt = 0;
//Port data
PORT_DATA_1 pOutputData ;
DWORD error = 0;
if (!OpenPrinter2(L",XcvMonitor Standard TCP/IP Port", &hPrinter, &PrinterDefaults, &PrinterOptions))
{
LPVOID lpMsgBuf;

How can i ping remote computer on my Windows computer with c++?

I used below code. It works, but in debug mode in Visual Studio if you stop the debug the computer gave blue screen so it is not useful. I did some research and i found this is a common bug for icmpapi. Is there a any way to ping computer c++?
#include <winsock2.h>
#include <iphlpapi.h>
#include <icmpapi.h>
//Declare and initialize variables
HANDLE hIcmpFile;
unsigned long ipaddr = INADDR_NONE;
DWORD dwRetVal = 0;
DWORD dwError = 0;
char SendData[] = "Data Buffer";
LPVOID ReplyBuffer = NULL;
DWORD ReplySize = 0;
QByteArray ipArray = computerIt->GetIP().toLocal8Bit();
const char *hostIP = ipArray.data();
ipaddr = inet_addr(hostIP);
if ( ipaddr == INADDR_NONE )
{
EventLogger::LogMessage(true, "<%s> Computer in <%s> Computer Group, IP initialization failed. (inet_addr(hostIP))", computerIt->GetName().toUtf8().constData(), computerGroupIt->GetName().toUtf8().constData());
break;
}
hIcmpFile = IcmpCreateFile();
if ( hIcmpFile == INVALID_HANDLE_VALUE )
{
EventLogger::LogMessage(true, "<%s> Computer in <%s> Computer Group, IcmpCreatefile returned error", computerIt->GetName().toUtf8().constData(), computerGroupIt->GetName().toUtf8().constData());
break;
}
// Allocate space for at a single reply
ReplySize = sizeof (ICMP_ECHO_REPLY) + sizeof (SendData) + 8;
ReplyBuffer = (VOID *) malloc(ReplySize);
if ( ReplyBuffer == NULL )
{
EventLogger::LogMessage(true, "<%s> Computer in <%s> Computer Group, unable to allocate memory for reply buffer", computerIt->GetName().toUtf8().constData(), computerGroupIt->GetName().toUtf8().constData());
break;
}
// Starting pinging
dwRetVal = IcmpSendEcho2(hIcmpFile, NULL, NULL, NULL,
ipaddr, SendData, sizeof (SendData), NULL,
ReplyBuffer, ReplySize, 1000);
if ( dwRetVal == 0 )
{
computerIt->SetAliveStatus(false);
}
else
{
computerIt->SetAliveStatus(true);
}
be careful.
at:
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366050(v=vs.85).aspx
the code works , BUT isĀ  missing an IMPORTANT POINT if you paste/copy this code:
MISSING free(ReplyBuffer)

WSARecvFrom target ip address

I use WSARecvFrom function. It looks like this:
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(listen_port);
bind(s, reinterpret_cast<PSOCKADDR>(&addr), sizeof(addr));
...
WSARecvFrom(s, ..., reinterpret_cast<sockaddr *>(&event->address), &event->addressLength, ...);
I can read From IP address from event->address. But how can I read target IP address UDP packet was sent to (socket was binded to INADDR_ANY - it listens all interfaces) ?
UPDATE. I found solution (for Windows Vista and higher). I wrote 2 functions: WSARecvFromEx allows to get target IP and WSASendToEx allows to send "from" IP:
//copyright (c) 2013 Vitaly. http://blog.coolsoftware.ru/
#if !(_WIN32_WINNT >= 0x0501)
typedef
INT
(PASCAL FAR * LPFN_WSARECVMSG) (
__in SOCKET s,
__inout LPWSAMSG lpMsg,
__out_opt LPDWORD lpdwNumberOfBytesRecvd,
__inout_opt LPWSAOVERLAPPED lpOverlapped,
__in_opt LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
#define WSAID_WSARECVMSG \
{0xf689d7c8,0x6f1f,0x436b,{0x8a,0x53,0xe5,0x4f,0xe3,0x51,0xc3,0x22}}
#endif !(_WIN32_WINNT >= 0x0501)
#if !(_WIN32_WINNT >= 0x0600)
typedef
INT
(PASCAL FAR * LPFN_WSASENDMSG) (
__in SOCKET s,
__in LPWSAMSG lpMsg,
__in DWORD dwFlags,
__out_opt LPDWORD lpNumberOfBytesSent,
__inout_opt LPWSAOVERLAPPED lpOverlapped OPTIONAL,
__in_opt LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine OPTIONAL
);
#define WSAID_WSASENDMSG /* a441e712-754f-43ca-84a7-0dee44cf606d */ \
{0xa441e712,0x754f,0x43ca,{0x84,0xa7,0x0d,0xee,0x44,0xcf,0x60,0x6d}}
#endif !(_WIN32_WINNT >= 0x0600)
LPFN_WSARECVMSG pfWSARecvMsg = NULL;
LPFN_WSASENDMSG pfWSASendMsg = NULL;
int WSARecvFromEx(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRecvd,
LPDWORD lpFlags,
struct sockaddr FAR * lpFrom,
LPINT lpFromlen,
char * pControlBuffer,
ULONG nControlBufferLen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
if (pControlBuffer != NULL &&
nControlBufferLen >= sizeof(WSACMSGHDR))
{
memset(pControlBuffer, 0, sizeof(WSACMSGHDR));
}
else
{
return WSARecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine);
}
if (pfWSARecvMsg == NULL)
{
return WSARecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine);
}
else
{
WSAMSG Msg;
Msg.name = lpFrom;
Msg.namelen = lpFromlen ? *lpFromlen : 0;
Msg.lpBuffers = lpBuffers;
Msg.dwBufferCount = dwBufferCount;
Msg.Control.buf = pControlBuffer;
Msg.Control.len = nControlBufferLen;
Msg.dwFlags = lpFlags ? *lpFlags : 0;
return pfWSARecvMsg(s, &Msg, lpNumberOfBytesRecvd, lpOverlapped, lpCompletionRoutine);
}
} //WSARecvFromEx()
int WSASendToEx(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
struct sockaddr FAR * lpTo,
int iTolen,
ULONG fromIp4,
char * pControlBuffer,
ULONG nControlBufferLen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
int sum = 0;
if (fromIp4 != INADDR_ANY &&
pControlBuffer != NULL &&
nControlBufferLen >= WSA_CMSG_SPACE(sizeof(struct in_pktinfo)))
{
memset(pControlBuffer, 0, WSA_CMSG_SPACE(sizeof(struct in_pktinfo)));
WSACMSGHDR *pCMsgHdr = (WSACMSGHDR *)pControlBuffer;
pCMsgHdr->cmsg_level = IPPROTO_IP;
pCMsgHdr->cmsg_type = IP_PKTINFO;
pCMsgHdr->cmsg_len = WSA_CMSG_LEN(sizeof(struct in_pktinfo));
struct in_pktinfo *pktinfo = (struct in_pktinfo *)WSA_CMSG_DATA(pCMsgHdr);
pktinfo->ipi_addr.s_addr = htonl(fromIp4);
sum += WSA_CMSG_SPACE(sizeof(struct in_pktinfo));
}
else
{
return WSASendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iTolen, lpOverlapped, lpCompletionRoutine);
}
if (pfWSASendMsg == NULL)
{
return WSASendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iTolen, lpOverlapped, lpCompletionRoutine);
}
else
{
WSAMSG Msg;
Msg.name = lpTo;
Msg.namelen = iTolen;
Msg.lpBuffers = lpBuffers;
Msg.dwBufferCount = dwBufferCount;
Msg.Control.buf = pControlBuffer;
Msg.Control.len = sum;
Msg.dwFlags = dwFlags;
return pfWSASendMsg(s, &Msg, dwFlags, lpNumberOfBytesSent, lpOverlapped, lpCompletionRoutine);
}
} //WSASendToEx()
Initialization:
if (dwMajorVersion >= 6)
{
if (pfWSARecvMsg == NULL)
{
// get WSARecvMsg pointer
GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
DWORD NumberOfBytes = 0;
if (WSAIoctl(socket_, SIO_GET_EXTENSION_FUNCTION_POINTER,
&WSARecvMsg_GUID, sizeof(WSARecvMsg_GUID),
&pfWSARecvMsg, sizeof(pfWSARecvMsg),
&NumberOfBytes, NULL, NULL) == SOCKET_ERROR)
{
printf("Could not get WSARecvMsg. WSAGetLastError returned [%i]", WSAGetLastError());
pfWSARecvMsg = NULL;
}
}
if (pfWSASendMsg == NULL)
{
// get WSASendMsg pointer
GUID WSASendMsg_GUID = WSAID_WSASENDMSG;
DWORD NumberOfBytes = 0;
if (WSAIoctl(socket_, SIO_GET_EXTENSION_FUNCTION_POINTER,
&WSASendMsg_GUID, sizeof(WSASendMsg_GUID),
&pfWSASendMsg, sizeof(pfWSASendMsg),
&NumberOfBytes, NULL, NULL) == SOCKET_ERROR)
{
printf("Could not get WSASendMsg. WSAGetLastError returned [%i]", WSAGetLastError());
pfWSASendMsg = NULL;
}
}
}
Example of usage WSASendToEx:
int result = WSASendToEx(event->socket_, &sendBufferDescriptor, 1, &dwSent, 0,
reinterpret_cast<sockaddr *>(&event->address), event->addressLength,
from, event->controlBuffer, sizeof(event->controlBuffer),
&event->overlapped, NULL);
Example of usage WSARecvFromEx:
int result = WSARecvFromEx(event->socket_, &recvBufferDescriptor, 1,
&numberOfBytes, &recvFlags,
reinterpret_cast<sockaddr *>(&event->address), &event->addressLength,
event->controlBuffer, sizeof(event->controlBuffer),
&event->overlapped, NULL);
There is no way to get the target IP from WSARecvFrom() when bound to INADDR_ANY. If you need the target IP, you would have to create and bind a separate socket for each local IP that you want to receive on, then you can use getsockname() to know which local IP a receiving socket is bound to.

Failing dll injection

I'm in the process of making a security program for my network. One of it's instances is to check and monitor what api's and libraries are called. The dll to do that and the program that go along with it are already finished. But there is a problem that I cant seem to fix.
When trying to inject my dll into system processes (such as explorer.exe, my main test system process) with NtCreateThreadEx I get the return value: C0000022, it means something along the lines of: Status_Access_Denied (it returns in NTSTATUS, but DWORD will do)
I have no idea what to do, I'm running as Administrator, I raised my privileges, and used the proper functions, still I get c0000022
Here's the code I'm using to inject
#include "main.h"
typedef DWORD NTSTATUS;
struct NtCreateThreadExBuffer{
ULONG Size;
ULONG Unknown1;
ULONG Unknown2;
PULONG Unknown3;
ULONG Unknown4;
ULONG Unknown5;
ULONG Unknown6;
PULONG Unknown7;
ULONG Unknown8;
};
typedef NTSTATUS (WINAPI *LPFUN_NtCreateThreadEx)
(
OUT PHANDLE hThread,
IN ACCESS_MASK DesiredAccess,
IN LPVOID ObjectAttributes,
IN HANDLE ProcessHandle,
IN LPTHREAD_START_ROUTINE lpStartAddress,
IN LPVOID lpParameter,
IN BOOL CreateSuspended,
IN ULONG StackZeroBits,
IN ULONG SizeOfStackCommit,
IN ULONG SizeOfStackReserve,
OUT LPVOID lpBytesBuffer
);
using namespace std;
//#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
#define CREATE_THREAD_ACCESS ( PROCESS_ALL_ACCESS )
BOOL LoadDll(char *procName, char *dllName);
BOOL InjectDLL(DWORD dwProcessID, char *dllName);
BOOL LoadDll(char *dllName, DWORD dwProcID){
printf("Process Id to Inject: %d",dwProcID);
if(!dwProcID){
printf("No vailid PID\n");
return false;
}
FILE* FileCheck = fopen(dllName, "r");
if(FileCheck==NULL){
printf("\nUnable to inject %s", dllName);
return false;
}
fclose(FileCheck);
if(!InjectDLL(dwProcID, dllName)){
printf("injection failed\n");
return false;
} else {
return true;
}
}
BOOL InjectDLL(DWORD dwProcessID, char *dllName){
HANDLE hProc;
HANDLE hToken;
char buf[50]={0};
LPVOID RemoteString, LoadLibAddy;
if(!dwProcessID)return false;
HANDLE hCurrentProc = GetCurrentProcess();
if (!OpenProcessToken(hCurrentProc,TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,&hToken)){
printf("OpenProcessToken Error:%d\n", GetLastError());
} else {
if (!RaisePrivleges(hToken, (char*)SE_DEBUG_NAME)){
printf("SetPrivleges SE_DEBUG_NAME Error:%d\n", GetLastError());
}
}
if (hToken)CloseHandle(hToken);
hProc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, dwProcessID);
printf("\nHandle to process: %x\n", hProc);
if(!hProc){
printf("OpenProcess() failed: %d", GetLastError());
return false;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if(!LoadLibAddy){
printf("GetProcAddress() failed: %d", GetLastError());
return false;
}
RemoteString = (LPVOID)VirtualAllocEx(hProc, NULL, strlen(dllName), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
if(RemoteString == NULL){
printf("VirtualAllocEx() failed: %d", GetLastError());
return false;
}
printf("\nRemote address: %x\n", RemoteString);
if(WriteProcessMemory(hProc, (LPVOID)RemoteString, dllName, strlen(dllName), NULL) == NULL){
printf("WriteProcessMemory() failed: %d", GetLastError());
return false;
}
/*
if(!CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL)){
printf("CreateRemoteThread() failed: %d", GetLastError());
return false;
}
*/
HMODULE modNtDll = GetModuleHandle("ntdll.dll");
if( !modNtDll )
{
printf("n failed to get module handle for ntdll.dll, Error=0x%.8x", GetLastError());
return 0;
}
LPFUN_NtCreateThreadEx funNtCreateThreadEx =
(LPFUN_NtCreateThreadEx) GetProcAddress(modNtDll, "NtCreateThreadEx");
if( !funNtCreateThreadEx )
{
printf("n failed to get function (NTCreateThreadEx) address from ntdll.dll, Error=0x%.8x\nTrying CreateRemoteThread api\n", GetLastError());
if(!CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL)){
printf("CreateRemoteThread() failed: %d", GetLastError());
return false;
} else {
printf("CreateRemoteThread success!\n");
return true;
}
return 0;
}
NtCreateThreadExBuffer ntbuffer;
memset (&ntbuffer,0,sizeof(NtCreateThreadExBuffer));
DWORD temp1 = 0;
DWORD temp2 = 0;
HANDLE pRemoteThread = NULL;
ntbuffer.Size = sizeof(NtCreateThreadExBuffer);
ntbuffer.Unknown1 = 0x10003;
ntbuffer.Unknown2 = 0x8;
ntbuffer.Unknown3 = &temp2;
ntbuffer.Unknown4 = 0;
ntbuffer.Unknown5 = 0x10004;
ntbuffer.Unknown6 = 4;
ntbuffer.Unknown7 = &temp1;
ntbuffer.Unknown8 = 0;
NTSTATUS status = funNtCreateThreadEx(
&pRemoteThread,
0x1FFFFF,
NULL,
hProc,
(LPTHREAD_START_ROUTINE) LoadLibAddy,
(LPVOID)RemoteString,
FALSE, //start instantly
NULL,
NULL,
NULL,
&ntbuffer
);
printf("NTCreateThreadEx return: %x\n", status);
// Resume the thread execution
WaitForSingleObject(pRemoteThread, INFINITE);
//Check the return code from remote thread function
DWORD dwExitCode;
if( GetExitCodeThread(pRemoteThread, (DWORD*) &dwExitCode) )
{
printf("\n Remote thread returned with status = %d\n", dwExitCode);
}
CloseHandle(pRemoteThread);
CloseHandle(hProc);
return true;
}
BOOL RaisePrivleges( HANDLE hToken, char *pPriv ){
TOKEN_PRIVILEGES tkp;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tkp.Privileges[0].Luid.HighPart = 0;
tkp.Privileges[0].Luid.LowPart = 0;
if (!LookupPrivilegeValue(NULL, pPriv, &tkp.Privileges[0].Luid)){
printf("LookupPrivilegeValue Error:%d\n", GetLastError());
return FALSE;
}
int iRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0x10, (PTOKEN_PRIVILEGES)NULL, 0);
if (iRet == NULL){
printf( "AdjustTokenPrivileges Error:%d\n", GetLastError());
return TRUE;
} else {
iRet = GetLastError();
switch (iRet){
case ERROR_NOT_ALL_ASSIGNED:
printf("AdjustTokenPrivileges ERROR_NOT_ALL_ASSIGNED\n" );
return FALSE;
case ERROR_SUCCESS:
return TRUE;
default:
printf("AdjustTokenPrivileges Unknow Error:%d\n", iRet);
return FALSE;
}
}
}
1) If you're running on VISTA or later then you're possibly trying to inject into a 'protected process' from a 'non protected process'. See Process Security and Access Rights in MSDN. Non protected processes can't create threads in protected processes; though I must admit I'd expect the call to open process to fail when you request the inappropriate access rights rather than the subsequent create thread call to fail.
2) Why are you using NtCreateThreadEx() rather than simply calling CreateRemoteThread()?
3) This probably isn't the cause of your problem, but... You're failing to allocate memory for the null terminator in the string, you should be allocating strlen(dllName) + 1.
4) I assume that the process that is doing the injecting and the process that you're injecting into are both the same architecture, you're not running an x86 exe on x64 and expecting to inject into an x64 exe?
Since it's hard to find the right answer to this problem, I am posting even though the thread is old.
I was trying to inject into x64 service on Win7 x64 and kept running into same problems. My solution was:
Compile both the injector and injection dll as x64.
Instead of CreateRemoteThread & NtCreateThreadEx (both failing) use RtlCreateUserThread.
You must specify the full path to the injected DLL, otherwise it will not be found.