2017-12-27 1201 views
0

我試圖攔截的Winsock2呼籲解決在同一臺主機上的進程之間的UDP數據包間歇性消失的情況。當它們「消失」時,它們會消失20秒,這足以中止正在運行的過程。攔截winsock的recvfrom函數提供了無效地址錯誤

我設法讓DLL注入工作,並正確截獲了2個winsock調用(我希望),因爲我可以做一個簡單的打印,但我需要能夠處理地址信息,以便我可以跟蹤誰發送什麼對誰...

不幸的是,我注入的上游過程顯然是調用recvfrom(是的,不是WSA ...等價物,這是舊的移植POSIX代碼)與NULL的「從」和「fromlen」參數。如果我在所有的接收作品中都不擺弄他們。如果我執行以下操作,則會收到「無效地址」錯誤(Winsock錯誤10014)。

的我在做一些愚蠢的事嗎?不是說我會感到驚訝....是的,用所需的調試重建目標應用程序會更容易,但由於數據中心遷移,構建環境下降,我需要彈藥來說「這不是應用。」

// dllmain.cpp : Defines the entry point for the DLL application. 
#include "stdafx.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include "mhook.h" 
#include <winsock2.h> 

// typedefs for function pointers... 

typedef int(WINAPI *rcvfrom_ptr) (
SOCKET   s, 
char   *buf, 
int    len, 
int    flags, 
struct sockaddr *from, 
int    *fromlen 
); 

typedef int(WINAPI *sendto_ptr) (
_In_  SOCKET    s, 
_In_ const char     *buf, 
_In_  int     len, 
_In_  int     flags, 
_In_  const struct sockaddr *to, 
_In_  int     tolen 
); 

// Function pointers for original calls. 

rcvfrom_ptr orig_rcvfrom; 
sendto_ptr orig_sendto; 

// 
// Helper functions. 
// 

typedef union sockaddrs { 
    struct sockaddr from; 
    struct sockaddr_in in_from; 
    // Need to verify Ipv6 support. may need to remigrate back to VS 2015 
    //struct sockaddr_in6 in6_from; 
} tsockaddrs; 

char *printaddr(char *buff,const int buffsz, const tsockaddrs *addr) 
{ 
    ... 
} 

// Shim functions. 
// 
// Still working on getting them to actually work and do what I need. 
// But I may as well develop the skeleton 

int WINAPI Myrecvfrom(SOCKET   s, 
       char   *buf, 
       int    len, 
       int    flags, 
       struct sockaddr *from, 
       int    *fromlen 
) 
{ 
    int result; 
    struct sockaddr *all_froms; 
    char addrbuff[100] = ""; 
    int newfromlen = sizeof(struct sockaddr); 

    all_froms = (struct sockaddr *)malloc(sizeof(struct sockaddr)); 
    memset((void *)all_froms,0,sizeof(struct sockaddr)); 

    printf("Receiving Packet!\n"); 
    if (from == NULL) { 
     printf("\tFrom addr == null, using internal structures\n"); 
     result = (orig_rcvfrom)(s, buf, len, flags, all_froms, &newfromlen); 
    } else { 
     printf("\tFrom addr != null, using passed structures\n"); 
     result = (orig_rcvfrom)(s, buf, len, flags, from, fromlen); 
     memcpy_s((void*)&all_froms,sizeof(all_froms),(void *)from,*fromlen); 
     if (fromlen != NULL) { 
      newfromlen=*fromlen; 
     } else { 
      newfromlen=sizeof(struct sockaddr); 
     } 
    } 

    if (result >0) {printf("received %d bytes\n",result);} 
    else if (result == SOCKET_ERROR) {printf("Socket Error %d occurred!\n",WSAGetLastError());} 
    if (newfromlen >0) { 
     if (printaddr(addrbuff,sizeof(addrbuff),(tsockaddrs *)all_froms)!=NULL) { 
      printf("received %d bytes from on port %d from host %s\n",result,((tsockaddrs *)(all_froms))->in_from.sin_port,addrbuff); 
     } 
     if (from != NULL) { 
      memcpy_s((void*)from,sizeof(struct sockaddr),(void*)&all_froms,newfromlen); 
     } 
     else 
     { 

     } 
     if (fromlen != NULL) *fromlen=newfromlen; 
    } 
    else { 
      printf("received %d bytes from unknown port and host\n",result); 
    } 

    if (all_froms != NULL) {free(all_froms);} 
    return result; 
} 

int WINAPI Mysendto(SOCKET    s, 
    const char     *buf, 
    int     len, 
    int     flags, 
    const struct sockaddr *to, 
    int     tolen 
) 
{ 
    printf("Sending packet!\n"); 

    return orig_sendto(s, buf, len, flags, to, tolen); 
} 

BOOL AttachHooks(void) 
{ 
    BOOL sethooks; 
    orig_rcvfrom = (rcvfrom_ptr)GetProcAddress(GetModuleHandle(L"ws2_32"), "recvfrom"); 
    sethooks = Mhook_SetHook((PVOID*)&orig_rcvfrom, Myrecvfrom); 
    if (sethooks) { 
     orig_sendto = (sendto_ptr)GetProcAddress(GetModuleHandle(L"ws2_32"), "sendto"); 
     sethooks &= Mhook_SetHook((PVOID*)&orig_sendto, Mysendto); 
    } 
    return sethooks; 
} 

BOOL APIENTRY DllMain(HMODULE hModule, 
         DWORD ul_reason_for_call, 
         LPVOID lpReserved 
        ) 
{ 

    switch (ul_reason_for_call) 
    { 
    case DLL_PROCESS_ATTACH: 
     printf_s("This is an attached DLL!\n"); 
     AttachHooks(); 
     break; 
    case DLL_THREAD_ATTACH: 
    case DLL_THREAD_DETACH: 
    case DLL_PROCESS_DETACH: 
     break; 
    } 
    return TRUE; 
} 
+0

的* UDP數據包*消失:這意味着他們正在被源發送的,但他們從來沒有到達目的地。這從* UDP *的* PoV *可以確定。如果你正在調整'recvfrom'(注意:這個函數非常好,我覺得'WSARecvFrom'只是它的一個包裝器),你也在目標端做這件事,如果包沒有達到它的可能性很低,你可以找到新的。另外:你怎麼稱呼'Myrecvfrom'?什麼參數(對於'from'和'fromLen'仍然是0)? – CristiFati

+0

錯誤的完整描述** ** 10014就是「**該系統在試圖在調用中使用指針參數檢測到無效的指針地址。**」這似乎更關係到內存衝突,由於進程的內存映射問題與注入的代碼比winsock代碼。 –

+0

@christifati - 我正在注入這個DLL並覆蓋winsock2 recvfrom。我的目標是最終顯示process1發送的數據包永遠不會處理2(反之亦然)。 –

回答

0

問題的原因是答覆的ACTUAL大小大於「struct sockaddr」的大小。實際上它是一個SOCKADDR_IN6結構。使用一個200字節的任意緩衝區而不是28字節的sockaddr結構,並且我能夠接收數據。

在這個過程中,我結束了轉換成「偷看」接收到的數據,而不是處理它,它被拉扯了之後,當與源代碼的PC完成安裝更新,我會後它。

在家工作是相當隔離,並沒有任何人誰反正在我的辦公室住在winsock的。在評論中「聊天」真的很有幫助。