In this video let's understand PLT and got PLT stands for procedure linkage table and got stands for
Global Offset Table.
When we call functions like printf from Lipsey, they are dynamically linked to our binary and then
executed.
Remember, this is not true for binaries that are statically linked when functions from shared libraries
like Lipsey are called a call to a piece of code in procedure linkage table is made.
This will in turn take help of dynamic linker, which will search through Lipsey Library for the address
of our print function, and it will add an entry in global offset table with the address of the function
invoked.
Once the address is resolved, it will get executed and the control will be transferred to the saved
return address.
When the same function is called for the next time in the code, the address stored in the global offset
table will be used instead of invoking dynamic linker to resolve the function address again.
So as you can see here on the picture, the PLT stub code is not taking the help of this dynamic linker
anymore to get the address of printf function from Lipsey.
Instead it is directly using the entry that is available in global offset table.
So to summarize, PLT is just a stub code which is going to invoke this dynamic linker to resolve the
addresses of the functions that are being invoked from Lipsey.
Once it resolves the address, the address is going to be updated in Global Offset Table.
If the same function is invoked for the next time.
Instead of resolving the address once again, the address will be picked from the global offset table.
This is how procedure linkage table and Global Offset Table works.
I have left some low level details during this explanation, but I think this should be enough for now
to understand what PLT and got are.
Now let's see a quick demo of how PLT and GT look like in GDB.
Let's navigate to x86 underscore 64 and let's navigate to a red to PLT.
Here we do have two files.
The first one is vulnerable point C and the second file is Makefile.
Let's quickly take a look at the contents of vulnerable point.
See if you notice we have main function.
Inside the main function we have three functions.
The first one is printf, the second one is one in function and get date is the third one.
After invoking this one function, we have a buffer overflow here.
Within the definition and inside the definition of get date, there is nothing much.
There is a system function which is invoked which is actually printing the date and we have another
printf now to understand plt and God, we can use these two function calls as example because to understand
God and PLT, we need a function being called more than once.
So printf here is a very good candidate for us to understand plt and geode.
Now let's take a look at the contents of Makefile.
If you notice, I have added an additional flag here, which is dash no dash p.
This flag must be specified here for this demo to work.
The reason for that is we are going to use the addresses within the binary while writing the exploit.
And if we don't specify this flag, the addresses are going to be changed on each run.
This is something like a slot within the binary.
Right?
So let's use this makefile to compile the program.
So I'm just typing make.
There are some warnings, but seems like we have our vulnerable binary ready.
Now let's load this binary using gdb.
And let's type this as Maine.
If you notice, there is a put call here, which is our printer.
If you remember, there is another printer within get debt.
So let's also type this as get debt.
If you notice, there is another call here.
So what I'm going to do is I'm going to set up a breakpoint at these two, puts calls.
So I'm just copying the first address and I'm just setting up a breakpoint there.
And I'm also copying this address associated with the second puts call and I'm setting up a breakpoint
there.
Hit enter.
Now let's run the binary using the command.
Run.
And if you notice the first breakpoint is hit which is at the call to puts function.
Now let's observe where the control is being redirected to.
This is where the control is being redirected to.
We are being redirected to execute some instructions in PLT section.
Immediately after that there is a jump instruction to put it dot, dot, plt.
So after landing in this PLD section, we are making another jump to this section which is dot dot plt.
Now let's keep executing see instruction.
So we have taken a jump and we have taken another jump.
If you notice, our execution now is landed in this section.
Now, we don't know what this section is.
We don't know where we are.
So let's quickly take the output off the map and let's try to understand which program in memory these
addresses belong to.
So if a7a is zero and if you notice this is what the address belongs to, what it means is these addresses
belong to this LD library, which is the dynamic linker loader.
This program is going to find out the address of put function from C and global offset table will be
updated with an entry.
This entire process is called lazy binding.
In a nutshell, this dynamic linker loader does all the heavy lifting in the background and finds the
correct addresses of functions in other shared libraries, even when ASL is on and dynamically links
it to executable via the global offset table.
So when the puts function is executed for the next time, the address will be readily available in the
global offset table.
Now let's type C to continue our execution.
Let's enter something.
Now we hit the second breakpoint.
You can see here we are about to call the function.
And we also have another instruction which is taking the jump to this God dot plot section.
Now let's type C and observe if we land on the dynamic linker section once again, I'm just typing a
sign.
If you observe we are already in the function this time the dynamic linker did not have to do the loading
once again as the address of the function was already available in the global offset table.
Let's quickly confirm that these addresses indeed belong to outputs from the Lipsey Library.
So I'm going to just type via map.
Let's see if you notice this.
This address is ending with seven E 40 5a0, and that should be in between these two addresses.
That means these addresses belong to Lipsey Library.
Right?
So that confirms that we have landed inside the function directly within Lipsey Library.
And the dynamic linker did not have to do the function resolution once again.
So this is how the procedure linkage table and global offset table works.
Just to recap, when a function which is available in Lipsey is called from within the library, a stab
code within PLT is going to be executed, which in turn is going to take help from this dynamic linker,
which is going to go through the Lipsey Library and search for the actual address of this print function.
And it is going to update that in global offset table when the next time the print function is invoked,
instead of going through the dynamic linker, this address will be picked from the global offset table
directly.
So that's how procedure linkage table and the global offset table work.