Welcome back, guys.
In this video, we start learning Somali and we do this step by step and we start with a really important
component, maybe the most important component.
And yeah, if we have understand this one, then the rest will be also not that hard anymore.
All right.
Okay, let's go.
Let's have a look at registers in Somali.
So I pulled out my graphic tablet and we make some fancy drawings to explain this.
All right, before we dive too deep into this register topic, let's first have a look at that very
basic function.
And based on this, we analyze how this CPU is handling those yeah.
Those single instructions and then we will figure out how registers work in Somali.
Alrighty.
Okay.
And so let's say we've got the following function.
We've got.
Yeah.
Public.
The function that returns an integer value in this function takes two parameters and add them together.
So we named this add power.
And here we have all two parameters in A and in B.
And this function also has an local variable named some.
And this one is being initialized with zero.
Then we have the sum which is equals.
Now these two parameters get added together and start in sum.
So oops.
The sum is equals A plus B.
And afterwards we return this variable.
What is value in this variable?
Why are returns sum?
All right.
And this is a very basic function written in a high level programming language.
But the CPU cannot handle it in this way.
So therefore, this function is being compiled and the compiler translates this high level function
into single instructions which can be handled by the CPU.
So let's have a look into this, but don't worry only on a very high level.
Therefore.
And let's draw this line over here.
All right.
So here now we have our CPU.
This is our CPU.
And this one has, of course, also some pins.
And some of them seem to be not connected and some of them they could be shorted out.
But yeah, this doesn't matter because we don't use them.
All righty.
So the CPU doesn't understand things like in a war and B well, also doesn't understand a variable named
sum.
What the CPU understands are registers.
So a CPU has register.
In this one, for example, or this one, or maybe also this one here.
And these registers are now some kind of placeholders for these values or these variables.
In this case, for example, this register can hold the variable A and this one holds the variable B
and this one holds the variable sum.
If you're talking about smartphones, we are most likely having an ARM architecture.
And the architecture has registers named from our zero to our one or two or three, and also some other
registers like the program counter, for example.
All right.
Now, if we compile this code over here.
Then the compiler is translating these into single instructions and this will end up in the following.
For example, if we call this function over here, the first argument, this parameter one, this one
will be stored in our register r zero.
So our zero is now holding a B will be stored into r one.
And regarding to the other parameters or registers, we do not have any other parameter.
Therefore these registers are not being used in our calling convention over here.
The program counter holds the value or the address of the next instruction.
But for now, let's ignore this.
So this is simply just set to the next instruction, which is going to be executed by the CPU.
All right.
The sum will be after what's also stored in the register and on the architecture.
The return value of a function will be stored in our zero.
So afterwards our zero is not holding a anymore.
It's holding the return value, which is some.
This is how a CPU is handling these values or references.
I mean, it's a little bit more complex, but on a high level, it looks exactly this way.
All right.
But what if we run out of registers?
For example, on the arm architecture, a zero up to three are being used as parameters.
So these registers hold the parameters of a function.
But what if our function now has ten parameters and then this CPU storing the first four parameters
in those registers over here are zero, one, two and three, and the others are being pushed onto the
stack.
The stack is the program memory.
So this one over here.
This one is the stag and this is then holding the other parameters so they get pushed into the memory.
That's the memory.
You might ask yourself why I'm telling you all of this.
And to be honest, I've had absolutely no clue.
Just kidding.
Smiley is acting on the same behavior, so Smiley is also using registers to store their values or variables.
It's it's pretty identical to the CPU, but of course, Smiley has other registers.
Otherwise, it would be absolutely ridiculous if Smiley would also use these registers over here.
That's, of course, not the case.
So Smiley has their own registers.
And what type of registers?
But let's have a look.
Let's make a cut over here.
So this is our smiley corner.
There we go.
The output in Somalia depends on the tool we are using, for example, to trade the compiler with.
Summarize all these registers into one block.
The APK tool instead is splitting them up.
And that's why I really like to use the APK tool.
The APK tool splits them up into two parts.
The first part is local registers.
These are the local registers used in a function.
For example, this one over here in our case we have int some and this is a local register.
Local registers only affects this function itself, so only registers which are being initialized or
used in this function over here and the other type.
Do you have a guess what it could be?
I am pretty sure you do the other type of parameters.
And I mean parameters.
Yeah.
That's not that hard.
Parameters are simply just registers or values passed to a function in this one and this one for example.
Alrighty.
In Smiley, if we're compiling an application with the APK tool, these parameters are named from p
zero up to p something.
P zero is also a special case.
So P zero is most of the time the this operator.
So this is a that's a really special register over here.
Therefore those parameters normally start at p one and simply count upwards.
So this one would be P to local registers.
They are named with V.
So in local registers we have V zero and it simply counts upwards.
In our case, we have a local register or a local variable named sum and this one would be our v zero
register.
But registers are not only regarding two local variables, like in this case, for example, V0, which
is referenced as some for example, this value over here, this value zero SPU cannot handle three tasks.
At one, a CPU will split up this instruction over here in several different instructions, and therefore
the value zero will be also stored in a register.
This can be the zero, but it could be also another one.
For example, b one.
And this is not a local variable and this is a local value which is temporary, stored in a register.
So to make this a little bit easier.
Registers are just some kind of placeholders for values.
Alrighty.
One important thing we need to remember if you are working with those registers, is that those registers,
if you initialize them at the beginning, it doesn't has to be the same at the end, not just regarding
to the values, also regarding to the variables.
For example, if you extend this function over here.
So at the beginning we are initializing B0 zero with the variable sum and then let's say we have some
bunch of other variables we want is holding.
The B two is holding.
I.
And so on.
Afterwards, we are returning, for example, we want.
Return some letters missing, I guess.
Yeah.
There we go.
All right.
So the compiler is now generating this code, and in a certain level, for example, in between here,
the compiler might recognize I'm not using the variable sum anymore.
This one is not going to be referenced or returned from this function anymore.
Therefore, we can recycle this register because also those registers are very valuable for the whole
program flow.
For example, regarding to runtime performance or memory usage or whatever else, the compiler tries
at best to optimize this code as good as possible.
And therefore, if the compiler recognizes, oh, okay, the, the variable sum is not going to be used
anymore, then it recycles the the register which is holding this variable in this case be zero might
be recycled and it might be initialized with a completely different variable at the end, for example,
set.
And now let's assume the program is not returning the one it's returning be zero at the end.
If you take a look at the beginning of this function, then we might think, Oh, okay, this function
returns the variable sum, but this register has been recycled and therefore overwritten at this point.
And yeah, the program returns this variable set instead.
So this is something we need to keep in mind.
Therefore, my approach is to keep track of every register and you will see this during this course.
So I write every smiley line into some sort of code line, what it does and what actually registers
holding which value.
By doing this, we can keep track of these registers and we do not lose control or get overwhelmed by
all this stuff.
In my opinion, this is the best way to learn.
SMILEY Because if you have analyzed the program code, for example, this part over here, this program
code, then we have reversed every single line which is in the smiley code over here.
And we do this during this course and you will see, yeah, at the beginning it might be a little bit
hard, but if you keep practicing this over and over again together with me, then you will be able
after this chapter to reverse and also write your own smiley code, which is super amazing.
I promise this to you if you keep on working together with me during the smiley chapter and reverse
and perform all these exercises together with me, then you will be able to read every single smiley
line and you will be also able to write your own smiley code so you can patch an application in whatever
way you like.
All right.
So let's summarize this here real quick.
I mean, we at the beginning.
So what is the key take away of here?
Okay.
So smiley acts on registers.
And if we are using the APK tool to decompile our application, the smiley files or the registers are
being split into two parts.
One is regarding to local registers and one is regarding to parameters.
So local registers starts with V and parameters starts with P.
Our parameters normally start with P, one and simply upwards, p two and so on.
We've got a special parameter register which is p zero.
Let's write it over here.
P zero is the this object most of the time.
So in 99%, p zero is holding this this object.
So for example, if you're writing Java code, we've gotten this dot, this is exactly the P zero register.
Don't worry too much about this right now.
We will learn this later on.
All right.
What we also need to remember is if we are initializing or assigning a variable on a value to register,
this register can be recycled.
So if this happens at the beginning, it doesn't mean that this register is holding this variable.
What is value at the end of this function?
So it can be overwritten, but it can be also completely recycled.
So instead of having the same variable, there could be a completely different one in there.
For example, the set variable.
We need to keep track of this and you will learn during this course how we can do this.
That's easy.
We simply reverse engineer every single line of Somali, and we write down what this instruction does.
And then we do not lose the track about this.
Maybe one last thing I need to mention over here.
So in my opinion, the best way to learn Somali is having an approach on our graphic tablet over here,
but then also some yeah, some learning experience on the slides.
So we take this code, we modify it a little bit, and then we will go through this once again on the
slides.
So it might be sometimes a little bit frustrating if we go through a topic twice on the on the graphic
tablet and also on the slides.
But for me personally and also the feedback I received, this approach is the best way to learn Somali.
Because Somali, it's all about practicing and repeating what we have learned and applying it to new
functions.
So by having this, it's sometimes a little bit boring.
If you discussed this twice on the graphic tablet over here and also on the slides, but you will see
the progress on yourself if we do this and keep doing it.
Okay.
So sometimes it's also a little bit better to have it on the slides instead of some messy error in going
around over here.
All righty.
And let's write this code.
They compile it and then analyze the smiley pad in there.
Afterwards we apply some patches and we will have a look at the modification on our slides.
Therefore, let's go.
Let's switch back to the Ubuntu VM.
Okay.
Here we are now with our ubuntu VM.
Let's write this function and have a look at a real world application.
So we opening up android studio.
Towards Android Studio one bash studio as H.
Okay.
Now let's go into this class and extend this method.
So we go into playoff and we adhere a new method named public int at power and we provide two integer
values.
And then we've got this sum which gets initialized with zero.
Then we have some equals A plus B and return some OC.
Let's compile this application and then we have to look into this with the APK tool and we also compare
this with the trade exclusion.
So we go to build build APK.
We also do not need to call this method because it will be decompile or it will be compiled into those
smiley files afterwards in this player class.
Sometimes there some kind of decompile optimization that strips out unused methods, but in our case,
we should be fine.
Here we have our APK.
And let's make this more clean.
So we add a new directory within the app's.
Smartly.
One method register.
Rename registers OC APK tool and registers.
All righty registers.
Smiley.
Com.
Hacking.
Smiley one and two.
We have our player smiley class.
Let's open this with Visual Studio code.
So I opening this directory over here, then I go into this one.
We close this one?
Yeah.
This is the old player, Smiley.
Yes.
So we closed this one and now we track this new into this.
And we have seen we've got this underneath here.
This is our new method.
Let's have a look into this.
Therefore, we switch to the Java syntax first.
Let's have a look into this.
We've got a method public named at power and we do not know what this one is over here.
This is just distraction for us right now.
We will learn more about this later on in a separate section.
But for now, we do not care.
Okay.
Next, we've got this local spawn.
And this is the amazing thing of the APK tool.
The APK tool is splitting up our registers into locals and parameters.
So let's open the source code and keep it next to us and then do the comparison over there.
And therefore, let me open this.
There we go.
All right.
So we've got our local register and local register.
In our case, be zero.
We can find this name over here.
Here and here can be some kind of placeholder, but it can be also a variable name with our Java code.
So if you take a look into this, we can see we've got this in some local variable over here and this
in some is our local register or it's referenced by our local register V0.
How do we know that this is the case?
We can find this information here.
It also starts with dot local.
So let's make this from here.
Over here.
All right.
We can see.
Let me get cleaned those dots real quick.
Okay.
We can see.
We have our local register.
We zero.
And this one is now referenced by this label over here some.
We do not care about this one.
And now we know this local register we zero is a local variable in our Java source code in this function
over here and this variable is named some.
So some is referenced by v zero as a local register.
All right.
So we know what this one means.
Then we've got those two lines.
We get rid of them.
But here we can now see those parameters of this function.
And we also got this labeling next to them.
So this is the nice thing about the APK tool we directly see.
Okay, we've got one local variable in this case variable, because we've got this label over here and
we've got two parameters.
So we can also find them over here, p one and P two.
The label regarding to the parameters annexed to them always so we can find them directly here.
Regarding to the local variable, we have to go into the source code and figure out if this is a local
variable or simply just in place order.
Then we've got this one here.
So let's mark this real quick.
Those are clear.
Yes.
Then we've got this one here.
And this is super nice.
This is really nice.
We've got this line nine and this line nine means we can go into the original Java source code and check
what is at line nine and we can find this over here.
There we go.
So we do not know what this concert slash something means.
We get rid of this.
But this one is referring to the instruction that is in our line nine in our Java code.
So if you take a look into our Java code, we can directly see what's going on right here.
We've got into some is equal to zero and this is exactly what this line does.
We know we zero is our sun.
And we can also see this one here.
Zero zero is the hex value for zero.
So.
And here by having this, we can look up the instruction and then figure out what this does, or we
can take a look at the original Java source code.
But those line numbers do not always match.
For example, in this case, if we open this application in excuse me, because we are hackers and we
do not have the source code, we will have a different line number over there because the compiler has
done some optimization and it's not storing this value in a separate variable.
It's simply just returning this a class P and therefore those line numbers mismatch.
But I would say regarding to real world applications, those line numbers match at least for 90% of
the time.
So these are a really good indicator.
They are not always correct or not always matching to the correct part, but most of the time they do.
And if we get more and more practice within Smiley, we directly see if those lines matches or if not,
okay, so we can most of the time rely on them.
And this is super nice because putting them side by side, each shade output, for example, or the
text to char and the smiley code makes this whole reverse engineering process a lot easier.
Okay.
So we also know what this one means.
Then we've got line 11.
Let's have a look into line 11.
We can also see we skip that line ten.
Super nice.
So it's always keeping those empty lines.
It's like having assembly code with debug symbols even better in my opinion.
So super nice OC.
Let's see, line 11, this one over here that we can see, we are adding those two values.
But OC, I mean, we do not know what this one means.
This instruction over here, we have talked about this one.
So this is the reference to the local variable in our Java source code over here.
This one.
We can also write it the other way.
We zero is referencing some.
I guess this is more accurate at this point.
All right.
So we do not know more about the ad in the instruction.
I mean, okay, we can look this up and here we can see those two values gets added together, those
two parameters, and then it's taught in some.
And that's, of course, what this instruction does.
But we only want to focus on those register.
And this also helps us a lot because let's have look into this.
We can see we've got our V0 over here, then we've got P one or wrong color.
P1 and we've got P2 so we know we zero is our sum.
So we know some and we also know P one is our label A our variable named A and a can be found here the
same for p two.
P two is pp2.
So we also got p two and we do not know what this instruction does, but what we know is those three
variables are involved in this instruction and this is at least a super nice information, even if we
cannot read the code on the left, isn't it?
Unfortunately, there's a little bit of a downside to this, but this is not a real problem.
We can handle this.
If you reverse engineer an application later on, we need to keep track of this.
In most cases, I guess in all cases the parameter does not change.
So P one will be also always referencing this variable, but our local registers might get recycled.
So let's say we are using the same variable here.
Then we've got a lot of code underneath this and the sum variable is not going to be used anymore.
Then it can happen that the compiler is recycling this register, be zero and adjust a new value to
this.
So at the beginning we figure out, okay, we've got our local spawn.
Local spawn is a real variable in our Java source code and here we are returning this value.
So we didn't talk about this one.
But yeah, let's say we are doing something with this, with this register right here.
Then it can happen that this register is holding something different because it's not going to be used
in the source code and registers our sources that the compiler wants to optimize and reuse.
And then the compiler says, for example, okay, I'm using the zero register to store another value
in there.
For example, the value ten.
And at the end we think, okay, we are doing something with the variable named sum, but we are doing
something with the value ten.
And this is something we need to keep track on this.
We do not know right now which instruction to change this register.
So we cannot know this right now.
We only also want to focus on those registers.
And now I'm yeah, I maybe a little bit too deep into this topic, but I would like to provide you as
many information as possible at the beginning that you learn as much.
Okay.
I hope this is not too overwhelming right now.
So if you reverse engineer an application later on, we simply need to keep track of those registers.
We simply write this down in this way.
It's not some anymore.
It's it's now, for example, number, and then we are going to go to move on in the source code.
All right.
So we also talked about this one.
And last but not least, line 13, we also do the same.
So I pick up my red color and then we take a look into line 13.
We do not know what return really does, but I mean, okay, this is exactly the same like within our
Java code.
So return means we are returning from the function and we are also returning the value stored in the
register we are going to return.
In our case we are returning v zero and v zero is holding our sum.
It did not change.
Right now this is a short function and the register has not been recycled yet.
But if you have a larger function, please keep track on this.
And yeah, that's all.
We do not understand the smiley code, but if we look at the result right now, even by only knowing
what registers are, we can figure out a little bit.
This is a really good base we can work on and for now on we will learn more and more about smiley up
codes and things like this, and within a few sections you will be already set up to understand your
first complete smiley program, which is super amazing.
Okay.
Nice.
Let's switch back to the slides and then B recap this once again because by repeating this over and
over, you will learn this a lot more faster.
Okay, so let's switch back.
Okay, here we are back at the slides.
Let's have a look into this.
I did hide the Java source code and yeah, let's talk about this one first.
So take a look into the smiley code and ignore all the rest.
Just focus on what we've learned under this register topic.
Can you find out how many parameters and local variables we have right now in this function?
And maybe you can think about this how it looks like in the Java source code, this might be a little
bit too much expectation from me, so don't worry, this one is not required.
But regarding to the amount of parameters and local variables, this would be super nice if you could
find this out.
You can post this video right now and think about this and in a few seconds I will move on on this point.
So let's have a look.
But I come back and let's have a look into this together.
So we've got this one over here.
Locals, too.
This means we've got two local variables, and we can also see those labels at the bottom.
We've got a new label, which is factor, and we've got our familiar labels some.
So maybe we have now a new variable name in our Java code, which is vector.
This is just an educated guess regarding to the parameters.
Let's have a look we've got now p one, p two and P three.
It seems like I have added a new parameter over there.
And the funny thing is, if you take a look into this line to those brackets, we can also see there
has been an additional EI in this bracket.
And yeah, I guess we can resolve this right now and talk about this in the next section more in detail.
This is the type of parameter we provide right here and I means integer.
So we provide here three integer values.
But this is just a preview for the next section.
So we didn't talk about this and I didn't expect you to also identify this type right here, but it
would be super nice if you have identified two local variables and three parameters.
Three, this way.
All right.
Sorry for interrupting here shortly.
So I don't want to confuse you, but I guess we should be pretty precise on this one.
The line three dot locates two means we are having two local registers with zero and we one.
And afterwards these local registers being assigned to variables.
This is in line 12 and also in line 20 decays.
Therefore we can afterwards talk about variables.
But at the beginning we only have two local registers and these local registers can be also placeholders.
So they do not have to be assigned to local variables.
All right.
I'm sorry for the interruption, but I guess this statement is very important in this context over here.
Now let's move on.
Okay, let's have a look into the Java source code.
How does it looks like?
Yes, we've got three parameters now and we've also got two local variables.
One is factor and one is some.
Let's mark them here real quick so we can see, okay, we zero and V one.
These are now our local variable and do not get distracted by all the stuff that's around our variables
and registers over there.
We will learn about this by making our way through the smiley chapter.
All right.
Okay, so this is what I wanted to teach you in this section.
We have learned something about registers.
We know they are local registers and parameter registers.
And we also know a register holds our value in case of an variable name or another value.
For example, the value zero can also be held by a register.
Register can also change during the function.
So if we initialize and register at the beginning, like here, for example, we initialize the zero
with two.
It doesn't mean that this register is still holding this value.
Two At the end of this function, it might get reused, it might be overwritten, or there are some
arithmetic operation happening on this register that changes this value.
All righty.
In the next section, we take a look at the data types, and then we can understand half of the problem
already.
So I'm looking forward to see you in the next section.