 Welcome to Melv analysis for Hedrox. I often get asked about easy to analyze beginner samples. And my recommendation is that you have a look at APT Melvier because oftentimes, not always, but oftentimes these are a little bit easier to analyze since they are targeted so they don't have to put that much work into evading antivirus software so the very nature of them being targeted and not mess spread to others means that the antivirus software usually don't know these Melvier before when they see them the first time. So for today's video, we're going to look at an APT Melvier from TOLA which is called Pilovac. There's a very nice unpacking chain and it has some slight de-opfuscation that you need to do and it's excellent to write a Python script or a Cybershaft recipe or binary refinery snippet so you can extract the C2s in the end. For this video, we are going to use binary refinery but I highly recommend if you want to train use the sample, try it yourself first and then you can check how I did it in this video. Let's see. So we put the sample in the hex editor and immediately we can see this is an office document so I'm going to proceed with actually I'm going to check the strings first and then we are going to proceed with only tools. Interesting part here. We see C users drawn pictures picture one and here's some odd string and these look like encrypted strings. That's going to be interesting. This is a JavaScript file referenced in this office document. So that's all. We see also your auto open and auto close. So let's take a look at the embedded VBA code that I expect there. So standard Microsoft Office Word. Let's do this. You see already here it detects the use of XOR. It detects potentially base 64 encoded strings and auto open, auto close is being used. Also W script show and run to run maybe the JavaScript file that we saw that may form.js. There's already a lot of things we can go to check out. Let's pipe this into file. So here we have the VBA script. Change the language to that. So the variable names, they don't make sense. So to make sense out of it, we should rename them. So here I already see there's some XOR going on. The first thing I'm going to do is I'm adding some spacing and tabs. So it's more clearly visible where functions start and end. For instance here we see an end function which starts here. So we can put tabs here and here's a loop. That already looks like some form of decrypt function. So let's call it decrypt. Based on how this is used, this is going to be the data and this is going to be the key. And this is the size. So it's running from 0 to size minus 1. So that's our decryption loop. Let's see where it's being used and it's here. So whatever's put in here is going to be decrypted. So this is our data. This is our size. Can rename this again. Another for loop. We see here now this is our size and we want to get. Now the question is where the data comes from. So let's see where it is being applied. So here this looks interesting. This is some sort of, let's see, there's our string that we found. And this is a regex matcher since we create this regex expression object here. And this is the pattern for the regex. It's a simple string that executes here on another string. This is the result of the match, actually the match results for, that's actually all of them. And this is then one of them. So we have here the match result index because of this line. Where does this go to? To the very end where it closes the document. So this is a kind of exit label. So this is the interesting part where a string is being used for the regex and it's a string conversion from this part into Unicode or from Unicode, I'm not sure. This is a byte object or byte array. And it's gonna be got from this active document full name. So it's getting the own file here, active document full name as this one or self file, something like that. And this is byte, byteStata, something like that. And that is the size of the byteStata size. I guess it should make a little bit more sense. We are currently in auto close. Where does this end? It ends here. So we are here in auto open. Let's see where this ends. So this goes to the very end. Let's put it like that, exit sub, end sub. Miss any, no. I don't think so. Another if and rest is not then interesting, I guess. So this is like the JS path. This is a folder, Microsoft Windows. Let's name it metal folder, file system, object. And now we can see the full picture basically. We see that it is looking in the own file for the string. We saw the string and then it's taking the next data of that size and decrypting innovative XOR afterwards this encrypted data here. Encrypted data is put into this file, which is the mail form JS file. So, or in data, file, object, something like that. It's not encrypted anymore, is it? And interestingly, when this thing is run, the JS, the mail form JS file, it puts there an argument that looks like that. So this might have some significance, we will see. Let's replicate this and just decode the data for the, so we get the JS file. Of course, we could also execute it, but I don't have any office on the system, and this is easy enough to simply decode. I would like you to take this as a moment to teach you binary or binary, specifically the ALU unit, because this is a very versatile unit for any form of custom decryption or encryption. First, let's grab the data from our file. So for that, we do the emit command, verify this is our file. And now we want to find the same string we are finding here using regX, but what I actually want to have is the data after that. So we already know that after that, there is size 15387, that's the data we want to get. So we put a wildcard here of that size, so we can grab this data and we want the first match. See what we get. So this is our data and that's the size. So if we set zero, we should get the whole match, including our weird string. So we can see indeed if we use the other one, it starts here, so this is working right. Now we can start the decode operation. This is not a simple XOR because here in this instance, the XORP has an initial seed and then it is changed in every iteration. So every iteration, the XORP is going to be computed this way. So this is perfect to be used for ALU. Like generally, if it wasn't changed, you would simply do XOR with 45, right? If it was the same key overall. But since it doesn't happen, we use this command. We are setting the seed for the key, which is 45. We want to calculate the XOR. Now S stands for the internal state that this state machine currently has and B is the current block, so the current data block. And we also got to put an epilogue because after the XOR operation, the key is changed. So we are doing this as well. We change our key. So this is changing the internal state by calculating this. So it basically sets the new internal state value. Let's see what we get and we get a Jscript file. You can now dump this file, dump what was called mailform.js. So that's it with the first part. So let's continue the analysis of the Jscript file here. Before we do that, I'm going to clean up a little bit on the desktop. Put the things here that we don't currently need. And I'm going to open this file in Notepad. So when checking our decoded script, you will notice that it is still messed up. While the beginning looks good, roughly from here it starts to be jumbo again. So let's check where this roughly happens. If you open this in a hex editor and you go to roughly 100, you will notice that this is starting to not work anymore at this point. So at 256 bytes roughly. And that's probably not a coincidence. So we need to fix this. Now usually I would try to find the error or something here in the module. And I tried the obvious of by one errors, but if you check the help of the LAU unit, you will see one option here that's called precision. And it says that this indicates the size of the variable that I used for computing the result. And that by default it's equal to the block size. What's the block size? We didn't specify it. So the default is one. It's one byte. If we say that the precision is zero, we have arbitrary variable sizes, which is what is being done in the algorithm here. So we're going to fix this to use the precision zero and see if this is any better. So we snip now at 254. You see now it's working. So let's dump this and here it is. So this is our script file. And one thing you may notice already is the eval expression here. We scroll down at some point, there is some mess of data again, though I don't think we did anything wrong with the decoding now. It's openastexplorer.net. So generally you will be greeted with a screen like that. So this is the abstract syntax tree parser Bible for JavaScript. And we are going to enter the code here starting from that point. It says unexpected token, so I guess it's missing brace. And here we can see the abstract syntax tree. We can see there are four function declarations and one try statement. Now the relevant part needs to happen here because the function declarations do not execute themselves. So when we want to see if there's anything interesting, so I would actually then check first in this area and see what it is doing. Furthermore, we can add the transform for bubble and get a pretty print of our script. So let's copy and paste this pretty print. And now look into the try catch statement. Oh, there is something wrong. And that is the transformation that is being done here. We don't want this transformation. So this reverses identifiers turn on prettier. So okay, that is better. And this is being executed. Now we could do the same again. We could try to reverse the encryption algorithm that is being used here. That looks like RC4. We can recognize this from the 24 loops going up to 256. So what is being put into that? It is this and that's coming from the arguments. So actually, we know this part already. This is the key to executing this or making this five work is here. So this is the RC4 key. And what is it going to do? So it's using this argument. This gets our data and that's the data. So actually, we should use binary refinery. That's too easy to not do. So let's use binary refinery for that. So this is a long string here. And we are going to use the mailform.js.veer. Since this is a string, we can just carve string and we want the single longest match. Let's see what comes out of that. That looks good. What we want to get rid of now is the quotes. So let's snip off the start in the beginning of this. That was the step variable. Okay. That's fine. Base 64 encoded. Then we get a jumbled mess. Better look with peak. And now we have an RC4 encryption with this key. Here and we get our script. And there we are. Again, let's pretty print this. And now we have the mega code basically in plain text. There's some encoding going on, but that is for the response of the server, which is not up anymore. And here are some strings we could decode to make them readable again. So let's do that. There's an easy way to do that. We look into, let's put this code in here actually. So it's the same here. Here we also have this problem that some encodings could be a little bit better when you check the extra value. You see that the raw value is like that, but the value is like that. So if we just delete this extra information, we will get back the raw value. We're just going to delete for the string literal, sorry, string literal delete pass node extra raw. Now we get all the raw values. Let's compare. So we had, for instance, app data Microsoft Windows. And this is what it looks like now. So similarly, if you go to this function, wscript, active x object is now readable. So let's use that. And here we are. I'm not sure how interesting it is now to go through this code here. I think it's pretty straightforward what it does. But we unpacked everything and we can now use this to actually analyze the back door here. You can see that it has some commands here. These are the commands that receives from the server. And whenever something is put as work, it will execute the receive data with. Let's see. So it's a very basic back door in that sense. That's the data it receives. And here you see the run command. So the data it receives, it will simply run. So we got the final back door. Now that we got the back door, let's put everything together to write one binary refinery script that can extract the C2 servers for us. We're going to get back to this very first sample and chain the other commands into that. So we got the carve strings, the snip, base 64, Rc4 with this key. Let's look at it. Wait, it's string not strings. So it's, of course, we need to carve the biggest. Let's look up carve. So what kind of formats do we have? Okay, I think it was one of the extract commands. Let's check the documentation. So it's XTP with which will carve common indicators. Let's see what we get from that. So this looks good. And now we can also specify that we want to see only the URLs. So that would be XTP URL. And that's how we get the C2s. So we are done. We analyzed the sample. We found the C2. We have a snippet to extract it. And yeah, let me know what you think. And if this kind of sharing of easy samples helps you along the way. If you want to learn method analysis from the ground up, then check the link in the description below. There's a link to my Udemy course for beginners. It contains 11 hours of video content and the link is the coupon link. That's a little bit cheaper for you. Then buying it from Udemy itself. So check it out and maybe I see you there.