CoinHive公判(第2回)傍聴メモ

CoinHive第2回公判を傍聴してきました。
傍聴内容について、どこまでブログに書いていいのかよく分かりませんので、どんな質問があったかについてのみ一部を記載しています。
もし問題がありましたら、ご指摘ください。

公判について

第2回公判 証人尋問
平成31年1月15日13:30-15:00
不正指令電磁的記録保管
証人:高木 浩光氏(産業技術総合研究所情報セキュリティ研究センター主任研究員)
場所:横浜地方裁判所第401号法廷

傍聴券の交付はありませんでしたが、傍聴希望者が多く、先着順となって傍聴できない人もいました。
私は開始45分ほど前に行きましたが、その時点で20人ほど並んでおり、最終的には50人以上(?)の傍聴希望者が来ていたように思います。
本件への関心の高さが窺えます。
ちなみに、開始10分前に法廷に入ることが出来ました。

内容

弁護側質問

JavaScriptの仕組みや、JavaScriptの性質(アクセス者はサイトアクセス前にどんなJavaScriptが実行されるか分からない、ブラウザを終了すればJavaScriptは止まる、ネイティブアプリと異なりファイルアクセスができない等の制限がある等)に関する質問
CoinHiveの実行によるPCへの影響、CoinHiveの設定値(スロットル)に関する質問
・クリプトジャッキングに関する質問

検察側質問

CoinHiveの実行によるPCへの影響に関する質問
JavaScriptの実行に関し、包括的許諾があるか。
CoinHiveについて、まわりや技術者の中で、望まない声はあるか。その人たちはなぜ望まないのか。 CoinHiveについて、規制は必要か。
・証人のブログでの表記について(魔女狩り、田舎警察 等)
マカフィー社のウイルス対策ソフトでCoinHiveが検出されることを検証したか。 ウイルス対策ソフトベンダによる検出の分類基準はあるか。

裁判官質問

CoinHive動作中に、アクセス者は(CoinHiveが動作していることに)気が付くか。
・他のサイトで実行されているJavaScriptと、CoinHiveは異なるものか。

参考URL

doocts.com

www.bengo4.com

detuxサンドボックス環境構築(暫定版)

Linuxプログラムのサンドボックスサービス「detux.org」が停止して困っていたので、GitHubに公開されているdetuxスクリプトGitHub - detuxsandbox/detux: The Multiplatform Linux Sandbox)を使って、サンドボックス環境を構築してみました。

ネットワーク回りはまだ不満があるので、とりあえず暫定版です。
GitHubに書かれていた内容を参考にしていますが、余計な処理が含まれているかもしれません。
その点はご了承ください。

目標

次のアーキテクチャ向けにコンパイルされたLinuxプログラムを実行し、通信先を調べるサンドボックス環境の構築

環境

今後は「VMware」、「Ubuntu」、「REMnux」と呼ぶことにします。
また、Ubuntu上でQEMUというソフトウェアを使って、各アーキテクチャDebianを動かしていきます。
こちらは「Debian」と呼んでいきます。

注意

この記事では、各種設定ファイルを直接編集していますが、編集前に設定ファイルのバックアップを取っておくことをオススメします。
また、スナップショットを利用できる仮想化ソフトウェアを使っている場合、適宜スナップショットを取ることをオススメします。

REMnuxの設定

REMnuxは、detuxサンドボックスから発生した通信に対してレスポンスを返すサーバの役割です。

