1

getaddrinfo と connect への呼び出しを挿入する小さな動的ライブラリを作成しました。Firefox と Safari で DYLD_INSERT_LIBRARIES を使用してこのライブラリを挿入し、www.apple.com の要求をハイジャックして www.microsoft.com に送信します。コードは Firefox で動作しますが、Safari は介在する関数を呼び出しますが、リダイレクトは無視されます。

Safari がリダイレクトを無視する理由と、おそらく addrinfo フラグを介して Safari を Firefox のように動作させる方法があるかどうかについて、誰かが洞察を持っているかどうか疑問に思っています。私のコードリストは次のとおりです。

// -*- mode: c++ -*-

#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <dlfcn.h>
#include <dns_sd.h>
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <cstring>
#include <string>

typedef int (*connect_type) (int, struct sockaddr const*, socklen_t);
typedef int (*getaddrinfo_type)(
        const char*, const char*, struct addrinfo const*, addrinfo**);

connect_type     real_connect     = 0;
getaddrinfo_type real_getaddrinfo = 0;

int
do_getaddrinfo_impl(const char* nodename, const char* servname,
                    struct addrinfo const* hints, struct addrinfo** ppai) 
{
    int result = real_getaddrinfo (nodename, servname, hints, ppai);
    if(result != 0) {
        fprintf(stderr, "! real_getaddrinfo error on %s: %s\n", nodename, gai_strerror(result));
    }

    return result;
}

int
do_getaddrinfo(const char* nodename, const char* servname,
               struct addrinfo const* hints, struct addrinfo** ppai) 
{
    if (0 == nodename) {
        return do_getaddrinfo_impl(nodename, servname, hints, ppai);
    }

    if (hints->ai_family == AF_INET6) {
        printf ("# do_getaddrinfo : IPv6 resolution\n");
        return do_getaddrinfo_impl(nodename, servname, hints, ppai);
    }

    if (   hints->ai_flags & AI_PASSIVE 
        || hints->ai_flags & AI_CANONNAME 
        || hints->ai_flags & AI_NUMERICHOST 
        || hints->ai_flags & AI_NUMERICSERV) {
        printf ("# do_getaddrinfo : unsupported resolution flags\n");
        return do_getaddrinfo_impl (nodename, servname, hints, ppai);
    }

    if ((hints->ai_flags & AI_V4MAPPED) && !(hints->ai_flags & AI_ALL)) {
        printf ("# do_getaddrinfo : unsupported IPv6-mapping\n");
        return do_getaddrinfo_impl (nodename, servname, hints, ppai);
    }

    // redirect requests for www.apple.com to microsoft at 65.55.57.80 (0x41373950)
    if(0 == strcmp(nodename, "www.apple.com")) {
        addrinfo* pai = (addrinfo*)calloc (1, sizeof (addrinfo));

        pai->ai_flags    = hints->ai_flags;
        pai->ai_family   = AF_INET;
        pai->ai_socktype = hints->ai_socktype;
        pai->ai_protocol = IPPROTO_TCP;
        pai->ai_addrlen  = sizeof (sockaddr_in);

        sockaddr* psa = reinterpret_cast< sockaddr* > (
            calloc (1, sizeof (sockaddr)));

        sockaddr_in& sain = reinterpret_cast< sockaddr_in& > (*psa);

#if !defined (POS_NO_SIN_LEN)
        sain.sin_len = sizeof *psa;
#endif // POS_NO_SIN_LEN

        sain.sin_family = AF_INET;
        sain.sin_addr.s_addr = htonl(0x41373950);

        pai->ai_addr = psa;
        pai->ai_canonname = 0;
        pai->ai_next = 0;

        *ppai = pai;

        return 0;
    }
    else {
        return do_getaddrinfo_impl(nodename, servname, hints, ppai);
    }
}

////////////////////////////////////////////////////////////////////////
extern "C" {

int
fake_getaddrinfo(const char* nodename, const char* servname,
                 struct addrinfo const* hints, struct addrinfo** ppai)
{
    if (real_getaddrinfo == 0)
        real_getaddrinfo = &getaddrinfo;

    return do_getaddrinfo (nodename, servname, hints, ppai);
}

int
fake_connect (int s, sockaddr const* ptr, socklen_t len)
{
    if (real_connect == 0)
        real_connect = &connect;

    return do_connect (s, ptr, len);
}

__attribute__((used)) static struct {
    void const *a, *b; 
} arr [] __attribute__ ((section ("__DATA, __interpose"))) = {
    { (void*)fake_connect, (void*)connect },
    { (void*)fake_getaddrinfo, (void*)getaddrinfo }
};

} // extern "C"
4

1 に答える 1

0

フォローアップの方法で、Safari がヒント パラメーターに AI_NUMERICHOST フラグを設定していたことを発見したため、そのフラグをサポートされていない解決フラグとしてテストした結果、リダイレクト コードが呼び出されませんでした。AI_NUMERICHOST のテストを削除し、次のビットを追加して問題を解決しました。

 if (hints->ai_flags & AI_NUMERICHOST) {

    //
    // Safari makes name resolution requests using AI_NUMERICHOST
    //

    in_addr_t addr = inet_addr (nodename);
    if (addr != INADDR_NONE)
        return do_getaddrinfo_impl (nodename, servname, hints, ppai);
}

それが他の誰かを助けることを願っています。

于 2012-06-12T14:22:21.290 に答える