Winsock2 recv() hook into a remote process - c++

I was trying to hook a custom recv() winsock2.0 method to a remote process, so that my function executes instead of the one in the process, i have been googling this and i found some really good example, but they lack description
typedef (WINAPI * WSAREC)( SOCKET s, char *buf, int len, int flags ) = recv;
Now my question is, what does this mean, or does, is this some sort of a pointer to the real recv() function?
And then the other piece of code for the custom function
int WINAPI Cus_Recv( SOCKET s, char *buf, int len, int flags )
{
printf("Intercepted a packet");
return WSAREC( s, buf, len, flags ); // <- What is this?
}
Sorry if these questions sound really basic, i only started learning 2 or 3 weeks ago.
Thanks.

where did you find such an example ?
the first line tries to define a new type WSAREC, which is a pointer to a function having the same signature as recv(). unfortunately, it is also trying to declare a variable of this type to store the address of the recv() function. the typedef is wrong since the function is lacking a return type. so it does not compile under Visual Studio 2003.
you may have more luck using:
int (WINAPI * WSAREC)( SOCKET s, char *buf, int len, int flags ) = &recv;
which declares only a variable of type "pointer to function", which stores the address of the recv().
now the second snippet is a function which has the same signature as the recv()function, which prints a message, then calls the original recv() through the function pointer declared above.
the code here only shows how to call a function through a pointer: it does not replace anything in the current process.
also, i am not sure you can interfere with another process and replace one function at your will. it would be a great threat to the security of the system. but why would you do that in the first place ??

Related

Getting C26xxx errors in my C++ Windows service code

I'm getting errors in my code. The code compiles, but I'd still like to get rid of the warnings. I've looked on stackoverflow and google and clicked on the warnings which take me to the microsoft.com page, explaining each, but I don't see concrete examples of how to get rid of them.
Here's the C++ code and the warnings.
void WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv);
VOID main() noexcept
{
CONST SERVICE_TABLE_ENTRY ste[] = { {L"MyService", ServiceMain}, {NULL, NULL} };
//C26485 Expression 'ste': No array to pointer decay (bounds.3).
StartServiceCtrlDispatcherW(ste);
}
// C26429 Symbol 'lpszArgv' is never tested for nullness, it can be marked as not_null (f.23).
// C26461 The pointer argument 'lpszArgv' for function 'ServiceMain' can be marked as a pointer to const (con.3).
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
{
// C26481 Don't use pointer arithmetic. Use span instead (bounds.1).
ssh = RegisterServiceCtrlHandlerExW(lpszArgv[0], (LPHANDLER_FUNCTION_EX) Service_Ctrl, 0);
...
}
Any help is appreciated.
Those are not compiler warnings but a code analysis warnings (based on CppCoreGuidelines), which give hints on how to improve code to prevent common errors - like null pointer dereferences and out of bound reads/writes. Fixing them might require use of gsl library of tools : https://github.com/microsoft/GSL.
//C26485 Expression 'ste': No array to pointer decay (bounds.3).
StartServiceCtrlDispatcherW(ste);
this informs you about potentially dangerous call, this function does not take information about size of the array so it might potentially lead to reading outside buffer. Analyzer does not know that this function relies on last element to be null initialized. You could silence this warning by allocating memory for ste on heap and releasing after the StartServiceCtrlDispatcherW call, or even better by wrapping allocated memory inside std::unique_ptr or even storing entries in std::vector
https://learn.microsoft.com/en-us/cpp/code-quality/c26485?view=msvc-170
// C26429 Symbol 'lpszArgv' is never tested for nullness, it can be marked as not_null (f.23).
// C26461 The pointer argument 'lpszArgv' for function 'ServiceMain' can be marked as a pointer to const (con.3).
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
You should be able to fix this warning with gsl:
const auto args = gsl::span<LPWSTR>(lpszArgv, dwArgc);
then use args as if it was lpszArgv. For instructions on how to use gsl see here: https://github.com/Microsoft/GSL
According to documentation, ServiceMain should always be called with at least one element in lpszArgv:
...The first parameter contains the number of arguments being passed to the service in the second parameter. There will always be at least one argument. The second parameter is a pointer to an array of string pointers. The first item in the array is always the service name.
https://learn.microsoft.com/en-us/windows/win32/services/writing-a-servicemain-function
So it should be fine to suppress this warning with:
#pragma warning(suppress: 26429 26461)
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
or better:
[[gsl::suppress(f.23)]]
[[gsl::suppress(con.3)]]
VOID WINAPI ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv)
links to both warnings:
https://learn.microsoft.com/en-us/cpp/code-quality/c26429?view=msvc-170
https://learn.microsoft.com/en-us/cpp/code-quality/c26461?view=msvc-170
// C26481 Don't use pointer arithmetic. Use span instead (bounds.1).
ssh = RegisterServiceCtrlHandlerExW(lpszArgv[0], (LPHANDLER_FUNCTION_EX) Service_Ctrl, 0);
..
this will be fixed if you use gsl::span as shown above