REMnuxのサイト(https://remnux.org/)からイメージファイルをダウンロードし、VMwareにインポートします。
VMwareのネットワーク設定を「NAT」から「LANセグメント」に変更します。
REMnuxを起動し、次のとおりネットワークを設定します。

$ sudo leafpad /etc/network/interfaces
auto eth0
iface eth0 inet static
address 192.168.1.1
netmask 255.255.255.0
broadcast 192.168.1.255
network 192.168.1.0

再起動し、次のコマンドを実行します。

$ inetsim
$ fakedns
$ accept-all-ips start

Ubuntuの設定

VMwareのネットワーク設定を「NAT」にしてUbuntuを起動します。

アップデート

$ sudo apt-get update
$ sudo apt-get upgrade

detuxフォルダの作成

$ cd ~
$ mkdir detux
$ cd detux

今後、Ubuntu上での作業はすべてdetuxフォルダで行います。

detuxスクリプトのダウンロード

GitHubhttps://github.com/detuxsandbox/detux)からzipファイル等の形ですべてダウンロードし、展開したファイル・フォルダをdetuxフォルダ直下に保存します。

イメージファイルのダウンロード

「#」行はコメントです。

#x86
$ wget https://people.debian.org/~aurel32/qemu/i386/debian_wheezy_i386_standard.qcow2 -P qemu/x86/1/

#x86-64
$ wget https://people.debian.org/~aurel32/qemu/amd64/debian_wheezy_amd64_standard.qcow2 -P qemu/x86-64/1/

#arm
$ wget https://people.debian.org/~aurel32/qemu/armel/debian_wheezy_armel_standard.qcow2 -P qemu/arm/1/
$ wget https://people.debian.org/~aurel32/qemu/armel/initrd.img-3.2.0-4-versatile -P qemu/arm/1/
$ wget https://people.debian.org/~aurel32/qemu/armel/vmlinuz-3.2.0-4-versatile -P qemu/arm/1/

#mips
$ wget https://people.debian.org/~aurel32/qemu/mips/vmlinux-3.2.0-4-4kc-malta -P qemu/mips/1/
$ wget https://people.debian.org/~aurel32/qemu/mips/debian_wheezy_mips_standard.qcow2 -P qemu/mips/1/

#mipsel
$ wget https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-3.2.0-4-4kc-malta -P qemu/mipsel/1/
$ wget https://people.debian.org/~aurel32/qemu/mipsel/debian_wheezy_mipsel_standard.qcow2 -P qemu/mipsel/1/

QEMU等のインストール

$ sudo apt-get -y install qemu
$ sudo apt-get -y install pcaputils
$ sudo apt-get -y install bridge-utils
$ sudo apt-get -y install python-pip
$ sudo apt-get -y install xtightvncviewer
$ sudo apt-get -y install wireshark-common

wireshark-commonインストールの際、「root以外のユーザがパケットをキャプチャできるようにしますか?」と聞かれたら「はい」を選択します。

pythonライブラリのインストール

$ pip install argparse==1.2.1
$ pip install dpkt==1.8.7
$ pip install ecdsa==0.13
$ pip install netaddr==0.7.18
$ pip install paramiko==1.16.0
$ pip install pexpect==4.0.1
$ pip install ptyprocess==0.5.1
$ pip install pycrypto==2.6.1
$ pip install python-magic==0.4.11
$ pip install wsgiref==0.1.2

QEMUをユーザ権限で実行するための設定

次の内容を追記します。「ユーザ名」の箇所はログインユーザ名(例:user)を記入してください。

$ sudo gedit /etc/sudoers
Cmnd_Alias QEMU_CMD = /usr/bin/qemu-*, /sbin/ip, /sbin/ifconfig, /sbin/brctl
ユーザ名 ALL = (ALL) NOPASSWD: QEMU_CMD

QEMU設定ファイルの編集

$ sudo gedit /etc/qemu-ifup

ファイルの内容をすべて消し、次の内容を書き込んでください。

#! /bin/sh
# Script to bring a network (tap) device for qemu up.
# The idea is to add the tap device to the same bridge
# as we have default routing to.

# in order to be able to find brctl
PATH=$PATH:/sbin:/usr/sbin
ip=$(which ip)
ifconfig=$(which ifconfig)

echo "Starting"  $1
if [ -n "$ip" ]; then
   ip link set "$1" up
else
   brctl=$(which brctl)
   if [ ! "$ip" -o ! "$brctl" ]; then
     echo "W: $0: not doing any bridge processing: neither ip nor brctl utility not found" >&2
     exit 0
   fi
   ifconfig "$1" 0.0.0.0 up
fi

switch=$(ip route ls | \
    awk '/^default / {
          for(i=0;i<NF;i++) { if ($i == "dev") { print $(i+1); next; } }
         }'
        )
    if [ -d /sys/class/net/br0/bridge/. ]; then
        if [ -n "$ip" ]; then
          ip link set "$1" master br0
        else
          brctl addif br0 "$1"
        fi
        exit    # exit with status of the previous command
    fi

