hello everyone my name is Michael and we're gonna take a look at some ransomware now today's sample is a ransomware that goes by the name float era and it's actually a variant of vortex which was a ransomware that I believe primarily targeted Polish victims for whatever reason but let's just take a look at detected easy kind of see it's a dotnet we're not seeing any of fuss occasion detected a lot of variants a lot of samples of this ransomware were heavily skated in the past I think this was probably like an early sample that I grabbed so we can just go ahead and decompile it in dotnet dn spy so one quick note before we get too far you will need a newer version of DeeAnn spy if you have like an older version like 2.0 or something it'll have trouble D compiling some of the asynchronous calls in here I learned that the hard way so let's go ahead and let's just take a quick look at the class names so we have a ESX win seems to be the project name likely and then sharp AES crypt if we kind of drill into here we can see kind of just some names that might be interesting later on that might be the main program we have a helpers namespace that has some api's or just like wrappers for some functions possibly so let's go ahead and go to the entry point and let's see what happens when you run it so it looks like we're checking for a slash reg if you run with a register command it looks like it's going to add some registry keys to associate itself with the right-click menu that likely that's interesting or you can unregister it and it looks like our main class is going to be this a exx win auto so first off we have a log path that might be interesting to watch out for so it's at program data slash keyboard which is a that's a hidden folder and then we actually have looks like we right we do have a log file we're gonna set up and an error log file so they're pretty good about debugging info here we'll see it's gonna have the current date and time start program ooh which I'm guessing is polish for a start program looks like they have a function forget the IP it logs that to the log or if it failed to get an IP I'm guessing that's what that says and then we have it get password function we'll see it calls another namespace of a of an API to get a password we'll take a look at that later so then if we get a password if it's not null then it looks like what we actually do with it first off is we do log part of the password so if the length is more than 3 we grab 0 through 4 the first four characters of the password and put it into our log so that might be helpful later if we find like an exploit or something so let's see then they oddly enough they use a click handler to continue and it looks like they check if there's a flag to see if it started if not go ahead and start so just from the variable names that are actually pretty explicit here we can see there's a queue for path and then in dotnet you use background workers it's it's how you make a thread for offloading tasks from the UI thread and we'll see just from the names I would assume we have a path finder that's gonna find and fill in a queue likely that's the code for when it's done it looks like it logs that it completed do work it's going to be the actual working function and we'll see yep it looks for the ignored paths it checks if it's in the startup paths and all this stuff checks the extension it looks for the a es6 attention and if all this stuff checks through adds it to the queue so we have two threads running we have one that's actively finding files to encrypt and then we're gonna have another one which is going to be this encrypter that's gonna actually encrypt the files and we'll see here at DQ's off of that off that path queue and otherwise it just sits and locks it so let's see so we have text variable which is going to be the actual file path likely so we're going to throw that into a asynchronous encryption function and then we're gonna log that we encrypt it I'm guessing this is like file name and then password so yeah we add that we encrypted this file name and then the first four characters of the password again substring four of the password so that you can verify that in case it ran multiple times which file got encrypted with which password then it looks to see if there's a file name in the ransom note in the current directory if not then it writes it and if we take a look in here let's see looks like they're actually gonna log the IP and the ID okay so here's the ransom note I'll see this is all Polish and here's where the name comes from for this variant flow Tara ransomware and this weird utf-16 character set other variants use like really fancy characters with circles and some of them said vortex and that's where the original name of it came from and we can already see there they're promising that's a s 256 but as I've learned from experience never trust the ransom note spoilers in this case it is AES 256 but don't want to trust it so all right so we got the password here take a look at this function encrypt now kind of an odd thing is that they actually make this a extension what I mean by that is this the this moniker here you'll notice that we passed it only to if you're not familiar with this in dotnet we only passed it two arguments even though it asked for three but that's because it's an extension off of the string class so it's kind of a weird way of calling that so we're gonna follow this passwords what I'm gonna be most interested in seeing if they handle correctly so we have this sharp AES crypt class we're going to call and encrypt with that it looks like we're going to use an extension of dot a ES and they did pass true to the delete they're gonna delete afterward error checking if they have an error put it in the air vile all right so we're gonna pass this to the encrypt function and this is just gonna open the file and then pass it to another function with the file streams alright so let's follow this password here so we take the password and this is just a static function that then makes an instance of this class and this sharp AES crypt actually before I get too far this is actually a standardized library that looks like they included and we'll see it's a c-sharp and lamentation of the AES crypt file format so blah blah blah here's how to install it and we'll see actually this is the exact the exact code that we're seeing here so they mentioned it's an ache yes crypt file format so that might be something interesting to look at once we once we get some encrypted files so we'll see it's a file encryption software so first off it's a software you can just run to encrypt files but it's also a specific format that you can use a library and this is how we would be able to read the file we'll look at that probably later so let's follow that password and since it's a like a standardized library addicts did not have any real flaws but we'll just kind of analyze real quick what it's doing here so we're gonna take a look at the password it's gonna be thrown into this here and it looks like we just have some checking for nulls making sure we got the right arguments and this is actually a pretty explicit format that has like if we take a look back here we have like a file marker and a versioning system they have different versions of it they have like this extension section where you can add different metadata basically so that's kind of interesting and we see that right here add an extension and it looks like it uses the created by extension that is actually mentioned right here examples of a standard extension is created by so that's kind of cool actually I lost my password variable keep that highlighted let's keep a look at that so if flag six if we're encrypting so I'm assuming this is going to be encrypting first off we're going to pass the password into a setup helper and we're going to use that as our probably as our crypto container let's pass this so this right here gives us a lot of information we're using Ridge and Dale which is AES and we're using no padding CBC mode now there's a hashing algorithm I've shot 256 let's keep that in mind there's a random number generator for some reason and then an H Mac H max shot 256 so that's interesting to see that there's going to be some verification here so let's just follow our password here so they first off pass it to encode password which takes it down here we have an encoding of utf-16 and then basically the gist of this entire function is it just checks for ending this it's actually the if you look in the original source code it tells you that with the comments it's basically just going to turn the password into bytes and then check the Indian 'since it's utf-16 I believe it actually in the wide characters so there's zero zone between each so it checks the Indiana sand this block right here just flips the Indian this so it's standard I guess so we've encoded our password and we're gonna generate an Aes key one so this is interesting so we take the password and we're going to throw it through our hashing function if we remember that's shot 256 and we're gonna hash it 8,000 times okay so then we do that and that's going to generate shot 256 is going to generate a 32 byte key so that means it is AES 256 or yes so already we can tell what the encryption is gonna be looks like they generate some random IVs based on the MAC address that's kind of that's an interesting entropy to use and then they do some hashing so it doesn't really matter how they generate an IV because that's typically stored with the file which now we can kind of take a look back at the format here we can see they're gonna they're gonna store an initialization vector or the IV in the file and then they actually have 48 octet switch is actually a byte they actually encrypt an IV and the AES key basically the gist of this if you actually read more into the the library itself and the help Docs and stuff each file with this library they generate a brand new password that's securely generated and then they encrypt that with the master password that you give it that's what it's talking about encrypted IV this is encrypted with like the password that the ransomware gave the library and then it's got an H Mac here and what that is is a way of verifying that this IV and and AES key have not been tampered with because there are ways you can kind of tamper the bytes even without knowing what they are you can tamper it so that when it decrypts it becomes corrupted or something so that's a way to verify that hasn't been messed with and then they have the encrypted message which is going to be encrypted with the AES key that's encrypted here and then we have a file size just for basically a check and then we have an H Mac of the encrypted message make sure that's not been tampered with as well so it's a pretty robust container here so that's pretty interesting I don't see any way of really breaking this the actual encryption itself so let's go ahead and take a look back at that that password generation because that might be our only chance at breaking this so let's skip back jump back I might jump too far let's find worthy let's find where they generated that password so we've got this current password we'll see this is a getter ok they probably initialize it somewhere so what I'm gonna do is I'm gonna do ctrl shift our and we're gonna analyze where this is set used by the get password function okay it was further up oops so we have our current password here current password blah blah blah so we're gonna call this API get password and this is the part that an older version of DN Spy will kind of choke on so we're gonna see oddly enough they they wipe the shadow copies while you're getting the password odd segmentation but we're gonna call a web client we're gonna download a string from a URI URI there we go and we'll see here here's the quote-unquote server that they are pulling data from and if I launch it in a browser this is a legit service well actually see each time I generate it it's a completely new gigantic string now this is actually I believe 120 characters yeah says right here so it looks like there's actually kind of a format you can request different things with the alphanumeric and the length of 120 so if we like there's actually different variants of this ransomware some of them use like 80 characters there's one that's like 260 something so that's kind of interesting you kind of had to know which variant the victim was hit with so at this point you would basically the the generation of the key is not done in the ransomware so we can't like see how its generated so at this point I would suspect I wouldn't have an idea on how to really break it except for I actually back in the day I looked up you know the owner of this website and communicated with him and he was actually very generous enough to give me the source code or the kind of the guts of how he generates random passwords with this tool obviously security we did it in a very security-conscious way he doesn't log any passwords and I agreed that it's good that he doesn't but he did post on get github version of his rant random generator basically so if we take a look here you know he's got some different settings that you can actually select on his site for you know which character set to use and the length which is basically what we saw in the URL here so he's just got a REST API that basically calls this function and we'll see here it actually uses the MT Rand command so if we go to or function if we go to Mt Rand for PHP [Music] the MT actually stands for Mersin twister now a Mersin twister is a pseudo-random number generator it's not cryptic at graphically safe you'll see function does not generate cryptographic secure Val use and blah blah blah there's actually some details about where they changed the algorithm because they fixed it in a couple versions and then they had to fix it again so if we go ahead and take his code here let's just find an online sandbox for PHP and let's kind of let's kind of play with this let's see how these passwords are generated let's paste that in here and generate random dream just use the default let's go ahead and call it with 120 characters I guess so I'll execute that and we get this nice little garbage here in each count each time we run it we're gonna get a completely different different password however since this is a pseudo-rng basically and it uses a Mersenne twister there's actually some known weight some other ways we could break a Mersenne twister but in this case we don't need to we can actually actually brute force it so secret with this is it it's only using a 32-bit seed specifically because PHP by default runs 32-bit and I actually did confirm a couple variables with with the developer of the website to see kind of how this is running and we can actually set the we can actually set the seed so if we do mt/s Rand let's just set a seed of 0 run that no matter how many times I run this we're gonna get the same password so we can basically iterate through and generate you know some 32 to the power of 32 that's not how you actually do it but that's how many possible passwords there are so if we do like a seed of 100 we're going to get the same password so a couple of ways we could we could just generate all these possible passwords and attack the file format and try each key with the file however we have a little bit of a anti brute force that's built into this AES library if we take a look where it was it if we take a look into here and the let's go to the encryption go to here follow the password go down to setup helper file the password go to generate when we go to generate this AES key we're doing a sha-256 8,192 times so this is like really really slow so each time we guess a password we got a hash it over at 8,000 times and then test it we can kind of optimize and tell whether since there's no padding we can't use padding to verify that our decryption worked because remember this first key is actually encrypting the key for the file so we can't like there we'd have to decrypt that key and then try that key on the file and we've got like a lot of steps so we could optimize this by checking it against the H maxeen if that matches but there's actually kind of a critical flaw that let me kind of bypass that so to say so if we actually go back this also turns into kind of a story of how I broke this ransomware over a year two years ago whenever it was if we go back to where they are calling this let me jump back to one where they use this we're logging the first four characters so what I was able to do is we can actually use these these to optimize generate all 2 to the 32nd power passwords and narrow that down to only the ones that that start with these four characters so that drastically limits our search space now the problem with this that I ran into is the website that generates these keys is actually running off of a CMS and this code was running as a plugin so what I mean by that is he had basically other functions in the CMS that calls emptier and for its own functions internally so there's an indeterminate number and I wasn't gonna ask him for the whole source code of his entire site that's just not very he had very secure you know he's got some other function that's calling s/m tear and randomly and we'll see that completely changes our that completely changes our outcome if we call it again and that completely changes our outcome so this actually means I had to do a little bit more work so I had to actually if we if we take a look here let's remove these let's take a look at we have this FL dollar sign l if we remove one of these empty rands well notice it chopped off the first letter we still have the rest of the string is actually the correct string is just because the first M tear and call takes that first slot basically and then we trimmed it off so we kind of offset so we've created a unknown offset so kind of what I did was I took two for efficiency because PHP a little slow when you're doing this you know two to the 32 power times I took this the source code of PHP which is written in C and compiled that down and generated all the possible seeds and with an offset so I generated say you know this this ransomware took 220 characters i generate like a thousand characters and then search that whole string for those four characters that we know in the in the password file so like let's just say it was you know these four characters so I'd used this as a possible result with that offset and then generate 120 characters from here and then try that password so as a bit of work but still narrowed down from 2 to the 32 power down to like 10,000 possible passwords and that was a little more reasonable to try even with the extreme hashing and such so we can we can kind of already tell how this is breakable but let's go ahead and run it real quick so we can kind of see it in action now of course you would want to be kind of careful about proxying your virtual machine before calling off to a situ but I just this developers website it's it's kind of a just a website that's for generating passwords it's not the malware authors server however there is another call in here if we go to send API here's the actual c2 of the command server for the malware author we'll see here they they post the IP ID and then the password I'm not sure okay that's the date of encryption let's go ahead and this will also kind of show another thing you can do in in this program let's go ahead and let's comment that out so let's go let me make sure okay return the string and downloaded a string what's it returning just returning empty okay so if we right click on here and go to edit method we can actually edit the code so let's just return MD compile and we don't have to worry about leaking my IP so let's go ahead and let's go ahead and start this lets break at the entry point don't know about extension don't care and wait for it to break alright there we go so we actually because of all the initializers and all that stuff and dotnet let's put a breakpoint here continue there we go now we're gonna generate our log file there's the log file go ahead and check it out program data keyboard nothing written yet but the folders been made okay now we wrote to it and there's time stamp start alright cool let's go ahead and let's find another place to breakpoint whoops it's a boolean lets go to the click handler which is our encryption go to start let's go into the worker let's go oh yeah let's let's break here let's go ahead and continue let it start its thing running actually I probably should have broke at the getting the password alright now we're broke so let's see we can see the current password so here's the password it generated from our API and right now it's on it looks like it prioritize going after my pictures folder how rude let's go ahead and jump into that function maybe hmm didn't let me go into it it's because it's called asynchronously or something okay looks like we're gonna jump over the the Christ anthem on let's let's go after desert or desert so once again here's our password and we're gonna jump into here encrypt oops that's a string concat alright jump into here little blah open up file streams and we could jump more into here so here's where we could actually watch the encryption happening if we so choose but we already know it's a es it's got a really explicit file format here goes the the file marker version and all that stuff so since it already encrypted a file and dropped a ransom note let's go ahead and take a look at this and a hex editor and here we can see that format so we have the AES file marker let's go ahead and just finish seven let me do that side-by-side the file format so we have AES okay then we have three bytes that are that's one byte that's the version number we have a reserved zero and then we have all this stuff for the for the extension block so that extension was created date and actually if you read in here the first the first two bytes here is the length of this extension it looks like with this resolution it's not gonna show both very well but we have this is the length and actually if we look here 23 bytes matches up with our created by sharp AES crypt and this is actually the library number 1.0 0.0 0.2 - 2 - and then there's like an IV and the encrypted key which is 30 yeah 30 hex and then then we got an H Mac and then the actual encrypted file starts somewhere somewhere in here and then like at the end of the file we have an H Mac which would be probably that big and I think this is uh this is a modulus like a modulus sized flag that file size and the actual encrypted message above it so that's all fine and dandy but let's let's go ahead and see if we can just decrypt that file ourselves so I've already got since I'm cheating and I have the password here let's go ahead and grab that password we're encrypting with and let's grab you know windows let's grab our encrypted file let's tell it it's sharp AES crypt so I actually embedded that library in my tool here and decrypt and yep this is a JPEG stream so we can go ahead and save that back to my pictures I would like my chrysanthemum back please that JPEG and we have rescued our precious flower picture how fitting flow Tara so that's been an aunt and an analysis of a ransomware that does some interesting things uses a kind of proprietary format it's actually open sourced so we can analyze its format without having to like mess with the ransomware too much and that generate say key using a public service that we were able that I was able to exploit back in the day the good news is I believe the criminals behind this ransomware were caught so happy ending and the keys from the server after they did fix the flaw that I was exploiting after a while but those keys were actually seized by the cert team and released and the victims were able to use my decrypter anyway so if you have any questions or comments feel free to put them in the comments but that'll be all for now tune in next time for some other ransomware shenanigans thanks