YTread Logo
YTread Logo

Basic Windows Reversing and Attacking Weak Crypto - FLARE-On 2018

May 03, 2020
Flare-On is a series of reverse engineering challenges from FireEye because they want to find and hire smart people interested in reverse engineering. So if you need work, contact me and I will sell you the solutions. It's a joke. I don't know how far I'll go yet as reverse engineering can take quite a while and I think a lot of challenges are based on Windows which isn't really my world. Anyway. The game is simple. Analyze the sample, find the key. Each key looks like an email address and ends in @

flare

-on.com. Enter the key for each challenge in the Flare-On CTF app to unlock the next challenge.
basic windows reversing and attacking weak crypto   flare on 2018
And OHHH BOY, I got mad at this browser terminal. ../ didn't work. LS, which is supposed to list files, only shows text and even after you have moved the cd to a directory it can just zoom out. LITERALLY UNPLAYABLE. So let's look at the first challenge. Registration for the Minesweeper Championship. Welcome to the fifth annual

flare

challenge! The world minesweeper championship is coming soon and we found the registration application. You weren't officially invited, but if you can figure out what the code is, you can probably get in anyway. Good luck. And here we can download the file.
basic windows reversing and attacking weak crypto   flare on 2018

More Interesting Facts About,

basic windows reversing and attacking weak crypto flare on 2018...

When you unzip the 7zip file with the infected password, you will get a .jar file. I am 100% sure that the first challenge will be the most

basic

thing ever. So I immediately used jd-gui which is a Java decompiler and right here in the main method you find that a string is compared to the email goldenticket

2018

@flare-on.com. This is our first flag. Let's copy into the form and send the flag. Correct. COOL! We solved the first challenge. So let's not waste time and move on to the next one. Ultimate minesweeper. You made your way to the Minesweeper Championship, good job.
basic windows reversing and attacking weak crypto   flare on 2018
Now is the time to compete. Here is the Ultimate Minesweeper binary. Defeat him, win the championship and we will take you to greater challenges. Again we get a 7zip file with the binary to download. This time we got an .exe file. I figured since it's still only the second challenge, it's still super simple. So I immediately opened the IDA disassembler, I'm using the free software version 7 here, to parse the .exe. But right here, when we selected how to upload the file, IDA saw that the binary appears to be a .net assembly binary. And if you tell ida to assume it's just a normal PE compiled binary, then it looks empty.
basic windows reversing and attacking weak crypto   flare on 2018
This is because it is a .net binary. As I said, I don't really have that experience with Windows, although of course as the years go by you learn things here and there. So I know that .net programs are not compiled to normal Intel x86 CPU machine code, but they are compiled to an intermediate language and are very good to decompile with tools like ILSpy. So we can open the binary there. Ultimate minesweeper. At first it was just clicking. I haven't even run the binary yet, I have no idea if we actually need to reproduce anything. But the code doesn't seem too big and I was just trying to get an idea of ​​what is implemented here.
And of course you will quickly see names like SuccessPopup or FailurePopup and MineField etc. And I immediately opted for SuccessPopup. What else would you look at? So this class has some texts as labels, an image and a text box. The initialization component initializes those…. Components. But also things like text. Congratulations, you have won the Ultimate Minesweeper Championship. And nobody cares. Here is its price: But there is no flag here. Hmmhm… Maybe it will display as an image? Does the image contain the flag? So I was looking for that image resource, but I only found these balloons...
Mhhh... also the other images don't have a flag. But by checking the success of PopupConstructor, which takes a key as a parameter, we can see that it is assigned to textBox1. And that happens after the other components have been initialized. So that key is most likely the flag. So where does the key come from? By right-clicking on the method name, we can select Analyze, which opens this tree structure below. And here we can check where this function is used. Therefore, it is used inside the main form's SquaredRevealedCallback. This method takes a column and row integer number and checks if a bomb was revealed.
Sounds like your typical minesweeper. In case a bomb was revealed, the error popup would appear and we would exit. But if that didn't happen, then we see a number being calculated based on the row and column and then added to, I guess, a list or array of revealed cells. So every time you don't discover a bomb, the cell number, which can be calculated by row multiplied by VALLOC_NODE_LIMIT + column? Well, that variable name is strange. The calculation would make sense if it were row * number of cells per row + the column. This way you simply number each cell.
So the fact that the cells per row value appears to be called VALLOC_NODE_LIMIT seems a bit strange and therefore I think it is intended to add a bit of obfuscation or confusion. So, either way we add the correct revealed cells to this array and if they are not unrevealed, we create the SuccessPopup with the key generated by getKey, which gets the array of revealed cells. So let's look at that method. First, we classify the set of revealed cells. A random is then initialized with an integer calculated based on the first, second and third, based on the first 3 cell numbers revealed.
And initializing random like that means that this is setting the initial value of the random number generator. In case you don't know, pseudonumber generators require a seed,

basic