echo "W: $0: no bridge for guest interface found" >&2

ネットワーク設定の確認

ifconfigでインターフェース名を調べます(ここではens33)。

$ ifconfig
ens33     Link encap:イーサネット  ハードウェアアドレス 00:0c:29:fd:21:80  
          inetアドレス:192.168.133.151  ブロードキャスト:192.168.133.255  マスク:255.255.255.0
          inet6アドレス: fe80::9e19:be2d:f2a6:f17f/64 範囲:リンク
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:1067793 エラー:196 損失:279 オーバラン:0 フレーム:0
          TXパケット:192198 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:1000 
          RXバイト:1576292236 (1.5 GB)  TXバイト:10459681 (10.4 MB)
          割り込み:19 ベースアドレス:0x2000 

lo        Link encap:ローカルループバック  
          inetアドレス:127.0.0.1  マスク:255.0.0.0
          inet6アドレス: ::1/128 範囲:ホスト
          UP LOOPBACK RUNNING  MTU:65536  メトリック:1
          RXパケット:260 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:260 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:1 
          RXバイト:21239 (21.2 KB)  TXバイト:21239 (21.2 KB)

ネットワーク設定

ネットワーク設定を追記します。
bridge_portsの行には、先に調べたインターフェス名を指定します。

$ sudo gedit /etc/network/interfaces
auto br0
iface br0 inet static
address 192.168.1.2
network 192.168.1.0
netmask 255.255.255.0
broadcast 192.168.1.255

bridge_ports ens33
bridge_maxwait 0

dumpcapをユーザ権限で実行するための設定

ユーザ名には、ログインユーザ名を指定します。

$ sudo usermod -a -G wireshark ユーザ名
$ sudo chmod 750 /usr/bin/dumpcap
$ sudo setcap cap_net_raw,cap_net_admin=eip /usr/bin/dumpcap

Ubuntuのシャットダウン

シャットダウン後、Ubuntuからインターネットに接続できなくなるため、他に入れたいパッケージ等があればシャットダウンする前に入れておいてください。

$ sudo shutdown -h now

VMwareのネットワーク設定

「NAT」から「LANセグメント」に変更し、Ubuntuを起動します。

Debianイメージの起動

$ sudo qemu-system-i386 -hda qemu/x86/1/debian_wheezy_i386_standard.qcow2 -vnc 127.0.0.1:0 -net nic,macaddr=00:11:22:33:44:55 -net tap -monitor stdio

ここで指定したMACアドレスは後で使うのでメモしておきます。
実行後、(qemu)というプロンプトが表示されます。このターミナルは閉じないようにしてください。

VNCDebianに接続

少し時間をおいてから、別のターミナルを起動し、次のコマンドでDebianVNC接続します。

vncviewer localhost

しばらく待つと、ログインプロンプトが表示されるので、root/rootでログインします。

Debianのネットワーク設定

# vi /etc/network/interfaces
address 192.168.1.10
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.1

# vi /etc/resolv.conf
nameserver 192.168.1.1

※もし、キーボードで「:」が出せない時は、shift-qを押すと「:」が出ると思います。

Debianの再起動

# shutdown -r now

シャットダウン後、VNC接続が切れるので、少し時間をおいて、ターミナルからDebianVNC接続します。

Debianから疎通確認

「//」行はコメントです。

// Ubuntuとの疎通確認
# ping 192.168.1.2

// REMnuxとの疎通確認
# ping 192.168.1.1

// DNSの確認(応答はREMnuxから返されます)
# ping aa.bb

// セグメント外IPアドレスとの疎通確認(応答はREMnuxから返されます)
# ping 5.5.5.5

疎通確認が済んだら、exitでDebianから抜け、VNCソフトウェアを落とします。

作成したDebianイメージの保存

(qemu)と表示されたプロンプトで次のコマンドを実行します。

(qemu) savevm init
(qemu) q

detux設定ファイルの編集

$ gedit detux.cfg

これまでDebianに設定した内容を、以下のように追記していきます。

#Config for x86 Linux VM
[x86-1]
#VM IP
ip=192.168.1.10
#SSH user (root)
user=root
#SSH password
password=root
#VM Nic's MAC Address
macaddr=00:11:22:33:44:55
#SSH PORT
port=22

