3

ネットワーク通信関連のシステム コールを変更する Java インターポーザを作成しています。基本的に、意図した受信者の IP とポートを変更したいと考えています。

コードは私のラップトップでは正しく動作しますが、大学の PC では次のようなスタック破壊エラーが発生します。

*** stack smashing detected ***: java terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7702dd5]
/lib/i386-linux-gnu/libc.so.6(+0xffd8a)[0xb7702d8a]
/home/mwaqar/vibe/ldinterposer_2.so(+0x28e4)[0xb77c98e4]
/home/mwaqar/vibe/ldinterposer_2.so(connect+0x9c5)[0xb77c9093]
/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/libnet.so(+0xceff)[0x8b226eff]
/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/libnet.so(Java_java_net_PlainSocketImpl_socketConnect+0x4c1)[0x8b227c51]

関連するコード ( connectシステム コールの挿入) は次のとおりです。

int connect(int fd, const struct sockaddr *sk, socklen_t sl)
{
struct sockaddr_in      *lsk_in  = (struct sockaddr_in *)  sk;
struct sockaddr_in6     *lsk_in6 = (struct sockaddr_in6 *) sk;

struct sockaddr_in      addr4;

unsigned int            len;
int                     nbytes, oport, tport, ret, i;
char                    ip_address[30];
char                    buffer[1024];   
char                    tempBuffer[1024];   

if((lsk_in->sin_family == AF_INET) || (lsk_in->sin_family == AF_INET6))
{
    if(lsk_in->sin_family == AF_INET)
    {
        oport = ntohs(lsk_in->sin_port);
        memcpy(&addr4.sin_addr.s_addr, &lsk_in->sin_addr.s_addr, sizeof(addr4.sin_addr.s_addr));
    }
    else if(lsk_in->sin_family == AF_INET6)
    {
        oport = ntohs(lsk_in6->sin6_port);
        memcpy(&addr4.sin_addr.s_addr, lsk_in6->sin6_addr.s6_addr+12, sizeof(addr4.sin_addr.s_addr));
    }

    memset(buffer, '\0', sizeof(buffer));
    sprintf(buffer, "%s%c%s%c%i", NAT_VM_CONNECT_RULE, NAT_VM_DELIMITER, (char *)inet_ntoa(addr4.sin_addr), NAT_VM_DELIMITER, oport);

    nbytes = send(sock, buffer, strlen(buffer), 0);
    if(DEBUG_MODE)
        fprintf(stdout, "[LD_INTERPOSER] Sent[%s]\n", buffer);

    memset(buffer, '\0', sizeof(buffer));
    nbytes = recv(sock, buffer, sizeof(buffer), 0);

    fprintf(stderr, "[LD_INTERPOSER] Received CONNECT [%s]\n", buffer);

    memset(ip_address, '\0', sizeof(ip_address));
    int pos = strrchr(buffer, NAT_VM_DELIMITER) - buffer;

    strncpy(ip_address, buffer, pos);
    ip_address[pos] = '\0';
    tport = atoi(buffer + pos + 1);

    if(lsk_in->sin_family == AF_INET)
    {
        lsk_in->sin_addr.s_addr = inet_addr(ip_address + 7);
        lsk_in->sin_port = htons(tport);
    }
    else if(lsk_in->sin_family == AF_INET6)
    {
        inet_pton(AF_INET6, ip_address, &(lsk_in6->sin6_addr));
        lsk_in6->sin6_port = htons(tport);
    }

    fprintf(stderr, "[LD_INTERPOSER] IP[%s], Port[%d] for VM[%s]\n", ip_address, tport, vm_ip);
}

int my_ret = real_connect(fd, sk, sl);
fprintf(stderr, "Done\n");
return my_ret;
}

ここで、sockは共有ライブラリの「コンストラクタ」で初期化したソケットです。

プログラムは正常に動作し、Doneを出力します。最後の(リターン)行で、スタック破壊エラーが発生します。何が原因なのかわかりません。

4

1 に答える 1

0

私はそれがラインにstrrcr戻ると思うNULL

int pos = strrchr(buffer, NAT_VM_DELIMITER) - buffer;

その後pos、巨大になり、次の行は無効なアドレスを読み書きします。

関数の戻り値を常に確認してください (特に、プログラムの外部から受け取ったデータに対して関数を実行する場合)。

また、コメントに書いたように、決して使用しないでsprintfください。何が失敗したのかわからないので、失敗したかどうかはわかりませんNAT_VM_CONNECT_RULE。バイト数を数えて問題がないとわかっていても、注意してsnprintf代わりに使用する必要があります。

于 2012-06-26T09:20:37.293 に答える