好きな人から愛のこもった返信を受け取る方法

2007/7/31

人知れず好意を抱いている相手から愛のこもった返信をもらえる方法があります。 なんと、「I LOVE YOU」という内容のパケットを送信すると「I LOVE YOU」と返ってきます。 (「愛している」とUTF8(もしくはJIS,SJIS,EUC)などで書くと「愛している」と返ってきます。)

仕組みは簡単です。 愛のメッセージを含んだICMP ECHOを相手に送信するだけです。 そうすれば愛のメッセージが含まれたICMP ECHO REPLYが、彼女(彼)の分身であるコンピュータから返ってきます。

以下がサンプルプログラムです。 PerlやRubyなど他の言語でも作成可能です。 興味のある方は試してみてください。 etherealやwiresharkと併用すると相手からの愛を目で見て確かめられます。

なお、愛の電子障壁(ファイアーウォール)などに阻まれる事もあるのでご注意下さい。 また、彼女(彼)のコンピュータのIPアドレス(もしくはホスト名)を知っている(もしくは調べる)必要があります。

念のため最後に。 最近はICMP送信が攻撃とみなされる事もありえます。 知らない組織宛に求愛するような事はやめましょう。 ご利用は計画的に。

この話が何の事だか理解不能な方へ

pingというコマンドと同じ事をしています。 pingとICMPに関する解説は「Windowsネットワークコマンド : ping」をご覧下さい。

Windows用

参考:IP Helper APIによる自作ping



#include 

#include 
#include 
#include 

int
main()
{
 HANDLE hIcmp;
 char *SendData = "I LOVE YOU"; /* 愛のささやき */
 LPVOID ReplyBuffer;
 DWORD dwRetVal;
 DWORD buflen;
 PICMP_ECHO_REPLY pIcmpEchoReply;

 hIcmp = IcmpCreateFile();

 buflen = sizeof(ICMP_ECHO_REPLY) + strlen(SendData) + 1;
 ReplyBuffer = (VOID*) malloc(buflen);
 if (ReplyBuffer == NULL) {
   return 1;
 }
 memset(ReplyBuffer, 0, buflen);
 pIcmpEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;

 dwRetVal = IcmpSendEcho(hIcmp, 
   inet_addr("127.0.0.1"), 
   SendData, strlen(SendData), 
   NULL, ReplyBuffer, 
   buflen,
   1000);
 if (dwRetVal != 0) {
   printf("Received %ld messages.\n", dwRetVal);
   printf("\n");
   printf("RTT: %d\n", pIcmpEchoReply->RoundTripTime);
   printf("Data Size: %d\n", pIcmpEchoReply->DataSize);
   printf("Message: %s\n", pIcmpEchoReply->Data);
 } else {
   printf("Call to IcmpSendEcho() failed.\n");
   printf("Error: %ld\n", GetLastError());
 }

 IcmpCloseHandle(hIcmp);

 return 0;
}




Linux用

参考:Linuxでの簡単なpingの作成(ICMPの送受信)



#include 

#include 
#include 

#include 
#include 

#define MSG "I LOVE YOU"


/*
 * チェックサムを計算する関数です。
 * ICMPヘッダのチェックサムフィールドを埋めるために利用します。
 * IPヘッダなどでも全く同じ計算を利用するので、
 * IPヘッダのチェックサム計算用としても利用できます。
 */
unsigned short
checksum(unsigned short *buf, int bufsz)
{
  unsigned long sum = 0;

  while (bufsz > 1) {
    sum += *buf;
    buf++;
    bufsz -= 2;
  }

  if (bufsz == 1) {
    sum += *(unsigned char *)buf;
  }

  sum = (sum & 0xffff) + (sum >> 16);
  sum = (sum & 0xffff) + (sum >> 16);

  return ~sum;
}

/* main 文はここからです。*/
int
main(int argc, char *argv[])
{
  int sock;
  struct sockaddr_in addr;
  int n;
  int pktlen;

  char buf[2000];
  struct icmphdr *icmphdrptr;
  struct iphdr *iphdrptr;

  if (argc != 2) {
    printf("usage : %s IPADDR\n", argv[0]);
    return 1;
  }

  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr(argv[1]);

  /* RAWソケットを作成します */
  sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  if (sock < 0) {
    perror("socket");
    return 1;
  }

  memset(buf, 0, sizeof(buf));

  icmphdrptr = (struct icmphdr *)buf;

  /* ICMPヘッダを用意します */
  icmphdrptr->type = ICMP_ECHO;
  icmphdrptr->code = 0;
  icmphdrptr->checksum = 0;
  icmphdrptr->un.echo.id = 0;
  icmphdrptr->un.echo.sequence = 0;

  /* ICMPヘッダのチェックサムを計算します */
  icmphdrptr->checksum = checksum((unsigned short *)icmphdrptr,
                               sizeof(struct icmphdr));

  snprintf(&buf[sizeof(struct icmphdr)],
           sizeof(buf) - sizeof(MSG), MSG);

  /* ICMPヘッダだけのICMPパケットを送信します */
  /* ICMPデータ部分はプログラムを簡潔にするために省いています */
  n = sendto(sock,
             buf,
             sizeof(struct icmphdr) + sizeof(MSG) /*includes '\0'*/,
             0, (struct sockaddr *)&addr, sizeof(addr));
  if (n < 1) {
    perror("sendto");
  }

  /* ICMP送信部分はここまでです*/
  /* ここから下はICMP ECHO REPLY受信部分になります */

  memset(buf, 0, sizeof(buf));

  /* 相手ホストからのICMP ECHO REPLYを待ちます */
  n = recv(sock, buf, sizeof(buf), 0);
  if (n < 1) {
    perror("recv");
  }

  /* 受信データからIPヘッダ部分へのポインタを取得します */
  iphdrptr = (struct iphdr *)buf;

  /*
   * 本当はIPヘッダを調べて
   * パケットがICMPパケットかどうか調べるべきです
   */

  /* 受信データからICMPヘッダ部分へのポインタを取得します */
  icmphdrptr = (struct icmphdr *)(buf + (iphdrptr->ihl * 4));

  /* ICMPヘッダからICMPの種類を特定します */
  if (icmphdrptr->type == ICMP_ECHOREPLY) {
    printf("received ICMP ECHO REPLY : [%s]\n",
           buf + sizeof(struct iphdr) + sizeof(struct icmphdr));
  } else {
    printf("received ICMP %d\n", icmphdrptr->type);
  }

  /* 終了 */
  close(sock);

  return 0;
}


プロフェッショナルIPv6解説動画シリーズ再生リスト

動画で学ぶ「プロフェッショナルIPv6」を作っています。 もしよろしければご覧ください。お楽しみいただければ幸いです!