Debianイメージの作成

ここまではx86Debianのイメージファイルを作成しましたが、x86-64、ARM、MIPS、MIPSELについても同様に作業していきます。
必要な作業は「Debianイメージの起動」から「detux設定ファイルの編集」までです。
イメージ起動時の指定方法は、以下の例を参考にしてください。 また、イメージ毎に変えた方がいい値は、DebianIPアドレスMACアドレスくらいかと思います。

  • 起動時のコマンド例
#x86-64
$ sudo qemu-system-x86_64 -hda qemu/x86-64/1/debian_wheezy_amd64_standard.qcow2 -vnc 127.0.0.1:0 -net nic,macaddr=00:11:22:33:44:56 -net tap -monitor stdio

#arm
$ sudo qemu-system-arm -M versatilepb -kernel qemu/arm/1/vmlinuz-3.2.0-4-versatile -initrd qemu/arm/1/initrd.img-3.2.0-4-versatile -hda qemu/arm/1/debian_wheezy_armel_standard.qcow2 -append "root=/dev/sda1" -vnc 127.0.0.1:0 -net nic,macaddr=00:11:22:33:44:57 -net tap -monitor stdio

#mips
$ sudo qemu-system-mips -M malta -kernel qemu/mips/1/vmlinux-3.2.0-4-4kc-malta -hda qemu/mips/1/debian_wheezy_mips_standard.qcow2 -append "root=/dev/sda1 console=tty0" -vnc 127.0.0.1:0 -net nic,macaddr=00:11:22:33:44:58 -net tap -monitor stdio

#mipsel
$ sudo qemu-system-mipsel -M malta -kernel qemu/mipsel/1/vmlinux-3.2.0-4-4kc-malta -hda qemu/mipsel/1/debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -vnc 127.0.0.1:0 -net nic,macaddr=00:11:22:33:44:59 -net tap -monitor stdio
  • detux設定ファイルの例
#Config for x86 Linux VM
[x86-1]
#VM IP
ip=192.168.1.10
#SSH user (root)
user=root
#SSH password
password=root
#VM Nic's MAC Address
macaddr=00:11:22:33:44:55
#SSH PORT
port=22

#Config for x86-64 Linux VM
[x86-64-1]
ip=192.168.1.20
user=root
password=root
macaddr=00:11:22:33:44:56
port=22

#Config for ARM Linux VM
[arm-1]
ip=192.168.1.30
user=root
password=root
macaddr=00:11:22:33:44:57
port=22

#Config for MIPS Linux VM
[mips-1]
ip=192.168.1.40
user=root
password=root
macaddr=00:11:22:33:44:58
port=22

#Config for MIPSEL Linux VM
[mipsel-1]
ip=192.168.1.50
user=root
password=root
macaddr=00:11:22:33:44:59
port=22

detuxサンドボックスの実行

--sampleの後に解析対象のファイルを指定します。

$ python detux.py --sample test_script/example_binary1 --report reports/test.json

結果はpcapフォルダとreportsフォルダに記録されます。

オプション

$ python detux.py -h
usage: detux.py [-h] --sample SAMPLE [--cpu {x86,x86-64,arm,mips,mipsel}]
                [--int {python,perl,sh,bash}] --report REPORT

optional arguments:
  -h, --help            show this help message and exit
  --sample SAMPLE       Sample path (default: None)
  --cpu {x86,x86-64,arm,mips,mipsel}
                        CPU type (default: auto)
  --int {python,perl,sh,bash}
                        Architecture type (default: None)
  --report REPORT       JSON report output path (default: None)

#ssmjp 2018/05に参加してきました

はじめに

「#ssmjp 2018/05」という勉強会に参加してきました。
ssmjpに参加するのは久しぶりでした。
最近のssmjpの一般参加枠は「抽選式」のことが多く、抽選に外れて行けないこともあったのですが、今回は特に興味のある内容だったので「先着順」のブログ枠で参加してきました。
どの発表も面白く、参加して良かったなという感想です。
興味のある発表の時は「ブログ枠」を申し込むのがおすすめです。

また、会場を提供していただいた「LINE株式会社」様、ありがとうございました!

ssmjp.connpass.com

