Volo di notte

お勉強の成果メモや日常のこと

夜間飛行へ移行中です

 

WindowsにSWIG導入

SWIG (Simplified Wrapper and Interface Generator) は、 C/C++ で書かれたプログラムやライブラリをPythonJavaなどのスクリプト言語から使えるようにするためのツール。PybindやCythonなど、類似品もありますが、2次元の物理エンジンpybox2dがSwig依存でしたので導入。

MINGW+MSYSの導入

まずSWIGをビルドする環境を整えます。

おおよその流れはこちら ⇒ MinGW+MSYSのインストール(2014年5月) | The Textbook of RayTracing @TDU

  • g++
  • MinGW AutoTools(autoconf, automake)
  • MYSYS ( bison / flex / tar / gzip / bzip2 / base / autoconf, automake)

は必ず必要なのでチェックを忘れないようにしましょう.

また、環境変数のPathに

の追加を忘れないように!

SWIGとPCREの準備

  1. Githubからswigをクローン (C:\MinGW\msys\1.0\home[ユーザー名]に展開)
  2. ~/Swig/直下にPCREからダウンロードしてきたtarファイルを置く (pcre-8.39.tar.gzまたはpcre-8.39.tar.bz2など)

SWIG/PCREのビルドとインストール

前項の続きから、

  1. “C:\MinGW\msys\1.0\msys.bat"を起動
  2. ~/Swig/Tools/pcre-build.shを実行し、PCREをビルド
  3. ~/Swig/autogen.shを実行⇒configureが生成される
  4. ~/Swig/configureを実行
  5. makeでビルド [make; make install]
$ cd ~/Swig
$ ~/Swig/Tools/pcre-build.sh
$ ~/Swig/autogen.sh
$ ./configure
$ make
$ make install

これで、C:\MinGW\msys\1.0\home[ユーザー名]\swig.exeが吐き出されるので、パスのとおる所に移せばインストール完了。 とりえあえず、C:\MinGW\binにコピーしておきました。

FAQ的な

Error: Unknown directive が出る

Error: Unknown directive ‘%exception'や Error: Unknown directive ’%pythoncode'が吐き出される場合ですが、~/Swig/Lib/の中身が参照できるところに入っていますか?
下記いずれかで直ると思います。

  1. make installを忘れない
  2. swig.exeからの相対パスが./Lib/になる場所にLib以下をコピー
  3. C:\MinGW\msys\1.0\local\share\swig\3.0.11以下にLibをコピー

参考の記事:// Swigが参照するパスについて

SWIG Library

Configure中にsyntax error near unexpected token ‘fi'がでる

syntax error near unexpected token ‘fi’ · Issue #815 · swig/swig · GitHub

環境によっては出るようです。

Line 5855 and line 5975 have “else” tokens that should be removed.

とあるようにfiの直前のelseを消しましょう。空のelseがあるのが良くありません。

代替手段(2017-03-01追記)

Anacondaでもswigの準備があるようです

conda install swig

いろいろ苦労したのがコマンド1つで解決

IoTデバイス感染型 DDoS攻撃ボット "Mirai"

背景

先週の金曜日(10/21)にアメリカのダイナミック・ネットワーク・サービシズ(Dyn)が大規模なDDoS攻撃を受けてダウンした。DynはTwitterをはじめとする多くの企業が使っているDNSサービスを提供しており、現地にいた友人のよるとインターネット接続への影響はかなり大きかったとのこと。

f:id:Chachay:20161025221005p:plain

この攻撃の元になっているのは"Mirai"と名前がつけられているマルウェアで、IoT機器を乗っ取って攻撃を仕掛けるというものらしい。IoT機器と呼ぶと難しいですが、ネットワークカメラとか皆さんの好きなRaspberryとかあれですよ。

Grandstream GXP1610 IP電話機 1-SIP LCD

Grandstream GXP1610 IP電話機 1-SIP LCD

