WriteFile with Windows Sockets returns invalid parameter error

前提是你 提交于 2019-12-08 01:57:37

问题


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.


回答1:


from WriteFile documentation

lpOverlapped [in, out, optional]

A pointer to an OVERLAPPED structure is required if the hFile parameter was opened with FILE_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




回答2:


MSDN says it should be possible.

Does it really? The socket handles documentation states:

A socket handle can optionally be a file handle in Windows Sockets 2. A socket handle from a Winsock provider can be used with other non-Winsock functions such as ReadFile, WriteFile, ReadFileEx, and WriteFileEx.

Note the word "optionally".

Per this discussion:

WriteFile with SocketHandle Fails

...

Not sure how you can read that page and think that it is a good idea to use a socket handle with ReadFile et al.

Let's start with this sentence "A socket handle can optionally be a file handle in Windows Sockets 2". That can be read two different ways:

  1. You can optionally use any socket handle as a file handle for ReadFile and friends

  2. A socket provider can optionally provide dual-use sockets that work with ReadFile as well as the socket functions.

Unfortunately there is not enough information in that article to conclusively decide whether #1 or #2 is correct. However the fact that ReadFile returns ERROR_INVALID_PARAMETER (per Mike Danes' comment) I am going to assume that #2 is the correct interpretation and your network socket is not also a file handle. (Note that frequently the MSDN documentation is written more from the perspective of the team that implemented API than from a consumer of the API. If you look at it in that light, #2 is the more likely interpretation -- I will agree that it is annoying because a consumer of the API is more likely to understand the sentence as #1)



来源:https://stackoverflow.com/questions/43939424/writefile-with-windows-sockets-returns-invalid-parameter-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!