ssmjpについて

ssmjpは(約)月1ペースで開催されている勉強会です。
通称は「ささみ」や「ししゃも」らしいです。
インフラや運用がメインテーマのようですが、LT(ライトニングトーク)の練習の場という位置付けなため、内容についても割と自由な感じのようです。
勉強会の雰囲気を伝えるため、今回の勉強会の最初に挙げられていた「過去にあった衝撃LT」を参考に記載しておきます。

資料について

DNSのこと

DNSとは

インターネットでは、宛先のIPアドレスが分からないと通信することはできません。
しかし、人間にはIPアドレスを覚えることは難しいです。一方で「hatenablog.com」といった名前(ドメイン名)であれば覚えやすくなります。
人間に分かりやすい「ドメイン名」と、人間には分かりづらい「IPアドレス」を関連付け、ドメイン名からIPアドレスを調べる仕組みがあればとても便利になります。
インターネット上でこの役割を果たしているのが「DNS」(ドメインネームシステム)という仕組みです。

ドメイン登録について

ドメインを利用する為には、.jpや.comといったトップレベルドメインTLD)を管理している機関であるレジストリ(登録管理機関)に情報伝達する必要があります。流れは次のようになります。

レジストラント -> レジストラ -> レジストリ

WHOISとは

ドメインの各情報を記載した、誰でも参照可能なデータベースのことです。
例えば、「hatenablog.com」のWHOIS情報を調べる場合、次のサイトを使えます。

WHOIS Search | ICANN WHOIS

はてなブログドメイン情報を確認できます・・・と書きたかったのですが、GDPRの影響か、ほとんどの登録者情報が「Not Disclosed」になってますね。
GDPRについては、次のページに詳細が書かれています。
ICANNがEUのGDPRに準拠したgTLD登録データのための暫定仕様を承認 - JPNIC

ドメイン名ハイジャック

ドメイン名ハイジャックとは、何らかの方法でドメイン名を乗っ取る行為のことです。
本来のサイトではなく、フィッシングサイトやマルウェア配布サイト等に誘導することが可能になります。
ドメイン名ハイジャックの原因としては、例えば、

などがあります。

ドメイン名ハイジャックへの対策として、例えば、

などがあります。

DNSトンネリングについて

DNSトンネリングとは、DNSの通信に、別の目的を持った情報を含めることで、偽装通信の一種です。
暗号通信とは目的が異なります。

  • 暗号通信
    • どのようなデータか確認できないようにする。
    • 通信が行われていることは認知されても良い。
  • 偽装通信
    • 意味のあるデータを送信していることを知られないようにする。

DNSトンネリングの例としては、マルウェアがあります。
DNSは、ファイアウォール等でフィルタリングされいることが少なく、またDNSのログを取得していることも少ない為、マルウェアを使用する攻撃者にとって、非常に都合の良い通信と言えます。 一部のマルウェアは、C2サーバ(攻撃者がマルウェアに指令を与える為に使用するサーバ)との通信にDNSトンネリングを悪用します。
マルウェアからのDNS要求の通信に、C2サーバに送信したい情報を乗せ、
C2サーバからのDNS応答の通信に、攻撃者からの指令情報を乗せます。

DNSトンネリングを使用するマルウェアには、「PlugX」や「Helminth」などがあります。
マルウェアからの情報送信にはqname、C2サーバからの指令にはTXTレコードを使用することが多いそうです。

DNSトンネリングを使用したC2サーバとの通信への対策としては、「フルリゾルバ(DNSキャッシュサーバ)以外からの53番ポートの通信をフィルタリングし、qnameをアノマリ検知(通常とは異なるパターンを検知)する」といった方法があります。

最後に

久しぶりのssmjpは、とても楽しめました。
私はセキュリティやネットワークが好きなので、これらのテーマの回にはまた参加したいと思います。

では。

bitcoinまとめ

便利なサイト

メモ

https://blockchain.info/ja/block-height/71000?format=json
->"hash":"00000000003eea76022498376477294a921cfabeee70f0630ce0fd45dc22179b"

Python3(MySQLと連携メモ)

インストール

sudo apt-get install mysql-server
sudo pip3 install PyMySQL

コマンド

#ユーザ「root」、パスワード「password」で接続
mysql -u root -ppassword

