<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    NtSockets - 直接與驅動通信實現sockets

    VSole2022-04-22 16:16:57

    本文為看雪論壇優秀???文章

    看雪論壇作者ID:zhenwo

    最近在研究syscall相關的技術,無意中發現了這個NtSockets(只使用NtCreateFile和NtDeviceIoControlFile 函數,直接操作afd.sys驅動實現socket),感謝作者@x86matthew。

    原文鏈接 NTSockets - Downloading a file via HTTP using the NtCreateFile and NtDeviceIoControlFile syscalls

    https://www.x86matthew.com/view_post?id=ntsockets

    項目的bug和不足

    作者只實現了TCP-client的代碼,并且x86下測試通過,但是在x64模式下連接到服務端時出現了錯誤。


    解決x64環境下connect中的bug

    1. 推測問題

    根據函數的返回狀態 0xc000000d 可知是參數錯誤。

     

    根據代碼:

    NtDeviceIoControlFile(pSocketData->hSocket, pSocketData->hStatusEvent, NULL, NULL, &IoStatusBlock, dwIoControlCode, (void*)pData, dwLength, bOutputBlock, sizeof(bOutputBlock));
    

    可以推測應該是傳入的pData和dwLength出現了錯誤,根據調用關系:

    struct NTSockets_ConnectDataStruct NTSockets_ConnectData;NTSockets_ConnectData.dwUnknown1 = 0;NTSockets_ConnectData.dwUnknown2 = 0;NTSockets_ConnectData.dwUnknown3 = 0;NTSockets_ConnectData.SockAddr.sin_family = AF_INET;NTSockets_ConnectData.SockAddr.sin_addr.s_addr = dwConnectAddr;NTSockets_ConnectData.SockAddr.sin_port = wConnectPort;ULONG sz = sizeof(NTSockets_ConnectData);if (NTSockets_SocketDriverMsg(pSocketData, 0x00012007, (BYTE*)&NTSockets_ConnectData, sz, NULL) != 0){    // error    return 1;}
    

    那么問題就出在結構體NTSockets_ConnectDataStruct上。

    struct NTSockets_ConnectDataStruct{    ULONG dwUnknown1;    ULONG dwUnknown2;    ULONG dwUnknown3;    struct sockaddr_in SockAddr;};
    

    2. 證實猜測

    隨便在網上找了個TCP-Client的代碼,選擇x64模式,在connect上下斷點,當在connect斷下來后,再在NtDeviceIoControlFile上下斷點,再運行。

    可以看到有幾次觸發斷點:

    dwIoControlCode0x01207b      mswsock.dll!SockGetInformation()    Unknown0x0120bf      mswsock.dll!WSPSetSockOpt()            Unknown0x012003      mswsock.dll!WSPBind()                Unknown0x012047      mswsock.dll!SockSetHandleContext()    Unknown0x012007     mswsock.dll!SockDoConnectReal()        Unknown
    

    這里我們只關心 dwIoControlCode為0x012007 的調用。通過對比參數可以找到參數以及大小。

    size 0x280x000000D8606FEE40  00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00                                             |AFIN |port |---IP---|0x000000D8606FEE50  30 ef 6f 60 d8 00 00 00 02 00 00 50 7f 00 00 01                    |------ZERO8----------|0x000000D8606FEE60  00 00 00 00 00 00 00 00
    

    而NtSockets代碼參數是:

    size 0x1c                                                        |AFIN |port0x0000002EE86FD9F8  00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 50                    |---IP---|  |------ZERO8----------|0x0000002EE86FDA08  c0 a8 0a 75 00 00 00 00 00 00 00 00
    

    3.解決辦法

    重新定義下NTSockets_ConnectDataStruct結構體就可以了。

    struct NTSockets_ConnectDataStruct{    SIZE_T dwUnknown1;    SIZE_T dwUnknown2;    SIZE_T dwUnknown3;    struct sockaddr_in SockAddr;};
    

    SIZE_T x86下是ULONG 在x64下是ULONGLONG。


    增加對UDP的支持

    先來看看TCP的細節,根據代碼可以看出TCP創建句柄跟bExtendedAttributes有關。所以我們關注下這個參數:

    NTSTATUS NTAPI NtCreateFile     (     PHANDLE      FileHandle,        ACCESS_MASK      DesiredAccess,        POBJECT_ATTRIBUTES      ObjectAttributes,        PIO_STATUS_BLOCK      IoStatusBlock,        PLARGE_INTEGER      AllocateSize,        ULONG      FileAttributes,        ULONG      ShareAccess,        ULONG      CreateDisposition,        ULONG      CreateOptions,        PVOID      EaBuffer,        ULONG      EaLength    )     dwStatus = NtCreateFile(&hSocket, 0xC0140000, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 1, 0, &bExtendedAttributes, sizeof(bExtendedAttributes));
    

    在socket函數下斷點,斷下來后在NtCreateFile函數下斷點。堆棧情況如下:

    0x000000EC37FCEE40  0000000000000000  ........0x000000EC37FCEE48  004f004400000000  ....D.O.0x000000EC37FCEE50  000000ec00000003  ....ì...0x000000EC37FCEE58  000000ec00000003  ....ì...0x000000EC37FCEE60  000000ec00000000  ....ì...0x000000EC37FCEE68  000000ec37fcef60  `?ü7ì...0x000000EC37FCEE70  002e006b00000039  9...k...
    

    這是x64下的情況,去除前4個參數(利用寄存器傳參),以上是第5-11參數。這里我們只關注后兩個參數:

    0x000000EC37FCEE68  000000ec37fcef60  `?ü7ì...  EaBuffer0x000000EC37FCEE70  002e006b00000039  9...k...  EaLength EaBuffer:0x000000EC37FCEF60  00 00 00 00 00 0f 1e 00 41 66 64 4f 70 65 6e 50  ........AfdOpenP0x000000EC37FCEF70  61 63 6b 65 74 58 58 00 00 00 00 00 00 00 00 00  acketXX.........0x000000EC37FCEF80  02 00 00 00 01 00 00 00 06 00 00 00 00 00 00 00  ................0x000000EC37FCEF90  08 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    

    對比NtSockets的EaBuffer:

    BYTE bExtendedAttributes[] =    {        0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1E, 0x00, 0x41, 0x66, 0x64, 0x4F, 0x70, 0x65, 0x6E, 0x50,        0x61, 0x63, 0x6B, 0x65, 0x74, 0x58, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,        0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,        0x00, 0x00, 0x00, 0x00, 0x60, 0xEF, 0x3D, 0x47, 0xFE    };
    

    我解惑的數據和作者給出的有些出入,不過不影響使用。

    截獲UDP的EaBuffer

    直接將socket的參數調整成UDP的。還是在socket斷下來以后,給NtCreateFile下斷點,以下是udp的堆棧情況。

    0x000000B698EFF308  0000000000000000  ........0x000000B698EFF310  0000000000000000  ........0x000000B698EFF318  004f004400000000  ....D.O.0x000000B698EFF320  000000b600000003  ....?...0x000000B698EFF328  000000b600000003  ....?...0x000000B698EFF330  000000b600000000  ....?...0x000000B698EFF338  000000b698eff430  0????...0x000000B698EFF340  002e006b00000039  9...k... EaBuffer:0x000000B698EFF430  00 00 00 00 00 0f 1e 00 41 66 64 4f 70 65 6e 50  ........AfdOpenP0x000000B698EFF440  61 63 6b 65 74 58 58 00 11 00 00 00 00 00 00 00  acketXX.........0x000000B698EFF450  02 00 00 00 02 00 00 00 11 00 00 00 00 00 00 00  ................0x000000B698EFF460  08 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    

    只要替換NtSockets中的bExtendedAttributes數組就可以產生UDP的連接。

    最終代碼

    #include #include   #pragma warning(suppress : 4996)#pragma warning(disable : 4996)#define _CRT_SECURE_NO_WARNINGS 1struct IO_STATUS_BLOCK{    union    {        DWORD Status;        PVOID Pointer;    };     DWORD* Information;}; struct UNICODE_STRING{    USHORT Length;    USHORT MaximumLength;    PWSTR Buffer;}; struct OBJECT_ATTRIBUTES{    ULONG Length;    HANDLE RootDirectory;    struct UNICODE_STRING* ObjectName;    ULONG Attributes;    PVOID SecurityDescriptor;    PVOID SecurityQualityOfService;}; struct FILE_FULL_EA_INFORMATION{    ULONG     NextEntryOffset;    UCHAR      Flags;    UCHAR   EaNameLength;    USHORT     EaValueLength;    CHAR     EaName[1];};    struct NTSockets_ConnectDataStruct{    SIZE_T dwUnknown1;    SIZE_T dwUnknown2;    SIZE_T dwUnknown3;    struct sockaddr_in SockAddr;}; struct NTSockets_BindDataStruct{    DWORD dwUnknown1;    struct sockaddr_in SockAddr;}; struct NTSockets_DataBufferStruct{    DWORD dwDataLength;    BYTE* pData;}; struct NTSockets_SendRecvDataStruct{    struct NTSockets_DataBufferStruct* pBufferList;    DWORD dwBufferCount;    DWORD dwUnknown1;    DWORD dwUnknown2;}; struct NTSockets_SocketDataStruct{    HANDLE hSocket;    HANDLE hStatusEvent;}; struct DNSClient_HeaderStruct{    WORD wTransID;    WORD wFlags;    WORD wQuestionCount;    WORD wAnswerRecordCount;    WORD wAuthorityRecordCount;    WORD wAdditionalRecordCount;}; struct DNSClient_RequestQueryDetailsStruct{    WORD wType;    WORD wClass;}; struct DNSClient_ResponseAnswerHeaderStruct{    WORD wName;    WORD wType;    WORD wClass;    WORD wTTL[2];    WORD wLength;}; DWORD(NTAPI* NtDeviceIoControlFile)(HANDLE FileHandle, HANDLE Event, VOID* ApcRoutine, PVOID ApcContext, struct IO_STATUS_BLOCK* IoStatusBlock, ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength);DWORD(NTAPI* NtCreateFile)(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, struct OBJECT_ATTRIBUTES* ObjectAttributes, struct IO_STATUS_BLOCK* IoStatusBlock, LARGE_INTEGER* AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength); DWORD NTSockets_CreateTcpSocket(struct NTSockets_SocketDataStruct* pSocketData,int bTcp){    struct IO_STATUS_BLOCK IoStatusBlock;    HANDLE hEvent = NULL;    HANDLE hSocket = NULL;    struct OBJECT_ATTRIBUTES ObjectAttributes;    struct NTSockets_SocketDataStruct SocketData;    struct UNICODE_STRING ObjectFilePath;    DWORD dwStatus = 0;         /* tcp extended attr        0x0000003395EFF130  00 00 00 00 00 0f 1e 00 41 66 64 4f 70 65 6e 50  ........AfdOpenP        0x0000003395EFF140  61 63 6b 65 74 58 58 00 00 00 00 00 00 00 00 00  acketXX.........        0x0000003395EFF150  02 00 00 00 01 00 00 00 06 00 00 00 00 00 00 00  ................        0x0000003395EFF160  08 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................        */     /*  udp        0x000000506EF3F040  00 00 00 00 00 0f 1e 00 41 66 64 4f 70 65 6e 50  ........AfdOpenP        0x000000506EF3F050  61 63 6b 65 74 58 58 00 11 00 00 00 00 00 00 00  acketXX.........        0x000000506EF3F060  02 00 00 00 02 00 00 00 11 00 00 00 00 00 00 00  ................        0x000000506EF3F070  08 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................    */      BYTE bEaUdp[] =    {        0x00,0x00,0x00,0x00,0x00,0x0f,0x1e,0x00,0x41,0x66,0x64,0x4f,0x70,0x65,0x6e,0x50,        0x61,0x63,0x6b,0x65,0x74,0x58,0x58,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,        0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,        0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00    };      BYTE bExtendedAttributes[] =    {        0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1E, 0x00, 0x41, 0x66, 0x64, 0x4F, 0x70, 0x65, 0x6E, 0x50,        0x61, 0x63, 0x6B, 0x65, 0x74, 0x58, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,        0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,        0x00, 0x00, 0x00, 0x00, 0x60, 0xEF, 0x3D, 0x47, 0xFE    };    printf("[*] NTSockets_CreateTcpSocket:: is %s !",bTcp ? "TCP" : "UDP");    struct FILE_FULL_EA_INFORMATION* ffe;    ffe = (struct FILE_FULL_EA_INFORMATION*)bTcp ? bExtendedAttributes : bEaUdp;     // create status event    hEvent = CreateEvent(NULL, 0, 0, NULL);    if (hEvent == NULL)    {        // error        return 1;    }     // set afd endpoint path    memset((void*)&ObjectFilePath, 0, sizeof(ObjectFilePath));    ObjectFilePath.Buffer = L"\\Device\\Afd\\Endpoint";    ObjectFilePath.Length = wcslen(ObjectFilePath.Buffer) * sizeof(wchar_t);    ObjectFilePath.MaximumLength = ObjectFilePath.Length;     // initialise object attributes    memset((void*)&ObjectAttributes, 0, sizeof(ObjectAttributes));    ObjectAttributes.Length = sizeof(ObjectAttributes);    ObjectAttributes.ObjectName = &ObjectFilePath;    ObjectAttributes.Attributes = 0x40;     // create socket handle    IoStatusBlock.Status = 0;    IoStatusBlock.Information = NULL;    dwStatus = NtCreateFile(&hSocket, 0xC0140000, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 1, 0, ffe, sizeof(bExtendedAttributes));    if (dwStatus != 0)    {        // error        CloseHandle(hEvent);         return 1;    }     // initialise SocketData object    memset((void*)&SocketData, 0, sizeof(SocketData));    SocketData.hSocket = hSocket;    SocketData.hStatusEvent = hEvent;     // store socket data    memcpy((void*)pSocketData, (void*)&SocketData, sizeof(SocketData));     return 0;} DWORD NTSockets_SocketDriverMsg(struct NTSockets_SocketDataStruct* pSocketData, DWORD dwIoControlCode, BYTE* pData, DWORD dwLength, DWORD* pdwOutputInformation){    struct IO_STATUS_BLOCK IoStatusBlock;    DWORD dwStatus = 0;    BYTE bOutputBlock[0x10];     // reset status event    ResetEvent(pSocketData->hStatusEvent);     // send device control request    IoStatusBlock.Status = 0;    IoStatusBlock.Information = NULL;    dwStatus = NtDeviceIoControlFile(pSocketData->hSocket, pSocketData->hStatusEvent, NULL, NULL, &IoStatusBlock, dwIoControlCode, (void*)pData, dwLength, bOutputBlock, sizeof(bOutputBlock));    if (dwStatus == STATUS_PENDING)    {        // response pending - wait for event        if (WaitForSingleObject(pSocketData->hStatusEvent, -1) != WAIT_OBJECT_0)        {            // error            return 1;        }         // complete - get final status code        dwStatus = IoStatusBlock.Status;    }     // check for errors    if (dwStatus != 0)    {        // error        return 1;    }     if (pdwOutputInformation != NULL)    {        // store output info        *pdwOutputInformation = (DWORD)IoStatusBlock.Information;    }     return 0;} DWORD NTSockets_ConvertIP(char* pIP, DWORD* pdwAddr){    char szCurrOctet[8];    DWORD dwCurrOctetIndex = 0;    DWORD dwCompletedOctetCount = 0;    char* pCurrByte = NULL;    DWORD dwEndOfOctet = 0;    DWORD dwEndOfString = 0;    DWORD dwOctet = 0;    BYTE bOctets[4];    DWORD dwAddr = 0;     // read IP string    memset(szCurrOctet, 0, sizeof(szCurrOctet));    dwCurrOctetIndex = 0;    pCurrByte = pIP;    for (;;)    {        // process current character        dwEndOfOctet = 0;        if (*pCurrByte == '\0')        {            // end of string            dwEndOfOctet = 1;            dwEndOfString = 1;        }        else if (*pCurrByte == '.')        {            // end of octet            dwEndOfOctet = 1;        }        else        {            // ensure this character is a number            if (*pCurrByte >= '0' && *pCurrByte <= '9')            {                if (dwCurrOctetIndex > 2)                {                    // invalid ip                    return 1;                }                 // store current character                szCurrOctet[dwCurrOctetIndex] = *pCurrByte;                dwCurrOctetIndex++;            }            else            {                // invalid ip                return 1;            }        }         // check if the current octet is complete        if (dwEndOfOctet != 0)        {            if (dwCurrOctetIndex == 0)            {                // invalid ip                return 1;            }             // convert octet string to integer            dwOctet = atoi(szCurrOctet);            if (dwOctet > 255)            {                // invalid ip                return 1;            }             // already read 4 octets            if (dwCompletedOctetCount >= 4)            {                // invalid ip                return 1;            }             // store current octet            bOctets[dwCompletedOctetCount] = (BYTE)dwOctet;             // current octet complete            dwCompletedOctetCount++;             if (dwEndOfString != 0)            {                // end of string                break;            }             // reset szCurrOctet string            memset(szCurrOctet, 0, sizeof(szCurrOctet));            dwCurrOctetIndex = 0;        }         // move to the next character        pCurrByte++;    }     // ensure 4 octets were found    if (dwCompletedOctetCount != 4)    {        // invalid string        return 1;    }     // store octets in dword value    memcpy((void*)&dwAddr, bOctets, 4);     // store value    *pdwAddr = dwAddr;     return 0;} WORD NTSockets_Swap16BitByteOrder(WORD wValue){    WORD wNewValue = 0;     // swap byte order - this assumes we are running on an x86-based chip    //*(BYTE*)((DWORD)&wNewValue + 0) = *(BYTE*)((DWORD)&wValue + 1);    //*(BYTE*)((DWORD)&wNewValue + 1) = *(BYTE*)((DWORD)&wValue + 0);    *(((BYTE*)&wNewValue) + 0) = *(((BYTE*)&wValue) + 1);    *(((BYTE*)&wNewValue) + 1) = *(((BYTE*)&wValue) + 0);      return wNewValue;} DWORD NTSockets_Connect(struct NTSockets_SocketDataStruct* pSocketData, char* pIP, WORD wPort){    struct NTSockets_BindDataStruct NTSockets_BindData;    struct NTSockets_ConnectDataStruct NTSockets_ConnectData;    WORD wConnectPort = 0;    DWORD dwConnectAddr = 0;     // bind to local port    memset((void*)&NTSockets_BindData, 0, sizeof(NTSockets_BindData));    NTSockets_BindData.dwUnknown1 = 2;    NTSockets_BindData.SockAddr.sin_family = AF_INET;    NTSockets_BindData.SockAddr.sin_addr.s_addr = INADDR_ANY;    NTSockets_BindData.SockAddr.sin_port = 0;    if (NTSockets_SocketDriverMsg(pSocketData, 0x00012003, (BYTE*)&NTSockets_BindData, sizeof(NTSockets_BindData), NULL) != 0)    {        // error        return 1;    }     // read connection ip    if (NTSockets_ConvertIP(pIP, &dwConnectAddr) != 0)    {        // error        return 1;    }     // use network byte order for connection port  //    wConnectPort = htons(wPort);    wConnectPort = NTSockets_Swap16BitByteOrder(wPort);     // connect to remote port    memset((void*)&NTSockets_ConnectData, 0, sizeof(NTSockets_ConnectData));    NTSockets_ConnectData.dwUnknown1 = 0;    NTSockets_ConnectData.dwUnknown2 = 0;    NTSockets_ConnectData.dwUnknown3 = 0;    NTSockets_ConnectData.SockAddr.sin_family = AF_INET;    NTSockets_ConnectData.SockAddr.sin_addr.s_addr = dwConnectAddr;    NTSockets_ConnectData.SockAddr.sin_port = wConnectPort;    ULONG sz = sizeof(NTSockets_ConnectData);    if (NTSockets_SocketDriverMsg(pSocketData, 0x00012007, (BYTE*)&NTSockets_ConnectData, sz, NULL) != 0)    {        // error        return 1;    }     return 0;} DWORD NTSockets_Send(struct NTSockets_SocketDataStruct* pSocketData, BYTE* pData, DWORD dwLength){    struct NTSockets_SendRecvDataStruct NTSockets_SendRecvData;    struct NTSockets_DataBufferStruct NTSockets_DataBuffer;    DWORD dwBytesSent = 0;    BYTE* pCurrSendPtr = NULL;    DWORD dwBytesRemaining = 0;     // set initial values    pCurrSendPtr = pData;    dwBytesRemaining = dwLength;     // send data    for (;;)    {        if (dwBytesRemaining == 0)        {            // finished            break;        }         // set data buffer values        memset((void*)&NTSockets_DataBuffer, 0, sizeof(NTSockets_DataBuffer));        NTSockets_DataBuffer.dwDataLength = dwBytesRemaining;        NTSockets_DataBuffer.pData = pCurrSendPtr;         // send current block        memset((void*)&NTSockets_SendRecvData, 0, sizeof(NTSockets_SendRecvData));        NTSockets_SendRecvData.pBufferList = &NTSockets_DataBuffer;        NTSockets_SendRecvData.dwBufferCount = 1;        NTSockets_SendRecvData.dwUnknown1 = 0;        NTSockets_SendRecvData.dwUnknown2 = 0;        if (NTSockets_SocketDriverMsg(pSocketData, 0x0001201F, (BYTE*)&NTSockets_SendRecvData, sizeof(NTSockets_SendRecvData), &dwBytesSent) != 0)        {            // error            return 1;        }         if (dwBytesSent == 0)        {            // socket disconnected            return 1;        }         // update values        pCurrSendPtr += dwBytesSent;        dwBytesRemaining -= dwBytesSent;    }     return 0;} int NTSockets_Recv(struct NTSockets_SocketDataStruct* pSocketData, BYTE* pData, DWORD dwLength){    struct NTSockets_SendRecvDataStruct NTSockets_SendRecvData;    struct NTSockets_DataBufferStruct NTSockets_DataBuffer;     DWORD dwBytesReceived = 0;        // set data buffer values    memset((void*)&NTSockets_DataBuffer, 0, sizeof(NTSockets_DataBuffer));    NTSockets_DataBuffer.dwDataLength = dwLength;    NTSockets_DataBuffer.pData = pData;     // recv current block    memset((void*)&NTSockets_SendRecvData, 0, sizeof(NTSockets_SendRecvData));    NTSockets_SendRecvData.pBufferList = &NTSockets_DataBuffer;    NTSockets_SendRecvData.dwBufferCount = 1;    NTSockets_SendRecvData.dwUnknown1 = 0;    NTSockets_SendRecvData.dwUnknown2 = 0x20;    if (NTSockets_SocketDriverMsg(pSocketData, 0x00012017, (BYTE*)&NTSockets_SendRecvData, sizeof(NTSockets_SendRecvData), &dwBytesReceived) != 0)    {        // error        return -1;    }       return dwBytesReceived;} DWORD NTSockets_CloseSocket(struct NTSockets_SocketDataStruct* pSocketData){    // close handles    CloseHandle(pSocketData->hSocket);    CloseHandle(pSocketData->hStatusEvent);     return 0;} DWORD DNSClient_Query(char* pDNSClient_IP, char* pTargetHost, char* pOutput, DWORD dwOutputMaxLength){    struct NTSockets_SocketDataStruct SocketData;    struct DNSClient_HeaderStruct DNSClient_RequestHeader;    struct DNSClient_RequestQueryDetailsStruct DNSClient_RequestQueryDetails;    struct DNSClient_HeaderStruct* pDNSClient_ResponseHeader = NULL;    struct DNSClient_ResponseAnswerHeaderStruct* pDNSClient_ResponseAnswerHeader = NULL;    DWORD dwIpAddrIndex = 0;    DWORD dwFoundRecord = 0;    DWORD dwCurrAnswerEntryStartIndex = 0;    DWORD dwHostLength = 0;    DWORD dwCurrLabelLength = 0;    WORD wRequestLength = 0;    WORD wResponseLength = 0;    WORD wBlockLength = 0;    WORD wAnswerCount = 0;    BYTE bIP[4];    BYTE bResponseBuffer[4096];    char szConvertedHost[1024];    char* pCurrDot = NULL;    char szIP[32];     // convert target host name to dns format    memset(szConvertedHost, 0, sizeof(szConvertedHost));    _snprintf_s(szConvertedHost, sizeof(szConvertedHost) - 1, -1, ".%s", pTargetHost);    dwHostLength = strlen(szConvertedHost) + 1;    for (DWORD i = 0; i < dwHostLength; i++)    {        // process domain labels        if (szConvertedHost[i] == '.' || szConvertedHost[i] == '\0')        {            // check if a previous separator exists            if (pCurrDot != NULL)            {                // calculate current label length                dwCurrLabelLength = (DWORD)(&szConvertedHost[i] - pCurrDot);                dwCurrLabelLength--;                if (dwCurrLabelLength == 0 || dwCurrLabelLength >= 64)                {                    return 1;                }                 // insert label length                *pCurrDot = (char)dwCurrLabelLength;            }             // store current dot position            pCurrDot = &szConvertedHost[i];        }    }     // create socket handle    if (NTSockets_CreateTcpSocket(&SocketData,1) != 0)    {        // error        return 1;    }     // connect to DNS server    if (NTSockets_Connect(&SocketData, pDNSClient_IP, 53) != 0)    {        // error        NTSockets_CloseSocket(&SocketData);         return 1;    }     // calculate request length    wRequestLength = sizeof(struct DNSClient_HeaderStruct) + dwHostLength + sizeof(DNSClient_RequestQueryDetails);    wBlockLength = NTSockets_Swap16BitByteOrder(wRequestLength);     // set request header details    memset((void*)&DNSClient_RequestHeader, 0, sizeof(DNSClient_RequestHeader));    DNSClient_RequestHeader.wTransID = NTSockets_Swap16BitByteOrder(1);    DNSClient_RequestHeader.wFlags = NTSockets_Swap16BitByteOrder(0x100);    DNSClient_RequestHeader.wQuestionCount = NTSockets_Swap16BitByteOrder(1);     // type A dns request    memset((void*)&DNSClient_RequestQueryDetails, 0, sizeof(DNSClient_RequestQueryDetails));    DNSClient_RequestQueryDetails.wType = NTSockets_Swap16BitByteOrder(1);    DNSClient_RequestQueryDetails.wClass = NTSockets_Swap16BitByteOrder(1);     // send request length    if (NTSockets_Send(&SocketData, (BYTE*)&wBlockLength, sizeof(WORD)) != 0)    {        // error        NTSockets_CloseSocket(&SocketData);         return 1;    }     // send request header    if (NTSockets_Send(&SocketData, (BYTE*)&DNSClient_RequestHeader, sizeof(DNSClient_RequestHeader)) != 0)    {        // error        NTSockets_CloseSocket(&SocketData);         return 1;    }     // send host name    if (NTSockets_Send(&SocketData, (BYTE*)szConvertedHost, dwHostLength) != 0)    {        // error        NTSockets_CloseSocket(&SocketData);         return 1;    }     // send host query details    if (NTSockets_Send(&SocketData, (BYTE*)&DNSClient_RequestQueryDetails, sizeof(DNSClient_RequestQueryDetails)) != 0)    {        // error        NTSockets_CloseSocket(&SocketData);         return 1;    }     // receive response length    if (NTSockets_Recv(&SocketData, (BYTE*)&wBlockLength, sizeof(WORD)) != 0)    {        // error        NTSockets_CloseSocket(&SocketData);         return 1;    }     // swap byte order    wResponseLength = NTSockets_Swap16BitByteOrder(wBlockLength);     // validate response length    if (wResponseLength < sizeof(struct DNSClient_HeaderStruct) || wResponseLength > sizeof(bResponseBuffer))    {        // error        NTSockets_CloseSocket(&SocketData);         return 1;    }     // receive response data    memset((void*)bResponseBuffer, 0, sizeof(bResponseBuffer));    if (NTSockets_Recv(&SocketData, bResponseBuffer, wResponseLength) != 0)    {        // error        NTSockets_CloseSocket(&SocketData);         return 1;    }     // set response header ptr    pDNSClient_ResponseHeader = (struct DNSClient_HeaderStruct*)bResponseBuffer;     // check flags (expect response, no error)    if (pDNSClient_ResponseHeader->wFlags != NTSockets_Swap16BitByteOrder(0x8180))    {        // error        NTSockets_CloseSocket(&SocketData);         return 1;    }     // validate question count    if (pDNSClient_ResponseHeader->wQuestionCount != NTSockets_Swap16BitByteOrder(1))    {        // error        NTSockets_CloseSocket(&SocketData);         return 1;    }     // get response answer count    wAnswerCount = NTSockets_Swap16BitByteOrder(pDNSClient_ResponseHeader->wAnswerRecordCount);     // read DNS response answers    dwCurrAnswerEntryStartIndex = wRequestLength;    for (DWORD i = 0; i < (DWORD)wAnswerCount; i++)    {        // validate start index        if ((dwCurrAnswerEntryStartIndex + sizeof(struct DNSClient_ResponseAnswerHeaderStruct)) > (DWORD)wResponseLength)        {            // error            NTSockets_CloseSocket(&SocketData);             return 1;        }         // get current response answer header ptr        pDNSClient_ResponseAnswerHeader = (struct DNSClient_ResponseAnswerHeaderStruct*)&bResponseBuffer[dwCurrAnswerEntryStartIndex];         // check if this is a type A record        if (pDNSClient_ResponseAnswerHeader->wType == NTSockets_Swap16BitByteOrder(1) && pDNSClient_ResponseAnswerHeader->wClass == NTSockets_Swap16BitByteOrder(1))        {            // ensure value length is 4 (ipv4 addr)            if (pDNSClient_ResponseAnswerHeader->wLength != NTSockets_Swap16BitByteOrder(4))            {                // error                NTSockets_CloseSocket(&SocketData);                 return 1;            }             // validate ip addr index            dwIpAddrIndex = dwCurrAnswerEntryStartIndex + sizeof(struct DNSClient_ResponseAnswerHeaderStruct);            if ((dwIpAddrIndex + 4) > (DWORD)wResponseLength)            {                // error                NTSockets_CloseSocket(&SocketData);                 return 1;            }             // store IP addr            memcpy((void*)bIP, (void*)&bResponseBuffer[dwIpAddrIndex], 4);             // set flag            dwFoundRecord = 1;             break;        }        else        {            // check next entry            dwCurrAnswerEntryStartIndex += sizeof(struct DNSClient_ResponseAnswerHeaderStruct);            dwCurrAnswerEntryStartIndex += NTSockets_Swap16BitByteOrder(pDNSClient_ResponseAnswerHeader->wLength);        }    }     // close socket    NTSockets_CloseSocket(&SocketData);     // ensure a valid record was found    if (dwFoundRecord == 0)    {        return 1;    }     // generate IP string    memset(szIP, 0, sizeof(szIP));    _snprintf_s(szIP, sizeof(szIP) - 1, -1, "%u.%u.%u.%u", bIP[0], bIP[1], bIP[2], bIP[3]);     // store value    strncpy_s(pOutput,32, szIP, dwOutputMaxLength);     return 0;}  int main(int argc, char* argv[]){    char* szIP = "127.0.0.1";    unsigned int dwPort = 80;    char buffer[1024] = "hello pediy.com !";    struct NTSockets_SocketDataStruct SocketData;     // get NtDeviceIoControlFile function ptr    NtDeviceIoControlFile = (unsigned long(__stdcall*)(void*, void*, void*, void*, struct IO_STATUS_BLOCK*, unsigned long, void*, unsigned long, void*, unsigned long))GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtDeviceIoControlFile");    if (NtDeviceIoControlFile == NULL)    {        return 1;    }     // get NtCreateFile function ptr    NtCreateFile = (unsigned long(__stdcall*)(void**, unsigned long, struct OBJECT_ATTRIBUTES*, struct IO_STATUS_BLOCK*, union _LARGE_INTEGER*, unsigned long, unsigned long, unsigned long, unsigned long, void*, unsigned long))GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCreateFile");    if (NtCreateFile == NULL)    {        return 1;    }     // create socket handle    printf("create socket !");    if (NTSockets_CreateTcpSocket(&SocketData,1) != 0)    {        // error        printf("Error: Failed to create TCP socket");         return 1;    }     // connect to server    printf("connect to server !");    if (NTSockets_Connect(&SocketData, szIP, (WORD)dwPort) != 0)    {        // error        printf("Error: Failed to connect to server");        NTSockets_CloseSocket(&SocketData);         return 1;    }    //send    printf("send ... !");    if (NTSockets_Send(&SocketData, (BYTE*)buffer, strlen(buffer)) != 0)    {        // error        printf("Error: Failed to send data to server");        NTSockets_CloseSocket(&SocketData);         return 1;    }    //recv    printf("recv ... !");    memset(buffer, 0, sizeof(buffer));    if (NTSockets_Recv(&SocketData, (BYTE*)buffer, sizeof(buffer) ) < 0)    {        // error        printf("Error: Failed to read HTTP response header");        NTSockets_CloseSocket(&SocketData);         return 1;    }     printf("buffer is: %s ",buffer);    printf("close socket !");    NTSockets_CloseSocket(&SocketData);    getchar();    return 0;}
    

    vs完整工程見附件。

    代碼測試

    以上為UDP測試動畫。


    以上為TCP測試動畫。

    隨后附上TCP-Server和UDP-Server的代碼實現,敬請期待!

    通信socket函數
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    項目的bug和不足作者只實現了TCP-client的代碼,并且x86下測試通過,但是在x64模式下連接到服務端時出現了錯誤。
    C++ Socket詳解與研究
    2021-11-09 06:06:32
    數據傳輸是病毒木馬的必備技術之一,而數據回傳也成為了病毒木馬的一個重要特征,我們就嘗試自己寫一個程序來實現數據的傳輸,本文嘗試通過c++來進行套接字(socket)的實現
    給木馬帶雙眼睛
    2023-04-18 09:56:25
    近月,內存馬的技術也產生新的變化,如利用websocket進行通信,Executor內存馬進行socket通信。本文介紹利用Poller內存馬實現全流量監控,這樣,攻擊方可以實時監控經過系統的每一個請求,或者增加了釣魚等信息利用的便利。這也就是說注入Poller的內存馬一定是不能出任何bug的,一旦出了,整個服務直接崩潰。反向,Executor是一個任務類,創建后就執行一個線程任務,如果這次業務異常,最多這次的請求無法正常執行罷了。
    背景最近項目里需要通過hook對APP的行為進行監控,需要滿足如下幾個需求:兼容性好,能夠兼容99.9%的APP。不能被APP的安全機制檢測到導致APP邏輯不正常或者hook失敗。因為APP量非常大,需要一種通用化方案,不能出現對特定APP進行定制的情況
    SAMPLE服務器的行為及其漏洞取決于一段時間內交換的一系列消息,這些消息決定了服務器的狀態。客戶端發送的消息序列以紅色突出顯示。AFLNET讀取響應報文并提取協議指定的狀態碼,確定當前的執行狀態。所出現了新的狀態序列哈希值則認為當前的測試用例是Interesting的。
    C:\Users\bk\Desktop\天府科技云APP\天府科技云服務平臺\天府科技云服務平臺.apkC:\Program Files\Java\jdk1.8.0_111\bin\jarsigner.exe?文件將解壓出來的classes.dex文件拷貝到dex2jar工具文件夾中執行命令:d2j-dex2jar classes.dex執行完畢后,得到反編譯而來的classes-dex2jar.jar文件使用jd-gui.exe或者luyten-0.5.4打開 classes-dex2jar.jar文件,得到360安全加固混淆加密的源代碼。應同時使用V1+V2簽名)6.應用完整性校檢將反編譯出來源碼中修改圖片文件名為test.png進行重新生成apk包,命令如下:java -jar apktool.jar b -f?
    RWCTF 5th Shellfind復現
    2023-01-28 09:45:29
    前言RealWorld CTF 5th 里的一道iot-pwn,根據真實設備固件改編而成,覺得題目貼近iot實戰且很有意思,故在此記錄一下復現過程。題目分析題目描述Hello?從中可以看出漏洞大概率存在于UDP服務中。相比于常規pwn題單一的二進制而言,我們首先要做的是尋找漏洞文件。下載到官方的固件后,可以采取bindiff等方法去找被修改過的二進制文件。可以初步判定漏洞應該是出在ipfind程序中。并且發現此固件為mips大端,且可疑漏洞文件沒開保護。
    根據廠商的要求,在修補后的固件未發布前,我對該漏洞細節進行了保密。若讀者將本文內容用作其他用途,由讀者承擔全部法律及連帶責任,文章作者不承擔任何法律及連帶責任。此時,我們驚喜地發現xxx系列產品的xxx型號固件并沒有被加密,可以成功解開。漏洞分析此部分以xxx固件為例進行分析,該固件是aarch64架構的。其他固件也許架構或部分字段的偏移不同,但均存在該漏洞。找到無鑒權的API接口顯然,此類固件的cgi部分是用Lua所寫的。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类