flat assembler
Message board for the users of flat assembler.

Index > Linux > ELF executable + relocations/fixups for ASLR?

Goto page Previous  1, 2, 3, 4  Next
Author
Thread Post new topic Reply to topic
Furs



Joined: 04 Mar 2016
Posts: 2541
Furs 23 Jan 2019, 21:22
revolution wrote:
No. I'm not experienced with GCC. I didn't know about that switch. Is there an example that shows this?
Unfortunately I'll only be able to do some tests perhaps tomorrow, but for now I found this very interesting article: https://eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries/

It seems it works if it's in .rel.sym? Maybe FASM generates the wrong relocations for ELF.
Post 23 Jan 2019, 21:22
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 23 Jan 2019, 22:00
Quote:
These days, position independent code (PIC) is a more popular approach, and some modern systems (such as x86-64) no longer support load-time relocation.
I admit, I have been testing on x86-64. And there I could only make load-time relocations to work when I made code writable.

PS. Relocations for executable/dynamic flavour of ELF are defined a bit differently compared to object ELF. With fasm you have to define them manually (like in "import" macro), though with fasmg you could easily make this automatic analogously to object relocations.
Post 23 Jan 2019, 22:00
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2541
Furs 29 Jan 2019, 12:47
revolution, did that work? Or you gave up on relocations?
Post 29 Jan 2019, 12:47
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20403
Location: In your JS exploiting you and your system
revolution 29 Jan 2019, 13:43
Yes, it works. But the exe doesn't have relocations. The entire code has to be PIC, and the exe has to be marked as PIE.

AFAICT there isn't an ELF relocation format to support repositioning an exe the way that PE does. But I would be happy to learn that that is wrong.
Post 29 Jan 2019, 13:43
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 29 Jan 2019, 14:45
revolution wrote:
AFAICT there isn't an ELF relocation format to support repositioning an exe the way that PE does. But I would be happy to learn that that is wrong.
The format is there, it's just that when a specific implementation (like Linux one) requires a writable section for these relocations to work, they become much less useful. They end up used only like the import section variables in PE, while they potentially could also relocate code. Not only like PE fixups, ELF relocations are robust enough that they could even path CALL instructions in code to refer to functions imported from another dynamic library, etc.

When I was performing a hiding code in Elf64_Rela experiment, I had a working example, unfortunately I cannot find it now. I may have deleted it out of disappointment.

Perhaps I should finally start working on the second chapter of my formats tutorial. It is likely to have such examples when I finish it.
Post 29 Jan 2019, 14:45
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20403
Location: In your JS exploiting you and your system
revolution 29 Jan 2019, 16:28
A writeable executable section is not a good thing. I'd rather write PIC code than deal with corrupted code.
Post 29 Jan 2019, 16:28
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2541
Furs 29 Jan 2019, 20:49
revolution wrote:
A writeable executable section is not a good thing. I'd rather write PIC code than deal with corrupted code.
Can't you just make it unwriteable at startup in code? BTW, did you test and see if it doesn't work if it's not writeable, after getting it to work writeable?

GCC with -fno-PIC seems to generate relocatable code:
Code:
static int var;
void test(int x)
{
  var = x;
}

int blah()
{
  return var;
}    
Code:
gcc -m32 -O2 -fno-PIC -shared test.c -o test.so
objdump -d -M intel test.so    
Code:
test.so:     file format elf32-i386


Disassembly of section .init:

00000364 <_init>:
 364:   53                      push   ebx
 365:   83 ec 08                sub    esp,0x8
 368:   e8 53 00 00 00          call   3c0 <__x86.get_pc_thunk.bx>
 36d:   81 c3 93 1c 00 00       add    ebx,0x1c93
 373:   8b 83 f8 ff ff ff       mov    eax,DWORD PTR [ebx-0x8]
 379:   85 c0                   test   eax,eax
 37b:   74 05                   je     382 <_init+0x1e>
 37d:   e8 2e 00 00 00          call   3b0 <__gmon_start__@plt>
 382:   83 c4 08                add    esp,0x8
 385:   5b                      pop    ebx
 386:   c3                      ret    

Disassembly of section .plt:

00000390 <__cxa_finalize@plt-0x10>:
 390:   ff b3 04 00 00 00       push   DWORD PTR [ebx+0x4]
 396:   ff a3 08 00 00 00       jmp    DWORD PTR [ebx+0x8]
 39c:   00 00                   add    BYTE PTR [eax],al
        ...

000003a0 <__cxa_finalize@plt>:
 3a0:   ff a3 0c 00 00 00       jmp    DWORD PTR [ebx+0xc]
 3a6:   68 00 00 00 00          push   0x0
 3ab:   e9 e0 ff ff ff          jmp    390 <_init+0x2c>

000003b0 <__gmon_start__@plt>:
 3b0:   ff a3 10 00 00 00       jmp    DWORD PTR [ebx+0x10]
 3b6:   68 08 00 00 00          push   0x8
 3bb:   e9 d0 ff ff ff          jmp    390 <_init+0x2c>

Disassembly of section .text:

000003c0 <__x86.get_pc_thunk.bx>:
 3c0:   8b 1c 24                mov    ebx,DWORD PTR [esp]
 3c3:   c3                      ret    
 3c4:   66 90                   xchg   ax,ax
 3c6:   66 90                   xchg   ax,ax
 3c8:   66 90                   xchg   ax,ax
 3ca:   66 90                   xchg   ax,ax
 3cc:   66 90                   xchg   ax,ax
 3ce:   66 90                   xchg   ax,ax

000003d0 <deregister_tm_clones>:
 3d0:   e8 e4 00 00 00          call   4b9 <__x86.get_pc_thunk.dx>
 3d5:   81 c2 2b 1c 00 00       add    edx,0x1c2b
 3db:   8d 8a 18 00 00 00       lea    ecx,[edx+0x18]
 3e1:   8d 82 18 00 00 00       lea    eax,[edx+0x18]
 3e7:   39 c8                   cmp    eax,ecx
 3e9:   74 1d                   je     408 <deregister_tm_clones+0x38>
 3eb:   8b 82 f0 ff ff ff       mov    eax,DWORD PTR [edx-0x10]
 3f1:   85 c0                   test   eax,eax
 3f3:   74 13                   je     408 <deregister_tm_clones+0x38>
 3f5:   55                      push   ebp
 3f6:   89 e5                   mov    ebp,esp
 3f8:   83 ec 14                sub    esp,0x14
 3fb:   51                      push   ecx
 3fc:   ff d0                   call   eax
 3fe:   83 c4 10                add    esp,0x10
 401:   c9                      leave  
 402:   c3                      ret    
 403:   90                      nop
 404:   8d 74 26 00             lea    esi,[esi+eiz*1+0x0]
 408:   f3 c3                   repz ret 
 40a:   8d b6 00 00 00 00       lea    esi,[esi+0x0]

00000410 <register_tm_clones>:
 410:   e8 a4 00 00 00          call   4b9 <__x86.get_pc_thunk.dx>
 415:   81 c2 eb 1b 00 00       add    edx,0x1beb
 41b:   55                      push   ebp
 41c:   8d 8a 18 00 00 00       lea    ecx,[edx+0x18]
 422:   8d 82 18 00 00 00       lea    eax,[edx+0x18]
 428:   29 c8                   sub    eax,ecx
 42a:   89 e5                   mov    ebp,esp
 42c:   53                      push   ebx
 42d:   c1 f8 02                sar    eax,0x2
 430:   89 c3                   mov    ebx,eax
 432:   83 ec 04                sub    esp,0x4
 435:   c1 eb 1f                shr    ebx,0x1f
 438:   01 d8                   add    eax,ebx
 43a:   d1 f8                   sar    eax,1
 43c:   74 14                   je     452 <register_tm_clones+0x42>
 43e:   8b 92 fc ff ff ff       mov    edx,DWORD PTR [edx-0x4]
 444:   85 d2                   test   edx,edx
 446:   74 0a                   je     452 <register_tm_clones+0x42>
 448:   83 ec 08                sub    esp,0x8
 44b:   50                      push   eax
 44c:   51                      push   ecx
 44d:   ff d2                   call   edx
 44f:   83 c4 10                add    esp,0x10
 452:   8b 5d fc                mov    ebx,DWORD PTR [ebp-0x4]
 455:   c9                      leave  
 456:   c3                      ret    
 457:   89 f6                   mov    esi,esi
 459:   8d bc 27 00 00 00 00    lea    edi,[edi+eiz*1+0x0]