MySQLコマンド

mysql> CREATE DATABASE scraping;
mysql> USE scraping;
mysql> CREATE TABLE pages ( id BIGINT(7) NOT NULL AUTO_INCREMENT ,
                            title VARCHAR(200) ,
                            content VARCHAR(10000) ,
                            created TIMESTAMP DEFAULT CURRENT_TIMESTAMP ,
                            PRIMARY KEY(id));
mysql> DESCRIBE pages;
+---------+----------------+------+-----+-------------------+----------------+
| Field   | Type           | Null | Key | Default           | Extra          |
+---------+----------------+------+-----+-------------------+----------------+
| id      | bigint(7)      | NO   | PRI | NULL              | auto_increment |
| title   | varchar(200)   | YES  |     | NULL              |                |
| content | varchar(10000) | YES  |     | NULL              |                |
| created | timestamp      | NO   |     | CURRENT_TIMESTAMP |                |
+---------+----------------+------+-----+-------------------+----------------+

mysql> INSERT INTO pages (title,content) VALUES ("Test page title" , "This is some test page content.");
mysql> SELECT * FROM pages;
+----+-----------------+---------------------------------+---------------------+
| id | title           | content                         | created             |
+----+-----------------+---------------------------------+---------------------+
|  1 | Test page title | This is some test page content. | 2016-10-16 21:41:49 |
+----+-----------------+---------------------------------+---------------------+

mysql> SELECT * FROM pages WHERE id = 1;
+----+-----------------+---------------------------------+---------------------+
| id | title           | content                         | created             |
+----+-----------------+---------------------------------+---------------------+
|  1 | Test page title | This is some test page content. | 2016-10-16 21:41:49 |
+----+-----------------+---------------------------------+---------------------+

mysql> SELECT id,title FROM pages WHERE content LIKE "%page content%";
+----+-----------------+
| id | title           |
+----+-----------------+
|  1 | Test page title |
+----+-----------------+

Python3による操作

import pymysql

conn = pymysql.connect(host='127.0.0.1',
                       user='root',
                       password='password',
                       db='mysql',
                       charset='utf8')

cur = conn.cursor()
cur.execute("USE scraping")
cur.execute("SELECT * FROM pages WHERE id = 1")
print(cur.fetchone())
cur.close()
conn.close()

# (1, 'Test page title', 'This is some test page content.', datetime.datetime(2016, 10, 16, 21, 41, 49))

Python3(簡単な処理メモ)

2つのリストから辞書を作成

list1 = ['a','b','c']
list2 = [1,2,3]

dic = dict(zip(list1,list2))
print(dic)
# {'a': 1, 'b': 2, 'c': 3}

文字列から文字コードに変換、文字コードから文字列に変換

codeData = ord('a')
print(codeData)
# 97

strData = chr(codeData)
print(strData)
# a

bytesからintに変換

inputData = b'\x01\x02\x03\x04'

intData = int.from_bytes(inputData,'big')
print("{:08X}".format(intData))
# 01020304

intData = int.from_bytes(inputData,'little')
print("{:08X}".format(intData))
# 04030201

intからbytesに変換

inputData = 0x01020304

bytesData = inputData.to_bytes(4,'big')
print(bytesData)
# b'\x01\x02\x03\x04'

bytesData = inputData.to_bytes(4,'little')
print(bytesData)
# b'\x04\x03\x02\x01'

Base64エンコード・デコード

import base64

inputData = b'Hello World!'
encoded = base64.b64encode(inputData)
print(encoded)
# b'SGVsbG8gV29ybGQh'

decoded = base64.b64decode(encoded)
print(decoded)
# b'Hello World!'

変形Base64エンコード・デコード

異なるBase64テーブル(大文字⇔小文字)を使用

import base64

base64Table   = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
mybase64Table = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/'
x = str.maketrans(mybase64Table, base64Table)

inputData = b'Hello World!'
encoded = base64.b64encode(inputData)
encoded = encoded.decode('utf-8').translate(x)
print(encoded.encode('utf-8'))
# b'sgvSBg8Gv29YBgqH'

decoded = base64.b64decode(encoded.translate(x))
print(decoded)
# b'Hello World!'