ally an initial value. And based on that the random numbers are generated. So using the same seed produces the SAME random values. So the creator of this challenge knows exactly which cells are correct. And so the integer that is calculated here will always be the same. So the random number generator will always generate the same numbers. At least as long as you've revealed the correct cells. This randomness can be easily attacked, but I'll explain that in a second.
Let's quickly finish that code first. So here you initialize a large byte array with seemingly random data and then fill a second byte array with random bytes from the random generator. After that we find a for loop that XORs both arrays together. And these bytes are returned encoded as ascii. So XOR decryption should reveal the key. Basically, we have an encrypted flag here and the key is generated dynamically via a pseudo-random number generator that requires the correct seed. And the right seed requires the right revealed cells. But! There is a

weak

ness. First of all, the seed is definitely a 32-bit integer.
And 32-bit integers are not that big. They range from approximately - 2 billion to = 2 billion. So only 4 billion options are possible here. Which means we can brute force all 4 billion options until we crack this byte array into the flag, which we know ends with @flare-on.com. But we can even optimize the brute force further, because we know that the seed is calculated based on three revealed cells. Which are also ordered just before. So this means that the first cell should be the smallest number, the second cell should be larger than that, and the third even larger. So these are already good limitations.
And also, based on the calculation that we have seen before, we can try to find what is the maximum quantity for a cell. This VALLOC_NODE_LIMIT number appears to be 30. Additionally, MineField is initialized with a size that is also VALLOC_NODE_LIMIT. Does that mean the maximum number for row and column is 30 or 31? Or 29? You know... erm... computing is complicated and I'm not exactly sure if the first cell here starts with 0 or 1 in the click callback handler. Whatever. Brute force doesn't get worse. So now we have even more limitations. This means that now we can simply copy and paste the getKey function and wrap it in some loops to try all the possible numbers for the first, second and third cell.
And here is the code. We have three loops, each loop is responsible for one cell. So a is the first, b the second and c the third possible cell revealed. And the maximum value for each of them is 30*30. That is the size of the minesweeper grid. And also because the revealed cells are sorted, we know that b must be greater than a, always, so we can always start with b being one greater than a. And the same happens with c. with c being at least one greater than b. And then that brute force, checking if the decrypted byte string contains flare-on.com, takes maybe 5 minutes.
Super fast…. Easy… but then I was surprised when brute force got to the end and found nothing… what the hell? That doesn't make any sense... that really confused me. So at some point I even brute forced all 4 billion possible integer values ​​for the seed, and it still didn't find it. That was very strange. So I went back to the decompiler and tried to find which are the correct cells. So I looked around a little bit and found this two-dimensional array, the minesweeper network called MinesPresent. It is boolean true or false, so it probably tells us if there is a mine or not.
And with the analysis function we can again search where it is used. Let's see where the get method is used and what this value reads. And does this GarbageCollect array exist? Which also has minesPresent boolean true or false, and that is used by AllocateMemory, which is passed in a MineField? And that one has two loops going from 0 to VALLOC_NODE_LIMIT, which we know is grid size 30. So just because these names like allocate memory, garbage collection, valloc, node_limit, blah blah, mean something, it's really confusing read the code. They refer to very different concepts in computing.
But the names deceive us. We know that the two-dimensional array variable GarbageCollect also has mine present. And this flag can be true or false and is assigned to it. So this loop loops through the entire 30x30 grid and decides based on this obscure if statement, using deriveVallocType, whether a particular cell has a mine or not. And that weird function takes r and c, which is obviously just row and cell, and does a calculation and flips the bits. And then checks if that result is contained in VALLOC_TYPES. So it's just to confuse us and obfuscate the cells that do and don't have a mine, but we won't be fooled!
We also don't have to invert those VALLOC_TYPES and figure out the row column, we can just copy and paste all the code again, make sure we get all the important numbers and then just print when we set false. So when a mine is not present. And when we run we find 3 cells where there should not be a mine. And now we can run the game, here it is, count the cells and rows and find the cells. One, two and three. AND WE WON! Here is the flag. [email protected]. But I'm still confused why our brute force didn't work.
But now that we know exactly the correct three cells, we can test our code. We can simply encode a, b and c based on the rows and columns we got. And otherwise the code is the same. Sow the random number generator, generate the xor key, xor the bytes and print the flag…. Ohhhhh…. I get it... I'm so dumb... Well, I had this whole ending prepared where I showed that even encoding the seed in a loop didn't really work and it was toggling flag and garbage. And I didn't find my mistake when I did the challenge. I also didn't find it when I prepared the video script and I didn't see it when I edited this part.
JUST NOW in my second round of editing where I draw my overlays, it clicked. I'm so dumb... the encrypted2 flags array is initialized once and the XOR operation is modifying those bytes!!! So in the next round of loop, we now have garbage in that array2 and it is no longer the encrypted flag. Then my brute force failed... now it works.

If you have any copyright issue, please Contact