00000460 <__do_global_dtors_aux>:
 460:   55                      push   ebp
 461:   89 e5                   mov    ebp,esp
 463:   53                      push   ebx
 464:   e8 57 ff ff ff          call   3c0 <__x86.get_pc_thunk.bx>
 469:   81 c3 97 1b 00 00       add    ebx,0x1b97
 46f:   83 ec 04                sub    esp,0x4
 472:   80 bb 18 00 00 00 00    cmp    BYTE PTR [ebx+0x18],0x0
 479:   75 27                   jne    4a2 <__do_global_dtors_aux+0x42>
 47b:   8b 83 f4 ff ff ff       mov    eax,DWORD PTR [ebx-0xc]
 481:   85 c0                   test   eax,eax
 483:   74 11                   je     496 <__do_global_dtors_aux+0x36>
 485:   83 ec 0c                sub    esp,0xc
 488:   ff b3 14 00 00 00       push   DWORD PTR [ebx+0x14]
 48e:   e8 0d ff ff ff          call   3a0 <__cxa_finalize@plt>
 493:   83 c4 10                add    esp,0x10
 496:   e8 35 ff ff ff          call   3d0 <deregister_tm_clones>
 49b:   c6 83 18 00 00 00 01    mov    BYTE PTR [ebx+0x18],0x1
 4a2:   8b 5d fc                mov    ebx,DWORD PTR [ebp-0x4]
 4a5:   c9                      leave  
 4a6:   c3                      ret    
 4a7:   89 f6                   mov    esi,esi
 4a9:   8d bc 27 00 00 00 00    lea    edi,[edi+eiz*1+0x0]

000004b0 <frame_dummy>:
 4b0:   55                      push   ebp
 4b1:   89 e5                   mov    ebp,esp
 4b3:   5d                      pop    ebp
 4b4:   e9 57 ff ff ff          jmp    410 <register_tm_clones>

000004b9 <__x86.get_pc_thunk.dx>:
 4b9:   8b 14 24                mov    edx,DWORD PTR [esp]
 4bc:   c3                      ret    
 4bd:   66 90                   xchg   ax,ax
 4bf:   90                      nop

000004c0 <test>:
 4c0:   8b 44 24 04             mov    eax,DWORD PTR [esp+0x4]
 4c4:   a3 1c 20 00 00          mov    ds:0x201c,eax
 4c9:   c3                      ret    
 4ca:   8d b6 00 00 00 00       lea    esi,[esi+0x0]

000004d0 <blah>:
 4d0:   a1 1c 20 00 00          mov    eax,ds:0x201c
 4d5:   c3                      ret    

Disassembly of section .fini:

000004d8 <_fini>:
 4d8:   53                      push   ebx
 4d9:   83 ec 08                sub    esp,0x8
 4dc:   e8 df fe ff ff          call   3c0 <__x86.get_pc_thunk.bx>
 4e1:   81 c3 1f 1b 00 00       add    ebx,0x1b1f
 4e7:   83 c4 08                add    esp,0x8
 4ea:   5b                      pop    ebx
 4eb:   c3                      ret    


It accesses var via mov eax,ds:0x201c and so on.
Post 29 Jan 2019, 20:49
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20403
Location: In your JS exploiting you and your system
revolution 29 Jan 2019, 21:36
Is the code section from GCC writeable?
Furs wrote:
Can't you just make it unwriteable at startup in code?
Maybe? What is the sys_call for changing access permissions?

Edit: answer my own question, Yes, if this is to be believed. But only if your kernel is not hardened, apparently. So the code might fail if someone tries to run it on a hardened system.
Post 29 Jan 2019, 21:36
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 30 Jan 2019, 11:16
Here's the simplest example that I could quickly prepare (assemble with fasm 1):
Code:
format ELF64 executable 3
entry start
include 'elf.inc'

segment interpreter readable
        db '/lib64/ld-linux-x86-64.so.2',0