How can I port DeviceIOControl to ioctl?

In my understanding, DeviceIOControl and ioctl are the same functions. They both send control codes to the hardware and return the responses. In an effort to reuse code, I am trying to create a function which will work in a cross-platform manner. Therefore, I've decided to use the DeviceIOControl api since it is fixed and specific. The problem is: how do I map ioctl to that?
I currently have:
int DeviceIoControl_issueCommand(DeviceHandle handle, int command, void *input, ssize_t sizeof_input, void *output, ssize_t sizeof_output, uint32_t *bytes_written){
#if SYSTEMINFORMATION_ISWINDOWS
int result = DeviceIoControl(handle,command,input,sizeof_input,output,sizeof_output,bytes_written,0);
if (result == 0){
result = -1; //-1 is the new error return
}
return result;
#else
int result = ioctl(handle, command, input); //this doesnt work!
return result;
#endif
}
Any help is greatly appreciated!
What you are asking is not possible without a lot of internal translation in DeviceIoControl_issueCommand. The function calls are completely different and expect different parameters and data. You can work around this by declaring an IOControl class and adding member functions for each type of IO functionality you want to support.
class IOControl
{
public:
void DoIoControlX();
void DoIoControlY(int param1, int param2);
};
Then provide an impelementation for each platform you need to support. One for Windows DeviceIOControl calls and one for systems that support ioctl
I actually found that there is an IOCTL which does pass raw data to and from the driver (at least for the hard drive): HDIO_DRIVE_TASKFILE (http://www.mjmwired.net/kernel/Documentation/ioctl/hdio.txt)

passing pointers to extern C function in a DLL from VB

I am a C++ (MSVC) writer, VB newbie trying to assist an expert VB.net writer who has just not done this task before.
We wish to develop both C/C++ and VB applications to use a DLL written in C++ with C extern-ed API functions. The C++ program is working just fine. It's VB where we are having difficulties.
The DLL provides an extern C function:
RegisterCallback( void* cbFuncPtr, void* dataPtr );
NOTE 1: See my note below for a design change and the reasons we made it.
NOTE 2: Additional update added as an answer below.
where the callback function havs this C typedef:
typedef (void)(* CALL_NACK)(void*);
The cbFuncPtr is expected to be a function pointer to some VB function that will get called as the CALL_BACK. The dataPtr is a pointer to a data structure that has this C definition:
typedef struct
{
int retCode;
void* a_C_ptr;
char message[500];
} cbResponse_t;
where a_C_ptr is an internal pointer in the DLL that the VB can cast tolong`. It uniquely identifies where in the DLL the callback was made and allows the VB function to recognize calls from same/different locations.
We are able to access and run the RegisterCallback() function from VB just fine. Logging shows we get there and that data is passed in. It is the actual data that seems to be the problem.
In reading about a million forum entries we have learned that VB doesn't know what pointers are and that a VB structure is more than just organized memory. We're pretty sure the "address" of a VB structure is not what C thinks an address is. We've seen repeated references to "marshaling" and "managed data", but lack enough understanding to know what that is telling us.
How should we code VB to give the DLL the execution address of its callback function and how do we code up a VB construct that the DLL can fill in just as it does for C++?
Might we need a DLL function where the calling app can say "C" or "VB" andhave the DLL handle the sturcture pointers differently? If so, how would one code up C to fill in the VB structure?
This is a bit too big and deep to just be an edit to the original posting...
From the link posted by #DaveNewman, I extracted this gem:
Here's a bit about the compact framework, but it's the same in the
grown-ups framework:
The .NET Compact Framework supports automatic marshaling of structures
and classes that contain simple types. All fields are laid out
sequentially in memory in the same order as they appear in the
structure or class definition. Both classes and structures appear in
native code as pointers to C/C++ structs.
Objects in the managed heap can be moved around in memory at any time
by the garbage collector, so their physical addresses may change
without notice. P/Invoke automatically pins down managed objects
passed by reference for the duration of each method call. This means
pointers passed to unmanaged code will be valid for that one call.
Bear in mind that there is no guarantee that the object will not be
moved to a different memory address on subsequent calls.
http://msdn.microsoft.com/en-us/library/aa446538.aspx#netcfmarshallingtypes_topic6
This is major hurdle for a RegisterCallback( fcnPtr, dataPtr) function. The pointer passed in at registration time could change at any time the RegisterCallback() is not the current statement. The posting author summed it up this way
You don't need to do anything as the structures are pinned automatically for duration of the call.
implying, of course, not pinned down outside the call.
For this reason we decided on a design change to have the response structure built in, so to speak, the C/C++ world of the DLL, not in VB's space. That way it'll stay put. The actual callback function's signature will remain unchanged so the VB program can know where the DLL put the response. This also allows the responders in the DLL to allocate separate response structures for separate needs.
Once again my update is too large for a mere comment!
Update 18 Apr 2013:
Well, the attempt to use the code from Calling Managed Code from Unmanaged Code cited above was a bust. We ended up having to add /clr to the DLL make turning the DLL into managed code, which made it unusable from a C application.
We are now testing the example at Callback Sample which I was able to show made a DLL that worked with both VB and C++. You'd need to have the PinvokeLib.dll Source to make this work.
Here is the code for the C++ (C really) tester. Compiled as a MSVC project.
NOTE: Notice the __cdecl in this line:
typedef bool (__cdecl *FPtr)(BOOL_FP_INT fp, int i );
It was the secret I had to find. The DLL and this app are compiled with __cdecl linkage, not __stdcall. They are the default in VC++ and I just used the defaults. I tried changing everything to __stdcall but that didn't work. Has to be __cdecl.
// PinvokeTester.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
#include <cstdlib>
#include <string.h>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <Windows.h>
#define PINVOKELIB_API __declspec(dllimport)
HINSTANCE hLib; // Windows DLL handle
bool CALLBACK VBCallBack( int value );
bool AttachLibrary( void );
void * GetFuncAddress( HINSTANCE hLib, const char* procname );
int main(int argc, char* argv[])
{
if ( !AttachLibrary() )
{
printf( "Lib did not attach.\n" );
exit(1);
}
typedef bool (CALLBACK *BOOL_FP_INT)(int i );
typedef bool (__cdecl *FPtr)(BOOL_FP_INT fp, int i );
FPtr TestCallBack = (FPtr)GetFuncAddress( hLib, "TestCallBack" );
TestCallBack( (BOOL_FP_INT)VBCallBack, 255 );
return 0;
}
bool CALLBACK VBCallBack( int value )
{
printf( "\nCallback called with param: %d", value);
return true;
}
bool AttachLibrary( void )
{
// Get a var for the IPC-dll library.
std::string dllName;
/*--- First, link to the IPC-dll library or report failure to do so. ---*/
dllName = ".\\PinvokeLib";
if ( NULL == (hLib = LoadLibraryA( dllName.c_str() )) )
{
printf( "\nERROR: Library \"%s\" Not Found or Failed to Load. \n\n", dllName.c_str() );
printf( "\"%s\"\n", GetLastError() );
return false;
}
return true;
}
//=====================================================================
void * GetFuncAddress( HINSTANCE hLib, const char* procname )
{
void * procAddr = NULL;
procAddr = (void *)GetProcAddress( hLib, procname );
// If the symbol wasn't found, handle error ---------------------
if ( NULL == procAddr )
{
std::cout << "ERROR: Could not get an address for the \""
<< procname << "\" function. : "
<< GetLastError() << std::endl;
exit( 7 );
procAddr = (void*)NULL;
}
return procAddr;
}

Accessing the member of a class that is part of a WiFi listener callback member function

I have a WiFi Listener registered as a callback (pointer function) with a fixed 3rd party interface. I used a static member of my function to register the callback function and then that static function calls a nonstatic member through a static cast. The main problem is that I cannot touch the resulting char * buff with any members of my class nor can I even change an int flag that is also a member of my class. All result in runtime access violations. What can I do? Please see some of my code below. Other problems are described after the code.
void *pt2Object;
TextWiFiCommunication::TextWiFiCommunication()
{
networkDeviceListen.rawCallback = ReceiveMessage_thunkB;
/* some other initializing */
}
int TextWiFiCommunication::ReceiveMessage_thunkB(int eventType, NETWORK_DEVICE *networkDevice)
{
if (eventType == TCP_CLIENT_DATA_READY)
static_cast<TextWiFiCommunication *>(pt2Object)->ReceiveMessageB(eventType,networkDevice);
return 1;
}
int TextWiFiCommunication::ReceiveMessageB(int eventType, NETWORK_DEVICE *networkDevice)
{
unsigned char outputBuffer[8];
// function from an API that reads the WiFi socket for incoming data
TCP_readData(networkDevice, (char *)outputBuffer, 0, 8);
std::string tempString((char *)outputBuffer);
tempString.erase(tempString.size()-8,8); //funny thing happens the outputBuffer is double in size and have no idea why
if (tempString.compare("facereco") == 0)
cmdflag = 1;
return 1;
}
So I can't change the variable cmdflag without an access violation during runtime. I can't declare outputBuffer as a class member because nothing gets written to it so I have to do it within the function. I can't copy the outputBuffer to a string type member of my class. The debugger shows me strlen.asm code. No idea why. How can I get around this? I seem to be imprisoned in this function ReceiveMessageB.
Thanks in advance!
Some other bizzare issues include: Even though I call a buffer size of 8. When I take outputBuffer and initialize a string with it, the string has a size of 16.
You are likely getting an access violation because p2tObject does not point to a valid object but to garbage. When is p2tObject initialized? To what does it point?
For this to work, your code should look something like this:
...
TextWifiCommunication twc;
p2tObject = reinterpret_cast<void*>(&twc);
...
Regarding the string error, TCP_readData is not likely to null-terminate the character array you give it. A C-string ends at the first '\0' (null) character. When you convert the C-string to a std::string, the std::string copies bytes from the C-string pointer until it finds the null terminator. In your case, it happens to find it after 16 characters.
To read up to 8 character from a TCP byte stream, the buffer should be 9 characters long and all the bytes of the buffer should be initialized to '\0':
...
unsigned char outputBuffer[9] = { 0 };
// function from an API that reads the WiFi socket for incoming data
TCP_readData(networkDevice, (char *)outputBuffer, 0, 8);
std::string tempString((char *)outputBuffer);
...

C++ TLS, somethings wrong

I'm learning about Thread Local Storage... (TLS)
Here is my TLS Alloc code:
//global variable
DWORD g_dwTlsIndex;
//inside DLLMain:
int val= 5;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_dwTlsIndex = TlsAlloc();
if ((g_dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
{
printf("No more indexes available");
}
void *pint;
memcpy(&pint, &val, sizeof val);
TlsSetValue(g_dwTlsIndex, pint);
break;
Now I try to get the value from the TLS: (in another CPP file)
// declare index value...
extern DWORD g_dwTlsIndex;
int data;
LPVOID d;
d = TlsGetValue(g_dwTlsIndex);
memcpy(&data, &d, sizeof d);
printf("Data: %d", data);
But data contains 0, where I put 5 in it.... What have I done wrong?
A few notes:
Your error checking statement should read:
if (g_dwTLSIndex == TLS_OUT_OF_INDEXES).
As it stands, you're assigning g_dwTlsIndex twice (and thus losing the reference with the first assignment.)
Do some basic debugging:
Call TlsGetValue in the line immiediately after TlsSetValue. Does that work at least?
Check the return codes. TlsGetValue and TlsSetValue both return a function telling you whether the assignment was successful. Was it?
Keep track of your index. You're using a global variable to store g_dwTlsIndex, so it could easily be getting altered. What is the value after alloc (use a printf to see). What is the value when you make the Get call? Do these values match?
These steps should help you find the problem.
I assume that val is local to DllMain?
What version of Windows are you running? 64-bit Windows has 64-bit pointers and 32-bit int, so all the memcpy calls will be incorrect. Rather than using memcpy, just cast the values directly:
TlsSetValue(g_dwTLSIndex,(LPVOID)5);
int data=(int)TlsGetValue(g_dwTLSIndex);