{"id":4847,"date":"2020-11-25T15:06:18","date_gmt":"2020-11-25T07:06:18","guid":{"rendered":"https:\/\/damogame.cn\/wordpress\/?p=4847"},"modified":"2020-11-25T15:06:18","modified_gmt":"2020-11-25T07:06:18","slug":"relro-relocation-read-only","status":"publish","type":"post","link":"https:\/\/i007.cc\/wordpress\/archives\/4847","title":{"rendered":"RELRO: RELocation Read-Only"},"content":{"rendered":"<div class=\"article-box__header\">\n<div class=\"article-box__meta\">\n<div class=\"item-list\">\n<div class=\"item lm\"><a href=\"https:\/\/my.oschina.net\/zhuzihasablog\/blog\/125289\">\u539f\u6587\u5730\u5740<\/a><\/div>\n<div><\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"article-box__content\">\n<div class=\"detail-box\">\n<div class=\"article-detail\">\n<div class=\"content\">\n<p>This article describes ELF relocation sections, how to abuse them for arbitrary code execution, and how to protect them at runtime.<\/p>\n<p><strong>ELF Relocation Sections<\/strong><\/p>\n<p>A dynamically linked ELF binary uses a look-up table called Global Offset Table (GOT) to dynamically resolve functions that are located in shared libraries.<\/p>\n<p>When you call a function that is located in a shared library, it looks like the following. This is a high-level view of what is going on, there are lots of things the linker is doing that we won\u2019t go into.<\/p>\n<p>First, the call is actually pointing to the Procedure Linkage Table (PLT), which exists in the .plt section of the binary.<\/p>\n<p>objdump -M intel -d\u00a0YOUR_BINARY<\/p>\n<pre class=\"hljs yaml\"><code><span class=\"hljs-attr\">80484da:<\/span>       <span class=\"hljs-string\">e8<\/span> <span class=\"hljs-number\">95<\/span> <span class=\"hljs-string\">fe<\/span> <span class=\"hljs-string\">ff<\/span> <span class=\"hljs-string\">ff<\/span>          <span class=\"hljs-string\">call<\/span>   <span class=\"hljs-number\">8048374<\/span> <span class=\"hljs-string\">&lt;printf@plt&gt;<\/span><\/code><\/pre>\n<p>The .plt section contains x86 instructions that point directly to the GOT, which lives in the .got.plt section.<\/p>\n<p>objdump -M intel -d\u00a0YOUR_BINARY<\/p>\n<pre class=\"hljs yaml\"><code><span class=\"hljs-number\">08048374<\/span> <span class=\"hljs-string\">&lt;printf@plt&gt;:<\/span>\r\n <span class=\"hljs-attr\">8048374:<\/span>       <span class=\"hljs-string\">ff<\/span> <span class=\"hljs-number\">25<\/span> <span class=\"hljs-number\">54<\/span> <span class=\"hljs-number\">97<\/span> <span class=\"hljs-number\">04<\/span> <span class=\"hljs-number\">08<\/span>       <span class=\"hljs-string\">jmp<\/span>    <span class=\"hljs-string\">DWORD<\/span> <span class=\"hljs-string\">PTR<\/span> <span class=\"hljs-string\">ds:0x8049754<\/span>\r\n <span class=\"hljs-attr\">804837a:<\/span>       <span class=\"hljs-number\">68<\/span> <span class=\"hljs-number\">20<\/span> <span class=\"hljs-number\">00<\/span> <span class=\"hljs-number\">00<\/span> <span class=\"hljs-number\">00<\/span>          <span class=\"hljs-string\">push<\/span>   <span class=\"hljs-number\">0x20<\/span>\r\n <span class=\"hljs-attr\">804837f:<\/span>       <span class=\"hljs-string\">e9<\/span> <span class=\"hljs-string\">a0<\/span> <span class=\"hljs-string\">ff<\/span> <span class=\"hljs-string\">ff<\/span> <span class=\"hljs-string\">ff<\/span>          <span class=\"hljs-string\">jmp<\/span>    <span class=\"hljs-number\">8048324<\/span> <span class=\"hljs-string\">&lt;_init+0x30&gt;<\/span><\/code><\/pre>\n<p>The .got.plt section contains binary data. The GOT contain pointers back to the PLT or to the location of the dynamically linked function.<\/p>\n<p>objdump -s\u00a0YOUR_BINARY<\/p>\n<pre class=\"hljs css\"><code><span class=\"hljs-selector-tag\">Contents<\/span> <span class=\"hljs-selector-tag\">of<\/span> <span class=\"hljs-selector-tag\">section<\/span> <span class=\"hljs-selector-class\">.got<\/span><span class=\"hljs-selector-class\">.plt<\/span>:\r\n 8049738 6<span class=\"hljs-selector-tag\">c960408<\/span> 00000000 00000000 3<span class=\"hljs-selector-tag\">a830408<\/span>  <span class=\"hljs-selector-tag\">l<\/span>...........<span class=\"hljs-selector-pseudo\">:...<\/span>\r\n 8049748 4<span class=\"hljs-selector-tag\">a830408<\/span> 5<span class=\"hljs-selector-tag\">a830408<\/span> 6<span class=\"hljs-selector-tag\">a830408<\/span> 7<span class=\"hljs-selector-tag\">a830408<\/span>  <span class=\"hljs-selector-tag\">J<\/span>..<span class=\"hljs-selector-class\">.Z<\/span>..<span class=\"hljs-selector-class\">.j<\/span>..<span class=\"hljs-selector-class\">.z<\/span>...\r\n 8049758 8<span class=\"hljs-selector-tag\">a830408<\/span> 9<span class=\"hljs-selector-tag\">a830408<\/span>                    ........<\/code><\/pre>\n<p>By default, the GOT is populated dynamically while the program is running. The first time a function is called, the GOT contains a pointer back to the PLT, where the linker is called to find the actual location of the function in question (this is the part we\u2019re not going into detail about). The location found is then written to the GOT. The second time a function is called, the GOT contains the known location of the function. This is called \u201clazy binding.\u201d<\/p>\n<p><strong>lazy<\/strong><\/p>\n<pre class=\"hljs sql\"><code> When generating an executable or shared library, mark it to\r\ntell the dynamic linker to defer function <span class=\"hljs-keyword\">call<\/span> resolution <span class=\"hljs-keyword\">to<\/span>\r\nthe point <span class=\"hljs-keyword\">when<\/span> the <span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-keyword\">is<\/span> called (lazy binding), rather\r\n<span class=\"hljs-keyword\">than<\/span> <span class=\"hljs-keyword\">at<\/span> <span class=\"hljs-keyword\">load<\/span> time.  Lazy binding <span class=\"hljs-keyword\">is<\/span> the default.  [<span class=\"hljs-number\">1<\/span>]<\/code><\/pre>\n<p>There are a couple of design constraints for the GOT and the PLT.<\/p>\n<ul>\n<li>Because the PLT contains code that is called by the program directly, it needs to be allocated at a known offset from the .text segment.<\/li>\n<li>Because the GOT contains data used by different parts of the program directly, it needs to be allocated at a known static address in memory.<\/li>\n<li>Because the GOT is \u201clazy binded,\u201d it needs to be writable.<\/li>\n<\/ul>\n<p><strong>GOT Overwrite<\/strong><\/p>\n<p>Since we know that the GOT lives in a predefined place and is writable, all that is needed is a bug that lets an attacker write four bytes anywhere. We\u2019ll use the following vulnerable program to simulate that. Note that we are operating on the same binary we examined above.<\/p>\n<p>Here we have an intentionality vulnerable program that is hopefully believable enough to make this demo realistic. Understanding this program is not necessary for understanding the exploitation and mitigation techniques being demonstrated, it is only included for completeness.<\/p>\n<div>\n<div>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td>\n<div>1<\/div>\n<div>2<\/div>\n<div>3<\/div>\n<div>4<\/div>\n<div>5<\/div>\n<div>6<\/div>\n<div>7<\/div>\n<div>8<\/div>\n<div>9<\/div>\n<div>10<\/div>\n<div>11<\/div>\n<div>12<\/div>\n<div>13<\/div>\n<div>14<\/div>\n<div>15<\/div>\n<div>16<\/div>\n<div>17<\/div>\n<div>18<\/div>\n<div>19<\/div>\n<div>20<\/div>\n<div>21<\/div>\n<div>22<\/div>\n<div>23<\/div>\n<div>24<\/div>\n<div>25<\/div>\n<div>26<\/div>\n<div>27<\/div>\n<div>28<\/div>\n<div>29<\/div>\n<div>30<\/div>\n<div>31<\/div>\n<div>32<\/div>\n<div>33<\/div>\n<div>34<\/div>\n<div>35<\/div>\n<div>36<\/div>\n<div>37<\/div>\n<div>38<\/div>\n<div>39<\/div>\n<\/td>\n<td>\n<div>\n<div>\/\/ Include standard I\/O declarations<\/div>\n<div>#include &lt;stdio.h&gt;<\/div>\n<div>\/\/ Include string declarations<\/div>\n<div>#include &lt;string.h&gt;<\/div>\n<div><\/div>\n<div>\/\/ Program entry point<\/div>\n<div>intmain(intargc,char** argv) {<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Terminate if program is not run with three parameters.<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0if(argc != 4) {<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Print out the proper use of the program<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0puts(&#8220;.\/a.out &lt;size&gt; &lt;offset&gt; &lt;string&gt;&#8221;);<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Return failure<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return-1;<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0}<\/div>\n<div><\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Convert size to an integer<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0intsize =atoi(argv[1]);<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Convert offset to an integer<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0intoffset =atoi(argv[2]);<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Place string into its own string on the stack<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0char* str = argv[3];<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Declare a 256 byte buffer on the stack<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0charbuffer[256];<\/div>\n<div><\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Print the location of the buffer for calculating the offset.<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0printf(&#8220;Buffer:\\t\\t%8x\\n&#8221;, &amp;buffer);<\/div>\n<div><\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Fill the buffer with the letter &#8216;A&#8217;.<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0memset(buffer, 65, 256 &#8211; 1);<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Null-terminate the buffer.<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0buffer[255] = 0;<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Attempt to copy the specified string into the specified location.<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0strncpy(buffer + offset, str, size);<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Print out the buffer.<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0printf(&#8220;%s&#8221;, buffer);<\/div>\n<div><\/div>\n<div>\u00a0\u00a0\u00a0\u00a0\/\/ Return success<\/div>\n<div>\u00a0\u00a0\u00a0\u00a0return0;<\/div>\n<div>}<\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>gcc -g -O0 -Wl,-z,norelro -fno-stack-protector -o\u00a0YOUR_BINARY\u00a0YOUR_SOURCE_CODE<\/p>\n<p>First, some reconnaissance. We know from the examination above, that our GOT entry for printf lives at0x08049754. We know from tesing the program, that our buffer will live on the stack at0xbffff284.<\/p>\n<pre class=\"hljs yaml\"><code><span class=\"hljs-string\">(gdb)<\/span> <span class=\"hljs-string\">x<\/span> <span class=\"hljs-number\">0x08049754<\/span>\r\n<span class=\"hljs-number\">0x8049754<\/span> <span class=\"hljs-string\">&lt;_GLOBAL_OFFSET_TABLE_+28&gt;:<\/span>\t<span class=\"hljs-number\">0x0804837a<\/span>\r\n<span class=\"hljs-string\">(gdb)<\/span> <span class=\"hljs-string\">p<\/span> <span class=\"hljs-string\">-(0xbffff284<\/span> <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-number\">0x08049754<\/span><span class=\"hljs-string\">)<\/span> <span class=\"hljs-string\">%<\/span> <span class=\"hljs-number\">0x80000000<\/span>\r\n<span class=\"hljs-string\">$1<\/span> <span class=\"hljs-string\">=<\/span> <span class=\"hljs-number\">1208263888<\/span>\r\n<span class=\"hljs-string\">(gdb)<\/span> <span class=\"hljs-string\">r<\/span> <span class=\"hljs-number\">4<\/span> <span class=\"hljs-number\">1208263888<\/span> <span class=\"hljs-string\">\\$\\$\\$\\$<\/span>\r\n<span class=\"hljs-attr\">Starting program:<\/span> <span class=\"hljs-string\">\/home\/hake\/code\/relro\/c<\/span> <span class=\"hljs-number\">4<\/span> <span class=\"hljs-number\">1208263888<\/span> <span class=\"hljs-string\">\\$\\$\\$\\$<\/span>\r\n<span class=\"hljs-attr\">Buffer:<\/span>\t\t<span class=\"hljs-string\">bffff284<\/span>\r\n\r\n<span class=\"hljs-string\">Program<\/span> <span class=\"hljs-string\">received<\/span> <span class=\"hljs-string\">signal<\/span> <span class=\"hljs-string\">SIGSEGV,<\/span> <span class=\"hljs-string\">Segmentation<\/span> <span class=\"hljs-string\">fault.<\/span>\r\n<span class=\"hljs-number\">0x08048374<\/span> <span class=\"hljs-string\">in<\/span> <span class=\"hljs-string\">printf@plt<\/span> <span class=\"hljs-string\">()<\/span>\r\n<span class=\"hljs-string\">(gdb)<\/span> <span class=\"hljs-string\">x<\/span> <span class=\"hljs-number\">0x08049754<\/span>\r\n<span class=\"hljs-number\">0x8049754<\/span> <span class=\"hljs-string\">&lt;_GLOBAL_OFFSET_TABLE_+28&gt;:<\/span>\t<span class=\"hljs-number\">0x24242424<\/span><\/code><\/pre>\n<p>Here, we see that we can overwrite the GOT entry for printf with our string. The program crashes because it\u2019s trying to jump to memory that is not mapped.<\/p>\n<p><strong>RELRO: RELocation Read-Only<\/strong><\/p>\n<p>To prevent the above exploitation technique, we can tell the linker to resolve all dynamically linked functions at the beginning of execution and make the GOT read-only. Note that we are operating on a different binary below compiled from the same source code.<\/p>\n<p><strong>now<\/strong><\/p>\n<pre class=\"hljs cs\"><code> When generating an executable or shared library, mark it to\r\ntell the <span class=\"hljs-keyword\">dynamic<\/span> linker to resolve all symbols <span class=\"hljs-keyword\">when<\/span> the program\r\n<span class=\"hljs-keyword\">is<\/span> started, or <span class=\"hljs-keyword\">when<\/span> the shared library <span class=\"hljs-keyword\">is<\/span> linked to <span class=\"hljs-keyword\">using<\/span>\r\ndlopen, instead of deferring function call resolution to the\r\npoint <span class=\"hljs-keyword\">when<\/span> the function <span class=\"hljs-keyword\">is<\/span> first called.  [<span class=\"hljs-number\">1<\/span>]<\/code><\/pre>\n<p>This exploitation mitigation technique is known as RELRO which stands for RELocation Read-Only. The idea is simple, make the relocation sections that are used to resolve dynamically loaded functions read-only. This way, they cannot overwrite them and we cannot take control of execution like we did above.<\/p>\n<p>You can turn on Full RELRO with the gcc compiler option:-Wl,-z,relro,-z,now. This gets passed to the linker as-z relro -z now. On most modern Linux distributions a variant of RELRO known as Partial RELRO is used by default. Partial RELRO uses the-z relrooption, but not the-z nowoption.<\/p>\n<p>gcc -g -O0 -Wl,-z,relro,-z,now -fno-stack-protector -o\u00a0YOUR_BINARY\u00a0YOUR_SOURCE_CODE<\/p>\n<pre class=\"hljs yaml\"><code><span class=\"hljs-attr\">80484fa:<\/span>       <span class=\"hljs-string\">e8<\/span> <span class=\"hljs-number\">95<\/span> <span class=\"hljs-string\">fe<\/span> <span class=\"hljs-string\">ff<\/span> <span class=\"hljs-string\">ff<\/span>          <span class=\"hljs-string\">call<\/span>   <span class=\"hljs-number\">8048394<\/span> <span class=\"hljs-string\">&lt;printf@plt&gt;<\/span>\r\n\r\n<span class=\"hljs-number\">08048394<\/span> <span class=\"hljs-string\">&lt;printf@plt&gt;:<\/span>\r\n <span class=\"hljs-attr\">8048394:<\/span>       <span class=\"hljs-string\">ff<\/span> <span class=\"hljs-number\">25<\/span> <span class=\"hljs-string\">f0<\/span> <span class=\"hljs-string\">9f<\/span> <span class=\"hljs-number\">04<\/span> <span class=\"hljs-number\">08<\/span>       <span class=\"hljs-string\">jmp<\/span>    <span class=\"hljs-string\">DWORD<\/span> <span class=\"hljs-string\">PTR<\/span> <span class=\"hljs-string\">ds:0x8049ff0<\/span>\r\n <span class=\"hljs-attr\">804839a:<\/span>       <span class=\"hljs-number\">68<\/span> <span class=\"hljs-number\">20<\/span> <span class=\"hljs-number\">00<\/span> <span class=\"hljs-number\">00<\/span> <span class=\"hljs-number\">00<\/span>          <span class=\"hljs-string\">push<\/span>   <span class=\"hljs-number\">0x20<\/span>\r\n <span class=\"hljs-attr\">804839f:<\/span>       <span class=\"hljs-string\">e9<\/span> <span class=\"hljs-string\">a0<\/span> <span class=\"hljs-string\">ff<\/span> <span class=\"hljs-string\">ff<\/span> <span class=\"hljs-string\">ff<\/span>          <span class=\"hljs-string\">jmp<\/span>    <span class=\"hljs-number\">8048344<\/span> <span class=\"hljs-string\">&lt;_init+0x30&gt;<\/span>\r\n\r\n<span class=\"hljs-attr\">Contents of section .got:<\/span>\r\n <span class=\"hljs-string\">8049fd4<\/span> <span class=\"hljs-string\">fc9e0408<\/span> <span class=\"hljs-number\">00000000<\/span> <span class=\"hljs-number\">00000000<\/span> <span class=\"hljs-string\">5a830408<\/span>  <span class=\"hljs-string\">............Z...<\/span>\r\n <span class=\"hljs-string\">8049fe4<\/span> <span class=\"hljs-string\">6a830408<\/span> <span class=\"hljs-string\">7a830408<\/span> <span class=\"hljs-string\">8a830408<\/span> <span class=\"hljs-string\">9a830408<\/span>  <span class=\"hljs-string\">j...z...........<\/span>\r\n <span class=\"hljs-string\">8049ff4<\/span> <span class=\"hljs-string\">aa830408<\/span> <span class=\"hljs-string\">ba830408<\/span> <span class=\"hljs-number\">00000000<\/span>           <span class=\"hljs-string\">............<\/span><\/code><\/pre>\n<p>The GOT entry for printf lives at0x08049ff0. The buffer will live on the stack at0xbffff284.<\/p>\n<pre class=\"hljs yaml\"><code><span class=\"hljs-string\">(gdb)<\/span> <span class=\"hljs-string\">x<\/span> <span class=\"hljs-number\">0x08049ff0<\/span>\r\n<span class=\"hljs-number\">0x8049ff0<\/span> <span class=\"hljs-string\">&lt;_GLOBAL_OFFSET_TABLE_+28&gt;:<\/span>\t<span class=\"hljs-number\">0x0804839a<\/span>\r\n<span class=\"hljs-string\">(gdb)<\/span> <span class=\"hljs-string\">p<\/span> <span class=\"hljs-string\">-(0xbffff284<\/span> <span class=\"hljs-bullet\">-<\/span> <span class=\"hljs-number\">0x08049ff0<\/span><span class=\"hljs-string\">)<\/span> <span class=\"hljs-string\">%<\/span> <span class=\"hljs-number\">0x80000000<\/span>\r\n<span class=\"hljs-string\">$1<\/span> <span class=\"hljs-string\">=<\/span> <span class=\"hljs-number\">1208266092<\/span>\r\n<span class=\"hljs-string\">(gdb)<\/span> <span class=\"hljs-string\">r<\/span> <span class=\"hljs-number\">4<\/span> <span class=\"hljs-number\">1208266092<\/span> <span class=\"hljs-string\">\\$\\$\\$\\$<\/span>\r\n<span class=\"hljs-attr\">Starting program:<\/span> <span class=\"hljs-string\">\/home\/hake\/code\/relro\/r<\/span> <span class=\"hljs-number\">4<\/span> <span class=\"hljs-number\">1208266092<\/span> <span class=\"hljs-string\">\\$\\$\\$\\$<\/span>\r\n<span class=\"hljs-attr\">Buffer:<\/span>\t\t<span class=\"hljs-string\">bffff284<\/span>\r\n\r\n<span class=\"hljs-string\">Program<\/span> <span class=\"hljs-string\">received<\/span> <span class=\"hljs-string\">signal<\/span> <span class=\"hljs-string\">SIGSEGV,<\/span> <span class=\"hljs-string\">Segmentation<\/span> <span class=\"hljs-string\">fault.<\/span>\r\n<span class=\"hljs-string\">strncpy<\/span> <span class=\"hljs-string\">(s1=0x8049ff0<\/span> <span class=\"hljs-string\">\"ph\\027\"<\/span><span class=\"hljs-string\">,<\/span> <span class=\"hljs-string\">s2=0xbffff5fc<\/span> <span class=\"hljs-string\">\"$$$\"<\/span><span class=\"hljs-string\">,<\/span> <span class=\"hljs-string\">n=4)<\/span> <span class=\"hljs-string\">at<\/span> <span class=\"hljs-string\">strncpy.c:43<\/span>\r\n<span class=\"hljs-number\">43<\/span>\t<span class=\"hljs-attr\">strncpy.c:<\/span> <span class=\"hljs-literal\">No<\/span> <span class=\"hljs-string\">such<\/span> <span class=\"hljs-string\">file<\/span> <span class=\"hljs-string\">or<\/span> <span class=\"hljs-string\">directory.<\/span>\r\n\t<span class=\"hljs-string\">in<\/span> <span class=\"hljs-string\">strncpy.c<\/span>\r\n<span class=\"hljs-string\">(gdb)<\/span> <span class=\"hljs-string\">x<\/span> <span class=\"hljs-number\">0x08049ff0<\/span>\r\n<span class=\"hljs-number\">0x8049ff0<\/span> <span class=\"hljs-string\">&lt;_GLOBAL_OFFSET_TABLE_+28&gt;:<\/span>\t<span class=\"hljs-number\">0x00176870<\/span><\/code><\/pre>\n<p>Here, we see that we cannot overwrite the GOT entry for printf with our string. The program crashes because it trying to write to a memory segment that is read-only.<\/p>\n<p><em>Technical note: All other memory corruption exploitation mitigation techniques were turned off for this demonstration.<\/em><\/p>\n<p><em>Technical note: RELRO automatically applies all the specified protections to following segments:.ctors,.dtors,.jcr,.dynamicand.got.<\/em><\/p>\n<p><strong>Some Handy Commands<\/strong><\/p>\n<p>Display Dynamic Relocation Entries<br \/>\nobjdump -R\u00a0YOUR_BINARY<\/p>\n<p>Show Program Header Table<br \/>\nreadelf -l\u00a0YOUR_BINARY<\/p>\n<p>Show Section Header Table<br \/>\nreadelf -S\u00a0YOUR_BINARY<\/p>\n<p>Display Relocations<br \/>\nreadelf -r\u00a0YOUR_BINARY<\/p>\n<p><strong>Thanks<\/strong><\/p>\n<p><a href=\"http:\/\/jon.oberheide.org\/\" rel=\"nofollow\">Jon Oberheide<\/a><\/p>\n<p><strong>Citations<\/strong><\/p>\n<p>[1] Manual page\u00a0<a href=\"http:\/\/unixhelp.ed.ac.uk\/CGI\/man-cgi?ld\" rel=\"nofollow\">ld(1)<\/a><\/p>\n<p><strong>Related Resources<\/strong><\/p>\n<p><a href=\"http:\/\/tk-blog.blogspot.com\/2009\/02\/relro-not-so-well-known-memory.html\" rel=\"nofollow\">RELRO \u2013 A (not so well known) Memory Corruption Mitigation Technique<\/a><br \/>\n<a href=\"http:\/\/www.exploit-db.com\/papers\/13203\/\" rel=\"nofollow\">How to Hijack the Global Offset Table with pointers<\/a><br \/>\n<a href=\"http:\/\/bottomupcs.sourceforge.net\/csbu\/x3824.htm\" rel=\"nofollow\">Chapter 9. Dynamic Linking: Global Offset Tables<\/a><br \/>\n<a href=\"http:\/\/greek0.net\/elf.html\" rel=\"nofollow\">The ELF format \u2013 How programs look from the inside<\/a><br \/>\n<a href=\"http:\/\/em386.blogspot.com\/2006\/10\/resolving-elf-relocation-name-symbols.html\" rel=\"nofollow\">Resolving ELF Relocation Name \/ Symbols<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u539f\u6587\u5730\u5740 This article de<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[],"tags":[119],"class_list":["post-4847","post","type-post","status-publish","format-standard","hentry","tag-03-"],"_links":{"self":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/4847","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/comments?post=4847"}],"version-history":[{"count":0,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/4847\/revisions"}],"wp:attachment":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/media?parent=4847"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/categories?post=4847"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/tags?post=4847"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}