RC4暗号化・復号

from Crypto.Cipher import ARC4

inputData = b'Hello World!'

key = 'password'
cipher = ARC4.new(key)
enc = cipher.encrypt(inputData)
print(enc)
# b'\xb7\x90Tb#\x1e\xe3\xc1\x13=\xcf]'

cipher = ARC4.new(key)
dec = cipher.decrypt(enc)
print(dec)
# b'Hello World!'

RC4暗号化・復号(PyCrypto無し)

def rc4Init(key):
    index1 = index2 = 0
    S = bytearray(range(256))
    for i in range(256):
        index2 = (key[index1]+S[i]+index2)&0xFF
        S[i],S[index2] = S[index2],S[i]
        index1 += 1
        if(index1 == len(key)):
            index1 = 0
    return S

def rc4(buffer,S):
    x = y = 0
    for i in range(len(buffer)):
        x = (x+1)&0xFF
        y = (S[x]+y)&0xFF
        S[x],S[y] = S[y],S[x]
        buffer[i] ^= S[(S[x]+S[y])&0xFF]
    return bytes(buffer)

def rc4Full(buffer,key):
    S = rc4Init(key)
    out = rc4(buffer,S)
    return out

inputData = b'Hello World!'
key = b'password'

buffer = bytearray(inputData)
enc = rc4Full(buffer,key)
print(enc)
# b'\xb7\x90Tb#\x1e\xe3\xc1\x13=\xcf]'

buffer = bytearray(enc)
dec = rc4Full(buffer,key)
print(dec)
# b'Hello World!'

AES-CBC暗号化・復号

from Crypto.Cipher import AES
from Crypto import Random

BS = AES.block_size
key = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F'
iv = Random.new().read(BS)
MODE = AES.MODE_CBC

def addPad(raw):
    padding = BS-len(raw)%BS
    return raw + padding.to_bytes(1,'big')*padding

def delPad(raw):
    padsize = raw[-1]
    return raw[:-padsize]

def encryptData(raw):
    temp = addPad(raw)
    cipher = AES.new(key,MODE,iv)
    return cipher.encrypt(temp)

def decryptData(raw):
    cipher = AES.new(key, MODE, iv)
    dec = cipher.decrypt(raw)
    return delPad(dec)

inputData = b'Hello World!'
enc = encryptData(inputData)

dec = decryptData(enc)
print(dec)
# b'Hello World!'

HexTextからバイナリに変換

import binascii

hexText = '0123456789ABCDEF'
binData = binascii.unhexlify(hexText)
print(binData)
# b'\x01#Eg\x89\xab\xcd\xef'

バイナリからHexTextに変換

import binascii

binData = b'\x00\x01\x02\x03'
hexText = binascii.hexlify(binData)
print(hexText.decode('utf-8'))
# 00010203

バイナリを逆順にする

binData = b'\x00\x01\x02\x03'
revData = binData[::-1]
print(revData)
# b'\x03\x02\x01\x00'

GZIPでデータを圧縮・展開

import gzip

binData = b'abcdefg'
packed = gzip.compress(binData,9)
print(packed)
# b'\x1f\x8b\x08\x00\x82`\x0bX\x02\xffKLJNIMK\x07\x00\xa6j*1\x07\x00\x00\x00'

unpacked = gzip.decompress(packed)
print(unpacked)
# b'abcdefg'

http://docs.python.jp/3/library/gzip.html#gzip.GzipFile
引数 compresslevel は 0 から 9 の整数を取り、圧縮レベルを制御します;
1 は最も高速で最小限の圧縮を行い、9 は最も低速ですが最大限の圧縮を行います。
0 は圧縮しません。デフォルトは 9 です。

GZIPでファイルに圧縮・ファイルから展開

import gzip

inputData = b'abcdefghijklmnopqrstuvwxyz'
with gzip.open('packed.gz','wb') as f:
    f.write(inputData)

with gzip.open('packed.gz','rb') as g:
    unpacked = g.read()
