Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to deeply understand GOT table and PLT table

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)05/31 Report--

This article shows you how to deeply understand the GOT table and the PLT table, the content is concise and easy to understand, it will definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.

Preface of 0x01

The operating system usually uses the method of dynamic linking to improve the efficiency of running programs. In the case of dynamic linking, all the functions in the link library will not be loaded together when the program is loaded, but will be loaded on demand when the program is executed. If a function is not called, then it will not be loaded in the program's life. This design can improve the fluency of the program and reduce the memory space. And the modern operating system does not allow to modify the code segment, can only modify the data segment, then the GOT table and PLT table came into being.

A preliminary study of 0x02 GOT Table and PLT Table

Let's take a brief look at an example.

Let's follow up on scanf@plt.

You will find that there are three lines of code

Jmp an address push a value into the stack jmp an address

If you look at the name of the function, you can see that this is the plt table of the scanf function. Don't rush to understand what plt is for. Let's move on and see what the first jmp is and where it jumps.

In fact, this is the got table of the corresponding function of the plt table, and we will find that the value of 0x201020 is the address of the stack command, and elsewhere it is 0. At this point, we want to ask:

What's the point of got and plt tables, and why are they jumping around?

2. What is the relationship between got table and plt table, and is there any corresponding relationship?

Then take a look at the answer with questions, and then verify that we need to understand that the operating system usually uses dynamic linking to improve the efficiency of the program, and can not be written back to the code segment.

In the above example, we can see that call scanf-> scanf's plt table-> scanf's got table, as for the value of the got table for the time being, we can form such a thinking at the moment, it can find the real scanf function from the got table for the program to load and run.

After we think so, then it becomes an indirect addressing process.

The small piece of code that gets the address of the function stored in the data segment is called the PLT (Procedure Linkage Table) process link table and the data segment that stores the function address is called the GOT (Global Offset Table) global offset table. After we have formed such a thinking, we will carefully understand the details inside.

0x03 re-explore GOT Table and PLT Table

Now that we understand such a rough process, let's take a look at how it is called step by step. There are several doubts that need to be solved:

How does the got table know the real address of the scanf function?

What is the structure of got table and plt table? Let's first take a look at the plt table. We just found that the third line of code in the scanf@plt table is jmp. Let's follow up and see what it is.

In fact, this is the beginning of a program's PLT table (plt [0]). What it does is:

Push got [1] jmp * * got [2]

This is followed by the plt table for each function. At this point, let's take a look at this mysterious GOT watch.

Except for these two (the address of the push 0xn of the printf and scanf functions, that is, the address of the second code of the corresponding plt table), the other got [1], got [2] is 0, so why does the plt table point to the got table with 0? Because we left behind a condition, the modern operating system is not allowed to modify the code segment, can only modify the data segment, that is, write back, a more professional term should be run-time relocation. When we run the program, our previous address and saved content have changed. before that, let's save the content of the link and make a comparison.

② looks for printf's plt table ③ jmp to plt [0] ④ jmp got [2]-> 0x00000 ⑤⑥ printf and scanf's got [3] got [4]-> plt [1] plt [2] the address of the second code ⑦⑧ confirms the above

Run the program and drop the breakpoint at scanf

You can see that the scanf@plt table has changed. Check the contents of got [4].

Continue debugging at the same address as push 0x1, until here, the got [4] address has been modified

Now I want to ask, where is this?

Then there is the call in got [2] to modify the address in got [3].

Then the problem arises, isn't it 0 at got [2] just now? why is it this (_ dl_runtime_resolve) now? This is run-time relocation.

Actually, the first three items of the got table are:

Got [0]: address of .dynamic section is the loading address of this ELF dynamic segment (.dynamic segment) got [1]: address of link_map object (0 at compile time) is the address of the link_map data structure descriptor of this ELF, function: link_map structure, combined with the offset of .rel.plt section. To really find the elf's .rel.pltgot [2]: address of _ dl_runtime_resolve function (populated with 0 at compile time), that is, the address of the _ dl_runtime_resolve function, to get the real function address and write back to the corresponding got table location.

So how does the got table know the real address of the scanf function at this point?

The problem has been solved. We can take a look at the loading process:

Speaking of which, you can see that before and after _ dl_runtimw_resolve, the real function address, that is, the address of the function in the glibc runtime, is written back to the code snippet, that is, got [n] (n > = 3). That is, when the function is called for the first time, it is dynamically parsed and loaded into .got.plt through the connector, and this process is called lazy loading or lazy loading.

At this point, it is drawing to a close, and when you call the same function for the second time, it will not be as troublesome as the first time, because you already have a real address in got [n], just jmp it directly.

The above content is how to deeply understand GOT table and PLT table. Have you learned any knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 244

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report