この間のCEATECもIoTを大きく掲げて、どんどんやろうぜみたいな雰囲気ですが、インターネットにつながった機器が増えてくると(場合によっては管理されずに野良化しているやつもいるはず!)、世界中のネットワークカメラが政府サーバに攻撃を仕掛けたりするディストピアが目に浮かんだりします。

現状ですら、ネットワークにつなげて2分もしないうちにマルウェアに感染する状況にあるといいます。

そのカメラは、12ドルのスマートウォッチを売ってる会社の、安物のノーブランド品だ。そういうものは、ファームウェアのアップデート、あるいは単純にパスワードの変更だけで問題が解決するが、やり方を知らない人もいるし、技術の分かる人でも2分でやるのは無理だ。 セキュリティカメラがWi-Fiネットワークに接続してから98秒後にマルウェアに感染した | TechCrunch Japan

最先端技術の分野ではどこの国も同じでしょうが、技術をあんまりわかってないおじさんたちがセキュリティに投資せずにどんどんやってっちゃう心配もなかったりしないでもない上に、長幼の序が厳しいこの国だと、さらにひどいことにならないかなという心配まで浮かんできた次第であります。

Miraiくん解体

その一方で、このMiraiのソースコードgithubで公開されるなどで話題を呼んでいます。読んでみると今後のIoTセキュリティどうするのという対策に役立つと感じたので、少しお付き合いください。

github.com

疑問1 "どうやって感染したの?"

とりあえず自分がお世話しているようなラズパイやネットワークカメラに感染する…というのはどうやってるのだろうという疑問ですが、IoT機器だけに能動的な行動、エッチなサイトを閲覧していたとかメールの添付ファイルを間違って開いちゃったとかいうのは原因ではなくて、どうもパスワードがイモだったからのようす。

どこかに感染したMiraiがパスワード設定の緩い別のIoT機器を見つけて、ディクショナリーアタックを仕掛けては侵入・感染し、次々に勢力を拡大しているそうです。

Gigazineさんが既報のとおりひどいパスワードを設定している人、(セキュリティ感覚が低い機器の)デフォルトのパスワードのまんまの人が乗っ取りにあってそう。

gigazine.net

一部ダメなパスワード例を抜粋しますので、良かったら確認してみてください。

root
パスワードなし,xc3511, vizxv, admin, 888888, xmhdipc, default, juantech, 123456, 54321, root, 12345, pass, 1111, 666666, password, 1234, klv123, klv1234, Zte521, hi3518, jvbzd, anko, zlxx., 7ujMko0vizxv, 7ujMko0admin, system, ikwb, dreambox, user, realtek, 00000000
admin
パスワードなし, admin, password, admin1234, smcadmin, 1111, 1111111, 1234, 12345, 54321, 123456, 7ujMko0admin, 1234, pass

(バリアントが出回ったら、この限りではないでしょうが)抜け漏れが心配なら原典のここの185行目までです。

疑問2 "感染するとやること"

1. 感染→住みやすいお家を作る

いったん感染すると、telnetサービスなどをkillしはじめて、外からのアクセスをシャットダウンするようにしていきます。一度感染されると、遠隔でロールバックや復旧ができなさそうなのやっかいだな。

山奥に設置したIoT機器のコントロールを取り戻すRPGとかそのうちできるで。

Mirai-Source-Code/killer.c at 6a5941be681b839eeff8ece1de8b245bcd5ffb02 · jgamblin/Mirai-Source-Code · GitHub

2. DDoS攻撃

HTTP flood, SYN floodなどだいたいなんでも実装されているそう。 あんまり興味ないので深追いせず。

https://github.com/jgamblin/Mirai-Source-Code/blob/6a5941be681b839eeff8ece1de8b245bcd5ffb02/mirai/bot/attack.h

3. 次の感染先を探す

GEなど特定の企業やペンタゴンを除いたランダムなIPアドレスを除いた広い世界にランダムにアクセスしていき、疑問1で言及したような、お鍵のゆるい機器に侵入。以下繰り返し。

4. そのほかの機能は?