segment dynamic readable
        dq DT_STRTAB,strtab
        dq DT_STRSZ,strsz
        dq DT_SYMTAB,symtab
        dq DT_SYMENT,sizeof.Elf64_Sym
        dq DT_RELA,rela
        dq DT_RELASZ,relasz
        dq DT_RELAENT,sizeof.Elf64_Rela
        dq DT_HASH,hash
        dq DT_NULL,0  

segment readable writeable

  rela:
        Elf64_Rela fixup,0,R_X86_64_64,msg      ; replace qword at "fixup" with absolute value of "msg"
  relasz = $-rela

  symtab:
        Elf64_Sym

  hash:
        dd 1,1
        dd 0
        dd 0

  strtab:
        db 0
  strsz = $-strtab

segment readable executable writeable

start:

        mov     rsi,qword 0
fixup = $ - 8
        mov     edx,msg.len
        mov     edi,1
        mov     eax,1
        syscall

        xor     edi,edi
        mov     eax,60
        syscall

segment readable writeable

msg db 'Hello world!',0xA
.len = $ - msg    
If you remove "writeable" attribute from code segment, it segfaults when trying to apply the relocation (at least on my machines).

Note that this is not a true relocation, for simplicity I have no symbols in symbol table and the relocation is just an absolute value that overwrites the original value in code (a relocation dealing with actual addresses needs to refer to a symbol, even if just a local one). But this is enough for this demonstration.

EDIT: I have the same result for 32-bit version, too:
Code:
format ELF executable 3
entry start
include 'elf.inc'

segment interpreter readable
        db '/lib/ld-linux.so.2',0

segment dynamic readable
  dd DT_STRTAB,strtab
  dd DT_STRSZ,strsz
  dd DT_SYMTAB,symtab
  dd DT_SYMENT,sizeof.Elf32_Sym
  dd DT_RELA,rela
  dd DT_RELASZ,relasz
  dd DT_RELAENT,sizeof.Elf32_Rela
  dd DT_HASH,hash
  dd DT_NULL,0

segment readable writeable

  rela:
        Elf32_Rela fixup,0,R_386_32,msg         ; replace dword at "fixup" with absolute value of "msg"
  relasz = $-rela

  symtab:
        Elf32_Sym

  hash:
        dd 1,1
        dd 0
        dd 0

  strtab:
        db 0
  strsz = $-strtab

segment readable executable writeable

start:

        mov     ecx,dword 0
fixup = $ - 4
        mov     edx,msg.len
        mov     eax,4
        mov     ebx,1
        int     0x80

        mov     eax,1
        xor     ebx,ebx
        int     0x80

segment readable writeable

msg db 'Hello world!',0xA
.len = $ - msg    
Post 30 Jan 2019, 11:16
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2541
Furs 30 Jan 2019, 18:25
Tomasz Grysztar wrote:
If you remove "writeable" attribute from code segment, it segfaults when trying to apply the relocation (at least on my machines).

Note that this is not a true relocation, for simplicity I have no symbols in symbol table and the relocation is just an absolute value that overwrites the original value in code (a relocation dealing with actual addresses needs to refer to a symbol, even if just a local one). But this is enough for this demonstration.

EDIT: I have the same result for 32-bit version, too
I can't use objdump on this example, are you sure it's even a correct ELF in the first place? It doesn't even have named sections. I don't know much about ELF, but I know that some sections are treated specially by the loader on Linux.

Using readelf:

GCC
Code:
Elf file type is DYN (Shared object file)
Entry point 0x3f0
There are 7 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00000000 0x00000000 0x005d8 0x005d8 R E 0x1000
  LOAD           0x000ef8 0x00001ef8 0x00001ef8 0x00120 0x00128 RW  0x1000
  DYNAMIC        0x000f04 0x00001f04 0x00001f04 0x000e8 0x000e8 RW  0x4
  NOTE           0x000114 0x00000114 0x00000114 0x00024 0x00024 R   0x4
  GNU_EH_FRAME   0x00054c 0x0000054c 0x0000054c 0x00024 0x00024 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
  GNU_RELRO      0x000ef8 0x00001ef8 0x00001ef8 0x00108 0x00108 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .eh_frame_hdr .eh_frame 
   01     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 
   02     .dynamic 
   03     .note.gnu.build-id 
   04     .eh_frame_hdr 
   05     
   06     .init_array .fini_array .jcr .dynamic .got    


