Now that you have learned how to step into functions and step out of functions, how to do an undo, and
also how to insert and delete comments,
let us continue with the analysis of this
crackme. And so this is the main function.
Over here,
if your argument count is not true, it will show you the usage.
And once it enters the usage, it will exit the program.
So I enter the usage.
Now, after printing the usage message, it will call the exit function to exit the program, and it will
not continue.
Let's step out of the function.
But let's assume we have entered two arguments.
So in this case, we have entered two arguments: C5 followed by a serial number.
So it satisfies this argument count.
So this part will not execute.
It will instead go to the next line and call another function called check_serial.
check_serial
pass the serial key that you entered, which in this case is
one, two, three, four, five, six, seven.
Argument
one, argv[1], is actually your serial key, just like argv[0] is your binary name,
C5.
So now let's go inside and see what this thing does.
So to enter, to step into the function, we double-click on it.
And here we see char param.
So we know that char param is argv[1].
Just check again, hitting back, argv[1].
So we can step into this and rename this as argv1.
So right-click on this and then rename variable as
argv1.
Or if you want to be more descriptive, you can straight away type "serial."
So you know that this is a serial key which you entered.
And then in here, it will use the string length function to count the length of the key which you entered,
and it will store the result in a variable called iVar1.
So from here we know that iVar1 must be the length.
We can rename it. Right-click and rename the variable as length.
So now when you click on length, it will highlight all the similarly selected variables or labels.
And you can see this length is being used in multiple places in this function.
Now on the next line, which is line ten,
it will then check whether your length is equal to 0x10.
0x prefix means that this is a hexadecimal.
So to convert this into a decimal number, we can use the calculator.
Select the programmer's calculator, and for the hex, select hex, and then type in here, zero one, sorry,
one zero, and then click on decimal, and it is 16.
So now we know that this is 16.
It is checking if the length is 16.
So if the length is 16, then your serial number length is correct.
So this suggests that it wants us to enter a serial number which is 16 characters long.
So we can actually convert this to show decimal number.
So to convert this, to show decimal number, select this by clicking this, and then go to the disassembly
view and look for it
here.
It's highlighted in light blue.
Whatever you click here will be highlighted in light blue.
For example, if I click on this, it will highlight this part.
If I click on this, it will highlight this part.
So if I wanted to select this, I will click on this and it highlights this part in light blue.
So now I can right-click on this and select "Convert" from the bottom here, and then select
"Unsigned Decimal (16)."
So select this one.
Unsigned means there is no negative number.
It is only positive numbers.
So now we can see, once we have converted it in the disassembly view, it is also changed and reflected
in the decompile view.
Now it's easier to read.
And then next one will be the while loop.
The while loop in this case
accepts two parameters.
Now, this is quite unique.
While you can have one parameter or can have two parameters.
So while loop in this example, the while loop accepts two parameters.
So in this case, the first parameter that it accepts is to assign something to length.
So in this case, it is assigning the length of the serial number.
And then maybe the length is 16, for example.
And then the second parameter here, it is checking whether local_1c is less than length.
So here is checking local_
1c is less than length.
So how do we understand the meaning of this?
Notice that the first parameter is separated from the second parameter with a comma.
That means it will perform this instruction first,
then only do this instruction.
So in this case here, the first instruction is just to assign 16 to the length, because we know that
it requires your length to be 16.
So definitely string length will return 16.
So this will not change the operation of the while loop.
The while loop will continue to move on to the second loop,
second parameter.
Now it will check whether local_1c is less than 16.
If it is less than 16, it will enter the loop and do the loop inside here.
If your local_1c is not equal, is not less than length, then it will quit the loop.
So this is how you can understand this.
So the first parameter is merely an expression to perform some assignment.
You can actually, is similar to writing length outside here
and then taking away this part.
So it's the same, actually.
Same.
All right.
So in this case here, the decompile, decompiler has put this statement inside the while loop, so
and separate it with a comma, separated with a comma with the second parameter, so it performs the same
action.
So now what is this local_1
c? Just ignore the ulong, ulong here.
The important part is the variable name.
So what does local_1c do? When you click on local_1c, it will highlight all the occurrences of
local_1
c, and you can notice something here.
local_1c is used inside every array element.
So this suggests that local_1c is an array index, and you can confirm it by looking down here.
Here is where you increase the value of the array index by two, and then go back to loop again and check
whether it is still less than length.
So this is just a way of going through every element of the array.
The array is serial.
Serial is a, is a number, is a serial key which you entered.
So knowing that this is an array index, we can rename it. Right-click and then rename it as array_index.
This makes it easier to understand our code when we are doing analysis.
So now we know that it is now checking in here, the if statement is checking whether each character
of the array minus
the next character, because it is plus one here.
And then when you minus the second character from the first character, is the result not equal to negative
one?
If it is not equal to negative one, that means your serial number is wrong.
Immediately it will return.
That means exit the loop.
So this is the algorithm for your serial key.
And this is what it means, like what it looks like.
So now I've used "i" to represent array index so that it's easier to, it's easier to read.
So in this case here,
see, it is trying to compare whether the first character minus the second character is not equal to
negative one.
So assuming that I entered a serial number like this,
"i," when it first enters the loop, will be zero.
So when "i" is zero, it's accessing the first serial key character, and it will take that first key character
minus "i" plus one.
"i" plus one is the second key character.
So it's trying to check whether one minus two is equal to negative one.
If it is not, then it will quit by returning.
It will not proceed with the rest of the loop.
So this suggests that in order to enter the correct serial, your first character must be less than the
second character by one, so that when you minus it, one minus two, you will get negative one.
After that, it will go down here, and then it will increase your array index by two.
So when you increase the array index by two, it will now become two.
"i" will be two.
When it first ran, "i" was zero.
Now, because you plus two, "i" becomes two.
So now if we test serial[2] minus serial[3], that means it will take serial[2]
minus serial[3] and see whether it is negative one.
Serial[2] refers to this "3."
Serial[0] is this "1."
Serial[1] is this "2."
Serial[2] is this "3."
Okay, so serial[
2] means "3" is referring to "3."
When you take "3" minus "4" and then check.
All right.
So because "3" minus "4" is negative one, that means you are correct.
Then it will go and increase the index by two again.
And then now you are going to test "4" and "5."
So "4" and "5" refers to zero, one, two, three, four.
These two: "5" minus "6."
So "5" minus "6" is negative one.
Then you increase by two again.
So you will check "7" minus "8" is negative one.
Yes, it is.
Then you will check, increase by two again.
That means you will check this and this.
Is it negative one?
Yes, it is still negative one.
So you must make sure that after "8," you must start from "1" again so that when you minus, "1" minus
"2," you still get negative one.
And then the total length must be 16 numbers.
So this is your password.
This is your serial key.
Okay.
So now you can test it out.
You go to here, and then you type in one, two, three, four, five, six, seven, eight,
one, two, three, four, five, six, seven, eight.
16 characters and hit Enter, and you get "good serial."
"Good serial."
So let us trace this thing inside here.
Now, how does it get "good serial"?
Notice here, if your, anytime it checks and finds that the moment it detects that the serial is
wrong, it will return this number.
What is this number? 0xffffffff in hexadecimal notation, 0xffffffff means negative one.
It is based on the two's complement notation.
You can go and read up on the internet about two's complement.
Two's complement notation is a way for the computer to
show negative numbers.
Okay.
So you want to show negative numbers?
For example, here,
when it's all ones,
it refers to all F's.
And then if it's all ones,
it means there is a negative number.
All right.
So
that is the meaning of two's complement notation.
We are using binary numbers to represent signed integers, so when you have a negative number, you put
negative, you put F's in front.
The most significant bit will be F's or one.
This indicates that it's a negative number.
If it's all F's, then for sure it's negative one.
All right.
So no need to go too much in there.
Just know that when you see 0xffffffff, it means negative one.
So when you return negative one, it will return to the caller of this function.
Let's step out of it.
So here, if we return negative one, then you know that something bad has gone wrong.
Something bad has happened.
That means your serial key is wrong.
So you can actually put a comment here to say that if the return value is negative one, it means wrong
serial key.
So this one, since you know it is a wrong serial key, you can rename this variable.
Okay, so just rename it now to return_value or return_integer.
And then over here it checks,
if your return is zero, then put "good serial."
So that is what we are seeing here.
"Good serial."
That means we return zero.
Right.
But if your return was negative one, this would not be true.
Instead, it will run this part and put "bad serial," which we saw here.
"Bad serial."
A return value of zero means your result is correct.
If the return value of negative one means your result is wrong.
So let's go back here and see what makes it return zero.
check_serial.
So over here it returns zero.
Here, it returns negative one.
So in here, the moment the wrong serial is entered, straight away, it returned negative one.
So if it doesn't return negative one, then it will continue to check all the remaining characters until
it finishes.
Once it finishes, it will quit the loop and come out here and return zero.
So we know that this is the return value.
See, this return is uVar1, so we can actually right-click on this and rename it as return_integer.
So when it returns zero, it means you have successfully entered the correct serial.
So when you return zero here and you go back out of the function, the zero will be written here and
stored here as zero.
And then when it comes here, it will check return zero.
The return integer is zero.
So this is true, and it shows you the good message.
So this is how to solve this crackme.
That's all for this video.
Thank you for watching.