print(unpacked)
# b'abcdefghijklmnopqrstuvwxyz'
$ xxd -g 1 packed.gz 
0000000: 1f 8b 08 08 f3 63 0b 58 02 ff 70 61 63 6b 65 64  .....c.X..packed
0000010: 00 4b 4c 4a 4e 49 4d 4b cf c8 cc ca ce c9 cd cb  .KLJNIMK........
0000020: 2f 28 2c 2a 2e 29 2d 2b af a8 ac 02 00 bd 50 27  /(,*.)-+......P'
0000030: 4c 1a 00 00 00                                   L....

GZIPマジックナンバーは「1F 8B」

JSONを扱う

import json

jsonStr = '{"data":[{"name":"taro","age":20},{"name":"jiro","age":18}]}'
jsonData = json.loads(jsonStr)

print(json.dumps(jsonData,indent=2))
# {
#  "data": [
#    {
#      "name": "taro",
#      "age": 20
#    },
#    {
#      "name": "jiro",
#      "age": 18
#    }
#  ]
# }

JSONファイルを扱う

import json

with open('jsonFile.json','r') as f:
    jsonData = json.load(f)

print(json.dumps(jsonData,indent=2))
# {
#  "data": [
#    {
#      "name": "taro",
#      "age": 20
#    },
#    {
#      "name": "jiro",
#      "age": 18
#    }
#  ]
# }

JSONを扱う2

import json

jsonStr = '{"data1":[{"name":"taro","age":20},{"name":"jiro","age":18}],"data2":[{"name":"hanako","age":19},{"name":"yoko","age":17}]}'
jsonData = json.loads(jsonStr)

print(jsonData["data1"][0]["name"])
# taro

for data in jsonData:
    for list in jsonData[data]:
        print("name: " + list["name"] + " age: " + str(list["age"]))
# name: taro age: 20
# name: jiro age: 18
# name: hanako age: 19
# name: yoko age: 17

ハッシュ値を計算する

import hashlib

inputData = b'hello'

md5 = hashlib.md5(inputData)
print(md5.hexdigest())
# 5d41402abc4b2a76b9719d911017c592

sha1 = hashlib.sha1(inputData)
print(sha1.hexdigest())
# aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d

ハッシュ値を計算する2

from Crypto.Hash import MD5,SHA

inputData = b'hello'

md5 = MD5.new()
md5.update(inputData)
print(md5.hexdigest())
# 5d41402abc4b2a76b9719d911017c592

sha1 = SHA.new()
sha1.update(inputData)
print(sha1.hexdigest())
# aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d

PBKDF2(HMACSHA1)

import hashlib

KS = 16

salt = b'\x01\x02\x03\x04\x05\x06\x07\x08'
password  = b'\x00\x00\x00\x00\x00\x00\x00\x00'

dk = hashlib.pbkdf2_hmac('sha1',password,salt,1000)
key = dk[:KS]

print(key)
# b';\x8f\x82\x03C\xb4\xb0\xd4PT\xffD\xda\xf4\xa6l'

LZNT1で圧縮・展開(RtlCompressBuffer,RtlDecompressBuffer)

# Windows上でのみ動作
import ctypes

def compressBuffer(data):
    size = len(data)
    compressed = ctypes.create_string_buffer(size * 13)
    workSize = ctypes.c_ulong(0)
    workFragSize = ctypes.c_ulong(0)
    ctypes.windll.ntdll.RtlGetCompressionWorkSpaceSize(2,ctypes.byref(workSize),ctypes.byref(workFragSize))

    workspace = ctypes.create_string_buffer(workSize.value)
    finalSize = ctypes.c_ulong(0)
    ctypes.windll.ntdll.RtlCompressBuffer(2, ctypes.c_char_p(data), size, compressed, size * 3 , 4096 , ctypes.byref(finalSize),workspace)
    return compressed[0:finalSize.value]

def decompressBuffer(data):
    size = len(data)
    uncompressed = ctypes.create_string_buffer(size * 40)
    finalSize = ctypes.c_ulong(0)
    ctypes.windll.ntdll.RtlDecompressBuffer(2, uncompressed, size * 3, ctypes.c_char_p(data), size, ctypes.byref(finalSize))
    return uncompressed[0:finalSize.value]

inputData = b'Hello World!'

compressed = compressBuffer(inputData)
print(compressed)
# b'\r\xb0\x00Hello Wo\x00rld!'

decompressed = decompressBuffer(compressed)
print(decompressed)
# b'Hello World!'