Let's continue with the analysis, so we know that this is the correct function.
We can rename it.
Just before we can rename it, we have to actually create a function because at the moment it is undefined.
So to create a function, you need to go back to the place where this function is found, which is over
here.
The start of the PUSH -.
And how did I get here?
I go to the string search.
Go back to the Unicode for the wrong message.
Over here.
And then I went back to the cross-reference.
Double-click on it.
And I land back over here.
Correct and wrong.
If you want to see the rest of the three dots here, you can use this and click on the three dots.
It will highlight the operator and you can drag.
And now you can see the rest of the three dots.
So now we have to look for the start of this function.
This whole thing is contained in a function.
So you need to scroll up and look for the PUSH
-, which marks the start of this function.
PUSH
-.
There you go.
So once you have found the PUSH, you can recreate a function here by right-clicking and select Create
Function.
So now you have a function.
And now you can double-click on this, go back to the Decompile, and now you have a proper function rather
than undefined function.
So now you can rename it by right-clicking or pressing L on the keyboard and rename it.
And we can call this CheckSerialKey.
We could rename it anything we like,
actually.
Right.
Let's now analyze this function.
We will start from what we know.
We know for sure that this iVar is important.
It needs to be zero in order to be correct.
So iVar1 is probably an integer.
We can rename it as result.
And this result is coming from this function.
This function is doing some kind of comparison, I believe, with either to -. iVar2.
There seems to be a Windows API,
GetLocalTime.
So let's go to Google Chrome and look it up.
GetLocalTime,
and probably this is the one that you want.
Getting local time.
Let's check it out.
So GetLocal
Time will return
system time to the parameter in which it is passed. And lpSystemTime
is a structure to receive current local date and time.
All right, let's take a look.
So that means we can rename local_30 to become SystemTime.
So this is called SystemTime.
So let's rename it.
All right.
So in SystemTime now, we are doing some kind of operation with SystemTime.
You can see here.
All right, let's refer to the API
one more, once more, and see what it does. In order to get a better understanding of what the SystemTime
structure, we need to enter this. Right-click, open a new tab.
And here is
the further explanation on what is SystemTime all about.
We have here the first member is year,
second member is month, and so on.
So what is it trying to do here?
SystemTime.
It is performing a bitwise operation, so we can look it up.
I've already got the page open here, and you can see bitwise binary right shift operator.
The left operand value is moved right by the number of bits specified by the right operand.
So when we use this understanding with this, it means you are shifting by 0x10. 0x10 is 16,
so that means we are accessing probably...
Definitely not the first one.
Probably we are shifting into the member here.
So a word is supposed to be...
A word
supposed to be two bytes, two bytes or 16 bits.
16 bits.
So when you perform a shift of 16 bits, that means you're accessing the second member,
the second member.
So one word is 16 bits.
If you perform a shift operation of 16 bits, that means you are accessing the month, the month.
So over here, you are shifting 16 bits to access the month.
So local_7c could be month.
So let's rename it to month.
So now you have month here.
Let's click on month.
And what is local_2c? local_2c shifts 16,
and you need to find out what is local_2c.
So sometimes we don't get any clue by looking at the decompile.
We can go back to the listing view to get some more hints.
And the hero in is the sprintf.
F.
I think this is sprintf because it takes this as a parameter to perform some kind of operation.
So what is sprintf?
Def?
If you look up the Internet, search for sprintf, sprintf takes a list of format specifiers to construct a string.
So, for example, if you have this kind of format specifier and you were using sprintf, you will put the
target string here, followed by your format specifier,
and then at the back you will put all your other strings here.
Like this.
So in the end, you will get a target string which is made up of string A, B, and D and C, all lumped
together in one new string.
So if you had something like this,
so in the end your target string will end up become dash, dash, dash, dash, dash, which is coming
from here, and then comma, then followed by the 11
coming from A, 22 coming from here, which is B, and 23 coming from here, which is C. So this
is the meaning of format specifiers.
So this is a kind of format specifier: string, integer, integer, integer.
So in the end, your target string will be this.
This will be your target string.
So we can make some deductions by analyzing the code here.
We know that the target string is like this is this one, so this must be the target string, so we can
just relabel this as target string.
So your target string is an actual key.
It might as well call the actual key.
Actual key string.
So we make assumptions like this and modify it as we discover more,
more data and more facts.
That means this one must be sprintf,
so we can relabel it as sprintf like that.
So from this we now can deduce that all the parameters above are the parameters that will be pushed
to be used by this function.
So we have one, we have local_78, local_60, which we don't know what it is, but we know for sure month
and month must be one of the parameters used by this function.
And if we are lost like this, sometimes it's good to go back to the listing, view the assembly view.
So this is the part where you move parameters to sprintf, and this is where you call the function sprintf.
So over here above will be all your parameters that are used by your sprintf.
So we can see that one of the parameters is month.
I will just turn this off.
One of the parameters is month.
Month, then...
So we have three others.
This one is typically used for storing strings.
Probably this will be your target string, so we can just relabel this as target.
Just edit label and call this target_string.
And then this one with month.
So what are the other two?
A lucky guess would be year, month, and day. Year, month, day.
So if we assume that this was year, we can call this year.
We can edit this as year.
And we can edit this to label this as day.
So just change the label to day.
And it makes sense because month is extracted from this.
You can see here month extracted from the SystemTime.
So it makes sense that the other two are also coming from SystemTime.
So we can deduce that most probably all these three are coming from SystemTime, and we can go back to
SystemTime to take a look.
SystemTime allows you to extract year, month, and day, all these three things like this.
So we can, based on this and other evidence we have seen, it is a good
deduction that probably this is day, month, and year. And how? And you can confirm the year further by
looking at param_1.
So when you look at param_1, param_1 receives the pointer to the address of this structure.
So the pointer to a structure is the first element of the structure usually.
And what is the first element of a structure?
Year.
So param_1 is actually a pointer to the year.
So we can actually rename this param_1.
Pointer to
SystemTime.
And since it's a pointer SystemTime, it also points to the year.
Pointer.
So we can properly read this pointer to SystemTime and first element.
So first element of the pointer of the structure is year itself.
Right.
So this makes more sense now.
So most likely we are right deducing that this is year, year, month, and day.
And this one probably is the string.
This one.
This string.
So this string is probably your name.
Because when we go back and take a look at the crackme, it asks you for a name.
There must be a reason why it wants a name.
It's probably going to use it to create the serial key.
And then when we see there's a string component here, we can more or less guess that this must be the
name which you enter.
So, and it requires a parameter for that.
So the parameter must be this.
So now that we have examined again, we can relabel this based on new findings.
So this is not target string.
We can relabel as name.
Name string.
So now this makes sense.
You see, it makes a lot of sense.
The name string goes to the %s format specifier here, goes to the %d here,
month goes to the other format specifier, and then goes to the last one.
So this tallies very well with our hypothesis, which we saw just now, that
the sprintf coming from here, sprintf coming from here, which we relabeled, accepts all these parameters in this
order.
Okay.
So based on this, we can more or less guess now what is our serial key.
So the first parameter will be whatever you enter.
So if let's enter test, then it will insert a dash, then it will insert the year.
So let's say today is 2021, then you insert the month.
Now it's March.
So March is 3, and finally the day.
So today's date is 19.
You can go up here and hover your mouse to confirm the date.
So 19th March 2021.
Right.
So now we're going to test this serial key and see if we are right.
So I'm going to enter test here, and then serial key will be test followed by dash, 2021,
3, and 19 is the day.
Yes, correct.
So now we have solved this crackme.
So this is how you do analysis.
Sometimes the decompile is not accurate and makes mistakes.
So we have to read between the lines and then go and analyze the other things in the listing, refer
online to the APIs like this, and then open up a notepad as a scratch pad to make your notes and test
hypothesis.
If your hypothesis is wrong, you refine, change it, and then test your hypothesis
again.
That's all for this video.
Thank you for watching.