2017-12-27 1200 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的。在评论中“聊天”真的很有帮助。