FASM
Code:
Elf file type is EXEC (Executable file)
Entry point 0x804915c
There are 5 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  INTERP         0x0000d4 0x080480d4 0x080480d4 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  DYNAMIC        0x0000e7 0x080480e7 0x080480e7 0x00048 0x00048 R   0x1
  LOAD           0x00012f 0x0804812f 0x0804812f 0x0002d 0x0002d RW  0x1000
  LOAD           0x00015c 0x0804915c 0x0804915c 0x0001f 0x0001f RWE 0x1000
  LOAD           0x00017b 0x0804a17b 0x0804a17b 0x0000d 0x0000d RW  0x1000    
I can see the DYNAMIC segment is not writeable in your case, maybe it makes a difference. But testing it shows it's not enough.


I think you need the GNU_RELRO segment. I don't know how to add it. Smile
Post 30 Jan 2019, 18:25
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2541
Furs 30 Jan 2019, 18:36
revolution wrote:
Is the code section from GCC writeable?
Furs wrote:
Can't you just make it unwriteable at startup in code?
Maybe? What is the sys_call for changing access permissions?

Edit: answer my own question, Yes, if this is to be believed. But only if your kernel is not hardened, apparently. So the code might fail if someone tries to run it on a hardened system.
I think that hardening is pretty stupid, how is runtime-generated code supposed to work, then? If I got this right, yet another example where security pisses on functionality.

According to wikipedia, looks like they have to special-case GCC's trampolines, which is just laughable and screws anyone else's runtime-generated code. Pretty disgusting if you ask me.

EDIT: Sorry, to answer your question in case you don't read my reply to Tomasz (heh Razz), the GCC code segment is not writeable. My guess is that GNU_RELRO thing is why it works (see above).
Post 30 Jan 2019, 18:36
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 30 Jan 2019, 18:54
Furs wrote:
I can't use objdump on this example, are you sure it's even a correct ELF in the first place? It doesn't even have named sections. I don't know much about ELF, but I know that some sections are treated specially by the loader on Linux.
I see that writing the ELF chapter of my tutorial is really needed. Wink

The design of ELF in general is quite complex but clever, and it gives a lot of freedom compared to other formats (like PE/COFF). The same format can handle being an executable, and object, or a mix of both. For example, run-time segments (defined in Program Headers) are mandatory for executable but optional for linkable object, while named sections are mandatory for object but optional for executable. Section headers are usually kept after linking to preserve the information that might be useful for debugging, etc. But everything that is actually necessary for run-time loading is kept in attributes of segments.

All the basic ELF examples that come packaged with fasm have always been kept minimal - they do not contain optional structures. Moreover, fasm's executable formatter never even had an option of adding section headers. By tweaking fasmg's macros you could perhaps do that and make a "hybrid" ELF with both segments and sections defined.

I should note that ELF was originally designed for System V Unix and not Linux specifically - the implementation in Linux might not be the most faithful one. There are assumptions made by Linux implementation that are not present in the specification and the problems with relocations discussed here are also a demonstration that Linux does not always use the capabilities of this format to full extent.

Furs wrote:
I think you need the GNU_RELRO segment. I don't know how to add it. Smile

I'm going to try it, it is interesting whether segment of this type is enough to change loader's behavior here.
Post 30 Jan 2019, 18:54
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20403
Location: In your JS exploiting you and your system
revolution 30 Jan 2019, 18:57
Furs wrote:
I think that hardening is pretty stupid, how is runtime-generated code supposed to work, then? If I got this right, yet another example where security pisses on functionality.
Well the security is another topic, but basically any code that is not from the original exe should be treated as a bad thing when you are considering the security of it. Code produced from data is really hard to make sure that it is always exactly what you think it is. You get something a little bit wrong in some other part of the app and suddenly the program is doing unexpected things (like following orders from a remote hacker).

