I've been struggling with Windows Sockets for two days not being able to just use write to socket as in Linux it is. I want to write my own shellcode and I'm playing around how to redirect stdout, stdin to socket handle (that's where my playings come from). I use Windows 7 x64, build 7601 if it's necessary. Here's my code
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main (int argc,char ** argv)
{
// boring code starts
if (argc < 2)
{
printf("Usage getstdhandle <ip> <port> ");
}
WSADATA wsadata;
int result = WSAStartup (MAKEWORD(2,2),&wsadata);
if (result != NO_ERROR)
{
printf("error with wsastartup");
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons (atoi(argv[2]));
server.sin_addr.s_addr = inet_addr (argv[1]);
SOCKET soc = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (soc == INVALID_SOCKET)
{
printf("Error with creating socket");
}
if (connect(soc,(struct sockaddr *)&server,sizeof(server)) == SOCKET_ERROR)
{
printf("Problem with connecting");
}
// boring code ends
const char * buf = "Tekscik \n"; // know it's not really good in new C standards
const char buf[] = "Test\n"; // not working also, shouldn't have any influence
bool isSent = WriteFile((HANDLE)soc,(LPCVOID)buf,(DWORD)10,NULL,NULL);
DWORD ret = GetLastError();
printf("%.08x",ret);
closesocket(soc);
WSACleanup();
return 0;
}
This is how i run my program
C:\Users\Domin568\Desktop>getstdhandle 192.168.56.1 5555
Tekscik
00000057 <---- Error code in hex
On my second machine i just run nc to listen for this data like this :
15:14|domin568[21] ~ $ nc -l -v -p 5555
Connection from 192.168.56.101:50328
15:15|domin568[22] ~ $
I get error code 0x57 which is :
ERROR_INVALID_PARAMETER 87 (0x57) The parameter is incorrect.
Local network traffic (any data sent, pure connections handshakes and FIN)
What could be the reason of that ? I know it's not good way for sending data but MSDN says it should be possible.
from WriteFile
documentation
lpOverlapped [in, out, optional]
A pointer to an
OVERLAPPED
structure is required if the hFile parameter was opened withFILE_FLAG_OVERLAPPED
, otherwise this parameter can be NULL.
but are socket
function create file (socket this is file handle, it point to FILE_OBJECT
structure) with FILE_FLAG_OVERLAPPED
? this is undocumented and you cannot control this. so you need use OVERLAPPED
as parameter for WriteFile
.
if use WSASocket
we already here have dwFlags option and can set or not set WSA_FLAG_OVERLAPPED
(which is equivalent of FILE_FLAG_OVERLAPPED
for CreateFile
)
why OVERLAPPED
structure is required when we use hFile opened with FILE_FLAG_OVERLAPPED
flag (no FO_SYNCHRONOUS_IO
flag in FILE_OBJECT
) ?
WriteFile
call ZwWriteFile
look for
PLARGE_INTEGER ByteOffset [in, optional]
parameter of ZwWriteFile
- but it optional only if we open file as synchronous. if file opened in asynchronous i/o mode - this parameter is mandatory.
from wrk source code
if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
}
else if (!ARGUMENT_PRESENT( ByteOffset ) && !(fileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) {
//
// The file is not open for synchronous I/O operations, but the
// caller did not specify a ByteOffset parameter. This is an error
// situation, so cleanup and return with the appropriate status.
//
if (eventObject) {
ObDereferenceObject( eventObject );
}
ObDereferenceObject( fileObject );
return STATUS_INVALID_PARAMETER;
}
this is exactly your case when you call
WriteFile((HANDLE)soc,(LPCVOID)buf,(DWORD)10,NULL,NULL);
NtWriteFile
return to you STATUS_INVALID_PARAMETER
which converted to win32 error ERROR_INVALID_PARAMETER
but next code will be worked ok.
OVERLAPPED ov = {};
BOOL isSent = WriteFile((HANDLE)soc,(LPCVOID)buf,(DWORD)10, 0, &ov);
because in this case ByteOffset
will be point to &ov.Offset
however for send data to socket much more better use WSASend