{"componentChunkName":"component---src-templates-post-template-js","path":"/linux-got-plt-en","result":{"data":{"markdownRemark":{"id":"ebfbf40f-f071-55ab-8803-3899a86d1338","html":"<blockquote>\n<p>This page has been machine-translated from the <a href=\"/linux-got-plt\">original page</a>.</p>\n</blockquote>\n<p>This article explores the overview of GOT and PLT along with practical verification.</p>\n<p>The motivation for writing this article was that I became confused about GOT while researching Position Independent Code (PIC).</p>\n<!-- omit in toc -->\n<h2 id=\"table-of-contents\" style=\"position:relative;\"><a href=\"#table-of-contents\" aria-label=\"table of contents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Table of Contents</h2>\n<ul>\n<li><a href=\"#shared-libraries-and-dynamic-linking\">Shared Libraries and Dynamic Linking</a></li>\n<li><a href=\"#flow-of-shared-library-function-calls\">Flow of Shared Library Function Calls</a></li>\n<li><a href=\"#got\">GOT</a></li>\n<li><a href=\"#plt\">PLT</a></li>\n<li>\n<p><a href=\"#tracing-got-and-plt-operations\">Tracing GOT and PLT Operations</a></p>\n<ul>\n<li><a href=\"#source-code-and-build\">Source Code and Build</a></li>\n<li><a href=\"#virtual-memory-output\">Virtual Memory Output</a></li>\n<li><a href=\"#call-instruction\">Call Instruction</a></li>\n<li><a href=\"#calling-shared-library-functions\">Calling Shared Library Functions</a></li>\n</ul>\n</li>\n<li><a href=\"#summary\">Summary</a></li>\n<li><a href=\"#references\">References</a></li>\n</ul>\n<h2 id=\"shared-libraries-and-dynamic-linking\" style=\"position:relative;\"><a href=\"#shared-libraries-and-dynamic-linking\" aria-label=\"shared libraries and dynamic linking permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Shared Libraries and Dynamic Linking</h2>\n<p>Most ELF binaries have library functions (predefined, frequently used convenient functions) linked via dynamic linking.</p>\n<p>Dynamic linking is a mechanism that links the actual body of library functions and other elements required for program execution at runtime.</p>\n<p>The counterpart to dynamic linking is static linking, where all necessary library functions and other components are linked into a single program beforehand.</p>\n<p>By using dynamic linking for functions and modules commonly used by multiple programs, such as library functions, there are benefits such as reducing the file size of programs and improving memory usage efficiency at runtime.</p>\n<p>You can check which shared libraries an ELF binary depends on using the <code class=\"language-text\">ldd</code> command.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ ldd test.o\nlinux-vdso.so.1 <span class=\"token punctuation\">(</span>0x00007ffdb417f000<span class=\"token punctuation\">)</span>\nlibc.so.6 <span class=\"token operator\">=</span><span class=\"token operator\">></span> /lib/x86_64-linux-gnu/libc.so.6 <span class=\"token punctuation\">(</span>0x00007f02af5ca000<span class=\"token punctuation\">)</span>\n/lib64/ld-linux-x86-64.so.2 <span class=\"token punctuation\">(</span>0x00007f02af7d7000<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Reference: <a href=\"https://linuxjm.osdn.jp/html/ld.so/man1/ldd.1.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Man page of LDD</a></p>\n<p>This article summarizes the mechanism for linking dynamically linked shared libraries at program runtime.</p>\n<h2 id=\"flow-of-shared-library-function-calls\" style=\"position:relative;\"><a href=\"#flow-of-shared-library-function-calls\" aria-label=\"flow of shared library function calls permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Flow of Shared Library Function Calls</h2>\n<p>When executing an ELF binary with dynamically linked library functions, the library functions are not bound until they are actually called during processing.</p>\n<p>This mechanism is called lazy binding and is supported by the PLT (Procedure Linkage Table).</p>\n<p>When a shared library function is called during program execution, the initially called address is not the actual shared library function, but an entry in the <code class=\"language-text\">.plt</code> section.</p>\n<p>The invoked PLT entry then jumps to an area called the GOT (Global Offset Table).</p>\n<p>Reference: <a href=\"https://amzn.to/3zwc6Y6\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Detailed Security Contest</a></p>\n<h2 id=\"got\" style=\"position:relative;\"><a href=\"#got\" aria-label=\"got permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>GOT</h2>\n<p>The GOT (Global Offset Table) refers to a section of computer program memory (executable files and shared libraries) used to ensure that programs compiled as ELF files can execute correctly.</p>\n<p>Reference: <a href=\"https://en.wikipedia.org/wiki/Global_Offset_Table\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Global Offset Table - Wikipedia</a></p>\n<p>Simply put, the GOT is an area for maintaining a list of library function addresses.</p>\n<p>This area is populated with the addresses of library functions used during program execution.</p>\n<p>The GOT makes it easy to relocate library functions within the process memory space.</p>\n<h2 id=\"plt\" style=\"position:relative;\"><a href=\"#plt\" aria-label=\"plt permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>PLT</h2>\n<p>The PLT (Procedure Linkage Table) is a collection of small code snippets for calling library functions.</p>\n<p>The PLT contains the same number of code entries as the library functions held by the GOT.</p>\n<p>The behavior of the code in the PLT is to jump to the value set in the GOT.</p>\n<p>When PLT code is called and the function address has not yet been set in the GOT, it sets the address in the GOT before jumping.</p>\n<p>Reference: <a href=\"https://keichi.dev/post/plt-and-got/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">What are PLT and GOT? · Keichi Takahashi</a></p>\n<h2 id=\"tracing-got-and-plt-operations\" style=\"position:relative;\"><a href=\"#tracing-got-and-plt-operations\" aria-label=\"tracing got and plt operations permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Tracing GOT and PLT Operations</h2>\n<p>From here, we’ll use GDB to examine the memory map in practice.</p>\n<h3 id=\"source-code-and-build\" style=\"position:relative;\"><a href=\"#source-code-and-build\" aria-label=\"source code and build permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Source Code and Build</h3>\n<p>The code used for verification is as follows.</p>\n<div class=\"gatsby-highlight\" data-language=\"c\"><pre class=\"language-c\"><code class=\"language-c\"><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;stdio.h></span></span>\n<span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\">&lt;stdlib.h></span></span>\n\n<span class=\"token keyword\">int</span> <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">int</span> a <span class=\"token operator\">=</span> <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> b <span class=\"token operator\">=</span> <span class=\"token function\">rand</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">int</span> c <span class=\"token operator\">=</span> <span class=\"token function\">rand</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> a <span class=\"token operator\">*</span> b<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Compile with the following command and launch with gdb.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">gcc -fcf-protection<span class=\"token operator\">=</span>none -no-pie -g test.c -o test.o\ngdb ./test.o</code></pre></div>\n<h3 id=\"virtual-memory-output\" style=\"position:relative;\"><a href=\"#virtual-memory-output\" aria-label=\"virtual memory output permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Virtual Memory Output</h3>\n<p>Linux provides the <code class=\"language-text\">/proc</code> directory as a pseudo-directory for currently running processes.</p>\n<p>Directly under the <code class=\"language-text\">/proc</code> directory, there are numeric directories corresponding to the PIDs of running processes, with process control tables mapped inside them.</p>\n<p>Reference: <a href=\"http://uralowl.my.coocan.jp/unix/job/ORACLE/oracle/pmap_linux.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">About Process Memory Maps (Linux)</a></p>\n<p>Reference: <a href=\"https://stackoverflow.com/questions/1401359/understanding-linux-proc-pid-maps-or-proc-self-maps\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">embedded - Understanding Linux /proc/pid/maps or /proc/self/maps - Stack Overflow</a></p>\n<p>To check the process memory map, I used the following command.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ <span class=\"token function\">cat</span> /proc/<span class=\"token variable\"><span class=\"token variable\">`</span>pidof test.o<span class=\"token variable\">`</span></span>/maps\naddress           permission offset   device inode      pathname\n00400000-00401000 r--p 00000000 fd:00 <span class=\"token number\">786517</span>                             /home/ubuntu/gottest/test.o\n00401000-00402000 r-xp 00001000 fd:00 <span class=\"token number\">786517</span>                             /home/ubuntu/gottest/test.o\n00402000-00403000 r--p 00002000 fd:00 <span class=\"token number\">786517</span>                             /home/ubuntu/gottest/test.o\n00403000-00404000 r--p 00002000 fd:00 <span class=\"token number\">786517</span>                             /home/ubuntu/gottest/test.o\n00404000-00405000 rw-p 00003000 fd:00 <span class=\"token number\">786517</span>                             /home/ubuntu/gottest/test.o\n7ffff7dc3000-7ffff7de8000 r--p 00000000 fd:00 <span class=\"token number\">945235</span>                     /lib/x86_64-linux-gnu/libc-2.31.so\n7ffff7de8000-7ffff7f60000 r-xp 00025000 fd:00 <span class=\"token number\">945235</span>                     /lib/x86_64-linux-gnu/libc-2.31.so\n7ffff7f60000-7ffff7faa000 r--p 0019d000 fd:00 <span class=\"token number\">945235</span>                     /lib/x86_64-linux-gnu/libc-2.31.so\n7ffff7faa000-7ffff7fab000 ---p 001e7000 fd:00 <span class=\"token number\">945235</span>                     /lib/x86_64-linux-gnu/libc-2.31.so\n7ffff7fab000-7ffff7fae000 r--p 001e7000 fd:00 <span class=\"token number\">945235</span>                     /lib/x86_64-linux-gnu/libc-2.31.so\n7ffff7fae000-7ffff7fb1000 rw-p 001ea000 fd:00 <span class=\"token number\">945235</span>                     /lib/x86_64-linux-gnu/libc-2.31.so\n7ffff7fb1000-7ffff7fb7000 rw-p 00000000 00:00 <span class=\"token number\">0</span> \n7ffff7fcb000-7ffff7fce000 r--p 00000000 00:00 <span class=\"token number\">0</span>                          <span class=\"token punctuation\">[</span>vvar<span class=\"token punctuation\">]</span>\n7ffff7fce000-7ffff7fcf000 r-xp 00000000 00:00 <span class=\"token number\">0</span>                          <span class=\"token punctuation\">[</span>vdso<span class=\"token punctuation\">]</span>\n7ffff7fcf000-7ffff7fd0000 r--p 00000000 fd:00 <span class=\"token number\">945231</span>                     /lib/x86_64-linux-gnu/ld-2.31.so\n7ffff7fd0000-7ffff7ff3000 r-xp 00001000 fd:00 <span class=\"token number\">945231</span>                     /lib/x86_64-linux-gnu/ld-2.31.so\n7ffff7ff3000-7ffff7ffb000 r--p 00024000 fd:00 <span class=\"token number\">945231</span>                     /lib/x86_64-linux-gnu/ld-2.31.so\n7ffff7ffc000-7ffff7ffd000 r--p 0002c000 fd:00 <span class=\"token number\">945231</span>                     /lib/x86_64-linux-gnu/ld-2.31.so\n7ffff7ffd000-7ffff7ffe000 rw-p 0002d000 fd:00 <span class=\"token number\">945231</span>                     /lib/x86_64-linux-gnu/ld-2.31.so\n7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 <span class=\"token number\">0</span> \n7ffffffde000-7ffffffff000 rw-p 00000000 00:00 <span class=\"token number\">0</span>                          <span class=\"token punctuation\">[</span>stack<span class=\"token punctuation\">]</span>\nffffffffff600000-ffffffffff601000 --xp 00000000 00:00 <span class=\"token number\">0</span>                  <span class=\"token punctuation\">[</span>vsyscall<span class=\"token punctuation\">]</span></code></pre></div>\n<p><code class=\"language-text\">maps</code> indicates contiguous virtual memory regions within a process or thread.</p>\n<p>The <code class=\"language-text\">address</code> records the start and end addresses of the region in the process address space, and <code class=\"language-text\">permission</code> records the permissions for that region.</p>\n<p>From the above results, we can see that two shared libraries are being used: <code class=\"language-text\">/lib/x86_64-linux-gnu/libc-2.31.so</code> and <code class=\"language-text\">/lib/x86_64-linux-gnu/ld-2.31.so</code>.</p>\n<p>Here, the shared library <code class=\"language-text\">/lib/x86_64-linux-gnu/ld-2.31.so</code> is mapped to <code class=\"language-text\">7ffff7fcf000</code>, but this is not a fixed address.</p>\n<p>The memory address where a shared library is deployed is determined at program runtime and may be deployed to different addresses depending on the circumstances.</p>\n<p>The mechanism that investigates which memory address a shared library is actually deployed to at runtime and calls it is PLT and GOT.</p>\n<h3 id=\"call-instruction\" style=\"position:relative;\"><a href=\"#call-instruction\" aria-label=\"call instruction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Call Instruction</h3>\n<p>Here’s an excerpt of the <code class=\"language-text\">call</code> instruction locations from the assembly source.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ disas main\nDump of assembler code <span class=\"token keyword\">for</span> <span class=\"token keyword\">function</span> main:\n   0x000000000040113e <span class=\"token operator\">&lt;</span>+1<span class=\"token operator\"><span class=\"token file-descriptor important\">3</span>></span>:call   0x401126 <span class=\"token operator\">&lt;</span>test<span class=\"token operator\">></span>\n   0x0000000000401146 <span class=\"token operator\">&lt;</span>+2<span class=\"token operator\"><span class=\"token file-descriptor important\">1</span>></span>:call   0x401030 <span class=\"token operator\">&lt;</span>rand@plt<span class=\"token operator\">></span>\n   0x000000000040114e <span class=\"token operator\">&lt;</span>+2<span class=\"token operator\"><span class=\"token file-descriptor important\">9</span>></span>:call   0x401030 <span class=\"token operator\">&lt;</span>rand@plt<span class=\"token operator\">></span>\nEnd of assembler dump.</code></pre></div>\n<p>The <code class=\"language-text\">call</code> instruction executes a combination of the following two processes:</p>\n<ul>\n<li>Push the address next to the <code class=\"language-text\">call</code> instruction (the instruction to execute after the function returns) onto the stack</li>\n<li>Jump to the address of the function being called</li>\n</ul>\n<p>Reference: <a href=\"https://vanya.jp.net/os/x86call/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Function Calls in x86 Assembly Language</a></p>\n<p>Here, let’s output the assembly for each of the two <code class=\"language-text\">call</code> instructions.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token comment\"># 0x401126 &lt;test></span>\n$ disas 0x401126\nDump of assembler code <span class=\"token keyword\">for</span> <span class=\"token keyword\">function</span> test:\n   0x0000000000401126 <span class=\"token operator\">&lt;</span>+<span class=\"token operator\"><span class=\"token file-descriptor important\">0</span>></span>:push   rbp\n   0x0000000000401127 <span class=\"token operator\">&lt;</span>+<span class=\"token operator\"><span class=\"token file-descriptor important\">1</span>></span>:mov    rbp,rsp\n   0x000000000040112a <span class=\"token operator\">&lt;</span>+<span class=\"token operator\"><span class=\"token file-descriptor important\">4</span>></span>:mov    eax,0x0\n   0x000000000040112f <span class=\"token operator\">&lt;</span>+<span class=\"token operator\"><span class=\"token file-descriptor important\">9</span>></span>:pop    rbp\n   0x0000000000401130 <span class=\"token operator\">&lt;</span>+1<span class=\"token operator\"><span class=\"token file-descriptor important\">0</span>></span>:ret    \nEnd of assembler dump.</code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token comment\"># 0x401030 &lt;rand@plt></span>\n$ disas 0x401030\nDump of assembler code <span class=\"token keyword\">for</span> <span class=\"token keyword\">function</span> rand@plt:\n   0x0000000000401030 <span class=\"token operator\">&lt;</span>+<span class=\"token operator\"><span class=\"token file-descriptor important\">0</span>></span>:jmp    QWORD PTR <span class=\"token punctuation\">[</span>rip+0x2fe2<span class=\"token punctuation\">]</span>        <span class=\"token comment\"># 0x404018 &lt;rand@got.plt></span>\n   0x0000000000401036 <span class=\"token operator\">&lt;</span>+<span class=\"token operator\"><span class=\"token file-descriptor important\">6</span>></span>:push   0x0\n   0x000000000040103b <span class=\"token operator\">&lt;</span>+1<span class=\"token operator\"><span class=\"token file-descriptor important\">1</span>></span>:jmp    0x401020\nEnd of assembler dump.</code></pre></div>\n<p>When comparing these, we can see that while the user function <code class=\"language-text\">test</code> is directly <code class=\"language-text\">call</code>ed, when calling <code class=\"language-text\">rand</code>, <code class=\"language-text\">rand@plt</code> is called instead.</p>\n<p>When <code class=\"language-text\">rand@plt</code> is called, the first <code class=\"language-text\">JMP</code> instruction calls <code class=\"language-text\">rand@got.plt</code>.</p>\n<p>This is because the destination address has not yet been set in the GOT.</p>\n<h3 id=\"calling-shared-library-functions\" style=\"position:relative;\"><a href=\"#calling-shared-library-functions\" aria-label=\"calling shared library functions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Calling Shared Library Functions</h3>\n<p>Next, we’ll set breakpoints at the first and second <code class=\"language-text\">rand</code> function call points respectively, and observe the changes in the GOT before and after the shared library function is bound through the PLT and GOT.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ b *0x401146\n$ b *0x40114e\n$ run</code></pre></div>\n<p>Now we’ve reached the first <code class=\"language-text\">rand</code> function call point.</p>\n<p>From the disassembly result of <code class=\"language-text\">rand@plt</code>, we know that the corresponding GOT address is <code class=\"language-text\">0x404018</code>.</p>\n<p>In other words, ultimately the address of the <code class=\"language-text\">rand</code> function body should be stored at <code class=\"language-text\">0x404018</code>.</p>\n<p>However, at this point, the <code class=\"language-text\">rand</code> function has not been called once during program execution, so the GOT contains the address of <code class=\"language-text\">rand@plt+6</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ telescope 0x404018\n0000<span class=\"token operator\">|</span> 0x404018 --<span class=\"token operator\">></span> 0x401036 <span class=\"token punctuation\">(</span><span class=\"token operator\">&lt;</span>rand@plt+<span class=\"token operator\"><span class=\"token file-descriptor important\">6</span>></span>:push   0x0<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Reference: <a href=\"https://gef.readthedocs.io/en/master/commands/dereference/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Command dereference - GEF - GDB Enhanced Features documentation</a></p>\n<p>The processing at address <code class=\"language-text\">rand@plt+6</code> pushes a value (0x0) onto the stack and then jumps to <code class=\"language-text\">0x401020</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ disas 0x401030\nDump of assembler code <span class=\"token keyword\">for</span> <span class=\"token keyword\">function</span> rand@plt:\n   0x0000000000401030 <span class=\"token operator\">&lt;</span>+<span class=\"token operator\"><span class=\"token file-descriptor important\">0</span>></span>:jmp    QWORD PTR <span class=\"token punctuation\">[</span>rip+0x2fe2<span class=\"token punctuation\">]</span>        <span class=\"token comment\"># 0x404018 &lt;rand@got.plt></span>\n   0x0000000000401036 <span class=\"token operator\">&lt;</span>+<span class=\"token operator\"><span class=\"token file-descriptor important\">6</span>></span>:push   0x0\n   0x000000000040103b <span class=\"token operator\">&lt;</span>+1<span class=\"token operator\"><span class=\"token file-descriptor important\">1</span>></span>:jmp    0x401020\nEnd of assembler dump.</code></pre></div>\n<p>The subsequent processing stores another value on the stack and then continues with processing that jumps to the address stored at <code class=\"language-text\">0x404010</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ x/16 0x401020\n   0x401020:push   QWORD PTR <span class=\"token punctuation\">[</span>rip+0x2fe2<span class=\"token punctuation\">]</span>        <span class=\"token comment\"># 0x404008</span>\n   0x401026:jmp    QWORD PTR <span class=\"token punctuation\">[</span>rip+0x2fe4<span class=\"token punctuation\">]</span>        <span class=\"token comment\"># 0x404010</span></code></pre></div>\n<p>Setting a breakpoint at <code class=\"language-text\">0x401036</code> and tracing the subsequent processing yielded the following results.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\"><span class=\"token operator\">=</span><span class=\"token operator\">></span> 0x401026:jmp    QWORD PTR <span class=\"token punctuation\">[</span>rip+0x2fe4<span class=\"token punctuation\">]</span>        <span class=\"token comment\"># 0x404010</span>\n <span class=\"token operator\">|</span> 0x40102c:nop    DWORD PTR <span class=\"token punctuation\">[</span>rax+0x0<span class=\"token punctuation\">]</span>\n <span class=\"token operator\">|</span> 0x401030 <span class=\"token operator\">&lt;</span>rand@plt<span class=\"token operator\">></span>:jmp    QWORD PTR <span class=\"token punctuation\">[</span>rip+0x2fe2<span class=\"token punctuation\">]</span>        <span class=\"token comment\"># 0x404018 &lt;rand@got.plt></span>\n <span class=\"token operator\">|</span> 0x401036 <span class=\"token operator\">&lt;</span>rand@plt+<span class=\"token operator\"><span class=\"token file-descriptor important\">6</span>></span>:push   0x0\n <span class=\"token operator\">|</span> 0x40103b <span class=\"token operator\">&lt;</span>rand@plt+1<span class=\"token operator\"><span class=\"token file-descriptor important\">1</span>></span>:jmp    0x401020\n <span class=\"token operator\">|</span>-<span class=\"token operator\">></span>   0x7ffff7fe7bb0:endbr64 \n       0x7ffff7fe7bb4:push   rbx\n       0x7ffff7fe7bb5:mov    rbx,rsp\n       0x7ffff7fe7bb8:and    rsp,0xffffffffffffffc0\n       0x7ffff7fe7bbc:sub    rsp,QWORD PTR <span class=\"token punctuation\">[</span>rip+0x14b45<span class=\"token punctuation\">]</span>        <span class=\"token comment\"># 0x7ffff7ffc708 &lt;_rtld_global_ro+232></span></code></pre></div>\n<p>The function being called here is <code class=\"language-text\">_dl_runtime_resolve</code>.</p>\n<p>The following reference was very helpful for details.</p>\n<p>Reference: <a href=\"https://syst3mfailure.io/ret2dl_resolve\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Ret2dl_resolve x64</a></p>\n<p>This function resolves the address of the target <code class=\"language-text\">rand</code> function and calls it.</p>\n<p>Since the GOT is updated at this point, subsequent calls to the <code class=\"language-text\">rand</code> function will directly call the resolved <code class=\"language-text\">rand</code> function address from the GOT.</p>\n<p>When we actually stop at the second <code class=\"language-text\">rand</code> function call point and check the contents of the GOT referenced by <code class=\"language-text\">rand@plt</code> as before, we find that it contains the address of the <code class=\"language-text\">rand</code> function body.</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ telescope 0x404018\n0000<span class=\"token operator\">|</span> 0x404018 --<span class=\"token operator\">></span> 0x7ffff7e0de90 <span class=\"token punctuation\">(</span><span class=\"token operator\">&lt;</span>rand<span class=\"token operator\">></span>:endbr64<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Therefore, on the second execution, <code class=\"language-text\">_dl_runtime_resolve</code> is not called, and the <code class=\"language-text\">rand</code> function is executed directly.</p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Summary</h2>\n<p>I started by reading UNIX code but ended up investigating GOT and PLT.</p>\n<p>Since <a href=\"https://amzn.to/3zwc6Y6\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Detailed Security Contest</a> contains more detailed information, I plan to dig deeper while also trying things like GOT Overwrite.</p>\n<h2 id=\"references\" style=\"position:relative;\"><a href=\"#references\" aria-label=\"references permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>References</h2>\n<ul>\n<li><a href=\"https://amzn.to/3zwc6Y6\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Detailed Security Contest</a></li>\n<li><a href=\"https://amzn.to/3n114Fn\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Debug Hacks - Debugging Techniques &#x26; Tools</a></li>\n</ul>","fields":{"slug":"/linux-got-plt-en","tagSlugs":["/tag/linux-en/","/tag/os-en/","/tag/kernel-en/","/tag/english/"]},"frontmatter":{"date":"2022-01-06","description":"This article summarizes the overview of GOT and PLT and presents practical verification results.","tags":["Linux (en)","OS (en)","Kernel (en)","English"],"title":"Tracing Library Function Calls Through GOT/PLT","socialImage":{"publicURL":"/static/a4f7c9e2f649a8b7bec38cf6b030aece/linux-got-plt.png"}}}},"pageContext":{"slug":"/linux-got-plt-en"}},"staticQueryHashes":["251939775","401334301","825871152"]}