All right, guys, welcome back.
And this challenge was different regarding to the ones we face so far, because now you've got several
options, things you have learned in the past.
So it was not regarding to a special topic.
It was regarding to what we have learned so far.
This makes it, of course, harder.
And in case if you strike it a little bit, don't worry too much about this.
We will take a look together into this right now.
And afterwards, I'm pretty sure that you understand the whole application function and how you can
patch this the next time on your own in case, of course, if you have successfully patched this, congratulations.
This is a real world application example and I have encountered this many times in the applications
regarding to different types of customers.
So therefore you successfully bypassed a real world rolling detection, which is really, really amazing.
So whatever which case we have right now, let's take a look into this together.
So I still get it open here and let's grab this application
downloads and root check and put it into a new app directory.
All right.
So let's have a look first with Shadi.
Excuse.
Okay.
So here we have the main activity.
Let's see, we've got some Android stuff and text view and button we've gotten if statement over here
root util is device rooted.
This sounds very promising.
Then we've got some stuff.
The device is rooted so we know regarding to the text.
And this one is our yeah.
This is the state we do not want to have, we want to have this one over here because here we will return
out of this method, out of this function.
So we leave this application.
Okay.
So now we know what we are dealing with regarding to this one over here.
Let's see if we can already patch this without taking a look into the routing detection.
I get out my graphic tablet and then we discuss this and let's go.
Okay.
Here we are back again.
Let's have a look into this.
All right.
This one is our if statement in this line.
So if you go into this function, we've got a lot of instructions, but here we leave this function.
So this one is our exit, exit.
And we do not want to go into this.
So let's recap this real quick, what we have learned in the last couple of videos.
And let's say we get rid of this instruction over here.
We patch this or delete this if statement.
As this brings us anything further.
Let's have a look.
So let's say this one does not exist anymore.
Okay, then we've got a regular instruction.
Another one.
But at this point, we are still leaving.
So this doesn't bring us that much until we also delete the return statement here.
If we delete this one, then we have some other additional instruction.
This one.
This one and this one.
Yes, that's missing.
All right.
This means we are having a device which shows, oh, this device is routed.
But we are also having a device which says, oh, everything is fine.
So by having these two states, we yeah, we got our task done.
But in my opinion, this is not a really clean solution because if we do not patch this, if construction
over here, this one and just deleted the device still gets flagged as being rooted.
And this will mean that, yeah, some features might not be possible to use in this app.
Of course in this activity it's fine, but maybe regarding to other services we might encounter some
trouble.
Therefore, this is a nice approach, but not the solution.
If you want to, you can try this to here get rid of the return statement and also of the if statement
there and see how good it goes.
But now I will come to the real solution.
Okay.
So let me clean the screen real quick.
All right.
And now let's have a look into this.
So this is our routing detection.
Let's see how it works.
I click into the class and here we go.
So first of all, I want to thank and mention the author of this.
I will blend it in right now.
So this rolling detection is working absolutely fine.
There is no problem within this ruling detection.
It protects the user from running an application on unmodified smartphone.
But still, as an attacker, we need to patch this.
So let's have a look how it works and how we can circumvent this.
Okay.
The first one sounds pretty promising.
So I get back my pen.
There we go.
The first method is, is device rooted.
And let's have a look at the function itself.
We do not have any parameters here, and we return an boolean value in this one.
Okay.
That's pretty interesting.
Let's see how it looks internally.
So let's clean this.
Okay, so we returning this method or the value of this method or the value of this method or this method?
There we go.
Okay, so this sign means one statement.
What does no statement do?
And let's see.
We've got this following binary table.
So we've got A and B, and this one is zero one, zero one and A is 0011.
So if we combine them with an or, then we get the following result zero and zero will be zero regarding
tone or statement, zero one will be one one and zero will be also one and one and one will be also
one.
This means if one condition is set to one, then the output will be one.
Otherwise, if both are negative or false, then the output will be zero.
All right.
Regarding to our rooting detection, this means if one of them returns true so one, then the whole
function here will become true.
So this boolean value here will become true.
This is pretty neat for the shooting detection because let's have a look into this.
For example, the first method check, method one check method one checks if we've got test keys enabled
in a build tech, whatever this means, if we have here a true statement, we do not need to go into
this and this to flag this device as being rooted, because one true statement here is enough to make
the whole output being rooted.
This means if the function here returns one, we get in true and this means the device is routed.
If this function returns a zero, which means false, the device is not being routed.
Okay, so let's see.
How can we get an zero?
And false statement.
Well, we have to be for all three methods.
So in this case, we also have a method C, and also this method C needs to be zero.
Okay.
So let me clean this up real quick and then we go into the functions in detail.
All right.
So we are having three methods.
Each of them returns a value.
And if one of these value is true, we lose.
So let's say I lose, because it's not your fault if I do not bypass this.
Okay?
All right.
Let's have a look into the first method.
The first method checks if you've got some build takes with the test keys enabled.
So if this is the case, we are returning.
True.
Otherwise, we are returning.
False.
Okay.
Next we've got this one here Czech method to this and this checks if certain applications are being
installed for example the superuser the as you binary.
And the other stuff.
If one of them is inside the device, the path exists.
It will return.
True.
So there we lose.
Well, let's say I lose.
And if it's false, we will.
It means none of these binaries or ipxe has been identified on the system.
Last but not least, we've got check root method three and check ups, and this method executes a system
command, which means we are checking if the issue binary exists on the system.
So these are our three rooting detections, and if one of them becomes true, then the whole device
is being flagged as rooted.
So one approach would be to patch all of these three methods over here.
So instead of returning true, we can go into this and return false.
But we have to do this for all methods.
So also here and also here, by doing this, all of them will return false.
Which means if we combine three false together, the output will be false.
Regarding to this or statement over here and this means our device is not rooted.
Okay.
This is a valid approach, but it requires a lot of effort and we are super lazy hackers.
Therefore we want to take the path with the least resistance like the electronic stuff does.
So what other options do we have?
Let's clean this up.
Instead of patching all of them, we can go for the master routing detection.
Which is this this method over here.
This method checks all three and afterwards it returns true or false if the device has been routed.
So by patching this method over here, we can simply say always return the value false.
So regarding to this challenge, I would recommend you to go for this part, simply patching it at this
point.
By adding a new cost value regarding to the register that is being returned and set it to false.
All right.
You can now pause and rewind this video in case you want to try this out.
I will move on with the real challenge and provide a solution for this.
Okay.
Here we are back on the left.
We've got the smiley code and on the right we've got the Decompile Java code.
Let's have a look into this.
We've got our file route util.
This is our class.
We do not extend a certain special class.
It's just an object.
This is our file name.
Then we have the constructor, and here we can see check root method one.
Okay.
If you take a look at the right, we can see.
Oh, that's strange because here we have is device rooted.
But yeah, this one seems to be missing right now on the left.
And this happens quite often in Smiley.
You can check this if you click left into these line numbers.
So here you have your line numbers regarding to your Java code.
And if you click left with the mouse button, then you can see the line numbers regarding to the smiley
code.
And here we can see those line numbers as are increasing.
But here we have some yeah.
Some strange looking.
So we are having 30 to 37, 30 to 30 back again.
So the smiley code is a little bit different regarding to the order than the Java code.
We have seen this in the if statements.
The compiler has produced a different order, which is faster for the for the CPU to execute instead
of going the Java approach.
So the Java order of this code.
All right.
But this is not a big deal.
We have seen this in the past and we can handle this.
So we just need to navigate around with the smiley code and we have to trust the smiley code on this.
Okay, we can see this one is check root method one, this one over here and let's go down here.
We have check root method two, this one over here.
Then we can see all those strings and binaries that get that's getting checked.
We go down here, we have check root method three.
All right.
If we go down, there we go.
At the end, we've got is device rooted.
All right.
And we can see this over here.
Line ten, this is line number ten.
Okay.
It's at the end of this file.
But I mean, who cares?
So we have found this.
And here, let's analyze this and try to patch it.
So the first one is a new instruction and we haven't talked about this yet, but if you take a look
at the smiley instruction that exists, so I hope you have your cheat sheet prepared.
You can see we cannot talk about all of them, but we have learned a lot of things about Smiley and
maybe we can apply this knowledge in your reading and also understanding what this instruction does.
So let's have a look.
This instruction is named invoke static.
So copy.
So now we are searching for this.
All right.
In invokes a static method with parameters, that's all.
It just invokes the method.
It doesn't do anything more.
Okay, let's see which method.
Let's have a look.
So I enable my pen.
And we can see we've gotten capital L This means we're having a class reference.
The class reference end ends at the semicolon.
So we are dealing with root util over here we are having root util.
Okay.
Then we've got this arrow, which means we are having a thought.
And after this thought, we've got a method name.
In this case, check root method one.
And so on.
And we can also see the return type of this is Boolean.
Okay.
So we do not know or we didn't know what this one does.
But now we know this one executes this method code.
So regarding to static methods, we do not have to create a new object.
We can simply use the class and then the method name to invoke this.
So this one is just executing this function, but it doesn't do more.
So therefore we have this next line.
This one moves the result into v zero.
But nevertheless, let's verify this because we are not familiar with this.
So let's see.
Move, result, move.
The result.
Values of the previous method invocation into v x.
All right.
So the return value of the previous method, which is this one here, gets now moved into V zero.
This means our week zero.
It's now being true or false.
Depends on what the return value of this method is, which means we are having 0x14 true and zero zero
if a false.
Then let's have a look into the next one.
Nice.
And if statement.
So if we zero is not equal.
Zero.
Let's write this down.
Yeah.
I enlarge this and be right this next to it.
Yeah.
It's nice.
So.
At this line if.
We zero is not equals zero.
We jumped to this condition.
This means if our we zero is set to true.
Because then we are having a0x1 in there.
We jump to condition one.
And if we look at condition one, let's see, here's the label.
Okay.
So we are jumping down there and then we are writing 0x1 into we zero, which is interesting because
we zero is still set to 0x1.
But nevertheless.
So we 00x1.
That's what this line does.
And then we are returning back this v zero.
Och.
This means our method will return.
True, because this one is set to true.
It means our routing detection is being set to true.
And therefore our device is routed.
So let's take a look at the code once again to verify if yeah.
If everything is correct right now we've got a boolean is device rooted is device rooted true means
our device is rooted.
And if this method returns true, then the whole method returns true, which means our device is being
routed.
So we can also circumvent this right now by patching this if instruction, so we can flip the logic
of this.
So here we get an additional patching option instead of going for this one over here at the end, we
can also flip the logic over here, but we need to take care about this because in our case this method
will return false.
So this doesn't flag our device as being rooted.
If we now start flipping the logic, this method will tell that our device is rooted, even if it's
not the case regarding to this check.
So this is something we need to consider.
All right?
So therefore, we do not go for this one.
Okay, so let's clean this up a little bit and then we do the next check.
So we've got a default statement for this one over here.
Okay.
So if this one is false, which is the case, by the way, for our routine detection, and therefore,
by flipping the logic, this will become true.
We will end up with a rooted device.
Therefore, we do not.
Flipping this logic here will not work for us right now.
Okay.
But if it's false, we go into the next one and here we have check root method two.
We've got the same approach like this one here.
So we have our class wrote you till dot.
Let's write it in this way.
Dot check road method one.
Sorry.
Method to returning this boolean value.
This Boolean value gets thought into we zero over here and we can see the same approach.
So also right here, if we zero is not equals, if we zero is not equal zero we jump to this condition
and our be zero is the output of the one before.
So.
Sorry.
The one before us.
Only this and this line.
So V0 is equal to.
Let's write it down.
Root util dot.
Check method.
Okay.
There we go.
It's getting a little bit messy, but I guess we can follow on this.
Okay, so this one, is this over here?
We are still using the V0 register.
And if this one is not equal to zero, we jump to condition one back again, which is this one here
and here.
We set our V0 to one.
Then we return b zero, which means we are having the same case.
Let's do this once again.
So if our zero is not equal, zero means or we zero is one, then all we zero will be set to one and
then be returning one, which means we are returning true.
Which is not OC because then we know our device is rooted.
So this method also needs to return.
False, but oh sorry.
Not also this method needs to definitely return false.
So regarding to the patching approach, we can flip the logic over here.
This will work because if you take a look.
We can see this method will definitely flag our device as being rooted because we have the seu binary
on our device.
We might also have the superuser apk.
I'm not sure, but one of these will definitely be true.
Therefore this method will return true.
So let's toggle the visibility.
Okay.
I clear this up real quick.
So this method here returns false for our case.
That's okay, but this one here will return.
True.
And therefore, we can flip this logic over here.
This should work.
Yes.
But we are going to make it a little bit easier.
So we are not patching it, vice versa.
I just want to show you all or many possibilities to solve this challenge right now.
You can also try this on yourself later on and if you have questions, yeah, please write me a message.
I'm so glad if I receive feedback on challenges like this and of course, I try my best to help you
out on it.
Okay.
All right.
So this will be also an approach that should work.
So what's next?
Okay.
Via in this method over here.
Yes, we talked about this one.
We end up here.
Otherwise, we talked about the the true statement.
But now we need to go into default and default statement once again, exactly the same.
But okay, now it's a little bit different.
Let's see.
All right, let's do this.
We invoke this method over here.
Root method, a root util check method three.
So regarding to this line and this line, it means one last chance to write it clean.
So let's see, we zero is root util.
Check method three.
Then we are having an if statement if.
Oh, that's interesting.
If we see a row is equal zero, we jump to condition zero.
All right.
Best condition.
Zero.
This condition zero.
Nice.
This means we are writing zero into v zero.
Okay.
And then we go to label one, go to one, which is this one here, and we are returning out.
So we are returning.
Be zero.
All right, this is different.
Oh, nice.
So what do we have here?
If this method now returns zero, then this device is being flagged as not rooted.
But the thing about this method is we can only reach this method, this point over here, this one,
if this one has been false and if this one has been false, only then we can reach this point over here,
which means if one of them has been not false, then we end up here in a router device.
All right.
So this is how the logic is implemented in Somali.
It's maybe a little bit confusing at the beginning, but if you go through this once again and here,
write it down exactly like we've done this on a whole paper completely, then you will realize this,
okay?
This is how the logic works.
And yeah, maybe then it's not that hard anymore.
I really encourage you to write it down in the following way, maybe a little bit more clean than I
do, and maybe also, yeah, more complete than I do.
But this is a really good approach to understand.
Somali.
Okay, so now let's see.
So if this one, then we jump to condition zero.
Condition zero was here.
And then from this one, we jump to this one and we skip this part here.
All right.
So by looking at this, I came up with two additional patching options, or at least one.
The other solution I see right now is regarding to the labels in this one.
This one and also this one, for example.
So these labels define and branch instruction.
We have our code.
Let's say this one check.
Let's call it check root and so on.
Based on this, there's a decision if we go on the left one, which is, for example, true, which
is in this case condition, one device is rooted.
What if you go into Ford's?
And then not true that
this is what we want to have in this false statement over here is not regarding to condition one, it's
regarding to condition zero.
Condition underscore zero.
So we can also change the label to achieve this task, but to manipulate the jump instruction, to not
go into this way, to always go into this way.
That's also a really nice solution, in my opinion.
And yeah, feel free and have a try on this one.
So the easiest solution I want to show you right now is the following.
We've got only two Boolean values in our function over here.
We've got this one here and this one.
This sets the device to false or not.
The device, sorry, the routing detection to being false, which means not rooted.
This one here sets the device to true sorry.
The routine detection to true, which means the device is routed.
So the simplest way to patch this rolling detection is to change this value to 0x0.
By doing this, the device will be also not rooted.
And therefore we can run our application as a normal as normal app.
All right.
The other solution is let me clear this real quick.
Before we return out of this.
At this point here, we can apply a new command or a new instruction which is constant slash for the
00x0.
So we can simply write this instruction once again just right before we return out of this function.
This means no matter what, even if our busy register is being set to one at this point over here,
which means true, we are overwriting the zero at this point.
Myth.
False.
And then we are returning the last venue.
This one over here.
Okay.
So I will show these two approaches in this video right now and I will make an additional video regarding
to patching those Trump labels.
Okay.
So one easy patch is simply this one.
I know this is ridiculous, but it should work if you take a look into this.
All methods now return false because there is no option for them to return true anymore.
All right.
So let's have a look.
So ADB uninstall uninstalled ADB install out APK success.
Loebsack.
There we go.
The device is not rooted.
Lock in is now possible.
And if you click log in, we've got our flag because yeah, we've got some insane smiley skills.
Nice.
So that's all we need to do.
I know it looks super simple and you might think, Oh, well, was it really that easy?
Yes, but we did a lot of work to understand that it's that easy because we reverse engineered this
application and figured out what's going on.
Okay.
In this case, this is a nice trick to check.
Okay.
There are only two boolean stakes available in here, but this comes with practice and experience and
smiley.
Okay, so don't worry about this.
If you've got some really complex or if you put a lot of effort into this, this is absolutely normal.
And it's not always that easy to patch this.
All right.
Let's revert this change.
So now we've cut back the original change.
If you build this, our device is still being flagged as rooted.
The other approach is to introduce a new smiley instruction over there.
So just before we turn out, we override this register which returns true or false for this Boolean
value.
And here, let's build this application also once again and install it.
I will fast forward this right now, so I will see you in a few moments.
And yes, you can see this one also works.
Nice.
Yes.
All right.
Let's have a look into the compiled output, how our routine detection works right now.
So this is our patched version.
So this is now this version over here we are overwriting the return value within false.
Let's see how the Java code looks to this.
Would you tell?
There we go.
This one has been now added.
So no matter what the first output is, it will return forwards.
This is what we have added by introducing this new instruction just before we return out of this function.
All right.
So this was an.
Yeah.
And really rough challenge right now.
Okay.
This patch was easy, but understanding what's going on was really not that easy.
And therefore, no matter how it worked out for you, if you could solve this or not solve this, and
if you also gone through this once again and solved it, no matter if you received some help regarding
to the solution video right here.
But if you have gone through this and have understood what's going on and if you have been able to reproduce
this, then this belt is for you right now.
There you go.
All right.
I will make an additional bonus with you regarding to this challenge because yeah, it was also pretty
interesting for me that there are these many options for us already to solve this.
So it's really nice to see how many opportunities we already have right now because we are just and
the half of the smiley topic.
So we get a lot of more power in the next chapter when we talk about methods and also yeah, introducing
or inserting more complex instructions.
So the bonus video will be directly after this video.
But if you already have patch, this conditional jumps over here, the delayed release, then you can
of course skip this.
If you're feeling pretty confident in doing this, of course, feel free to skip this.
It's not really required.
We will move on with objects, which is the last huge chapter in our smart learning process.
And by doing this, yeah, we will get even more power and hacking these applications.
So I see you.