もう少し読んでみないとわかりませんが、こんなところじゃない?

おわりに

IoTするならセキュリティ勉強しよう。

おうちで学べるセキュリティのきほん

おうちで学べるセキュリティのきほん

あと、IoTマルウェアに日本語の名前(一説によるとアニメ系?)つけるのはやっているみたいですね。

mokake.hatenablog.com

[Python] タスクトレイ アイコンのツールチップ テキストを取得する

タスクトレイ(通知領域)に収められているアイコンのツールチップには、タスク自動化などで使える情報がたくさんあります。 例えばGoogleフォトバックアップでは「写真100枚をバックアップしました」などとお知らせしてくれます。

これをPythonで取得して使えるようなlist形式にします。

ツールチップのイメージ

f:id:Chachay:20161004215724p:plain

2つの通知領域

Windows 7以降には、常時表示される通知アイコンと通常隠れていて表示をOn/Offできるものがあります。

(それぞれの切り替えには下記を参照してください)

Windows 10 タスクバーの通知領域のアイコンを非表示にする

それぞれのアイコンのツールチップは別々のWindowにぶら下がっており、Spy++などでハンドルを見ると

常時表示される通知領域
Shell_TrayWnd > TrayNotifyWnd > SysPager > ToolbarWindow32 以下の"ボタン"としての性格
通常非表示の通知領域
NotifyIconOverflowWindow > ToolbarWindow32 以下の"ボタン"としての性格

を持つことがわかります。

ツールチップテキストの取得

WindowsAPIをふんだんに使うので、まずPython for Windows Extensionsが必要になります。Anacondaの人は、最初から入っていると思います。

ツールバーのWindowハンドルをFindWindow/FindWindowExで取得したら、 あとはメモリからテキストを読み込んでいくだけの簡単なお仕事になります。

# -*- coding: utf-8 -*-
import win32gui, win32process, win32api, win32con
import ctypes, copy

PAGE_READWRITE = 0x04
MEM_COMMIT     = 0x1000
MEM_RESERVE    = 0x2000
MEM_RELEASE    = 0x8000
TB_BUTTONCOUNT = 0x418
TB_GETBUTTONTEXT = 0x42D

tipslist = []

def GetTips(hWnd):
    threadId, processId = win32process.GetWindowThreadProcessId(hWnd)

    pHandle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, 0, processId)
    VirtualM = ctypes.windll.kernel32.VirtualAllocEx(pHandle.handle, 0, 256, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)

    # タスクアイコン数取得
    count = win32api.SendMessage(hWnd, TB_BUTTONCOUNT, 0, 0)

    for i in range(count):
        res = win32api.SendMessage(hWnd, TB_GETBUTTONTEXT, i, VirtualM)
        STR = ctypes.create_string_buffer(1024)
        print i,res, STR
        ctypes.windll.kernel32.ReadProcessMemory(pHandle.handle, VirtualM, STR, 1024, 0)
        tipslist.append(copy.copy(STR.value.decode('cp932')))
        print STR.value.decode('cp932')

    ctypes.windll.kernel32.VirtualFreeEx(pHandle.handle, VirtualM, 0, MEM_RELEASE)
    ctypes.windll.kernel32.CloseHandle(pHandle.handle)

# 常時表示のタスクトレイからWindow Handle取得
hW = win32gui.FindWindow("Shell_TrayWnd", None)
hW = win32gui.FindWindowEx(hW, 0, "TrayNotifyWnd", None)
hW = win32gui.FindWindowEx(hW, 0, "SysPager", None)
hW = win32gui.FindWindowEx(hW, 0, "ToolbarWindow32", None)
GetTips(hW)

# 通常非表示のタスクトレイからWindow Handle取得
hW = win32gui.FindWindow("NotifyIconOverflowWindow", None)
hW = win32gui.FindWindowEx(hW, 0, "ToolbarWindow32", None)
GetTips(hW)
    
# 取得した結果の表示
print("\nタスクアイコン数:", len(tipslist))
print(tipslist)