2017-12-27 11 views
0

동일한 호스트의 프로세스간에 UDP 패킷이 간헐적으로 사라지는 경우 문제를 해결하기 위해 winsock2 호출을 가로 채려고합니다. "사라지다"면 20 초와 같이 사라지며, 이는 실행중인 프로세스를 중단시키기에 충분합니다.winsock recvfrom 함수를 가로 채면 잘못된 주소 오류가 발생합니다.

나는 DLL 인젝션을 사용할 수 있었고 간단한 프린트를 할 수 있기 때문에 2 개의 winsock 호출이 올바르게 가로 챌 수 있었다. (하지만 희망한다.) 주소 정보를 처리 할 수 ​​있어야한다. 무엇을 누구에게 ...

유감스럽게도, 내가 주입하고있는 업스트림 프로세스는 분명히 recvfrom (예, WSA ...이 아니라 포팅 된 POSIX 코드)를 호출하는 것입니다. "from"과 "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 *에서 OK입니다. 'recvfrom'을 조정하면 (참고 :이 함수는 완벽하게 괜찮습니다.'WSARecvFrom'은 그 위에 래퍼라는 감각을 가지고 있습니다.) 당신은 목적지 측에서도 이것을하고 있습니다. 그리고 패킷이 거기에 도달하면 새로운 가능성을 알 수있는 가능성이 낮습니다. 또한 : Myrecvfrom은 어떻게 부릅니까? 어떤 인수 ('from'와'fromLen'을위한 여전히 0)? – CristiFati

+0

오류 ** 10014 **에 대한 전체 설명은 "** 호출에서 포인터 인수를 사용하여 잘못된 포인터 주소를 감지했습니다. **"프로세스 메모리 매핑 문제로 인해 메모리 위반과 관련이있는 것 같습니다. winsock 코드보다 주입 된 코드가 있습니다. –

+0

@christifati -이 DLL을 주입하고 winsock2 recvfrom을 무시합니다. 그리고 내 목표는 결국 process1에 의해 보내지는 패킷이 결코 2를 처리하지 못함을 보여 주거나 그 반대 일 것입니다. –

답변

0

문제의 원인은 응답의 실제 크기가 "struct sockaddr"크기보다 큰 것입니다. 사실 SOCKADDR_IN6 구조가 돌아 왔습니다. 28 바이트 sockaddr 구조 대신 200 바이트의 임의의 버퍼를 사용하여 데이터를 가져올 수있었습니다.

처리 중에 필자는받은 데이터를 가져온 후에 처리하는 대신 "수신 대기"로 변환했습니다. 소스 코드가있는 PC에서 업데이트 설치가 완료되면 게시 할 것입니다.

집에서 일하는 것은 상당히 고립되어 있습니다. 어쨌든 내 사무실의 winsock에 사는 사람은 없습니다. 댓글에서 "채팅"하는 것이 정말 도움이되었습니다.

관련 문제