Why come back in this video?
We will learn how to hook a native function this spring.
Compare function with freedom.
Therefore let's directly dive into this.
So here we are back in Ubuntu VM and I've got most of the stuff still open.
For example, this one over here.
This is the function we want to hook.
Let's see this string compare function.
All right.
And to hook this, we need to get the address and then we can simply use our interceptor dot attach.
And this one, by the way.
That's not the address.
This is the offset in this image over here.
So we cannot simply use yet this value in our interceptor dot attached.
We have to enumerate it, but that's absolutely no big deal.
So therefore, let's pull out our code editor and let's see how we can do this.
So we are creating a new file.
This one is JavaScript.
Okay, so the first thing we need to do is we need to get the address of the string compare function
and then we need to hook into this one with our interceptor interceptor to attach to this address.
And then we have our callbacks and then we need to print out these parameters.
All right.
And let's do this over here.
So we put this on the left and this one on the right.
We start over here getting the address of the string compare function.
So getting the address is within the module enumerate exports or imports.
Therefore, we have to identify if this one is an export or an import within cheap drive.
We have already seen that it's being an import, but we can also think about this.
This is a function that has been defined in the Ellipse.
C And this function is being included out of the slip.
C into our code.
So therefore we know this one is an import.
Let's also pull out free and put this on the right because then it's way easier to to play around with
this one.
We hook into this process.
Let's see if it's still running this application.
Yes, it's still running.
So we hook into this process.
It's come packing and then let's see, funk of freedom.
No, I have to look it up within the Android manifest XML.
We've got this package name.
C funk freedom.
Did I misread?
Okay.
That's a little bit.
This is interesting.
Let's see.
This application is still up.
Maybe let's try to restart it with freedom.
Yes.
I'm not sure.
It seems to be some some back.
So simply just restart this application or close it and start with freedom.
All right.
So now let's see a module dot enumerate imports.
This is a function that requires the library we want to enumerate, and we can get this within the libs
directory.
Here we have it a lit native dash lip as oh, by the way, if you're looking into the main activity,
the lip in front is not mentioned over here.
So here we only got native dash lip and therefore I guess the best way is simply to check this lip directory
over here and take the whole library name out of this one.
Alrighty.
Okay.
So let Native Dash.
Let us all and let's see if this one works.
Perfect.
Now we can see we've got all these functions free.
Ma'am, set, ma'am.
Copy, malloc and so on.
Here we have our string compare.
But we do not want to do it all the time in this way, manually searching for this value.
Therefore, we're taking our approach, iterating over this array and finding this one.
We can also see this function has been imported out of the ellipsis dot so, so exactly what we have
thought about.
Okay, so let's see.
This works.
Therefore we copy it.
Over here we are creating a new array, import function array.
And here we have this one.
And then we need to iterate over this array.
So make this a bit larger and this is import function array for each.
Then we've got our anonymous function and within this function we've got our elements.
Okay.
And this is now a single element which has an address, module, name and type.
This means if element dot name and then includes.
Yes.
So includes that we have it.
The string compiler, I guess it was string compare.
Then print it out and console lock element of name and console lock element of address.
Okay, let's see if this works.
Yes.
We've got string compere at this address.
Nice.
So now we can create our new address.
Very able.
And we can assign this address over here.
Okay, that's definitely not good.
Not in good name for this one.
At risk of offspring.
Compare.
Maybe.
Let's do it this way.
This one is equals element.
Start address.
All right, now we're having the address and then we can use our interceptor dot attach.
So interceptor oops capitalized.
Not attached.
Then we've got our address.
Offspring COMPERE And then we've got our callbacks and we are double clicking into this.
Curly brackets enter.
And then we've got our on entry callback, which has our arguments.
And this one is important right now x and let's see.
And zero is our value and x one and this is the value of the flag.
Okay.
So here we have these on enter.
I'll call back.
And this means we want to print out maybe both.
Then we know what we have entered and what's been compared against.
I need to add the space over here now to print out this value.
We have to learn some new things.
But first, maybe let's do it the simple way.
Maybe let's just say param one equals
zero
and param two as equals x one.
Maybe let's see if we are at least getting some something in here and then we've got this only function.
Which is the return value.
And this is now very interesting because if you're having a look into this one, so if you're using
the main page string compare here we have it.
We can see string compares returning in integer value.
Can we find out based on what exactly is missing?
Yes.
Okay.
This is not that easy to understand.
Let's see.
Yes.
To be honest, I do not get anything out of this one.
I have to look it up somewhere else.
Okay.
So I like to use the reference from C++ dot com.
Let's see if it's a little bit more easier in there.
Okay.
Let's scroll down a little bit.
Yeah.
Parameters return.
Nice.
So this looks a little bit or a little bit more understandable.
There we go.
I mean, is it that hard to provide this easy explanation to this one?
If the return value of string compare is set to zero, then both strings are being equal.
Which means we might also just change the return value of string compared to influence our our whole
resort.
The application might think that the result has been correct and performs all the other stuff in there.
So this might be awesome solution that works.
It depends on the use case regarding to our use case where we have to get this this key out of this
application.
It's not a possibility, but maybe for other ones.
Okay.
So now we know hooking the return value is an option, but we would like to observe those parameters.
Okay.
So let's get this back.
This means over here, we can simply just print out the return value.
And this one is the return value.
And this is being printed out here.
Okay.
And let's see if this one works.
So.
Yes.
Regarding to this one, we are not printing them out really right now.
I guess we are just getting the addresses.
But let's see, I pasted in and that's not good approach.
So we should restart this application.
And then also resume it.
And now we are pasting it in.
And so here we have it.
Now let's get back the smartphone screen.
I hit check in 3 to 1.
All right.
What happens over here?
The thing that happens is we've got a lot of string compare functions in our method over here.
So we are now hooking every spring compare function in this application.
I mean, it seems to work and it looks absolutely fantastic.
But I guess this is not something we want to have.
Nevertheless, let's first figure out how we can print out those parameters.
And then we will.
We will find some solution to only focus on our input over here.
Alrighty.
Okay.
So back to our script and this one over here.
I guess this a return value.
We can use our approach in two inch 32.
Let's see.
Not this one.
And here we have it.
So we need to exit out of this.
Oops.
Then we need to relaunch this application and resume and then we can use it.
So let's see.
I'm hitting click in or check in 3 to 1.
All righty.
Here we can see we've got now integer values.
And yet we have also seen that they might be greater or less or zero.
It depends on if the string is equal or not.
Here we can see this, for example, those has been two identical strings regarding to those references.
So therefore, let's see how we can print out these strings behind those addresses.
Unfortunately, I guess our Java type casting approach doesn't work over here.
Nevertheless, let's try this real quick.
So we need our string class reference, Java use, and then Java Lang string, and then we need to typecast
it.
So instances equals Java cast.
And then, let's see.
I'm not sure about this one anymore.
Therefore, we have to look into the documentation.
So within travel script then we are searching for cast.
Yes, we have to use Java cast.
The first argument is our pointer and this one is the class which we want to typecast it.
If we go back into this one, this means this one zero.
That's our pointer.
And by the way, in this time it is at zero.
Why?
Because we are not in decay function anymore.
Therefore, our first parameter is not an environment pointer regarding to the Java and decay.
This is now really an argument that's been provided to string.
Compare this one over here.
And this is our s one and our argument one is our is two.
Alrighty.
So we are not within the k-word anymore.
We are in the plain C C++ word right now.
So therefore all arguments are exactly like we have them in this function definition over here.
Okay, let's close this and let's see.
Acts 1a0.
Sorry.
And then this is our string class reference.
So let's see if we can do it this way.
This has to be changed as one bracket.
So let's exit out.
Sue.
We are entering this opening this application, 3 to 1.
OC it crashes so we can see.
Yes, chain eye detection error, chain object and things like this we cannot use and typecast from
our our Java string reference to this reference over here.
This is now an plain C string and therefore we cannot typecast it in this way.
Now is the question how can we access this value then?
And the answer for this one can unfortunately this time not being found in the official documentation.
I don't know why, but it's not a big deal.
I will show you how we can do this.
And I mean, then we have everything set up.
You only need to watch these videos if you want to know how to print out indicate parameters, plane,
see parameters or travel parameters.
Alrighty.
Okay.
So let's go back into our code.
This one over here.
So this one is not working.
That's bad.
Not the question.
How is it working?
And we have in freedom another nice object, which is the memory object.
So we can use memory.
And then we've got this method.
Let's see, let's restart this application.
Memory.
Right.
And then we've got a lot of things read and see string.
That's not point.
The read UTF eight string.
All right.
This is the method we want to use.
And also here we have to provide an pointer and address to this function.
And this one is now our arts in zero.
Okay.
Let's see if this one works.
And paste it in.
I hit chicken 3 to 1.
And we can see.
Yes, it seems to work.
We've got this string over here.
Parameter one, we've got this one over here, Android OS message and things like this.
So it doesn't look like that.
It did work, but it seems to work.
Yes, I guess it works in this way.
All right.
So this is how we can print out an and string regarding to in plain C function in freedom.
And let's also do this for the other part and this one over here.
So we copy this.
And we're using this phone over here.
I'm sorry.
It's not this one.
All right, let's see if it still works, and then we can also compare them and see those results if
it's really working.
We are restarting this application or I need to provide this no pass attribute hook in 3 to 1.
And let's see, this one was one string.
This is the other.
They are not equal.
Let's find some some strings that has been equal.
There we have it.
Yes.
Android OS and Android OS.
And those strings has been equal.
Therefore, we're having this return value zero.
Nice.
And this means in there, there needs to be our flag.
And also the other part that's been compared against.
How can we find this right now?
I mean, we could save this into an external file and then browse through this.
But this is not idea.
The easy approach is the folder.
If we have this over here, we can write an if statement once again, for example, we can say if this
one over here.
Maybe let's write this into a variable.
Well, let's name this.
We use an input.
Okay.
This is our user input.
And now we're searching through all the string composer functions that has an argument with our user
input.
And this means this is the string compare function that's being used over here.
Alrighty.
Okay.
So if our user input includes and then let's see flag.
And then we want to print out those two parameters.
All right.
And this should work.
The thing we are doing right now is the following.
Maybe let's draw this real quick.
Okay.
Within our interceptor attach and this one over here, we are now hooking all these string compare functions
in and string compare parameter one, parameter two.
And we get a lot of output if you're are using this one over here.
So this is a lot of output.
We have seen this in the previous example.
Therefore, we want to limit it and we are limiting it in the following way.
We are fetching our ARX zero, which is our user input in this one over here and we are now telling
freedom only print out these string compare parameters.
I mean, we are still hooking them, but we are only printing them out if this parameter over here contains
this word flag, which is this one.
If this is the case, then we print it out, which means we are not having these menus right now.
We are only having these two which compare our flag with the value.
I mean, if we are having multiple strings that contains flag, then we need to choose a different payload
over here maybe one, two, three, five, four, six, eight, six, seven, nine, one.
If we are providing this one over here as the user input, we can then search within the ARX zero for
this user input and we can by doing this we can limit it to only print this one out, this string comparison
function.
Alrighty.
I mean, we are still hooking them and this might be a little bit laggy, but we are only printing this
one out.
Let's try this out.
Okay, so we clean the screen and now let's see.
So we close this one.
We restarted.
Okay.
Now I paste the script in and you hit check in 3 to 1.
All right, we can see Flex seems to be contained a lot, way more often than expected.
No, sorry.
This is.
This is the return value.
My fault we are printing still out all these return values and we can see I have to close this one.
It's out of control right now.
Let's close this.
Okay, good.
You can see hugging and see function might be a little bit messy.
All right.
I didn't thought about this one.
We are still printing out the return value.
So this is also okay.
Never.
Never mind.
Just keep it in this way.
So we are just ignoring the return value right now.
Let's try this once again.
Okay.
We paste it in and check in 3 to 1, then we have it.
Nice.
We only got one.
Yes, we only got one and we can see parameter one is flag.
That's our user input and here we can see parameter two and this is this free the hooks.
Okay, insane free the hooks.
This means this is our flag that's being compared with our value over here.
Perfectly nice.
If you change this one and let's see to only flag, we can check now we are only providing just flag.
Okay, perfect.
So this means even if you're hooking or this string, compare functions which are a lot, we can limit
the output to the ones we are interested in.
This one over here, we can define this or we can manipulate this in a way by using a unique identifier
and checking this identifier in our argument.
I mean, flag is also being included in this one over here.
And let me bring this one up again here.
We can see it's also included in parameter two, but this one is not being checked, only the one we
are providing in parameter one, which is also included in the source code over here.
I mean, to be 100% sure we can choose a more unique one.
And for example, multiple three, four, five, six and then a little typo nine, eight zero.
Let's also do this over here.
One, two, three, four, five, six, 7980.
And let's relaunch this application.
Mean resume.
Here we have it.
And now let's paste it in this one.
If you are, let's verify if you are using FLAC, then we can see no output.
But if you're using 1234567980.
Then we can see we have our output over here.
All right.
This is an amazing trick, which is absolutely useful.
If we go back into this one, maybe let's also see how we can hook this return value over here.
It might be interesting to see what's the what's the return value of this function.
And if we enable this one over here, then we are hooking once again all return values, which is definitely
something we do not want to have.
We get a lot of output to get only the return value of this.
One of this string compare function, we have to use or introduce a new variable because these functions
are independent and therefore we cannot provide one parameter into the other one.
But I mean, we can define this globally.
So let's see, we are creating here a new one is our function and this one is set to false a boolean
value.
All right.
If we are in within our function, we are setting this one to true.
And if this one is set to true, then we are printing out the return value.
Okay.
And afterwards we need to set it to false once again, because otherwise we would have all these return
values be printed out after this function.
Okay.
So maybe let's commend this real quick, introducing the new state to get the or let's say to.
Only print out the return value of our string.
Compare.
And here verifying that this is our string compare which we are interested in and here and setting it
back to false.
Otherwise all return values afterwards would be printed out.
All righty.
This is what this new variable does.
Let's see if this works.
So we close this one, we restart it.
We resume, and then you're taking the script.
Maybe I make this a little bit larger.
Yes, we can use all of this OC and we pasted it in.
Green.
Yes, this should work.
So let's see.
We are hugging right now for this one.
If we click check, nothing.
Nothing appears, which is good.
But if you're doing one, two, three, four, five, 67980.
And hitting check once again in 3 to 1.
There we have it.
And we can also see the return value.
It's not identical.
Nice, isn't it?
Let's verify if this one is really working.
So let's also provide this one over here.
Then we have to make this adjustment once again.
Yes.
So we have to restart this application.
Resume.
I mean, you can also apply this no pause.
I don't know why I'm not using it, so it's a little bit annoying, but yeah, so you feel free to use
it.
Okay, so we are applying this one and let's see now we have the the original flag and this one should
now return and return value of zero and let's see.
And 3 to 1 nets so we can see this is definitely the return value.
Yeah.
Regarding to our function over here and we are really accurate with our hook right now.
So if we go back, we are now just printing out the string compare over here and this one and non other.
I mean regarding to the hook, we are definitely hooking all the other string compares, but we are
not printing them out.
Alrighty.
Okay.
So this one over here, this is freaking amazing and this trick is super neat.
It will come super handy if you're reverse engineering native libraries and want to hook certain functions,
for example, C library functions.
Okay.
Maybe one last thing regarding to this one over here.
This approach I have seen in the comment from the from the free the developer that read UTF eight string
might sometimes not work so is also an additional function that tries to read and string.
This is unfortunately really complex within freedom.
So free that doesn't know at this point what type of string it has and these types are different.
Therefore we have to try it out.
If some of them works in this case, read UTF eight string works perfectly fine.
But I also want to mention that we've got other functions.
For example, this one maybe let's let's check this out in freedom because I cannot remember it any
more correctly.
So let's do this over here, right?
I guess.
Yeah, it's a C string.
Okay.
This is also a function that tries to read and string out of an address.
And yeah, if this one, this UTF eight approach doesn't work, then we can try this one over here.
Maybe.
Let's see if it would work.
So.
Or you know what?
Let's keep them in here.
And now let's.
Let's provide them over here.
Okay.
And here we have to insert X zero.
That's not R0.
And here we have to insert.
Box one, and we need to make sure that we are also fetching or adjusting this one.
Let's see if this one works.
I'm also not sure about this, but this can come handy.
So let's see.
We are restarting this application.
Oh, we resume it.
We provide our script, and we have to provide the correct flag.
Okay.
And let's see.
Three, two, one.
Yes.
Yes, it works.
Perfect.
So in case if the if one approach doesn't work, then simply just try the other one.
So within the cheat sheet, I will also provide some additional ones.
We cannot talk about all of them and it's also not clear when we have to use what, because it really
depends on the library and this is something we cannot reverse engineer or figure out.
Just simply trial error for this one already.
If you encounter some errors, have a look into cheat sheet.
And if you still encounter errors, please write me a message.
I have also promised you that we've got several approaches and one of them is also this is freaking
amazing with in Chitra we've got this function over here at this address.
This is of course not the real address, but we can make a hook which is really precise on this one
so we can tell freedom to only hook this single function over here.
And this is it's amazing because let's assume we have not that easy access to our input parameters,
but we want to figure out what is happening in there so we could hook native function but and then we
will get a lot of outputs.
So a ton of output, therefore only making one hook.
Exactly.
At this point this would be absolutely nice.
Right?
Let's figure this out.
But this time we are not doing this on a real smart form.
So we are not doing this over here.
We are using the virtual machine.
I will prepare a whole bonus section regarding to debugging Android devices and also apps on the virtual
machine.
But regarding to Android devices, we have to consider a lot of things and this would make this video
unnecessary.
Long But in the virtual machine it's way easier.
Therefore, we are doing this approach over there.
But don't worry, with in the bonus section, you will get all these information that are necessary
to also perform and precise work like this one over here on your device already.
Okay, for now, let's quit this over here and let's put up our beta machine, okay?
If we're using a virtual machine, let's see if this one is still running.
Yes, we are still connected to this one and we are only having one ADB device.
So if you've got still multiple devices listed and the easiest way is to simply unplug your device and
then using ADB Kill Dash server and reconnecting to your virtual machine.
Yes.
And then we should have access to this one.
All right, perfect.
We can already see we've got an x 86 prompt, which means if you want to hook a library within the x
86 version, we have to use it also inside.
So we need to load this into Twitter because all these addresses and extraction will change.
This one here is the architecture and this is completely different from the x 86.
We had an little section about this y and smartphone is using an ARM architecture and while your PC
is using an X 86 version.
All right.
So this means what we need to do is we need to close this project and get close to.
All right.
And then we've got it over here.
And this is our project.
So we can stay in our project and we can include this library once again, but this time for the x86
version.
So let's do this.
We are opening the code browser and then within file import file we are now selecting not this one,
we are selecting x 86 in case if we're using the x86 and 64 bit version, then of course you need to
use the x86 64.
The addresses in there might also change, but the approach is the same.
So you're good to go.
Also using this one over here, I will do it for the 32 bit version.
So we select this file to be imported and now we can see this already exists.
Therefore, with any program name we have to make an adjustment and I simply name this leap native x
86.
We can see it has been automatically being detected by Chitra and all we need to do is and simply loading
this.
Okay.
And then we've got one quick scan fetching all these information.
And now once again, this little native x 86 has not been analyzed.
Would you like to analyze it right now?
I keep saying yes.
And this time we do not have this aggressive instruction finder and this time we only using this de
compiled parameter id och this x86 six does not have modes like arm or thumb.
Therefore, we also not having this aggressive instruction finder in here.
We can also see some libraries has not been found, but that's absolutely no big deal.
These are also just external libraries and we are interested in this function which is used in this
list so we can simply ignore this.
Okay.
We can see it's being analyzed also on the bottom.
Right.
Now, we have to wait until this one has been finished.
It has been finished.
And let's get back into our symbol tree.
And we're looking for hide and seek once again.
I mean, the symbols are the same regarding to the name, but now we can see the output is a little
bit different.
Yes.
We've got some more stuff in here.
And we can also see this one.
It's yeah, this typecasting over here, it's a little bit more confusing.
Nevertheless, let's get out a graphic tablet and let's do also this quick analysis over here.
Alrighty, let's do this.
Okay, so here we have our graphic tablet and let's grow apples.
Okay, so here at the first parameter, we forgot once again our environment pointer, this one over
here, this is our this object.
And here in parameter three, we're having our trade string.
So this one, this is our object or this is our, let's say, user input.
Regarding to those parameters, it's exactly the same.
And let's rename this so we can do this by clicking on this and hitting the L letter in this one.
And this is our environment and pointer.
I'm sorry.
Environment point now.
And this one over here.
This is our.
This object.
And this one is our user input.
Okay.
Now let's track this user input.
Okay.
User input is being assigned to local 64.
So this is something we also need to rename user input.
Oops.
And this time it seems to be a local bar.
Let's see, our user input is also being used in Local 40.
This one over here and here we can see once again get string UTF chars our environment pointer and this
one is an address.
We do not care about this one.
And here we are having our user input, which means and this will be afterwards our user input.
So this is also our user input.
We've got a lot of user inputs or references in here.
And then once again, within this string compare, we can see here we are having our user input.
Nice.
And this one is in local variable and we can see this one has been not defined.
I mean, this one over here, we are not getting printed out this nice text so it's not showing in this
one is not showing our flag right now.
So local underscore for see this is our flag.
But this time we are not having that easy access to it.
Therefore we want to hook this function, this string compare function.
Maybe let's clear this.
And so we want to hook this function.
And once again, we want to observe this parameter.
And we also want to observe this parameter.
This is our flag.
Okay.
Therefore, we taking a look into this one.
This is the address.
But this is not the device address.
If we are hovering over this one, we get a lot of useful information.
So I hover to this address.
Yes.
So let me clear the screen maybe.
Okay.
So here we are having an image based offset, this one over here.
And this means the following.
Our library, our lib native, the lib.
As all this will be loaded into an ad and fixed offset, which means and value will be added to this
one.
Let's say the value is 0x1.
In this value, for example, it doesn't has to be this value and it doesn't really matter.
And Chitra is loading this library at this fixed address and then we are now having this offset.
So at plus eight D, six C, this is an hex value plus this offset, we can now find this instruction,
this string compare function.
We only got some additional things.
Let's see.
We've got memory block offset, but to be honest, we can ignore this one.
This is not really relevant.
And then we've gotten function offset and this can come also super handy.
Our function is named hide and seek.
So within our within our library, we've got this function.
Hide and seek.
And so on.
And now we're having an offset from this function to this point.
Maybe let's say this is the point where the string compare is right now
and this is the offset over here plus zero x CC.
So this is the offset from the function to the string compare in here.
I guess we will later go up to this one and then we will see this.
All right.
And then we've got this one.
I mean, it's exactly the same over here.
This means from the starting point of this library lib, negative dash lib as all plus this value,
and this is the value which will be used later on.
So we are using this offset to identify where this function is being located on our virtual machine.
All right.
So this was a lot input right now and we are pretty deep into reverse engineering this native library
right now.
Maybe let's try to summarize this real quick.
What is important?
The important part is that we identify where our user input will be compared.
This is the function we need to hook.
In this case, it's string compare over here and this time we do not want to hook all string compares.
We only want to hook this string compare function.
Therefore we need to get the address of this one.
But this over here, this is not the real address because this smartphone is loading these libraries
at different points.
It might also change every time we are launching an application.
Maybe.
Let's talk about this one really quick.
And this application is loading a lot of libraries.
For example, this one over here, our lib native the lib.
So there will be also another one, for example, the lib C.
Let's see.
And so and there will be tons of other libraries that's been loaded.
All of them will be now assigned to certain memory addresses and for example, seven, H, B, B and
so on.
And this one will be at zero X, seven F and so on.
And this means based on the memory layout of our smartphone, we are getting different addresses and
for example, this one over here.
And therefore what Chitra is doing is the following.
And Chitra is loading this library into its tool.
And she addressed providing a base address, for example, zero x ten 000000.
And from this point on, everything will be aligned and it will be all the time the same based on this.
This is the base address.
So every time we are providing the same base address, we have our functions at the same point.
For example, this one over here.
This is our function.
Hide and seek.
All right.
Okay.
So this is the difference by this address in this free to function, which is zero x ten.
And I'm not sure anymore.
Let's say six C is different from the real address in this device.
So now we can say, okay, we are fetching one time the real address in our device and this one over
here, and then we can apply all these patches on this address.
Yes.
And this would normally work, but not on modern smartphones anymore, because every time we are relaunching
an application.
So every time this one will be restarted.
These addresses change.
So afterwards this might be 0x7200 ten.
The reason for this change is in security feature, and this security feature is named as LR address
space layout randomization.
So let's assume we identify and buffer overflow within our application and for example in this library
at a certain point let's say over here.
So here we are having in buffer overflow.
What an attacker does is the following the attacker jumps to a certain function and for example, the
system function within our loop.
C and then it's executing an command in there.
By having an address based layout randomization.
The attacker can can overwrite this address at this point, but the attacker does not know where the
system Lipsey is being located.
There are some countermeasures regarding to this one from the perspective of an attacker.
But let's make this not too complex so the attacker can overwrite this pointer at this address and the
attacker can make the decision where we want to move on in the program.
But if we if we are assigning every time a new address to the base address, then this layout over here
will change.
So this one over here, the offset is still the same.
But in this one, this is, for example, not ten anymore and this one is now 721.
Maybe it's located now at 710 or maybe at and complete different one, 80, 20 and things like this.
This means the address which will be hardcoded here in this one, this cannot be reliable, used to
jump to a certain function within the lib binary.
Okay.
This is now really deep into exploitation, which is also not this topic.
I just want to point out that yeah.
That we cannot rely on those Chitra addresses and that we are also getting every time a new address
here restarting this application so we can also not rely on those fixed values.
Okay, this is the reason behind this.
It's an countermeasure.
It's named as LR and it's good to have in our smartphone, to be honest.
Okay.
So now let's get back to our main topic, which is about hooking this function, this string compare
function being back over here.
We now know why we cannot simply use this address over here.
This will change and it will change every time we we are launching this application.
But what that's not change is the offset, this one.
This offset doesn't change the lit library.
This one.
This does change.
But not the offset.
So therefore, it's absolutely clear what we need to do.
I mean, not right now, but if we have done this once, then it would be clear we need to get the address
of this library, this one, this address, and we can do this with freedom, which is absolutely amazing.
So we can tell free that to fetch this address of this library, then we need to add this offset to
this library.
And that's offset, which means we end up at this address.
By having this address, we can then use our interceptor.
Interceptor dot attach on this address and then we can also provide our callbacks.
So sorry, the bracket is not that's not close in there.
We have to provide our callbacks.
So I guess it's not the cleanest writing, but I guess we know what we have here.
Maybe.
Let's do this.
Call backs.
Way better, I guess.
Okay.
Nevertheless, we will do this afterwards.
So this is our plan.
And by having this plan, we are only hooking this address over here.
And this address is this single string compound.
So this means we are having access to those parameters.
Where are they?
Here.
And this one and also this one.
So we can print them out afterwards and we can make an really precise hook in our native library, which
is freaking awesome, right?
Absolutely.
Let's pull all of this together in one single script and let's do this.
Okay.
And first, let's create a new script.
It changed to JavaScript.
And people summarize really quickly steps we need to take.
The first one is getting the base address of this library and getting the base address of this native
lit.
Sorry, it's lit native and lit as old library.
Then we are getting the offset into our stream compare function.
Then we are adding both together, which ends up in the address we want to hook.
And then all we need to do is simply printing out, printing out the parameters.
All right.
And this is our attack plan.
So let's see the offset.
This is something we can fetch from Chitra by marking this address and keeping the mouse over this one.
We can see the offset is HD six.
See the H at the end simply means that's an hex value.
So HD six C.
Green.
Lets see offset HD and six c.
Maybe let's put this on the right and verify this.
Yes.
This is our offset and this is an hex value.
Perfect.
Now we need to get this base address of this native library.
And freedom, of course, has an amazing function for this one.
But first, we need to start the free server on our on our virtual machine.
So here we then data local temp
and here we have this one free the server.
By the way, I have updated Frieda.
I guess it doesn't matter, but in case if you are having some new features or running into trouble
within the most up to date version, I would like to have it in my course.
Alrighty.
OC in case if you encounter some troubles regarding to the old version or this one over here, please
write me a message.
We will figure this out.
So the Frieda server is running right now and let's get back our screen.
Do we have it already installed?
Yes.
And this is our C func Frieda.
And if you click track, the flag is wrong.
All right.
This is working perfectly.
So now we can attach number three to this one free to dash you.
Com app hacking to see funk of Freedom.
Yes.
I encountered this now quite often.
I'm not sure what's the reason behind this, but what works is if we are restarting this application
with the F option, then our hook will work.
So resume.
Yes.
So we can see this one works.
I'm not sure what's the reason behind this?
All right, maybe.
Let's put this on the left and this one on the right.
So within the module, we've got another nice function, which is you get base address.
This one over here.
And then we simply need to provide the library where we want to have the space address in our case,
little native dash lit.
So this is our library and we want to fetch the space address.
And here we have it.
This is the base address.
Maybe.
Let's try something.
If we are restarting this application, let's see if this one changes.
And once again.
Yes.
So we can see here we're having a different one.
This means.
We cannot simply rely on a single one.
We need to fetch this at runtime.
Okay, so this one over here is now our new base address.
Let's put this on the right and write this down.
This is the command to get this address.
And we are creating a new variable to store this address of our string, compare and function.
No.
This is the address or let's call it.
Okay.
And let's put the mouse on the right and then let's assign this to a new variable.
The variable space address.
Okay.
So this function over here has also been very amazing feature.
I mean, the author might have also thought about this to not always calculate it manually, the offset
regarding to the space address.
So we are talking now about this one, this little native dash LIPOSOMAL Plus HD six C.
So our offset over here, what we need to do is we need to fetch this value and we have to add this
value on top of it because that's the difference from our lip, native lip from the beginning.
Woops, that's not a straight line, but I guess it works out to this one over here.
All righty.
This is this offset right now.
And this also doesn't change.
We do not need to do it manually.
And Frida has this amazing feature.
Let's make this a little bit larger.
We can use it, and then we can simply provide our offset to this one.
So we are using this one and this one, and then let's make this large again.
We are adding this value on top of it.
And let's see.
And there we go.
Now we can see this value has been added on top.
And this means this one right now.
This is our address of this.
String.
Copy.
Sorry.
String.
Compare.
Function over here.
This one.
Okay.
So we can summarize this together.
And at the offset tool string compare and function maybe to the.
Let's make this a little bit larger then you can read the whole comment.
Okay.
Base address.
Or let's maybe rename this.
Address to hook.
As our final address we need to attach.
So this one is now the address that's being applied to our to our intercept interceptor dot attach from
this one that's also included over here.
I mean, it's also renamed us.
It's the offset to our spring compare function.
Now we've got everything together.
That's also done.
And the only thing we need to do is we need to use our interceptor attach on this one.
So intercept that thought attach.
And then we've got our address to hook and this one.
And then we've got our callbacks.
Double click curly bracket a few times, enter on enter callback.
And then in this function here, we're having our arguments.
And this one is now the single string compare function within our native dash lit as our library that
performs the check of the flag.
All right, so let's print this out.
Parameter one is.
And now we are using memory dot read UTF.
I need to have this freed up because I cannot memorize this one.
So memory dot read UTF eight string OC.
This one over here.
And we're using this on arcs and zero.
One bracket is missing and there we have it.
And this can be deleted.
This is our parameter one.
And now we're doing this for parameter to.
And in this time there are some promising.
We are also having this on leave and function.
This is now our red value and this time we can directly print out this return value because we are only
hooking one single function.
Therefore this won't be flooded.
Like the previous example that we have hooked every single string compare function.
Alrighty.
Okay.
So this one here is our return value.
And this one we know.
The return value for return value is zero.
If strings are equal.
Equal.
So this means our return value is an integer.
Yes.
And this looks perfect.
Let's see if this one works.
I mean, these are just a few lines to hook and very complex function within the native library.
Amazing, right?
Let's see if this works.
So let's copy this.
Okay.
We're restarting this application.
I resume manually.
I hope you have attached this dash rational pause that it's not the dump like I'm doing it right now.
Okay.
Here we have our application.
I'm super excited if this one is working.
Okay.
No arrows.
Let's see.
I'm hitting check in.
Three, two, one.
Okay.
We are getting an error, but we are also having this one flag in Saint Fidelis.
All right.
The first parameter seems to work, but the second one doesn't.
And now we also have to mention we are on a different architecture.
This means these parameters are now changed.
This is now a lot of stuff I know.
And this is really unfortunate.
And we can unfortunately not talk about all of this right now.
If you have some questions, of course, feel free to write me a message.
But let me try to summarize this real quick.
I'm really sorry that it's that complex right now, but maybe you can figure out what's going on.
And this would be absolutely amazing.
So within the last example, our first parameter, and this was the string we have inserted into this
application and this one over here is now a different architecture and therefore the calling convention
is different.
These parameters are being swapped and the first parameter, we are not having our string right now.
We are having this solution, this one over here.
And to be honest, I do not know why we cannot decode this second one and this one.
This is our string that's being provided to to this function over here.
So maybe there's some issue regarding to the typecasting.
All right.
So this is what's happening over here.
I mean, it's amazing.
We can see we are only hooking one single function and this one over here.
And it seems to work.
I mean, it works.
We've got the proof over here.
So what we can try is the following.
Instead of using this, read UTF eight.
We can we can try to use this, read c string and let's see.
Och, no, we're not having Frida anymore.
I get it back because I would like to use the anthology of Frida.
So read C string this one.
Okay.
Read, let's see.
Spring, maybe.
See, spring is able to print it out.
Let's see.
I mean, we can leave this open.
We apply now our patch.
Has the application been resumed?
We are not sure about this one.
Maybe.
Let's change this.
We are hitting check in 3 to 1.
All right.
We are not getting an error, but we can see this one.
I mean, it's not being typecast to in C string and there seems to be also no sea string, but at least
we are not getting an error.
I will do some research on this, what's happening in there, and then I will provide an update on how
to hook this parameter.
Right now, I have also no clue why this is the case regarding to this post and from the main developer
we can see.
You can't be called byte at a certain position.
So this is regarding to playing around with read C string or read UTF eight string.
So dealing with strings when the encoding is not known right now, it's it's really rough.
And unfortunately, there's not an easy way.
We have to use a lot of options and simply try them out if they work.
All right.
Okay.
So this is all for this video right now.
Maybe let's do a little bit of recap.
But in Chitra, we have identified where our parameters are being passed into this function and this
one over here.
So we have cracked it down from this one to this one and from here into this function.
Then we know this is the function we want to hook.
Here we have seen we've got an address, but this address is not the real address.
This address will be calculated based on the loading point of this one.
Plus this offset.
This one will unfortunately change every time we are relaunching this application.
So we cannot use an hardcoded value.
But this is absolutely no problem for us and Frieda right now because Frieda has this amazing feature
get paste address out of this library and this even more amazing feature to automatically add in certain
value onto this one.
So by having this line, we are getting the offset within our application to this point over here to
this address in our smartphone app.
By having this one, the rest is pretty easy.
We can yeah, we can apply our interceptor dot attach on this address and then we are using these arguments
to print them out.
This one, I'm not sure why this one fades right now, but I will provide an update to this video over
here and also within the cheatsheet.
I will provide a lot of options that you can try out yet to read out in certain string.
Over here we've got the return value and I guess we didn't check the return value, so let's go back.
Okay.
It seems like the return value does not get printed out over here.
Maybe because of this error, this would be a little bit strange.
Okay.
So this one is also unfortunate.
And for now, I have no explanation why this is the case.
Also on this, I will provide an update.
What's the issue and how to solve this?
Regarding to our hooking approach, we have seen we can also hook really precise one function in our
complete code and we have also seen we can hook all of these functions in our code, which will be a
little bit messy.
But we also know how to deal with this one by providing a unique identifier.
Over here, for example, this 11234567980.
And then checking for this unique identifier and only printing out this function that has this set as
an argument.
Here we have seen this works perfectly fine.
And this is also my recommendation of choice to go for this one over here.
Alrighty.
All right.
And this is all for this video right now.
And the next one we will have a look into in real world capture the flick.
This will be our red pad challenge.
And this one, it's really not that easy.
So if you can solve this, this would be freaking awesome.
And then you absolutely deserve your red pad.
You would be an absolutely free ninja in hooking all these Java methods, creating new instances, observing
instances, or playing around with the NDDC or even playing key functions like we're having it over
here.
So this is what we have learned in this chapter and this is a lot and it's freaking awesome that you
are still there and made it through the end of this one.
Therefore, I'm really looking forward to see you in the next section.
Maybe having a dip into the challenge.
See you there.