遠隔操作ウイルスから学ぶ命名法
by kuippa on 2月.24, 2013, under virus, セキュリティ
遠隔操作ウイルス情報として関数名やクラス名が公開されていて(2012/12に公開)、ここに来てプログラマー界隈で注目をあつめ話題になっている。
トップ / 事件ファイル / 遠隔操作ウイルスによる連続威力業務妨害等事件 / ウイルス情報
これを見たプログラマーの感想。
「これを作ったの50代はありえてもこれを書いたひとが40歳未満はないんじゃない?」「だよねー!」という会話が某所で繰り広げられた。
ウイルスの命名法は捜査撹乱、迷彩でわざとなのか、わざとじゃないのか?で意見が割れるのかもしれないが、これはわざとじゃないと思う。迷彩なら関数名は後でf1とかで置換して難読化しておけばいいので、中途半端にやるほうが癖がでる。動けばよしとされていた時代のもっと世俗的なプログラマーの足跡をここには感じる。最近はコーディング規約で変数名や関数名フォーム名の命名規約を定める。コードバージョン管理が無かったような時代はソフトウエアの可読性や品質が問われることがなく、動けばよしと作られたプログラムが多かった。命名規則がないとどうなるか。映画の脚本でのト書きで書かれている主人公とか、犯人とかの表現が、シーンごとにかわるようなもので演劇者はシナリオを読んでも理解に時間がかかる。シナリオが長編になったり、演劇者が多くなるようなケースでは表記の統一がより重要になる。
ひるがえってこの遠隔操作ウイルス「iesys.exe」のクラス名・関数名はどうか。現代の若いプログラマーが引き笑いしながら話題にするほど凄く微妙な命名になっている。命名規約があきらかに複数入り交じっているのだ。これが意味するのは作った時代が違うコードの再利用か、そこらへんで拾ってきたコピペプログラミングだ。
さて、遠隔操作ウイルスをみてみよう。
フォームの命名方法
www.keishicho.metro.tokyo.jp/jiken/jikenbo/enkaku/image/pdf/4form.pdf
Form1という名前は自動でつけられる初期値である。やっつけで無い限り名前を変更する。これだけで、やっつけ感満載だ。
コントロールはtestBtn、insTextなどとなっている。
buttonをbtn、Insertをinsなどと母音を抜いて三文字に略すのは、コンピュータがまだ低スペックであったころにできた伝統的な手法だ。いまでも使われている。
windowsアプリでは10年ほど前はハンガリアン記法が採用されることが多かった。VisualStudio.net になってからは、そうでもないらしい。コントロール名をつけるときはオブジェクトの参照をすることが多いので、web世代になってもコントロール名にハンガリアン的に接頭辞することもある。この場合、btnRunやbtnTestとされる。命名法の目的は統一性の確保である。このプログラムではtestやinsという挙動が先に書きかたで「きちんと統一」されている。
- Form1は自動で命名された
- コントロール名には「機能名+コントロール種別(3文字)」の形式を採用
φ(´・ω・`*)ゞ お勉強 ハンガリアン記法
「iesys.exe」のクラス名・関数名
www.keishicho.metro.tokyo.jp/jiken/jikenbo/enkaku/image/pdf/4class.pdf
クラス名の命名方法
Form1、Common、Common_Crpt、Common_TCP、Fimeman、Operec
クラス名の命名方法で重要なことはそのクラスがどのような機能を受け持つか一瞥して推測できることだ。
- Form1は、めんどくさがって名前をつけなかったがメインフォームだ。
- Commonは共通で利用する関数などを配置しているものとおもわれる。
- Common_Crptは内容をみるに、暗号化のための共通クラスだろう。関数名はcryptにしているのにクラス名はcrptにしている理由はよくわからないが、4文字制限をコーディング規約に持っているところなどもあり、そいう癖が反映されたのかもしれない。
- Common_TCPはTCP/IPの通信用のクラスだろう。
- Fimemanは含まれる関数の名前をみるかぎり外部からファイルを操作するためのファイルI/0クラスのようだ。manは何故つけたし?man、man・・・、manipulationのman?(managerのmanじゃねという指摘あり。そうかも!)
- Operecはおそらくオペレーションレコードの略。その名の通り操作をロギングしていくためのクラスだろう。
クラスの構成をみていくと、メインモジュールがないことがわかる。Form1に名前を付けなくて済んだ理由がたぶんここにあって、モジュールにせずにフォームに全部機能を書いちゃえというやっつけ感がここで見えてくる。Form1以外のモジュールは他のプログラムでも使いまわしているのだろう。
関数の命名方法
Form1はツッコミどころが満載なので後回し・・・・・・。
Common、Common_Crpt、Common_TCP、Fimeman、Operecの関数の名前のつけかたをそれぞれみてみると、フォーム名の名前の付け方と同様ある程度統一されていることがわかる。どれも、「機能名+コントロール種別」になっている。これは一般的な名前の付け方で、これだけで少なくともずぶの素人でないことはここからもわかる。ちなみに語の区切りを大文字にするやり方をキャメルケースといったりするらしい。
GetUnixTimeなどは、最初が大文字になっているので、一般的なプログラミングの命名法とはずれる。最初を小文字にしてgetUnixTimeとするのが一般的だ。
ただ、これについてはGetUnixTimeが表に2つある時点で(同一関数名はプログラム内に重複することはない)、捜査官などプログラムを普段しない人がエクセルに打ちなおすなどしたときにエクセルの自動補正やIMEの補正で大文字になってしまったんじゃないか疑惑が強くでてきているので判断を保留したい。
※追記1:2つあるのはオーバーロードじゃね?との指摘をいただきました。そういうこと?だとしたらGetUnixTime でclassを書いてそうだけど、ひとつのモジュールにまとめてるのかな
※追記2:最初の大文字はMS系だとあるよというツッコミをいただきました。関数名も?最初を大文字にするのはClass名という命名規約を採用することもあるので、GetUnixTimeが同一モジュール内にねじ込まれたClassであれば辻褄があってきます。
関数名に「 _ 」を接続語にしてつないでいるものがある。_Sと_Eはstartとendの略だろう。_partialは機能が足りなくなってつくった機能拡張だろう。このプログラムの作者は関数を拡張するときに「 _ 」をつかうことにしているようだ。ここにも設計者の統一性がみてとれる。個別に関数の機能を名前から推測してみるとCryptエンコードをかけた書き込みを拾って、抜き出してseedをuid、ユニークIDから作っているのだろうか?ロジックはわからないが、ここらへんの構成にやっつけ感はない。むしろ何回か使いまわして機能を洗練させた感じだ。
面白いのがaddKaigyo、removeKaigyo、プログラムを実行してみたらhtmlの改行コード<br>やらsjisファイルの改行コードが邪魔でデコードできなかったので、後から足したような印象だ。本当にreplaceしたいのがcrlfのような改行コードならこんな関数化する必要はないと思われる。共通処理にSanitizeもあるので、若干web操作系の処理がもぐりこんでいるようだ。
接頭語にasyがついているものがあるが、これはなんだろう??? 意味がわからない…。
んー。asy…asyGetRequestとgetRequestが似た名前であるところを見ると、遠隔操作とかでgetRequestを呼び出すラップ関数なんだろうけど、mstscとかrshとかのリモートコマンドの犯人なりの名称なんだろうか?asy,asy,asy,,,access ,accessory? あー、accessoryかな??わからん。
※追記:コメントでご指摘いただきました。非同期通信のasyncじゃね?と。おお、たぶんそう。
なんでこのご時世に「したばらば掲示板」がつかわれたかわからないかったが、コードの再利用ということであれば合点がいく。Form1以外の関数群にはある程度の統一性があり、それなりに練られていて、機能が足りなくなって拡張したなどの手を入れられメンテナンスされてきた時代感がある。今回のためだけに作ったのならcommonなど分ける必要もないし、このキーロガー的な部分なんて完全に他でつくった奴の使い回しだよね。たぶん。もしかしたら何かしらのスケルトンを利用したのかもしれないけど。
で、ここまで見て気になるのが、set系が見当たらないこと。あることはあるが、そういう意味のsetではない。
つまり、プログラムがそもそもクラス化されていない事を意味している。これってば、javaの人が書くような特徴じゃないし、C#で育った人でもないわーと強く思う所以。
で、問題児のForm1。つっこみどころが多すぎて・・・・・・。
まぁ、上からいきましょうか。
一番うえのfetchMyThreadIDですが、これにすごい年齢を感じてしまうのは私だけでしょうか。C#あんまさわったことないんだけどfetchってあったっけ?最近fetchって使います?なんか汎用機から固定長で渡されたデータやら、ADO接続だとかで初期のoracleデータベースとかに接続して帰ってきたデータを変数やら配列に格納するのにぶんぶん回すのによく使われてた気がするんですが、最近はfetchなんかせんでも、ライブラリとかが連想配列に分解してくれるので、いらんのではないかと思うんです。
でも、今回のように掲示板をクロールして自分で割付が必要な場合はfetchに似たような処理が必要でしょう。でも、kakikoShitarabaとか、addKaigyoとかの「おもいきりのいい命名」をしてしまう人が、fetchって命名するかね?・・・と。ここから導かれる結論は、こんにちはおっさん!です。
※追記:Bootstrap(twitterのオープンソースデザインテンプレート)で最近使うよという指摘ありました。
次に関数名をアンダーバーで接続するような命名法ですが、あまりお目にかかりませんが、PHPのZendの定数とかがこういう命名規約だったと思います。見かけなくもないけど、ほとんどみないです。
ins_end_forceとかはなんかもう一周まわってる感じがします。あまりに他の命名方法と統一感がありません。フォーム名などを規則性をもって命名をした人と同じ人物が同じ時期に書いたとは到底思えんのです。こんなのを織り交ぜちゃう人なら他の関数群も全体的にこんな命名方法になり、もっと統一感がない感じで逆に統一感がでます。他があながち揃っているからこの異質さが目立ってきます。
※追記:_で接続するスネークケースはrubyやpythonでつかうよという指摘がありました。rubyのrailsとかだと英単語が今回のような名前の付け方だとスキャフォールドが機能しないのではないかと思います。英単語の単数形、複数形などが重要でruby使いから来た_接続ではなさそうです。というかrailsの匂いが関数名からは微塵も感じません。pythonの匂いがするかどうかは私がpythonほとんどわからないので、わからないです。
φ(´・ω・`*)ゞ お勉強 スネークケース、キャメルケース
XXXXX_Tickはまだいいです。Visual Studioでフォームイベント系が確かこういう風に命名されるので。_clickなどイベント系のメソッドはこのような命名法がされます。こういうイベント系のメソッドと関数がごっちゃになるのが嫌なのでみんなモジュールとかを分けたりする理由だったりします。ここではごった煮になっています。
Form1の構成をみる限り、Form1を書いた人と、他のモジュールを書いたひとが同じとは思えないほど大雑把でいい加減です。Form1は設計なしにいきなり書きだしたのでしょう。デバッグ兼ねて動かしながら作ってますよね。もしかしたら、何か下敷きとなるプログラムがあったのかもしれないなとおもいました。
_getElementByIDとかなんなんでしょうか(怒)
ひっくり返っちゃいますよね。ここらへんjavascriptから来てる命名ですよね。(※注:javaとjavascriptは別物です。)
javascriptとかサーバースクリプト系言語ではrubyでいうhelperクラスのようなグローバル関数名の頭にアンダーバーをつけて、グローバルアクセスの関数や変数であることを区別する書き方があります。でも、そのような関数名の名前の付け方を採用するなら、この関数はForm1などに置いてはいけませんし、ここで_をつけるなら、Common関数の全部が_で始まるべきです。そうせずに_getElementByIDだけなのは、なぜでしょう? 他人が書いた関数のコピペだから?
※追記:_始まりはProtectedとかアクセス修飾子じゃねぇのと指摘あり。もちろん、そのような使い方をすることがありますが、アクセシビリティレベルの修飾子がここにしか出てこないのが疑問に感じた所以です。
φ(´・ω・`*)ゞ お勉強 アクセシビリティレベル 修飾子
_getXXX系の関数は名前から推測するに、おそらく「したらば掲示板」のHTMLのDOM解析などをしているのでしょうが、だとすれば機能としては、Common_TCPにまとめて格納されてもいい関数です。なぜDOM解析をForm1でやった!という感じです。おそらくform1に埋め込まれたwb(ウェブブラウザ)にCommon_TCPからアクセスするにはform1.wbを呼ばなければいけないために、めんどくさいから関数機能そのものをform1に移動させたのだとおもいます。Common_TCPで機能をわざわざまとめ外出しにしたひとと同じ人とはおもえませんね。他にもkakikoMyThreadはForm1にいるのにkakikoShitarabaは外出しされている。なんでしょう、この途中まで統一されてたけど、メンテナンスで後から手をいれられてぐちゃぐちゃにされた感は。やはり同一人物とは思えません。
Form1の関数の数も多いですが、タイマーイベントの多さとか、なんかものすごいやっつけ感がつたわってきます。
ここからくる感想と結論は、kakikoShitarabaはすくなからず昔につくった再利用で、kakikoMyThreadは今回中身を改変して利用したからなのではないでしょうか。
ins_end、ins_end_forceや_getElementByIDは今回のプログラムの中ではどこかしらかのコピペ改変っぽい。
プログラミングの変数名や関数名のつけたにはいろいろなお作法がありますが、お作法はなんのためにあるかというと、開発者がわからなくならないようにするためです。
話題の遠隔操作ウイルスを見るとせっかく統一性をもって開発をはじめたのに途中でめんどくさくなって動けばいいやという強引さが見えます。もしくは全くの他人が途中から書き足しているかです。テストケースを書いた形跡もなければ、名前空間や構造体へのアクセスの関数もみあたりません。その他の命名方法を見る限り、素人ではなさそうだけど、結構ベテラン臭がかおるオブジェクト指向以前の人間の匂いがするねーというお話しでした。
まあなんでもかんでもファイルつくりまくるjavaな人の書き方ではないよね?
※追加:わたしは、C#は8年ぐらいまえにパッケージソフト開発で書いたことがあるぐらいでさっぱり覚えてません。ごめんなさい。.net詳しい人が今回のエントリーを見てよくわかってねぇやつが書いていると言っているぐらいなので私は容疑者リストからは外しておいて下さい。
また、冒頭でコピペって書いてしまったので、今回の沿革操作ウイルスがコピペで動くような印象を与えてしまったかもしれませんが、これはコピペでは作れません。書こうと思えば書けるけれども、めんどくさいからという理由で、きちんと書けば書ける人のいい加減なコピペです。じゃなかったらバーストモードとか実装しねぇから。それなりの上級設計力を感じます。
あと、これじゃ勉強できないという人がいたので、勉強ポイントでも書き足しておきましたφ(´・ω・`*)ゞ
※宣伝:第183回 三鷹プログラマーズカフェは遠足に出まして、高円寺こけむさズで開催されます。
↑ 遠隔操作ウイルスの事はやるかしらんけどきてね。
3 Comments for this entry
3 Trackbacks / Pingbacks for this entry
-
プログラムソースコードを読めば、その人の人となりがわかる | ろはpro
3月 7th, 2013 on 12:51 PM[...] 遠隔操作ウイルスから学ぶ命名法 | Knowledge base func [...]
-
江川紹子ツイッターまとめ | 有名人最新ツイッターまとめ
8月 13th, 2013 on 8:10 PM[...] @kuippa 名前の付け方でっす。でもヨタ話なので話半分でお願いします。 http://t.co/y5y3sW65Sq [...]
2月 27th, 2013 on 3:59 PM
>接頭語にasyがついているもの
恐らくasyncの略で、非同期ソケット通信しているのではないでしょうか。
個人的には.NET以前のVBを良く使っていた人の匂いがします。
フォームに直接コード書きまくるところやタイマーを使ってるあたりが何となくですけども。
2月 27th, 2013 on 5:53 PM
あっ! asyncか。なるほど、そうですね。辻褄あいますね。
タイマーイベントが多いのは、タイマー系のプログラムを迷彩にしていたからというお話しもあるようですが、それにしても多いですね。
オブジェクトを生成しないで、パネルコントロールに頼るあたり、私もこれを書いた人はそれこそVB6、もしくはもっと上の世代でプログラムをやっていたひとのように見えます。
3月 7th, 2013 on 9:44 AM
>_getElementByID
アクセス修飾子がprivate, protectedなメソッドなのでは?