弁財天
ゴフマン「専門家を信じるのではなく、自分自身で考えて判断せよ」
ゴフマン「専門家を信じるのではなく、自分自身で考えて判断せよ」
Win10の環境が手に入ったので、Cygwinに
iplog-2.2.3を
移植してみてWin10の環境の理解を深めてみたw
つかWindowsサーバーにもiplogを導入し、PCがどこにアクセスし、誰がアクセスしてくるのかをモニターする。そして民主主義を目指すというのが本当の目的ww
Windows版のlibpcapが必要。WinPcapに互換性のあるlibpcap.aがあるのでこれを使ってみる。
WinPcapのディレクトリを見るとx64ディレクトリ下に libwpcap.a がない。
Cygwin64のバグでWindowsのDLLを呼び出しすロードモジュールを正しく作成できないみたいだ。
Problems using a DLL with Cygwin 64 bit
$ ./iplog 6 [main] iplog (7132) C:\cygwin64\usr\local\sbin\iplog.exe: *** fatal error - cygheap base mismatch detected - 0x180324400/0xF54400. This problem is probably due to using incompatible versions of the cygwin DLL. Search for cygwin1.dll using the Windows Start->Find/Search facility and delete all but the most recent version. The most recent version *should* reside in x:\cygwin\bin, where 'x' is the drive on which you have installed the cygwin distribution. Rebooting is also suggested if you are unable to find another cygwin DLL. $こんなエラーになる。
C/C++言語でのプログラミングについてのHOWTO/FAQ集
この"--kill-at"がない場合,DLLを使用するプログラムとインポートライブラリの静的リンクまでは行えるが,DLLとの動的リンクの際に失敗する(プログラムが起動中に異常終了し,エラーメッセージが出ないこともあるので注意が必要).これと似たことが起きた。 エラーなしでロードモジュールの作成はできるのだが、 実行すると何もエラーメッセージなしでプログラムが終了してしまう現象。
32ビットのCygwinなら何も問題なく32ビットのDLLとリンクしてロードモジュールを実行できる。 ふむ。WpdPack/Lib/x64/wpcap.libにlibwpcap.aが付属してなかったのはCygwin64環境ではDLL問題があって実行できないからだ。
なのでCygwin64環境は捨てw。
Cygwin32に切り替えるときは
いろいろトラブルので注意。
Cygwinのサービスの残骸が残って消せないときは
C:\>sc delete apache C:\>sc delete sshd C:\>sc delete cygserver [SC] DeleteService SUCCESSみたいにscコマンドで削除してしまう。
パッケージを消すつもりでトップのディレクトリCygwin64を_Cygwin64とリネームしても、リネームしたディレクトリ下のプログラムを拾ってくる仕様ってどうなのよ?なので完全な消去が必要w
teratermのcyglaunch.exeが動かない。
Cygwinを64→32に切り替えてcyglaunchから起動できないと悩んでたら、 C:\Program Files (x86)\teraterm\cygterm+-i686\cygterm.exe をひとつ上のディレクトリにコピーする仕様みたいだw
なんだかなー。
32ビットのlibpcap.aの作成はdlltoolと.defファイルで作成する。
dlltool --kill-at --def wpcap.def --dllname wpcap.dll --output-lib libpcap.awpcap.defはnmで作成してもいいし、ソースの中のWpcap_no_extensions.defを使ってもいい。
もっとすげーやり方。
Re: Net::Pcap installation help (and not with the library)
MinGWのpexports
すっげーw。--WinPcap
- Make sure WinPcap is installed - if not, install it
- Unzip WinPcap Developers Pack http://www.winpcap.org/devel.htm in same parent directory Net::Pcap was unzipped in, e.g.,:
tmp\Net-Pcap-0.16\.. tmp\WpdPack\..- IF on x64 platform, check on the existence of the x64 libraries:
dir WpdPack\lib\x64\*.a- They may not exist. If not, built them:
pexports \Windows\system32\wpcap.dll > wpcap.def dlltool --as-flags=--64 -m i386:x86-64 -k --output-lib libwpcap.a --input-def wpcap.def pexports \Windows\system32\Packet.dll > Packet.def dlltool --as-flags=--64 -m i386:x86-64 -k --output-lib libpacket.a --input-def Packet.def move libwpcap.a WpdPack\lib\x64 move libpacket.a WpdPack\lib\x64
#!/usr/bin/sh echo "LIBRARY wpcap.dll" >wpcap_lib.def echo "EXPORTS" >> wpcap_lib.def nm /WpdPack/Lib/wpcap.lib| sed -n -e"s/.* T _//p"|grep -v "\.text">>wpcap_lib.def dlltool --kill-at --def wpcap_lib.def --dllname wpcap.dll --output-lib libpcap.a cp libpcap.a /WpdPack/Lib/.まぁこんなファイルをねつ造すればいいのだな。
LIBRARY wpcap.dll DESCRIPTION 'Win32 Packet Capture Library' EXPORTS bpf_dump bpf_filter bpf_image bpf_validate endservent eproto_db DATA getservent install_bpf_program pcap_activate pcap_breakloop pcap_close pcap_compile pcap_compile_nopcap pcap_create pcap_createsrcstr pcap_datalink pcap_datalink_name_to_val pcap_datalink_val_to_description pcap_datalink_val_to_name pcap_dispatch pcap_dump pcap_dump_close pcap_dump_file pcap_dump_flush pcap_dump_ftell pcap_dump_open pcap_file pcap_fileno pcap_findalldevs pcap_findalldevs_ex pcap_free_datalinks pcap_freealldevs pcap_freecode pcap_get_airpcap_handle pcap_geterr pcap_getevent pcap_getnonblock pcap_hopen_offline pcap_is_swapped pcap_lib_version pcap_list_datalinks pcap_live_dump pcap_live_dump_ended pcap_lookupdev pcap_lookupnet pcap_loop pcap_major_version pcap_minor_version pcap_next pcap_next_etherent pcap_next_ex pcap_offline_filter pcap_offline_read pcap_open pcap_open_dead pcap_open_live pcap_open_offline pcap_parsesrcstr pcap_perror pcap_read pcap_remoteact_accept pcap_remoteact_cleanup pcap_remoteact_close pcap_remoteact_list pcap_sendpacket pcap_sendqueue_alloc pcap_sendqueue_destroy pcap_sendqueue_queue pcap_sendqueue_transmit pcap_set_buffer_size pcap_set_datalink pcap_set_promisc pcap_set_snaplen pcap_set_timeout pcap_setbuff pcap_setdirection pcap_setfilter pcap_setmintocopy pcap_setmode pcap_setnonblock pcap_setsampling pcap_setuserbuffer pcap_snapshot pcap_stats pcap_stats_ex pcap_strerror wsockinit
Windows 7 network adapter device name using winpcap
Linux環境だとeth0とかens0とかになるネットワークインターフェイスのデバイス名はWin環境では
getmac /fo csv /v
で調べることができるとか。
C:\Users\hoge>getmac /fo csv /v "接続名","アダプター","物理アドレス","トランスポート名" "Wi-Fi","Realtek RTL8723BE Wireless LAN 802.11n PCI-E NIC","xx-xx-xx-xx-xx-xx","メディアが切断されています" "eth0","Realtek PCIe GBE Family Controller","80-FA-xx-xx-xx-xx","\Device\Tcpip_{00DE027D-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" C:\Users\hoge>eth0とか名前を変えちゃえばいいのかとか思ってたけど違うw
Obtaining the device list
WinPcapにデバイスリストを取得するサンプルがある。
gcc -I/wpdpack/include -L/wpdpack/lib -lpcap pcap_filter.c -o pfだとエラー。
gcc -I/wpdpack/include -L/wpdpack -L/wpdpack/lib pcap_filter.c -o pf -lpcapこれだとpf.exeが作製される。-lpcap引数の場所に意味があるみたいだけど、よくわからんな。
$ gcc -I /WpdPack/Include/ -L /WpdPack/Lib devlist.c -o devlist -lpcap $ ./devlist.exe 1. rpcap://\Device\NPF_{00DE027D-XXXX-XXXX-XXXX-XXXXXXXXXXXX} (Network adapter 'Realtek PCIe GBE Family Controller' on … $どうもpcap_open_live()に渡すデバイス名は
\Device\Tcpip_{00DE027D-xxxx-xxxx-xxxx-xxxxxxxxxxxx}ではなく
rpcap://\Device\NPF_{00DE027D-XXXX-XXXX-XXXX-XXXXXXXXXXXX}みたいだ。
configureはこんな。
./configure --host=linux --with-libpcap=/wpdpack --with-libpcap-includes=/wpdpack/include --with-libpcap-libs=/wpdpack/lib
iplog.cをコンパイルするのにincludeファイルが足りない。 なのでLinuxからテケトーにパクってくる。
/usr/include/netinet/if_ether.h /usr/include/linux/if_ether.h /usr/include/linux/types.h /usr/include/linux/posix_types.h /usr/include/linux/stddef.h /usr/include/asm/posix_types.h /usr/include/asm/posix_types_64.h /usr/include/asm/posix_types_32.h /usr/include/asm-generic/posix_types.h /usr/include/asm-generic/bitsperlong.h /usr/include/asm/bitsperlong.h /usr/include/net/ethernet.h
src/iplog_pcap.c で interfacesの名前の文字列を比較して openするのだけど 文字列が一致しないから動かない。 なので/etc/iplog.confには
# Listen on eth0 and eth1 #interface eth0,eth1 interface {00DE027D-XXXX-XXXX-XXXX-XXXXXXXXXXXX}な定義をしてだな。 pcap_open_live()の直前でデバイス名の先頭に"rpcap://\\Device\\NPF_"を付けるように src/iplog_pcap.cにパッチw
static int open_pcap_device(struct pcap_data *pdata) { u_char fstring[1024], *temp, errbuf[PCAP_ERRBUF_SIZE]; struct bpf_program filt; u_int i = 0; u_char devname[60]; memset(devname, 0, sizeof(devname)); strcpy(devname, "rpcap://\\Device\\NPF_"); strcat(devname, pdata->name); pdata->pd = //pcap_open_live(pdata->name, SNAPLEN, opt_enabled(PROMISC), 0, errbuf); pcap_open_live(devname, SNAPLEN, opt_enabled(PROMISC), 0, errbuf);
linux/if.h:#define IFNAMSIZ 1616文字はeth0とかなら足りるが
struct pcap_data { struct pcap_data *next; struct pcap_data *prev; int dl; pcap_t *pd; ipaddr_t *addr; size_t num_addr; //u_char name[IFNAMSIZ]; u_char name[60]; };
Signal 11(SIGSEGV)で落ちるときは -gオプションをつけてコンパイル、iplog実行時に-o オプションを付けてマルチスレッドを禁止してデバッグ。 gdb src/iplogで起動。 run -oで実行、落ちたら bt コマンドで落ちた個所を特定する。
(gdb) run -o Starting program: /home/hoge/src/iplog-2.2.3/src/iplog -o [New Thread 628.0x1d44] [New Thread 628.0x534] [New Thread 628.0x17e8] [New Thread 628.0x928] [New Thread 628.0x20] [New Thread 628.0x1a18] [New Thread 628.0x1b78] [New Thread 628.0x1b18] Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 628.0x1b18] 0x0040a7d8 in read_packets (data=0x200442d0) at iplog.c:328 328 FD_SET(fd, &rfds); (gdb) bt #0 0x0040a7d8 in read_packets (data=0x200442d0) at iplog.c:328 #1 0x61112ead in pthread::thread_init_wrapper(void*) () from /usr/bin/cygwin1.dll #2 0x61094c91 in pthread_wrapper@4 () from /usr/bin/cygwin1.dll #3 0x00000000 in ?? () (gdb)iplog.cの328行目でSIGSEGVで落ちる。
/* #ifdef THREADED_LIBPCAP_IS_BROKEN FD_SET(fd, &rfds); select(fd + 1, &rfds, NULL, NULL, &tv); #endif */へんなコードをコメントアウト。
$ uname -a CYGWIN_NT-10.0-WOW HOGE 2.4.1(0.293/5/3) 2016-01-24 11:24 i686 Cygwin $な環境。 これでiplogのCygwin32ビット環境への移植完了。実行可能になった。
win10pcap.orgでpcap_open_live()に渡すデバイス名の頭に"rpcap://\\Device\\NPF_"を付けるとエラーになるぞw バイナリ互換とは言えないだろ。
Apr 6 09:08:34 IP packet with invalid checksum to hoge1 (192.168.x.x) from hoge2 (192.168.x.y)うーむ。TCPヘッダーの解読ができない。
tcpdumpのサンプル www.tcpdump.org/sniffex.c を同じlibpcap.a/wpcap.dllとコンパイル・リンクしたものはUDP/TCPの識別ができる。 src/iplog_input.c の識別ロジックがダサいのか。
www.tcpdump.org/sniffex.c
sniffexでUDPとICMPが引っかからないと思ったらコードのswitch文でreturnしてるし。orz.
code_snippet/ether_bridge/headers.h
/* UDP header */ struct sniff_udp { unsigned short int uh_sport; unsigned short int uh_dport; unsigned short int uh_len; unsigned short int uh_check; }; /* total udp header length: 8 bytes (=64 bits) */いいものみっけ。
code_snippet/ether_bridge/headers.c
const struct sniff_udp *udp; /* The TCP header */ … /* define/compute udp header offset */ udp = (struct sniff_udp*)(packet + SIZE_ETHERNET + size_ip);
$ diff sniffex.c o/sniffex.c 270,277d269 < /* UDP header */ < struct sniff_udp { < unsigned short int uh_sport; < unsigned short int uh_dport; < unsigned short int uh_len; < unsigned short int uh_check; < }; /* total udp header length: 8 bytes (=64 bits) */ < 435,436d426 < const struct sniff_udp *udp; < 442,444d431 < char proto[10]; < char src[20]; < char dst[20]; 446c433 < /* printf("\nPacket number %05d:\n", count); */ --- > printf("\nPacket number %d:\n", count); 460c447 < /* print source and destination IP addresses --- > /* print source and destination IP addresses */ 463d449 < */ 468,469c454 < //printf(" Protocol: TCP\n"); < strcpy(proto,"TCP"); --- > printf(" Protocol: TCP\n"); 472,477c457 < //printf(" Protocol: UDP\n"); < strcpy(proto,"UDP"); < udp = (struct sniff_udp*)(packet + SIZE_ETHERNET + size_ip); < sprintf(src, "%s:%d", inet_ntoa(ip->ip_src), ntohs(udp->uh_sport)); < sprintf(dst, "%s:%d", inet_ntoa(ip->ip_dst), ntohs(udp->uh_dport)); < printf("%5d %20s -> %-20s %s\n", count, src, dst, proto); --- > printf(" Protocol: UDP\n"); 480,485c460 < //printf(" Protocol: ICMP\n"); < strcpy(proto,"ICMP"); < udp = (struct sniff_udp*)(packet + SIZE_ETHERNET + size_ip); < sprintf(src, "%s:%d", inet_ntoa(ip->ip_src), -1); < sprintf(dst, "%s:%d", inet_ntoa(ip->ip_dst), -1); < printf("%5d %20s -> %-20s %s\n", count, src, dst, proto); --- > printf(" Protocol: ICMP\n"); 488,492c463 < //printf(" Protocol: IP\n"); < strcpy(proto,"IP"); < sprintf(src, "%s:%d", inet_ntoa(ip->ip_src), -1); < sprintf(dst, "%s:%d", inet_ntoa(ip->ip_dst), -1); < printf("%5d %20s -> %-20s %s\n", count, src, dst, proto); --- > printf(" Protocol: IP\n"); 495,499c466 < //printf(" Protocol: unknown\n"); < sprintf(proto,"%d", ip->ip_p); < sprintf(src, "%s:%d", inet_ntoa(ip->ip_src), -1); < sprintf(dst, "%s:%d", inet_ntoa(ip->ip_dst), -1); < printf("%5d %20s -> %-20s %s\n", count, src, dst, proto); --- > printf(" Protocol: unknown\n"); 515,519d481 < //1001 192.168.24.38:22 -> 192.168.24.38:53793 TCP < sprintf(src, "%s:%d", inet_ntoa(ip->ip_src), ntohs(tcp->th_sport)); < sprintf(dst, "%s:%d", inet_ntoa(ip->ip_dst), ntohs(tcp->th_dport)); < printf("%5d %20s -> %-20s %s\n", count, src, dst, proto); < /* 522d483 < */ 532a494 > */ 537d498 < */ 553c514 < int num_packets = 10000; /* number of packets to capture */ --- > int num_packets = 10; /* number of packets to capture */ $
$ cat cc.sh #!/bin/sh for s in sniffex sniffex_ip do cc -g -O -I ../WpdPack/Include -c -o ${s}.o ${s}.c cc -g -O -I ../WpdPack/Include -o ${s}.exe ${s}.o -L ../WpdPack/Lib/x64 -lwpcap done $
$ ./sniffex "\\Device\\NPF_{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" sniffex - Sniffer example using libpcap Copyright (c) 2005 The Tcpdump Group THERE IS ABSOLUTELY NO WARRANTY FOR THIS PROGRAM. Device: \Device\NPF_{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} Number of packets: 10 Filter expression: ip 1 192.168.99.38:22 -> 192.168.99.93:52040 TCP 2 192.168.99.93:52040 -> 192.168.99.38:22 TCP 3 153.156.202.233:4500 -> 192.168.99.38:4500 UDP 4 192.168.99.38:4500 -> 153.156.202.233:4500 UDP 5 192.168.99.38:4500 -> 153.156.202.233:4500 UDP 6 192.168.99.38:22 -> 192.168.99.93:52040 TCP 7 192.168.99.38:22 -> 192.168.99.93:52040 TCP 8 192.168.99.93:52040 -> 192.168.99.38:22 TCP 9 192.168.99.38:4500 -> 153.156.202.233:4500 UDP 10 192.168.99.38:22 -> 192.168.99.93:52040 TCP Capture complete.おぉぉ。おもろいなー。これ。自作パケットキャプチャ。
$ ps|grep sniff 5620 3080 5620 5520 pty0 197108 16:32:12 /home/hoge/src/sniffex/sniffex $ taskkill /pid 5520 /f SUCCESS: The process with PID 5520 has been terminated. $Ctrl+Cでは止まらない。taskkillコマンドを使う。
iplogもsniffexもpcapを使った実装で、iplogが動かなくて、sniffexが動く理由がわからないけど、sniffexのコードをiplogに移植すれば動くよーになるはず。 やらないけどw。
Bonaponta in Cygwin 2016年4月4日 午後 04:59 JST