Anyhow, the point being that if you want to ensure maximum usability of your code then you can't reasonably expect everyone else to run their kernel in a particular way.

However if fasm can be coaxed to make a functioning ASLR capable exe with relocations and a writeable code segment then I still think it is a good improvement. Just for the sake of completeness. No need to limit the users arbitrarily. The thing that makes me cringe is the idea of making code use ASLR for "security" and also making the code writeable to break the security. I think this a flaw in the way Linux load programs.
Post 30 Jan 2019, 18:57
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 30 Jan 2019, 19:05
All right, GNU_RELRO seems like a good clue. It is Linux-specific addition:
Quote:
PT_GNU_RELRO
The array element specifies the location and size of a segment which may be made read-only after relocation shave been processed.
(The typo is copied as-is from the document.)

It is easy to add this segment option into fasmg's elfexe.inc and do some experiments.
Post 30 Jan 2019, 19:05
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20403
Location: In your JS exploiting you and your system
revolution 30 Jan 2019, 19:08
I see that the examples posted by Tomasz have an interpreter section. Does that mean the it is the interpreter that does the relocations? If so then the loader is not processing the relocs at all?
Post 30 Jan 2019, 19:08
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 30 Jan 2019, 19:21
I can confirm that changing code segment to PT_GNU_RELRO allows to apply relocations to it without "writeable" attribute. I am adding this value to possible settings in fasmg's elfexe.inc.

Interestingly, this means that GCC separates the code that needs to be relocated from the "bulk" code, because it still makes a regular code segment and PT_GNU_RELRO is just an additional one.
Post 30 Jan 2019, 19:21
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 30 Jan 2019, 19:37
revolution wrote:
I see that the examples posted by Tomasz have an interpreter section. Does that mean the it is the interpreter that does the relocations? If so then the loader is not processing the relocs at all?
That is a good question. The GCC-generated headers that Furs showed do not have INTERP segment, so it might be not used for PT_DYN files.
Post 30 Jan 2019, 19:37
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20403
Location: In your JS exploiting you and your system
revolution 30 Jan 2019, 19:38
So we need to include foreign code into our exe to make it relocatable (i.e. the interpreter .so)? If so then we should just write our own relocator and then we can do whatever we need in whatever format we need, since the outcome is going to be the same.

And that also suggests that a relocatable exe from GCC can't be run on a hardened kernel because it isn't allowed to change segment permissions.
Post 30 Jan 2019, 19:38
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 30 Jan 2019, 19:54
What I found when experimenting:
  • In ET_EXEC file I can put code in PT_GNU_RELRO segment and apply relocations to it without marking the segment as writable (the loader/interpreter must be making it writable temporarily to apply relocations). So far, so good.
  • When I make the same file, but change type to ET_DYN, it crashes when it's trying to access PT_INTERP segment at its default address (as it is not there, because ASLR has chosen a different address). This suggests that ET_DYN files are not supposed to have PT_INTERP segment. OK, not a big deal.
  • But when I make ET_DYN with no PT_INTERP segment, the relocations are not applied (even though PT_DYNAMIC is present).
So perhaps GCC-made exe is invoking an interpreter on its own, or even applying relocations on its own?
Post 30 Jan 2019, 19:54
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20403
Location: In your JS exploiting you and your system
revolution 30 Jan 2019, 20:50
Tomasz Grysztar wrote:
What I found when experimenting:
  • In ET_EXEC file I can put code in PT_GNU_RELRO segment and apply relocations to it without marking the segment as writable (the loader/interpreter must be making it writable temporarily to apply relocations). So far, so good.
  • When I make the same file, but change type to ET_DYN, it crashes when it's trying to access PT_INTERP segment at its default address (as it is not there, because ASLR has chosen a different address). This suggests that ET_DYN files are not supposed to have PT_INTERP segment. OK, not a big deal.
  • But when I make ET_DYN with no PT_INTERP segment, the relocations are not applied (even though PT_DYNAMIC is present).
So perhaps GCC-made exe is invoking an interpreter on its own, or even applying relocations on its own?
So it appears as though the loader will do the symbol binding for .so files, and the interpreter (if included) will process the relocations.
Post 30 Jan 2019, 20:50
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2, 3, 4  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.