読者です 読者をやめる 読者になる 読者になる

Volo di notte

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

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

IoT Security

背景

先週の金曜日(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] タスクトレイ アイコンのツールチップ テキストを取得する

Python Windows

タスクトレイ(通知領域)に収められているアイコンのツールチップには、タスク自動化などで使える情報がたくさんあります。 例えば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)

WAVファイル, MP3ファイルを無音部分で分割

Python

仕事で音声ファイルを無音部分で分割する必要がでてきたけど、 Audacityでやっても分割前の空音が残ってしまったり、保存時のファイル名指定が面倒だったり、 なかなか思い通りにならなかったのでPythonで処理しました。

必要なものなどのメモ書き。

環境

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

AnacondaでFFMPEGmenpoさんが公開しているので、これを使った。

conda install -c menpo ffmpeg

また、pydubはpipでインストール.

pip install pydub

ファイルの読み込み~無音部分での分割

pydubにsplit_on_silenceというクラスがあるので、これを使うだけ。

from pydub import AudioSegment
from pydub.silence import split_on_silence

sound = AudioSegment.from_file("./untitled1.wav", format="wav")
chunks = split_on_silence(
    sound,

    # 1500ms以上の無音がある箇所で分割
    min_silence_len=1500,

    # -30dBFS以下で無音とみなす
    silence_thresh=-30, 

    # 分割後500msだけ、無音を残す
    keep_silence=500
)

# 分割数の表示
print len(chunks)

表示された分割数で所望数通り、分割されているか確認してね。 silence_threshやmin_silence_lenのパラメータで多少の調整は必要。

ファイル名リストの作成~保存

作成したいファイル名が連番でなかったので、リストで作成(ここは好きにすればよい)。 その名前に従って分割した音声ファイルを保存。前節の分割数とfilelistの要素数が同じになるように注意。

filelist = ["file_hoge1","hogegennhogehoge","foo_bar","lucky_you",]

for i, chunk in enumerate(chunks):
    chunk.export(u"./分割/"+filelist[i]+".wav", format="wav")

Easy peasy Japanesey!