TUCoPS :: Phrack Inc. Issue #63 :: p63-0x09.txt

Phrack, Inc. Issue 63, File 09/20 - Embedded Elf Debugging


                             ==Phrack Inc.==

              Volume 0x0b, Issue 0x3f, Phile #0x09 of 0x14

|=-------=[ Embedded ELF Debugging : the middle head of Cerberus ]=------=|
|=-----------------------------------------------------------------------=|
|=-------------=[ The ELF shell crew <elfsh@devhell.org> ]=--------------=|
|=-----------------------------------------------------------------------=|


I. Hardened software debugging introduction
     a. Previous work & limits
     b. Beyond PaX and ptrace()		
     c.	Interface improvements
II. The embedded debugging playground
     a. In-process injection
     b. Altenate ondisk and memory ELF scripting (feat. linkmap)
     c. Real debugging : stepping and backtracing 
     d. Dynamic analyzers generation 
III. Better multiarchitecture ELF redirections
     a. CFLOW: PaX-safe static functions redirection		
     b. ALTPLT technique revisited				
     c. ALTGOT technique : the RISC complement			
     d. EXTPLT technique : unknown function postlinking
     e. IA32, SPARC32/64, ALPHA64, MIPS32 compliant algorithms		 
V. Constrained Debugging
     a. ET_REL relocation in memory				
     b. ET_REL injection for Hardened Gentoo (ET_DYN + pie + ssp)
     c. Extending static executables				
VI. Past and present
VII. Greetings  
VIII. References



[NOTE of ELFsh crew]
[This article is in beta version. The final release is for this week]



-------[ I. Hardened software debugging introduction
	 
	 
	      In the past, binary manipulation work has focussed on virii
	 writing, backdoors deployment, or creation of tiny or obfuscated
	 executables. Besides the tools from the GNU project such as the
	 GNU debugger [1] (which focuss more on portability than 
	 functionalities), no major binary manipulation framework does
	 exist. For the last ten years, the ELF format has been a succes 
	 and most UNIX Operating System and distributions rely on it. 
	 However, the existing tools do not take advantage of the format 
	 and most of the reverse engineering related software are either 
	 very architecture specific, or simply do not care about binary 
	 internals for extracting and redirecting information.

	 Since our first published work on the ELF shell, we improved so
	 much the new framework that it is now time to publish a second
	 deep article on advances on ELF techniques. We will explain in
	 great details the 8 new reverse engineering functionalities that 
	 cut with the existing methodology of binary manipulation based
	 reverse engineering. Those techniques allow for a new type of 
	 approach on debugging and extending closed source software. We
	 worked on many architectures (x86, alpha, sparc, mips) and 
	 focussed on hardened environment where binaries are linked with 
	 security protections enabled (such as hardened gentoo binaries) 
	 in PaX [2] protected machines.


----[ A. Previous work & limits


	 In the first part of the Cerberus articles serie, we introduced 
	 a new residency technique called ET_REL injection. It consisted 
	 in compiling C code into relocatable (.o) files and inject them 
	 into existing closed source binary programs. This technique was 
	 proposed for INTEL and SPARC architectures on the ELF32 format. 
	 We improved this technique so that both 32 and 64 bits binaries 
	 are supported so we added alpha64 and sparc64 support. We also 
	 worked on the MIPS r5000 architecture and now provide a nearly 
	 complete environment for it as well. We now also allow for ET_REL
	 injection into ET_DYN objects (shared libraries) so that our 
	 technique is compatible with fully randomized environments such 
	 as provided by Hardened Gentoo with the PaX protection enabled
	 on the Linux Operating System. We also worked on other OS such as
	 BSD based ones, Solaris, and HP-UX and we claim portability on 
	 those as well. 

	 A major innovation of our debugging framework is the absence of
	 ptrace. We do not use kernel residency like in [8] so that even
	 unprivilegied users can use this and it is not Operating System
	 dependent.

	 Existing debuggers use to rely on the ptrace system call so that 
	 the debugger process can attach the debuggee program and enable 
	 various internal process manipulations such as dumping memory, 
	 putting breakpoing, doing step by step analysis, and so
	 on. We propose the same features without using the system call 
	 and we added new major contributions to that common interface.
	 
	 The reasons why we do not use ptrace are multiple and simple. 
	 First of all, a lot of hardened or embedded systems do not 
	 implement it, or just disable it. That's the case for grsecurity 
	 based systems or phone systems whoose Operating System is ELF 
	 based but without a ptrace interface. The second major reason of 
	 not using ptrace is the performance penalties of such a debugging
	 system. We do not suffer from performance penalties since the 
	 debugger resides in the same process. We provide a full userland 
	 technique that does not have to access the kernel memory, thus 
	 it is useful in all stage of a penetration test when debugging 
	 sensible software on hardened environment is needed and no system
	 update is possible. We allow for plain C code injection inside 
	 new binary files (in the static perspective) and processes (in 
	 the runtime mode) using a unified software. When possible, we 
	 only use ELF techniques that reduce forensics evidence on the 
	 disk and only works in memory.


----[ B. Beyond PaX and ptrace


	 Another key point in our framework are the greatly improved 
	 redirection techniques. We can redirect almost all control flow, 
	 wheter or not the function code is placed inside the binary 
	 itself (CFLOW technique) or in a library on which the binary 
	 depends. Our previous work presented new hijacking techniques 
	 such that ALTPLT. We improved this techniques and passed though 
	 many rewrites and now allow a complete architecture independant
	 implementation. We completed ALTPLT by a new technique called 
	 ALTGOT so that hijacking function and calling back the original 
	 one is possible on Alpha and Mips RISC machines as well. We also 
	 created a new technique called EXTPLT which allow for unknown 
	 function (for which no dynamic linking information is available 
	 at all) using a new postlinking algorithm compatible with ET_EXEC
	 and ET_DYN objets.


----[ C. Interface improvements


	 Our Embedded ELF debugger implementation is a prototype. 
	 Understand that it is really usable but we are still in the 
	 development process. All the code presented here is known to work,
	 but you may encounted a problem. In that case drop us an email so 
	 that we can go further and you can get a patch. The only 
	 assumption that we made is the ability to read the debuggee 
	 program. In all case, you can also debug in memory the unreadable 
	 binaries on disk. However the debugger is enhanced when binary 
	 files are readable. Because the debugger run in the same address 
	 space, you can still read memory [3] [4] and restore the binary 
	 program. 

	 Then you can start a debugging session using the reconstructed 
	 binary. We do not provide binary reconstruction facilities but 
	 other related work suggest that it is really usable.
	 
	 The central communication language in the Embedded ELF Debugger 
	 (e2dbg) framework is our scripting facilities. We augmented the 
	 scripting capabilities with loop, transparent support for lazy 
	 typed variables (like in bash or perl). The source command and 
	 user defined macros are also supported. We also developed a 
	 peer2peer stack so called Distributed Updates Management Protocol
	 - DUMP - that allow for linking multiple debugger instances using
	 the network. For completeness, we also now support multiuser 
	 (parallel or shared) sessions, and workspaces support. We will go
	 through the use of such interface in the first part of the paper,
	 besides the use of all the new techniques. In the second part, we 
	 give technical details about the implementation of such features 
	 on multiple architectures. The last part is dedicated to the most
	 recent and advanced techniques we developed in the last weeks for
	 constrained debugging in protected binaries.
	 


-------[ II. The embedded debugging playground
     

---[ A. In-process injection

     
	We have different techniques for injecting the debugger
	inside the debuggee process. Thus it will share the address
	space and the debugger will be able to read its own data 
	and code for getting (and changing) information in the 
	debuggee process.

	Because the ELF shell is composed of 40000 lines of code, 
	we did not want to recode everything for allowing process
	modification. We used some trick that allow us to select
	wether the modifications are done in memory or on disk. The
	trick consists in 10 lines of code, which are :


 (libelfsh/section.c)

     
 /* Fill an anonymous (unknown content) section */
 void		*elfsh_get_anonymous_section(elfshobj_t *file, 
					    elfshsect_t *sect)
 {
  ELFSH_PROFILE_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Bad parameter checking */
  if (file == NULL || sect == NULL)
    ELFSH_PROFILE_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid NULL parameter", NULL);

  /* If the section is already loaded */
  if (sect->data != NULL)
    ELFSH_PROFILE_ROUT(__FILE__, __FUNCTION__, __LINE__, 
		      (elfsh_get_raw(sect)));

  sect->data = elfsh_load_section(file, sect->shdr);
  ELFSH_PROFILE_ROUT(__FILE__, __FUNCTION__, __LINE__, 
  (elfsh_get_raw(sect)));
 }


	What is the technique about ? It is quite simple : if the debugger
	internal flag is set to static mode (ondisk modification), then we
	return the pointer on the data cache for the section we want to
	modify. However if we are in dynamic mode (process modification), 
	then we just return the address of that section. The debugger runs
	in the same process and thus will think that the returned address
	is a readable (or writable) buffer. We can reuse all the ELF shell
	API by just taking care of using the elfsh_get_raw() function when
	accessing the ->data pointer. The process/ondisk selection is then
	transparent for all the debugger/elfsh code.



<2 outputs : by ld_preload, by static injection>


---[ B. Altenate ondisk and memory ELF scripting (feat. linkmap)


	Let's see how to use the embedded debugger and its mode
	command that does the memory/disk selection. We there
	print the Global Offset Table (.got). First the memory
	got is displayed, then we get back in static mode and
	the ondisk GOT is displayed:


 ========= BEGIN EXAMPLE 1 =========
 (e2dbg-0.65) list

 .::. Working files .::.
 [001] Sun Jul 31 19:23:33 2005  D ID: 9 /lib/libncurses.so.5
 [002] Sun Jul 31 19:23:33 2005  D ID: 8 /lib/libdl.so.2
 [003] Sun Jul 31 19:23:33 2005  D ID: 7 /lib/libtermcap.so.2
 [004] Sun Jul 31 19:23:33 2005  D ID: 6 /lib/libreadline.so.5
 [005] Sun Jul 31 19:23:33 2005  D ID: 5 /lib/libelfsh.so
 [006] Sun Jul 31 19:23:33 2005  D ID: 4 /lib/ld-linux.so.2
 [007] Sun Jul 31 19:23:33 2005  D ID: 3 ./ibc.so.6
 [008] Sun Jul 31 19:23:33 2005  D ID: 2 /lib/tls/libc.so.6
 [009] Sun Jul 31 19:23:33 2005 *D ID: 1 ./a.out_e2dbg

 .::. ELFsh modules .::.
 [*] No loaded module

 (e2dbg-0.65) mode

 [*] e2dbg is in DYNAMIC MODE

 (e2dbg-0.65) got

 [Global Offset Table .::. GOT : .got ]
 [Object ./a.out_e2dbg]

 0x080498E4: [0] 0x00000000       <?>

 [Global Offset Table .::. GOT : .got.plt ]
 [Object ./a.out_e2dbg]

 0x080498E8: [0] 0x0804981C       <_DYNAMIC@a.out_e2dbg>
 0x080498EC: [1] 0x00000000       <?>
 0x080498F0: [2] 0x00000000       <?>
 0x080498F4: [3] 0x0804839E       <fflush@a.out_e2dbg>
 0x080498F8: [4] 0x080483AE       <puts@a.out_e2dbg>
 0x080498FC: [5] 0x080483BE       <malloc@a.out_e2dbg>
 0x08049900: [6] 0x080483CE       <strlen@a.out_e2dbg>
 0x08049904: [7] 0x080483DE       <__libc_start_main@a.out_e2dbg>
 0x08049908: [8] 0x080483EE       <printf@a.out_e2dbg>
 0x0804990C: [9] 0x080483FE       <free@a.out_e2dbg>
 0x08049910: [10] 0x0804840E      <read@a.out_e2dbg>

 [Global Offset Table .::. GOT : .elfsh.altgot ]
 [Object ./a.out_e2dbg]

 0x08049928: [0] 0x0804981C       <_DYNAMIC@a.out_e2dbg>
 0x0804992C: [1] 0xB7F4A4E8       <_r_debug@ld-linux.so.2 + 24>
 0x08049930: [2] 0xB7F3EEC0       <_dl_rtld_di_serinfo@ld-linux.so.2 + 477>
 0x08049934: [3] 0x0804839E       <fflush@a.out_e2dbg>
 0x08049938: [4] 0x080483AE       <puts@a.out_e2dbg>
 0x0804993C: [5] 0xB7E515F0       <__libc_malloc@libc.so.6>
 0x08049940: [6] 0x080483CE       <strlen@a.out_e2dbg>
 0x08049944: [7] 0xB7E01E50       <__libc_start_main@libc.so.6>
 0x08049948: [8] 0x080483EE       <printf@a.out_e2dbg>
 0x0804994C: [9] 0x080483FE       <free@a.out_e2dbg>
 0x08049950: [10] 0x0804840E      <read@a.out_e2dbg>
 0x08049954: [11] 0xB7DAFFF6      <e2dbg_run@ibc.so.6>

 (e2dbg-0.65) mode static

 [*] e2dbg is now in STATIC mode

 (e2dbg-0.65) got

 [Global Offset Table .::. GOT : .got ]
 [Object ./a.out_e2dbg]

 0x080498E4: [0] 0x00000000       <?>

 [Global Offset Table .::. GOT : .got.plt ]
 [Object ./a.out_e2dbg]

 0x080498E8: [0] 0x0804981C       <_DYNAMIC>
 0x080498EC: [1] 0x00000000       <?>
 0x080498F0: [2] 0x00000000       <?>
 0x080498F4: [3] 0x0804839E       <fflush>
 0x080498F8: [4] 0x080483AE       <puts>
 0x080498FC: [5] 0x080483BE       <malloc>
 0x08049900: [6] 0x080483CE       <strlen>
 0x08049904: [7] 0x080483DE       <__libc_start_main>
 0x08049908: [8] 0x080483EE       <printf>
 0x0804990C: [9] 0x080483FE       <free>
 0x08049910: [10] 0x0804840E      <read>

 [Global Offset Table .::. GOT : .elfsh.altgot ]
 [Object ./a.out_e2dbg]

 0x08049928: [0] 0x0804981C       <_DYNAMIC>
 0x0804992C: [1] 0x00000000       <?>
 0x08049930: [2] 0x00000000       <?>
 0x08049934: [3] 0x0804839E       <fflush>
 0x08049938: [4] 0x080483AE       <puts>
 0x0804993C: [5] 0x080483BE       <malloc>
 0x08049940: [6] 0x080483CE       <strlen>
 0x08049944: [7] 0x080483DE       <__libc_start_main>
 0x08049948: [8] 0x080483EE       <printf>
 0x0804994C: [9] 0x080483FE       <free>
 0x08049950: [10] 0x0804840E      <read>
 0x08049954: [11] 0x0804614A      <e2dbg_run + 6>

 =========  END EXAMPLE 1 =========


	   There are many things to notice in this dump. First
	   you can verify that it actually does what it is 
	   supposed to by looking the first GOT entries which
	   are reserved for the linkmap and the rtld resolve
	   function. Those entries are filled at runtime, so
	   the static GOT version contains NULL pointers for
	   them. However the GOT which stands in memory has
	   them filled. 

	   Also, the new version of the GNU linker does insert
	   multiple GOT sections inside ELF binaries. Section
	   .got handles the pointer for external variables, while
	   .got.plt handles the external function pointers. In
	   earlier versions of LD, those 2 sections were merged.

	   Finally, you can see in last the .elfsh.altgot section.
	   That is part of the ALTGOT technique and it will be 
	   explained as a standalone algorithm in the next parts
	   of this paper. The ALTGOT technique allow for a size
	   extension of the Global Offset Table. It allows different
	   things depending on the architecture. On x86, ALTGOT is
	   only used when EXTPLT is used, so that we can add extra 
	   function to the host file. On MIPS and ALPHA, ALTGOT
	   allows to redirect an external function without losing
	   the real function address. We will develop both of these
	   techniques in the next parts.



---[ C. Real debugging : backtrace, breakpoints, and step


          When performing debugging using a debugger embedded in the 
	  debuggee process, we are not using ptrace so we cannot 
	  modify so easily the process address space. That's why 
	  we have to do small static changes : we add the debugger
	  as a DT_NEEDED dependancy. The debugger will overload some 
	  signal handlers (SIGTRAP, SIGINT, SIGSEGV ..) so that it 
	  can takes control on those events. We can redirect functions
	  as well using either the CFLOW or ALTPLT technique (ondisk
	  modification) so that we takes control at the desired moment.
	  Obviously we can also set breakpoints in runtime but that
	  need to mprotect the code zone if it was not writable (which
	  is incompatible with the mprotect option of PaX). Fortunately
	  we assume for now that we have read access to the debuggee
	  program, which means that we can copy the file and disable
	  that option.


 ========= BEGIN EXAMPLE 2 =========

 elfsh@WTH $ cat inject_e2dbg.esh
 #!../../vm/elfsh
 load a.out
 set 1.dynamic[08].val 0x2
 set 1.dynamic[08].tag DT_NEEDED
 redir main e2dbg_run
 save a.out_e2dbg

 =========  END EXAMPLE 2 =========


	   Let's see the modified binary .dynamic section, where the
	   extra DT_NEEDED entries were added using the DT_DEBUG
	   technique that we published 2 years ago :


 ========= BEGIN EXAMPLE 3 =========

 elfsh@WTH $ ../../vm/elfsh -f ./a.out -d DT_NEEDED

 [*] Object ./a.out has been loaded (O_RDONLY)

 [SHT_DYNAMIC]
 [Object ./a.out]

 [00] Name of needed library => libc.so.6 {DT_NEEDED}

 [*] Object ./a.out unloaded

 elfsh@WTH $ ../../vm/elfsh -f ./a.out_e2dbg -d DT_NEEDED

 [*] Object ./a.out_e2dbg has been loaded (O_RDONLY)

 [SHT_DYNAMIC]
 [Object ./a.out_e2dbg]

 [00] Name of needed library => libc.so.6 {DT_NEEDED}
 [08] Name of needed library => ibc.so.6 {DT_NEEDED}

 [*] Object ./a.out_e2dbg unloaded

 =========  END EXAMPLE 3 =========


	   Let's see how we redirected the main function to
	   the hook_main function. You can notice the
	   overwritten bytes between the 2 jmp of the 
	   hook_main function. This technique is available
	   for x86 and MIPS architecture :


 ========= BEGIN EXAMPLE 4 =========

 elfsh@WTH $ ../../vm/elfsh -f ./a.out_e2dbg -D main%40

 [*] Object ./a.out_e2dbg has been loaded (O_RDONLY)

 08045134 [foff: 308] hook_main + 0  jmp   <e2dbg_run>
 08045139 [foff: 313] hook_main + 5  push  %ebp
 0804513A [foff: 314] hook_main + 6  mov   %esp,%ebp
 0804513C [foff: 316] hook_main + 8  push  %esi
 0804513D [foff: 317] hook_main + 9  push  %ebx
 0804513E [foff: 318] hook_main + 10 jmp   <main + 5>

 08045139 [foff: 313] old_main + 0   push  %ebp
 0804513A [foff: 314] old_main + 1   mov   %esp,%ebp
 0804513C [foff: 316] old_main + 3   push  %esi
 0804513D [foff: 317] old_main + 4   push  %ebx
 0804513E [foff: 318] old_main + 5   jmp   <main + 5>

 08048530 [foff: 13616] main + 0     jmp   <hook_main>
 08048535 [foff: 13621] main + 5     sub   $2010,%esp
 0804853B [foff: 13627] main + 11    mov   8(%ebp),%ebx
 0804853E [foff: 13630] main + 14    mov   C(%ebp),%esi
 08048541 [foff: 13633] main + 17    and   $FFFFFFF0,%esp
 08048544 [foff: 13636] main + 20    sub   $10,%esp
 08048547 [foff: 13639] main + 23    mov   %ebx,4(%esp,1)
 0804854B [foff: 13643] main + 27    mov   $<_IO_stdin_used + 43>,(%esp,1)
 08048552 [foff: 13650] main + 34    call  <printf>
 08048557 [foff: 13655] main + 39    mov   (%esi),%eax

 [*] No binary pattern was specified

 [*] Object ./a.out_e2dbg unloaded

 =========  END EXAMPLE 4 =========

	   
	   Let's now execute the debuggee program, in which the 
	   debugger was injected.


 ========= BEGIN EXAMPLE 5 =========

 elfsh@WTH $ ./a.out_e2dbg


         The Embedded ELF Debugger 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org 

 [*] Sun Jul 31 17:56:52 2005 - New object ./a.out_e2dbg loaded
 [*] Sun Jul 31 17:56:52 2005 - New object /lib/tls/libc.so.6 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object ./ibc.so.6 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/ld-linux.so.2 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/libelfsh/libelfsh.so loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/libreadline.so.5 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/libtermcap.so.2 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/libdl.so.2 loaded
 [*] Sun Jul 31 17:56:53 2005 - New object /lib/libncurses.so.5 loaded

 (e2dbg-0.65) b puts

 [*] Breakpoint added at <puts@a.out_e2dbg> (0x080483A8)

 (e2dbg-0.65) continue

         [..: Embedded ELF Debugger returns to the grave :...]

 [e2dbg_run] returning to 0x08045139
 [host] main argc 1
 [host] argv[0] is : ./a.out_e2dbg

 First_printf test


         The Embedded ELF Debugger 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org 

 [*] Sun Jul 31 17:57:03 2005 - New object /lib/tls/libc.so.6 loaded

 (e2dbg-0.65) bt

 .:: Backtrace ::.
 [00] 0xB7DC1EC5 <vm_bt@ibc.so.6 + 208>
 [01] 0xB7DC207F <cmd_bt@ibc.so.6 + 152>
 [02] 0xB7DBC88C <vm_execmd@ibc.so.6 + 174>
 [03] 0xB7DAB4DE <vm_loop@ibc.so.6 + 578>
 [04] 0xB7DAB943 <vm_run@ibc.so.6 + 271>
 [05] 0xB7DA5FF0 <e2dbg_entry@ibc.so.6 + 110>
 [06] 0xB7DA68D6 <e2dbg_genericbp_ia32@ibc.so.6 + 183>
 [07] 0xFFFFE440 <_r_debug@ld-linux.so.2 + 1208737648>
 [08] 0xB7DF7F3B <__libc_start_main@libc.so.6 + 235>
 [09] 0x08048441 <_start@a.out_e2dbg + 33>

 (e2dbg-0.65) b

 .:: Breakpoints ::.

 [00] 0x080483A8 <puts@a.out_e2dbg>

 (e2dbg-0.65) delete 0x080483A8

 [*] Breakpoint at 080483A8 <puts@a.out_e2dbg> removed

 (e2dbg-0.65) b

 .:: Breakpoints ::.

 [*] No breakpoints

 (e2dbg-0.65) b printf

 [*] Breakpoint added at <printf@a.out_e2dbg> (0x080483E8)

 (e2dbg-0.65) dumpregs

 .:: Registers ::.

         [EAX] 00000000 (0000000000) <unknown>
         [EBX] 08203F48 (0136331080) <.elfsh.relplt@a.out_e2dbg + 1811272>
         [ECX] 00000000 (0000000000) <unknown>
         [EDX] B7F0C7C0 (3086010304) <__guard@libc.so.6 + 1656>
         [ESI] BFE3B7C4 (3219371972) <_r_debug@ld-linux.so.2 + 133149428>
         [EDI] BFE3B750 (3219371856) <_r_debug@ld-linux.so.2 + 133149312>
         [ESP] BFE3970C (3219363596) <_r_debug@ld-linux.so.2 + 133141052>
         [EBP] BFE3B738 (3219371832) <_r_debug@ld-linux.so.2 + 133149288>
         [EIP] 080483A9 (0134513577) <puts@a.out_e2dbg>

 (e2dbg-0.65) stack 20

 .:: Stack ::.
 0xBFE37200 0x00000000 <(null)>
 0xBFE37204 0xB7DC2091 <vm_dumpstack@ibc.so.6>
 0xBFE37208 0xB7DDF5F0 <_GLOBAL_OFFSET_TABLE_@ibc.so.6>
 0xBFE3720C 0xBFE3723C <_r_debug@ld-linux.so.2 + 133131628>
 0xBFE37210 0xB7DC22E7 <cmd_stack@ibc.so.6 + 298>
 0xBFE37214 0x00000014 <_r_debug@ld-linux.so.2 + 1208744772>
 0xBFE37218 0xB7DDDD90 <__FUNCTION__.5@ibc.so.6 + 49>
 0xBFE3721C 0xBFE37230 <_r_debug@ld-linux.so.2 + 133131616>
 0xBFE37220 0xB7DB9DF9 <vm_implicit@ibc.so.6 + 304>
 0xBFE37224 0xB7DE1A7C <world@ibc.so.6 + 92>
 0xBFE37228 0xB7DA8176 <do_resolve@ibc.so.6>
 0xBFE3722C 0x080530B8 <.elfsh.relplt@a.out_e2dbg + 38072>
 0xBFE37230 0x00000014 <_r_debug@ld-linux.so.2 + 1208744772>
 0xBFE37234 0x08264FF6 <.elfsh.relplt@a.out_e2dbg + 2208758>
 0xBFE37238 0xB7DDF5F0 <_GLOBAL_OFFSET_TABLE_@ibc.so.6>
 0xBFE3723C 0xBFE3726C <_r_debug@ld-linux.so.2 + 133131676>
 0xBFE37240 0xB7DBC88C <vm_execmd@ibc.so.6 + 174>
 0xBFE37244 0x0804F208 <.elfsh.relplt@a.out_e2dbg + 22024>
 0xBFE37248 0x00000000 <(null)>
 0xBFE3724C 0x00000000 <(null)>

 (e2dbg-0.65) continue

         [..: Embedded ELF Debugger returns to the grave :...]

 First_puts


         The Embedded ELF Debugger 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org 

 [*] Sun Jul 31 18:00:47 2005 - /lib/tls/libc.so.6 loaded
 [*] Sun Jul 31 18:00:47 2005 - /usr/lib/gconv/ISO8859-1.so loaded

 (e2dbg-0.65) dumpregs

 .:: Registers ::.

         [EAX] 0000000B (0000000011) <_r_debug@ld-linux.so.2 + 1208744763>
         [EBX] 08203F48 (0136331080) <.elfsh.relplt@a.out_e2dbg + 1811272>
         [ECX] 0000000B (0000000011) <_r_debug@ld-linux.so.2 + 1208744763>
         [EDX] B7F0C7C0 (3086010304) <__guard@libc.so.6 + 1656>
         [ESI] BFE3B7C4 (3219371972) <_r_debug@ld-linux.so.2 + 133149428>
         [EDI] BFE3B750 (3219371856) <_r_debug@ld-linux.so.2 + 133149312>
         [ESP] BFE3970C (3219363596) <_r_debug@ld-linux.so.2 + 133141052>
         [EBP] BFE3B738 (3219371832) <_r_debug@ld-linux.so.2 + 133149288>
         [EIP] 080483E9 (0134513641) <printf@a.out_e2dbg>

 (e2dbg-0.65) linkmap

 .::. Linkmap entries .::.
 [01] addr : 0x00000000 dyn : 0x0804981C -
 [02] addr : 0x00000000 dyn : 0xFFFFE590 -
 [03] addr : 0xB7DE3000 dyn : 0xB7F0AD3C - /lib/tls/libc.so.6
 [04] addr : 0xB7D95000 dyn : 0xB7DDF01C - ./ibc.so.6
 [05] addr : 0xB7F29000 dyn : 0xB7F3FF14 - /lib/ld-linux.so.2
 [06] addr : 0xB7D62000 dyn : 0xB7D93018 - /lib/libelfsh.so
 [07] addr : 0xB7D35000 dyn : 0xB7D5D46C - /lib/libreadline.so.5
 [08] addr : 0xB7D31000 dyn : 0xB7D34BB4 - /lib/libtermcap.so.2
 [09] addr : 0xB7D2D000 dyn : 0xB7D2FEEC - /lib/libdl.so.2
 [10] addr : 0xB7CEB000 dyn : 0xB7D2A1C0 - /lib/libncurses.so.5
 [11] addr : 0xB6D84000 dyn : 0xB6D85F28 - /usr/lib/gconv/ISO8859-1.so

 (e2dbg-0.65) exit

 [*] Unloading object 1 (/usr/lib/gconv/ISO8859-1.so)
 [*] Unloading object 2 (/lib/tls/libc.so.6)
 [*] Unloading object 3 (/lib/tls/libc.so.6)
 [*] Unloading object 4 (/lib/libncurses.so.5)
 [*] Unloading object 5 (/lib/libdl.so.2)
 [*] Unloading object 6 (/lib/libtermcap.so.2)
 [*] Unloading object 7 (/lib/libreadline.so.5)
 [*] Unloading object 8 (/home/elfsh/WTH/elfsh/libelfsh/libelfsh.so)
 [*] Unloading object 9 (/lib/ld-linux.so.2)
 [*] Unloading object 10 (./ibc.so.6)
 [*] Unloading object 11 (/lib/tls/libc.so.6)
 [*] Unloading object 12 (./a.out_e2dbg) *

         .:: Bye -:: The Embedded ELF Debugger 0.65

 =========  END EXAMPLE 5 =========


	   As you see, the use of the debugger is quite similar to other
	   debugger. The difference is about the implementation technique
	   which allows for hardened and embedded systems debugging where
	   ptrace is not present or disabled.

	   We were told [9] that the sigaction system call enables the 
	   possibility of doing step by step execution without using
	   ptrace. We did not have time to implement it but we will 
	   provide a step-capable debugger in the very near future. Since 
	   that call is not filtered by grsecurity and seems to be quite 
	   portable on Linux, BSD, Solaris and HP-UX, it is definitely 
	   worth mentioning.


---[ D. Dynamic analyzers generation 


           Obviously, tools like ltrace [7] can be now done in elfsh scripts 
	   for multiple architectures since all the redirection stuff is 
	   available.     

	   We also think that the framework can be used in dynamic software
	   instrumentation. Since we support multiple architectures, we let
	   the door open to other development team to develop such modules
	   or extension inside the ELF shell framework.

	   We did not have time to include an example script for now that 
	   can do this, but we will soon. The kind of interresting stuff
	   that could be done and improved using the framework would
	   take its inspiration in projects like fenris [6].

	   We do not deal with encryption for now, but some promising API 
	   [5] could be implemented as well for multiple architectures very
	   easily.

	   



-------[ III. Better multiarchitecture ELF redirections


	 In the first issue of the Cerberus ELF interface, we presented
	 a redirection technique that we called ALTPLT. This technique
	 is not enough since it allows only for PLT redirection. 
	 Morever, we noticed a bug in the previously released 
	 implementation of the ALTPLT technique : On the SPARC
	 architecture, when calling the original function, the 
	 redirection was removed and the program continued to work as if
	 no hook was installed. This bug came from the fact that Solaris
	 does not use the r_offset field for computing its relocation 
	 but get the file offset by multiplying the PLT entry size by the 
	 pushed relocation offset on the stack at the moment of dynamic 
	 resolution. 

	 We found a solution for this problem. That solution consisted in
	 adding some architecture specific fixes at the beginning of the 
	 ALTPLT section. However, such a fix is too much architecture
	 dependant and we started to think about an alternative technique
	 for implementing ALTPLT. As we had implemented the DT_DEBUG 
	 technique by modifying some entries in the .dynamic sections, we
	 discovered that many other entries are erasable and allow for
	 a very strong and architecture independant technique for 
	 redirecting access to various sections. More precisely, when 
	 patching the DT_PLTREL entry, we are able to provide our own 
	 pointer. DT_PLTREL is an architecture dependant entry and the  
	 documentation about it is quite weak, not to say inexistant. 

	 It actually points on the section of the executable beeing   
	 runtime relocated (e.g. GOT on x86 or MIPS, PLT on sparc and 
	 alpha). By changing this entry we are able to provide our own 
	 PLT or GOT, which leads to possibly extending it.

	 Let's first have look at the CFLOW technique and then comes
	 back on the PLT related redirections using the DT_PLTREL
	 modification.



---[ A. CFLOW: PaX-safe static functions redirection		


	 CFLOW is a simple but efficient technique for
	 function redirection. Let's see the host file 
	 that we use for this test:


 ========= BEGIN EXAMPLE 6 =========

 elfsh@WTH $ cat host.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int     legit_func(char *str)
 {
   printf("legit func (%s) !\n", str);
   return (0);
 }

 int	main()
 {
   char  *str;
   char  buff[BUFSIZ];

   read(0, buff, BUFSIZ-1);

   str = malloc(10);
   if (str == NULL)
     goto err;
   strcpy(str, "test");
   printf("First_printf %s\n", str);
   fflush(stdout);
   puts("First_puts");
   printf("Second_printf %s\n", str);

   free(str);

   puts("Second_puts");

   fflush(stdout);
   legit_func("test");
   return (0);
  err:
   printf("Malloc problem\n");
   return (-1);
 }

 =========  END EXAMPLE 6 =========


	   Let's look at the relocatable file that we are going to inject
	   in the above binary.


 ========= BEGIN EXAMPLE 7 =========

 elfsh@WTH $ cat rel.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int     glvar_testreloc = 42;
 int     glvar_testreloc_bss;
 char    glvar_testreloc_bss2;
 short   glvar_testreloc_bss3;

 int     hook_func(char *str)
 {
    printf("HOOK FUNC %s !\n", str);
    return (old_legit_func(str));
 }

 int     puts_troj(char *str)
 {
   int   local = 1;
   char  *str2;

   str2 = malloc(10);
   *str2 = 'Z';
   *(str2 + 1) = 0x00;

   glvar_testreloc_bss  = 43;
   glvar_testreloc_bss2 = 44;
   glvar_testreloc_bss3 = 45;

   printf("Trojan injected ET_REL takes control now "
          "[%s:%s:%u:%u:%hhu:%hu:%u] \n",
         str2, str,
         glvar_testreloc,
         glvar_testreloc_bss,
         glvar_testreloc_bss2,
         glvar_testreloc_bss3,
         local);

   free(str2);

   putchar('e');
   putchar('x');
   putchar('t');
   putchar('c');
   putchar('a');
   putchar('l');
   putchar('l');
   putchar('!');
   putchar('\n'); 

   old_puts(str); 

   write(1, "calling write\n", 14);
   fflush(stdout);
   return (0);
 }

 int     func2()
 {
   return (42);
 }

 =========  END EXAMPLE 7 =========

	  
	  As you can see, the relocatable object use of unknown functions
     like write and putchar. Those functions do not have an symbol, plt 
     entry, got entry, or even relocatable entry in the host file.
	   
     We can call it however using the EXTPLT technique that will be 
     described as a standalone technique in the next part of this paper. 
     For now let's focuss on the CFLOW technique that allow for redirection
     of the legit_func by the hook_func. This function does not have a PLT
     entry and we cannot use simple PLT infection for this. 

     We developped a technique that is PaX safe for ondisk redirection of
     this kind of function. It consists of putting the good old jmp
     instruction at the beginning of the legit_func and redirect the flow
     on our own code. ELFsh will take care of executing the overwritten
     bytes somewhere else and gives back control to the redirected
     function, just after the jmp hook.
	   
     Let's see more:


 ========= BEGIN EXAMPLE 8 =========

 elfsh@WTH $ file a.out
 a.out: ELF 32-bit LSB executable, Intel 80386, dynamically linked, \
 not stripped
 elfsh@WTH $ cat relinject.esh
 #!../../../vm/elfsh

 load a.out
 load rel.o

 reladd 1 2

 redir puts puts_troj
 redir legit_func hook_func

 save fake_aout

 quit

 =========  END  EXAMPLE 8 =========


    The result of the ORIGINAL binary is as follow:


 ========= BEGIN EXAMPLE 9 =========

 elfsh@WTH $ ./a.out

 First_printf test
 First_puts
 Second_printf test
 Second_puts
 LEGIT FUNC
 legit func (test) !

 ========= END EXAMPLE 9 ===========


     Now let's inject the stuff:

	   
 ========= BEGIN EXAMPLE 10 ========

 elfsh@WTH $ ./relinject.esh


         The ELF shell 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org 

 ~load a.out

 [*] Sun Jul 31 15:30:14 2005 - New object a.out loaded

 ~load rel.o

 [*] Sun Jul 31 15:30:14 2005 - New object rel.o loaded

 ~reladd 1 2
 Section Mirrored Successfully !

 [*] ET_REL rel.o injected succesfully in ET_EXEC a.out

 ~redir puts puts_troj

 [*] Function puts redirected to addr 0x08047164 <puts_troj>

 ~redir legit_func hook_func

 [*] Function legit_func redirected to addr 0x08047134 <hook_func>

 ~save fake_aout

 [*] Object fake_aout saved successfully

 ~quit

 [*] Unloading object 1 (rel.o)
 [*] Unloading object 2 (a.out) *
         .:: Bye -:: The ELF shell 0.65

 ========= END EXAMPLE 10 =========


	   Let's now execute the modified binary.

	   
 ========= BEGIN EXAMPLE 11 =========

 elfsh@WTH $ ./fake_aout

 First_printf test
 Trojan injected ET_REL takes control now [Z:First_puts:42:43:44:45:1]
 extcall!
 First_puts
 calling write
 Second_printf test
 Trojan injected ET_REL takes control now [Z:Second_puts:42:43:44:45:1]
 extcall!
 Second_puts
 calling write
 HOOK FUNC test !
 Trojan injected ET_REL takes control now [Z:LEGIT FUNC:42:43:44:45:1]
 extcall!
 calling write
 legit func (test) !
 elfsh@WTH $

 =========  END EXAMPLE 11 =========


	   Fine. Clearly legit_func has been redirected on the hook 
	   function, and hook_func takes care of calling back the
	   legit_func using the old symbol technique described in
	   the first issue of the Cerberus articles serie.

	   Let's see the original legit_func code which is redirected
	   using the CFLOW technique.
	   

 ========= BEGIN EXAMPLE 12 =========

 080484C0 legit_func + 0        push   %ebp                             
 080484C1 legit_func + 1        mov    %esp,%ebp                        
 080484C3 legit_func + 3        sub    $8,%esp                          
 080484C6 legit_func + 6        mov    $<_IO_stdin_used + 4>,(%esp,1)   
 080484CD legit_func + 13       call   <.plt + 32>                      
 080484D2 legit_func + 18       mov    $<_IO_stdin_used + 15>,(%esp,1)  

 ========= END EXAMPLE 12 =========


	   Now the modified code:



 ========= BEGIN EXAMPLE 13 =========

 080484C0 legit_func + 0        jmp    <hook_legit_func>               
 080484C5 legit_func + 5        nop                                    
 080484C6 legit_func + 6        mov    $<_IO_stdin_used + 4>,(%esp,1)  
 080484CD legit_func + 13       call   <puts>                          
 080484D2 legit_func + 18       mov    $<_IO_stdin_used + 15>,(%esp,1) 
 080484D9 legit_func + 25       mov    8(%ebp),%eax                    
 080484DC legit_func + 28       mov    %eax,4(%esp,1)                  
 080484E0 legit_func + 32       call   <printf>                        
 080484E5 legit_func + 37       leave                                  
 080484E6 legit_func + 38       xor    %eax,%eax                       

 ========= END EXAMPLE 13 =========

 
	We create a new section .elfsh.hooks whoose data is array
	of hook code stubs like this one:


 ========= BEGIN EXAMPLE 14 =========

 08042134 hook_legit_func + 0   jmp    <hook_func>                     
 08042139 old_legit_func  + 0   push   %ebp                            
 0804213A old_legit_func  + 1   mov    %esp,%ebp                       
 0804213C old_legit_func  + 3   sub    $8,%esp                         
 0804213F old_legit_func  + 6   jmp    <legit_func + 6>                

 ========= END EXAMPLE 14 =========


     The MIPS logs are on Devhell Labs machine which is down
     as we are at WTH and we will put them in the updated
     version of that article as soon as we get back.


---[ B. ALTPLT technique revisited				


     ALTPLT technique v1 was presented in the Cerberus ELF Interface
     paper. As already stated, it was not satisfying and we finally
     found the .dynamic DT_PLTREL trick:


 =============== BEGIN EXAMPLE 16 ================

 [SECTION HEADER TABLE .::. SHT is not stripped]
 [Object fake_aout]

 [000] 0x00000000 -------                 foff:00000000 sz:00000000 link:00
 [001] 0x08042134 a-x---- .elfsh.hooks    foff:00000308 sz:00000016 link:00
 [002] 0x08043134 a-x---- .elfsh.extplt   foff:00004404 sz:00000048 link:00
 [003] 0x08044134 a-x---- .elfsh.altplt   foff:00008500 sz:00004096 link:00
 [004] 0x08045134 a--ms-- rel.o.rodata.str1.32 foff:12596 sz:04096  link:00
 [005] 0x08046134 a--ms-- rel.o.rodata.str1.1  foff:16692 sz:04096  link:00
 [006] 0x08047134 a-x---- rel.o.text      foff:00020788 sz:00004096 link:00
 [007] 0x08048134 a------ .interp         foff:00024884 sz:00000019 link:00
 [008] 0x08048148 a------ .note.ABI-tag   foff:00024904 sz:00000032 link:00
 [009] 0x08048168 a------ .hash           foff:00024936 sz:00000064 link:10
 [010] 0x080481A8 a------ .dynsym         foff:00025000 sz:00000176 link:11
 [011] 0x08048258 a------ .dynstr         foff:00025176 sz:00000112 link:00
 [012] 0x080482C8 a------ .gnu.version    foff:00025288 sz:00000022 link:10
 [013] 0x080482E0 a------ .gnu.version_r  foff:00025312 sz:00000032 link:11
 [014] 0x08048300 a------ .rel.dyn        foff:00025344 sz:00000016 link:10
 [015] 0x08048310 a------ .rel.plt        foff:00025360 sz:00000056 link:10
 [016] 0x08048348 a-x---- .init           foff:00025416 sz:00000023 link:00
 [017] 0x08048360 a-x---- .plt            foff:00025440 sz:00000128 link:00
 [018] 0x08048400 a-x---- .text           foff:00025600 sz:00000736 link:00
 [019] 0x080486E0 a-x---- .fini           foff:00026336 sz:00000027 link:00
 [020] 0x080486FC a------ .rodata         foff:00026364 sz:00000116 link:00
 [021] 0x08048770 a------ .eh_frame       foff:00026480 sz:00000004 link:00
 [022] 0x08049774 aw----- .ctors          foff:00026484 sz:00000008 link:00
 [023] 0x0804977C aw----- .dtors          foff:00026492 sz:00000008 link:00
 [024] 0x08049784 aw----- .jcr            foff:00026500 sz:00000004 link:00
 [025] 0x08049788 aw----- .dynamic        foff:00026504 sz:00000200 link:11
 [026] 0x08049850 aw----- .got            foff:00026704 sz:00000004 link:00
 [027] 0x08049854 aw----- .got.plt        foff:00026708 sz:00000040 link:00
 [028] 0x0804987C aw----- .data           foff:00026748 sz:00000012 link:00
 [029] 0x08049888 aw----- .bss            foff:00026760 sz:00000008 link:00
 [030] 0x08049890 aw----- rel.o.bss       foff:00026768 sz:00004096 link:00
 [031] 0x0804A890 aw----- rel.o.data      foff:00030864 sz:00000004 link:00
 [032] 0x0804A894 aw----- .elfsh.altgot   foff:00030868 sz:00000048 link:00
 [033] 0x0804A8E4 aw----- .elfsh.dynsym   foff:00030948 sz:00000208 link:34
 [034] 0x0804AA44 aw----- .elfsh.dynstr   foff:00031300 sz:00000127 link:33
 [035] 0x0804AB24 aw----- .elfsh.reldyn   foff:00031524 sz:00000016 link:00
 [036] 0x0804AB34 aw----- .elfsh.relplt   foff:00031540 sz:00000072 link:00
 [037] 0x00000000 ------- .comment        foff:00031652 sz:00000665 link:00
 [038] 0x00000000 ------- .debug_aranges  foff:00032324 sz:00000120 link:00
 [039] 0x00000000 ------- .debug_pubnames foff:00032444 sz:00000042 link:00
 [040] 0x00000000 ------- .debug_info     foff:00032486 sz:00006871 link:00
 [041] 0x00000000 ------- .debug_abbrev   foff:00039357 sz:00000511 link:00
 [042] 0x00000000 ------- .debug_line     foff:00039868 sz:00000961 link:00
 [043] 0x00000000 ------- .debug_frame    foff:00040832 sz:00000072 link:00
 [044] 0x00000000 ---ms-- .debug_str      foff:00040904 sz:00008067 link:00
 [045] 0x00000000 ------- .debug_macinfo  foff:00048971 sz:00029295 link:00
 [046] 0x00000000 ------- .shstrtab       foff:00078266 sz:00000507 link:00
 [047] 0x00000000 ------- .symtab         foff:00080736 sz:00002368 link:48
 [048] 0x00000000 ------- .strtab         foff:00083104 sz:00001785 link:47

 [SHT_DYNAMIC]
 [Object ./testsuite/etrel_inject/etrel_original/fake_aout]

 [00] Name of needed library            =>           libc.so.6 {DT_NEEDED}
 [01] Address of init function          =>          0x08048348 {DT_INIT}
 [02] Address of fini function          =>          0x080486E0 {DT_FINI}
 [03] Address of symbol hash table      =>          0x08048168 {DT_HASH}
 [04] Address of dynamic string table   =>          0x0804AA44 {DT_STRTAB}
 [05] Address of dynamic symbol table   =>          0x0804A8E4 {DT_SYMTAB}
 [06] Size of string table              =>      00000127 bytes {DT_STRSZ}
 [07] Size of symbol table entry        =>      00000016 bytes {DT_SYMENT}
 [08] Debugging entry (unknown)         =>          0x00000000 {DT_DEBUG}
 [09] Processor defined value           =>          0x0804A894 {DT_PLTGOT}
 [10] Size in bytes for .rel.plt        =>      0000072 bytes {DT_PLTRELSZ}
 [11] Type of reloc in PLT              =>            00000017 {DT_PLTREL}
 [12] Address of .rel.plt               =>          0x0804AB34 {DT_JMPREL}
 [13] Address of .rel.got section       =>          0x0804AB24 {DT_REL}
 [14] Total size of .rel section        =>      00000016 bytes {DT_RELSZ}
 [15] Size of a REL entry               =>      00000008 bytes {DT_RELENT}
 [16] SUN needed version table          =>          0x080482E0 {DT_VERNEED}
 [17] SUN needed version number         =>             0001 {DT_VERNEEDNUM}
 [18] GNU version VERSYM                =>          0x080482C8 {DT_VERSYM}

 =============== END EXAMPLE 16 ================
     

	As you can see, various sections has been copied and extended,	
	and their entries in .dynamic changed. That holds for .got 
	(DT_PLTGOT), .rel.plt (DT_JMPREL), .dynsym (DT_SYMTAB), and
	.dynstr (DT_STRTAB). Changing those entries allow for the 
	new ALTPLT technique without any line of assembly. The specific
	ALTPLT technique allow still for function redirection with the
	capability of calling back the original function without erasing
	the hook as you call it. The output of that binary was already
	pasted and we wont copy it again here.



---[ C. ALTGOT technique : the RISC complement			


	       On ALPHA and MIPS architecture, calls to PLT entries are 
       done differently. Indeed, instead of a direct call instruction on 
       the entry, an indirect jump is used for using the GOT entry linked 
       to the desired function. If such entry is filled, then the 
       function is called directly. By default, the GOT entries contains 
       the pointer on the PLT entries. When the dynamic linker is called 
       the GOT entries are filled and then the indirect jump instruction
       on MIPS and ALPHA do not use the PLT entry anymore. What do we 
       learn from this ? Simply that we cannot rely on a classical PLT 
       hijacking because the PLT entry code wont be called if the GOT 
       entry is already filled.

       Let's see how to developed the ALTGOT technique on the ALPHA 
       architecture:


 ========= BEGIN EXAMPLE 17 =========

 elfsh@alpha$ cat host.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int main()
 {
   char  *str;

   str = malloc(10);
   if (str == NULL)
     goto err;
   strcpy(str, "test");
   printf("First_printf %s\n", str);
   fflush(stdout);
   puts("First_puts");
   printf("Second_printf %u\n", 42);
   puts("Second_puts");
   fflush(stdout);
   return (0);
  err:
   printf("Malloc problem %u\n", 42);
   return (-1);
 }

 elfsh@alpha$ gcc host.c -o a.out
 elfsh@alpha$ file ./a.out
 a.out: ELF 64-bit LSB executable, Alpha (unofficial), for NetBSD 2.0G,
       dynamically linked, not stripped

 ========= END EXAMPLE 17 =========


	   The original binary executes:


 ========= BEGIN EXAMPLE 18 =========

 elfsh@alpha$ ./a.out
 First_printf test
 First_puts
 Second_printf 42
 Second_puts

 ========= END EXAMPLE 18 ==========


	   Let's look again the relocatable object we are injecting:


 ========= BEGIN EXAMPLE 19 =========

 elfsh@alpha$ cat rel.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int     glvar_testreloc = 42;

 int     glvar_testreloc_bss;
 char    glvar_testreloc_bss2;
 short   glvar_testreloc_bss3;


 int     puts_troj(char *str)
 {
   int   local = 1;
   char  *str2;

   str2 = malloc(10);
   *str2 = 'Z';
   *(str2 + 1) = 0x00;

   glvar_testreloc_bss  = 43;
   glvar_testreloc_bss2 = 44;
   glvar_testreloc_bss3 = 45;

   printf("Trojan injected ET_REL takes control now "
         "[%s:%s:%u:%u:%hhu:%hu:%u] \n",
         str2, str,
         glvar_testreloc,
         glvar_testreloc_bss,
         glvar_testreloc_bss2,
         glvar_testreloc_bss3,
         local);

   old_puts(str);
   fflush(stdout);
   return (0);
 }

 int     func2()
 {
   return (42);
 }

 ========= END EXAMPLE 19 =========


	   Now we inject the stuff:


 ========= BEGIN EXAMPLE 20 =========

 elfsh@alpha$ ./etrel_injecter

 [*] ET_REL injected

 elfsh@alpha$ ./fake_aout
 First_printf test
 Trojan injected ET_REL takes control now [Z:First_puts:42:43:44:45:1]
 First_puts
 Second_printf 42
 Trojan injected ET_REL takes control now [Z:Second_puts:42:43:44:45:1]
 Second_puts

 ========= END EXAMPLE 20 ==========



 ========= BEGIN EXAMPLE 21 =========

 elfsh@alpha$ elfsh -f fake_aout -s -p

 [*] Object fake_aout has been loaded (O_RDONLY)

 [SECTION HEADER TABLE .::. SHT is not stripped]
 [Object fake_aout]

 [000] 0x000000000 -------                     foff:00000 sz:00000
 [001] 0x120000190 a------ .interp             foff:00400 sz:00023
 [002] 0x1200001A8 a------ .note.netbsd.ident  foff:00424 sz:00024
 [003] 0x1200001C0 a------ .hash               foff:00448 sz:00544
 [004] 0x1200003E0 a------ .dynsym             foff:00992 sz:00552
 [005] 0x120000608 a------ .dynstr             foff:01544 sz:00251
 [006] 0x120000708 a------ .rela.dyn           foff:01800 sz:00096
 [007] 0x120000768 a------ .rela.plt           foff:01896 sz:00168
 [008] 0x120000820 a-x---- .init               foff:02080 sz:00128
 [009] 0x1200008A0 a-x---- .text               foff:02208 sz:01312
 [010] 0x120000DC0 a-x---- .fini               foff:03520 sz:00104
 [011] 0x120000E28 a------ .rodata             foff:03624 sz:00162
 [012] 0x120010ED0 aw----- .data               foff:03792 sz:00000
 [013] 0x120010ED0 a------ .eh_frame           foff:03792 sz:00004
 [014] 0x120010ED8 aw----- .dynamic            foff:03800 sz:00352
 [015] 0x120011038 aw----- .ctors              foff:04152 sz:00016
 [016] 0x120011048 aw----- .dtors              foff:04168 sz:00016
 [017] 0x120011058 aw----- .jcr                foff:04184 sz:00008
 [018] 0x120011060 awx---- .plt                foff:04192 sz:00116
 [019] 0x1200110D8 aw----- .got                foff:04312 sz:00240
 [020] 0x1200111C8 aw----- .sdata              foff:04552 sz:00024
 [021] 0x1200111E0 aw----- .sbss               foff:04576 sz:00024
 [022] 0x1200111F8 aw----- .bss                foff:04600 sz:00056
 [023] 0x120011230 a-x---- rel.o.text          foff:04656 sz:00320
 [024] 0x120011370 aw----- rel.o.sdata         foff:04976 sz:00008
 [025] 0x120011378 a--ms-- rel.o.rodata.str1.1 foff:04984 sz:00072
 [026] 0x1200113C0 a-x---- .alt.plt.prolog     foff:05056 sz:00048
 [027] 0x1200113F0 a-x---- .alt.plt            foff:05104 sz:00120
 [028] 0x120011468 a------ .alt.got            foff:05224 sz:00072
 [029] 0x1200114B0 aw----- rel.o.got           foff:05296 sz:00080
 [030] 0x000000000 ------- .comment            foff:05376 sz:00240
 [031] 0x000000000 ------- .debug_aranges      foff:05616 sz:00048
 [032] 0x000000000 ------- .debug_pubnames     foff:05664 sz:00027
 [033] 0x000000000 ------- .debug_info         foff:05691 sz:02994
 [034] 0x000000000 ------- .debug_abbrev       foff:08685 sz:00337
 [035] 0x000000000 ------- .debug_line         foff:09022 sz:00373
 [036] 0x000000000 ------- .debug_frame        foff:09400 sz:00048
 [037] 0x000000000 ---ms-- .debug_str          foff:09448 sz:01940
 [038] 0x000000000 ------- .debug_macinfo      foff:11388 sz:12937
 [039] 0x000000000 ------- .ident              foff:24325 sz:00054
 [040] 0x000000000 ------- .shstrtab           foff:24379 sz:00393
 [041] 0x000000000 ------- .symtab             foff:27527 sz:02400
 [042] 0x000000000 ------- .strtab             foff:29927 sz:00948

 [Program header table .::. PHT]
 [Object fake_aout]

 [00] 0x120000040 -> 0x120000190 r-x  => Program header table
 [01] 0x120000190 -> 0x1200001A7 r--  => Program interpreter
 [02] 0x120000000 -> 0x120000ECA r-x  => Loadable segment
 [03] 0x120010ED0 -> 0x120011510 rwx  => Loadable segment
 [04] 0x120010ED8 -> 0x120011038 rw-  => Dynamic linking info
 [05] 0x1200001A8 -> 0x1200001C0 r--  => Auxiliary information

 [Program header table .::. SHT correlation]
 [Object fake_aout]

 [*] SHT is not stripped

 [00] PT_PHDR
 [01] PT_INTERP         .interp
 [02] PT_LOAD           .interp .note.netbsd.ident .hash .dynsym .dynstr
                        .rela.dyn .rela.plt .init .text .fini .rodata
 [03] PT_LOAD           .data .eh_frame .dynamic .ctors .dtors .jcr .plt
                        .got .sdata .sbss .bss rel.o.text rel.o.sdata
                        rel.o.rodata.str1.1 .alt.plt.prolog .alt.plt
                        .alt.got rel.o.got
 [04] PT_DYNAMIC        .dynamic
 [05] PT_NOTE           .note.netbsd.ident

 [*] Object fake_aout unloaded

 ========= END EXAMPLE 21 =========


          Segments are extended the good way. Everything works well.



---[ D. EXTPLT technique : unknown function postlinking


	  This technique is one of the major one of the new ELFsh
	  version. It works on ET_EXEC and ET_DYN files, including
	  when the injection is done directly in memory. EXTPLT
	  consists in adding a new section (.elfsh.extplt) so that
	  we can add entries for new functions. When coupled to
	  .got, .dynsym, and .dynstr mirroring extension, it allows
	  for placing relocation entries that match the needs of 
	  the new ALTPLT/ALTGOT couple. Let's look at the additional
	  relocation information using the elfsh -r command :

	  First the original binary:

 
 ========= BEGIN EXAMPLE 22 =========

 [*] Object ./a.out has been loaded (O_RDONLY) 

 [RELOCATION TABLES]
 [Object ./a.out]

 {Section .rel.dyn} 
 [000] R_386_GLOB_DAT  0x08049850 sym[010] : __gmon_start__   
 [001] R_386_COPY      0x08049888 sym[004] : stdout           

 {Section .rel.plt} 
 [000] R_386_JMP_SLOT  0x08049860 sym[001] : fflush           
 [001] R_386_JMP_SLOT  0x08049864 sym[002] : puts             
 [002] R_386_JMP_SLOT  0x08049868 sym[003] : malloc           
 [003] R_386_JMP_SLOT  0x0804986C sym[005] : __libc_start_main
 [004] R_386_JMP_SLOT  0x08049870 sym[006] : printf           
 [005] R_386_JMP_SLOT  0x08049874 sym[007] : free             
 [006] R_386_JMP_SLOT  0x08049878 sym[009] : read             

 [*] Object ./testsuite/etrel_inject/etrel_original/a.out unloaded 
	  
 ========= END EXAMPLE 22 =========


	    Let's now see the new relocation tables:


 ========= BEGIN EXAMPLE 23 =========
	  
 [*] Object fake_aout has been loaded (O_RDONLY) 

 [RELOCATION TABLES]
 [Object ./fake_aout]

 {Section .rel.dyn} 
 [000] R_386_GLOB_DAT  0x08049850 sym[010] : __gmon_start__   
 [001] R_386_COPY      0x08049888 sym[004] : stdout           

 {Section .rel.plt} 
 [000] R_386_JMP_SLOT  0x0804A8A0 sym[001] : fflush           
 [001] R_386_JMP_SLOT  0x0804A8A4 sym[002] : puts             
 [002] R_386_JMP_SLOT  0x0804A8A8 sym[003] : malloc           
 [003] R_386_JMP_SLOT  0x0804A8AC sym[005] : __libc_start_main
 [004] R_386_JMP_SLOT  0x0804A8B0 sym[006] : printf           
 [005] R_386_JMP_SLOT  0x0804A8B4 sym[007] : free             
 [006] R_386_JMP_SLOT  0x0804A8B8 sym[009] : read             

 {Section .elfsh.reldyn} 
 [000] R_386_GLOB_DAT  0x08049850 sym[010] : __gmon_start__   
 [001] R_386_COPY      0x08049888 sym[004] : stdout           

 {Section .elfsh.relplt} 
 [000] R_386_JMP_SLOT  0x0804A8A0 sym[001] : fflush           
 [001] R_386_JMP_SLOT  0x0804A8A4 sym[002] : puts             
 [002] R_386_JMP_SLOT  0x0804A8A8 sym[003] : malloc           
 [003] R_386_JMP_SLOT  0x0804A8AC sym[005] : __libc_start_main
 [004] R_386_JMP_SLOT  0x0804A8B0 sym[006] : printf           
 [005] R_386_JMP_SLOT  0x0804A8B4 sym[007] : free             
 [006] R_386_JMP_SLOT  0x0804A8B8 sym[009] : read             
 [007] R_386_JMP_SLOT  0x0804A8BC sym[011] : _IO_putc         
 [008] R_386_JMP_SLOT  0x0804A8C0 sym[012] : write            

 [*] Object fake_aout unloaded 

 =========  END EXAMPLE 23 =========     


	    As you see, _IO_putc and write functions has been used
	    in the injected object. We had to insert them inside
	    the host binary so that the output binary can work.
	    
	    The .elfsh.relplt section is copied from the .rel.plt
	    section but with a doubled size so that we have room
	    for additional entries.




---[ E. IA32, SPARC32/64, ALPHA64, MIPS32 compliant algorithms		 


	   We did not have time to write the pseudo-algorithms for all
           these techniques. Since it is something we care about 
	   particulary, the article will be updated in the week with all
	   pseudo-algorithms information as soon as we return from WTH.

	   Stay tuned.



-------[ V. Constrained Debugging


	 In nowadays environment, hardened binaries are usually
	 of type ET_DYN. We had to support this kind of injection
	 since it allows for library files modification as much
	 powerful as the the executable files modification. Moreover
	 some distribution comes with a default binary set compiled
	 in ET_DYN, such has hardened gentoo.

	 Another improvement that we wanted to be done is the ET_REL
	 relocation in memory. The algorithm for it is the same than
	 the ondisk injection, but this time the disk is not changed
	 so it reduces forensics evidences like in [12]. It is believed 
	 that this kind of injection can be used in exploits and direct
	 process backdooring without touching the hard disk. Evil eh ?

	 We are aware of another implementation of the ET_REL injection	
	 into memory [10]. Ours supports a wider range of architecture and
	 couples with with the EXTPLT technique directly in memory.

	 A last technique that we wanted to develop was about extending
	 and debugging static executables. We developed a new technique
	 that we called EXTSTATIC algorithm. It allows for static
	 injections by taking parts of libc.a when functions or code is
	 missing. The same ET_REL injection algorithm is used except
	 that more than one relocatable file taken from libc.a is injected 
	 at a time using a recursive dependency algorithm.


---[ A. ET_REL relocation in memory				


	 Because we want to be able to provide a handler for 
	 breakpoints (wether or not they are done using the 
	 0xCC ia32 opcode or the more portable redirection
	 function), we allow for direct mapping of an ET_REL
	 object into memory. We use extra mmap zone for this, 
	 always taking care that it does not break PaX : we
	 do not map any zone beeing both executable and writable.


	 Let's look at some simple binary that does just use
	 printf and puts.


 ========= BEGIN EXAMPLE 24 =========

 elfsh@WTH $ ./a.out
 [host] main argc 1
 [host] argv[0] is : ./a.out

 First_printf test
 First_puts
 Second_printf test
 Second_puts
 LEGIT FUNC
 legit func (test) !
 ========= END EXAMPLE 24 =========


	   We use a small elfsh script as e2dbg so that it creates
	   another file with the debugger injected inside it, using
	   regular elfsh techniques. Let's look at it :



 ========= BEGIN EXAMPLE 25 =========	  
 elfsh@WTH $ cat inject_e2dbg.esh
 #!../../vm/elfsh
 load a.out
 set 1.dynamic[08].val 0x2
 set 1.dynamic[08].tag DT_NEEDED
 redir main e2dbg_run
 save a.out_e2dbg
 ========= END EXAMPLE 25 =========


	   We then execute the modified binary.


 ========= BEGIN EXAMPLE 26 =========

 elfsh@WTH $ ./aout_e2dbg


         The Embedded ELF Debugger 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org

 [*] Sun Jul 31 16:24:00 2005 - New object ./a.out_e2dbg loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/tls/libc.so.6 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object ./ibc.so.6 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/ld-linux.so.2 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/libelfsh/libelfsh.so loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/libreadline.so.5 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/libtermcap.so.2 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/libdl.so.2 loaded
 [*] Sun Jul 31 16:24:00 2005 - New object /lib/libncurses.so.5 loaded

 (e2dbg-0.65) quit

         [..: Embedded ELF Debugger returns to the grave :...]

 [e2dbg_run] returning to 0x08045139
 [host] main argc 1
 [host] argv[0] is : ./a.out_e2dbg

 First_printf test
 First_puts
 Second_printf test
 Second_puts
 LEGIT FUNC
 legit func (test) !
 elfsh@WTH $

========= END EXAMPLE 26 =========


	   Okay, that was easy. What if we want to do something more
	   interresting like ET_REL object injection into memory. We
	   will make use of the profile command so that we can see
	   the autoprofiling feature of e2dbg. This command is always
	   useful to learn more about the internals of the debugger, 
	   and for debugging problems inherent to the debugger.
	   
	   

 ========= BEGIN EXAMPLE 27 =========

 elfsh@WTH $ ./a.out_e2dbg


         The Embedded ELF Debugger 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org 

 [*] Sun Jul 31 16:12:48 2005 - New object ./a.out_e2dbg loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/tls/libc.so.6 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object ./ibc.so.6 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/ld-linux.so.2 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/libelfsh.so loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/libreadline.so.5 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/libtermcap.so.2 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/libdl.so.2 loaded
 [*] Sun Jul 31 16:12:48 2005 - New object /lib/libncurses.so.5 loaded

 (e2dbg-0.65) linkmap

 .::. Linkmap entries .::.
 [01] addr : 0x00000000 dyn : 0x080497D4 -
 [02] addr : 0x00000000 dyn : 0xFFFFE590 -
 [03] addr : 0xB7E73000 dyn : 0xB7F9AD3C - /lib/tls/libc.so.6
 [04] addr : 0xB7E26000 dyn : 0xB7E6F01C - ./ibc.so.6
 [05] addr : 0xB7FB9000 dyn : 0xB7FCFF14 - /lib/ld-linux.so.2
 [06] addr : 0xB7DF3000 dyn : 0xB7E24018 - /lib/libelfsh.so
 [07] addr : 0xB7DC6000 dyn : 0xB7DEE46C - /lib/libreadline.so.5
 [08] addr : 0xB7DC2000 dyn : 0xB7DC5BB4 - /lib/libtermcap.so.2
 [09] addr : 0xB7DBE000 dyn : 0xB7DC0EEC - /lib/libdl.so.2
 [10] addr : 0xB7D7C000 dyn : 0xB7DBB1C0 - /lib/libncurses.so.5

 (e2dbg-0.65) list

 .::. Working files .::.
 [001] Sun Jul 31 16:24:00 2005  D ID: 9 /lib/libncurses.so.5
 [002] Sun Jul 31 16:24:00 2005  D ID: 8 /lib/libdl.so.2
 [003] Sun Jul 31 16:24:00 2005  D ID: 7 /lib/libtermcap.so.2
 [004] Sun Jul 31 16:24:00 2005  D ID: 6 /lib/libreadline.so.5
 [005] Sun Jul 31 16:24:00 2005  D ID: 5 /lib/libelfsh.so
 [006] Sun Jul 31 16:24:00 2005  D ID: 4 /lib/ld-linux.so.2
 [007] Sun Jul 31 16:24:00 2005  D ID: 3 ./ibc.so.6
 [008] Sun Jul 31 16:24:00 2005  D ID: 2 /lib/tls/libc.so.6
 [009] Sun Jul 31 16:24:00 2005 *D ID: 1 ./a.out_e2dbg

 .::. ELFsh modules .::.
 [*] No loaded module

 (e2dbg-0.65) source ./etrelmem.esh

 ~load myputs.o

 [*] Sun Jul 31 16:13:32 2005 - New object myputs.o loaded

 [!!] Loaded file is not the linkmap, switching to STATIC mode

 ~switch 1

 [*] Switched on object 1 (./a.out_e2dbg)

 ~mode dynamic

 [*] e2dbg is now in DYNAMIC mode

 ~reladd 1 10

 [*] ET_REL myputs.o injected succesfully in ET_EXEC ./a.out_e2dbg

 ~profile
         .:: Profiling enable

 + <vm_print_actual@loop.c:38>
 ~redir puts myputs
 + <vm_implicit@implicit.c:91>
 + <cmd_hijack@fcthijack.c:19>
 + <elfsh_get_metasym_by_name@sym_common.c:283>
 + <elfsh_get_dynsymbol_by_name@dynsym.c:255>
 + <elfsh_get_dynsymtab@dynsym.c:87>
 + <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_get_dynsymbol_name@dynsym.c:17>
 [W]     <elfsh_get_dynsymbol_by_name@dynsym.c:274>      Symbol not found
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_get_dynsymbol_name@dynsym.c:17>
 [P] --- Last 2 function(s) recalled 12 time(s) ---
 + <elfsh_get_symbol_by_name@symbol.c:236>
 + <elfsh_get_symtab@symbol.c:110>
 + <elfsh_get_symbol_name@symbol.c:20>
 [P] --[ <elfsh_get_symbol_name@symbol.c:20>
 [P] --- Last 1 function(s) recalled 114 time(s) ---
 + <elfsh_hijack_function_by_name@hijack.c:25>
 + <elfsh_setup_hooks@hooks.c:199>
 + <elfsh_get_pagesize@hooks.c:783>
 + <elfsh_get_archtype@hooks.c:624>
 + <elfsh_get_arch@elf.c:179>
 + <elfsh_copy_plt@altplt.c:525>
 + <elfsh_static_file@elf.c:491>
 + <elfsh_get_segment_by_type@pht.c:215>
 + <elfsh_get_pht@pht.c:364>
 + <elfsh_get_segment_type@pht.c:174>
 [P] --[ <elfsh_get_segment_type@pht.c:174>
 [P] --- Last 1 function(s) recalled 4 time(s) ---
 + <elfsh_get_arch@elf.c:179>
 [P] --[ <elfsh_get_arch@elf.c:179>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_relink_plt@altplt.c:121>
 + <elfsh_get_archtype@hooks.c:624>
 [P] --[ <elfsh_get_arch@elf.c:179>
 [P] --[ <elfsh_relink_plt@altplt.c:121>
 [P] --[ <elfsh_get_archtype@hooks.c:624>
 [P] --- Last 3 function(s) recalled 1 time(s) ---
 + <elfsh_get_elftype@hooks.c:662>
 + <elfsh_get_objtype@elf.c:204>
 + <elfsh_get_ostype@hooks.c:709>
 + <elfsh_get_real_ostype@hooks.c:679>
 + <elfsh_get_interp@interp.c:41>
 + <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_get_section_by_name@section.c:168>
 + <elfsh_get_section_name@sht.c:474>
 [P] --[ <elfsh_get_section_name@sht.c:474>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_get_symbol_by_name@symbol.c:236>
 + <elfsh_get_symtab@symbol.c:110>
 + <elfsh_get_symbol_name@symbol.c:20>
 [W]     <elfsh_get_symbol_by_name@symbol.c:253>         Symbol not found
 [P] --[ <elfsh_get_symbol_name@symbol.c:20>
 [P] --- Last 1 function(s) recalled 114 time(s) ---
 + <elfsh_is_pltentry@plt.c:73>
 [W]     <elfsh_is_pltentry@plt.c:77>               Invalid NULL parameter
 + <elfsh_get_dynsymbol_by_name@dynsym.c:255>
 + <elfsh_get_dynsymtab@dynsym.c:87>
 + <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_get_dynsymbol_name@dynsym.c:17>
 [P] --[ <elfsh_is_pltentry@plt.c:73>
 [P] --[ <elfsh_get_dynsymbol_by_name@dynsym.c:255>
 [P] --[ <elfsh_get_dynsymtab@dynsym.c:87>
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_get_dynsymbol_name@dynsym.c:17>
 [P] --- Last 5 function(s) recalled 1 time(s) ---
 + <elfsh_get_plt@plt.c:16>
 + <elfsh_is_plt@plt.c:49>
 + <elfsh_get_section_name@sht.c:474>
 + <elfsh_is_altplt@plt.c:62>
 [P] --[ <elfsh_is_plt@plt.c:49>
 [P] --[ <elfsh_get_section_name@sht.c:474>
 [P] --[ <elfsh_is_altplt@plt.c:62>
 [P] --- Last 3 function(s) recalled 3 time(s) ---
 + <elfsh_get_anonymous_section@section.c:334>
 + <elfsh_get_raw@section.c:691>
 [P] --[ <elfsh_is_plt@plt.c:49>
 [P] --[ <elfsh_get_section_name@sht.c:474>
 [P] --[ <elfsh_is_altplt@plt.c:62>
 [P] --[ <elfsh_get_anonymous_section@section.c:334>
 [P] --[ <elfsh_get_raw@section.c:691>
 [P] --- Last 5 function(s) recalled 44 time(s) ---
 + <elfsh_get_arch@elf.c:179>
 [P] --[ <elfsh_get_arch@elf.c:179>
 [P] --- Last 1 function(s) recalled 1 time(s) ---
 + <elfsh_hijack_plt_ia32@ia32.c:258>
 + <elfsh_get_foffset_from_vaddr@raw.c:85>
 + <elfsh_get_pltentsz@plt.c:94>
 [P] --[ <elfsh_get_arch@elf.c:179>
 [P] --[ <elfsh_hijack_plt_ia32@ia32.c:258>
 [P] --[ <elfsh_get_foffset_from_vaddr@raw.c:85>
 [P] --[ <elfsh_get_pltentsz@plt.c:94>
 [P] --- Last 4 function(s) recalled 1 time(s) ---
 + <elfsh_munprotect@runtime.c:97>
 + <elfsh_get_parent_section@section.c:380>
 + <elfsh_get_parent_segment@pht.c:304>
 + <elfsh_segment_is_readable@pht.c:14>
 + <elfsh_segment_is_writable@pht.c:21>
 + <elfsh_segment_is_executable@pht.c:28>
 + <elfsh_raw_write@raw.c:22>
 + <elfsh_get_parent_section_by_foffset@section.c:416>
 + <elfsh_get_sht@sht.c:159>
 + <elfsh_get_section_type@sht.c:887>
 + <elfsh_get_anonymous_section@section.c:334>
 + <elfsh_get_raw@section.c:691>
 + <elfsh_raw_write@raw.c:22>
 + <elfsh_get_parent_section_by_foffset@section.c:416>
 + <elfsh_get_sht@sht.c:159>
 + <elfsh_get_section_type@sht.c:887>
 + <elfsh_get_anonymous_section@section.c:334>
 + <elfsh_get_raw@section.c:691>
 + <elfsh_get_pltentsz@plt.c:94>
 + <elfsh_get_arch@elf.c:179>
 + <elfsh_mprotect@runtime.c:135>

 [*] Function puts redirected to addr 0xB7FB6000 <myputs>

 + <vm_print_actual@loop.c:38>
 ~profile
 + <vm_implicit@implicit.c:91>
         .:: Profiling disable


 [*] ./etrelmem.esh sourcing -OK-

 (e2dbg-0.65) continue


         [..: Embedded ELF Debugger returns to the grave :...]

 [e2dbg_run] returning to 0x08045139
 [host] main argc 1
 [host] argv[0] is : ./a.out_e2dbg

 First_printf test
 Hijacked puts !!! arg = First_puts
 First_puts
 Second_printf test
 Hijacked puts !!! arg = Second_puts
 Second_puts
 Hijacked puts !!! arg = LEGIT FUNC
 LEGIT FUNC
 legit func (test) !
 elfsh@WTH $

 ========= END EXAMPLE 27 =========


	   Really cool. We hijacked 2 functions (puts and legit_func) using
	   the 2 different (ALTPLT and CFLOW) techniques.



---[ B. ET_REL relocation into ET_DYN				


	  We ported the ET_REL injection and the EXTPLT technique to ET_DYN
	  files. The biggest difference is that ET_DYN files have a 
	  relative address space ondisk. Of course, stripped binaries 
	  have no effect on our algorithms and we dont need any	      
	  non-mandatory information such as debug sections or anything.

	  Let's see what happens on this ET_DYN files:


 ========= BEGIN EXAMPLE 28 =========

 elfsh@WTH $ file main
 main: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), 
 stripped

 elfsh@WTH $ ./main
 0x800008c8 main(argc=0xbfa238d0, argv=0xbfa2387c, envp=0xbfa23878, 
	         auxv=0xbfa23874) __guard=0xb7ef4148
 ssp-all (Stack) Triggering an overflow by copying [20] of data into [10] \
 of space
 main: stack smashing attack in function main()
 Aborted

 elfsh@WTH $ ./main AAAAA
 0x800008c8 main(argc=0xbf898e40, argv=0xbf898dec, envp=0xbf898de8, 
	         auxv=0xbf898de4) __guard=0xb7f6a148
 ssp-all (Stack) Copying [5] of data into [10] of space

 elfsh@WTH $ ./main AAAAAAAAAAAAAAAAAAAAAAAAAAA
 0x800008c8 main(argc=0xbfd3c8e0, argv=0xbfd3c88c, envp=0xbfd3c888, 
                 auxv=0xbfd3c884) __guard=0xb7f0b148
 ssp-all (Stack) Copying [27] of data into [10] of space
 main: stack smashing attack in function main()
 Aborted

 ========= END EXAMPLE 28 =========


	   For the sake of fun, we decided to study in priority  the
	   hardened gentoo binaries [11] . Those comes with PIE (Position
	   Independant Executable) and SSP (Stack Smashing Protection)
	   built in. It does not change a line of our algorithm. Here
	   are some tests done on a stack smashing protected binary
	   with an overflow in the first parameter, triggering the
	   stack smashing handler. We will redirect that handler
	   to show that it is a normal function that use classical
	   PLT mechanisms.


 ========= BEGIN EXAMPLE 29 =========

 elfsh@WTH $ cat simple.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int     fake_main(int argc, char **argv)
 {
   old_printf("I am the main function, I have %d argc and my "
  	      "argv is %08X yupeelala \n",
              argc, argv); 

   write(1, "fake_main is calling write ! \n", 30);

   old_main(argc, argv);

   return (0);
 }

 char*   fake_strcpy(char *dst, char *src)
 {
   printf("The fucker wants to copy %s at address %08X \n", src, dst);
   return ((char *) old_strcpy(dst, src));
 }

 void    fake_stack_smash_handler(char func[], int damaged)
 {
   static int i = 0;
   printf("calling printf from stack smashing handler %u\n", i++);
   if (i>3)
     old___stack_smash_handler(func, damaged);
   else
     printf("Same player play again [damaged = %08X] \n", damaged);
   printf("A second (%d) printf from the handler \n", 2);
 }

 int fake_libc_start_main(void *one, void *two, void *three, void *four, 
                          void *five, void *six, void *seven)
 {
   static int i = 0;

   old_printf("fake_libc_start_main \n");
   printf("start_main has been run %u \n", i++);
   return (old___libc_start_main(one, two, three, four, five, six, seven));
 }

 ========= END EXAMPLE 29 =========

	   
	   The elfsh script that allow for the modification is :


 ========= BEGIN EXAMPLE 30 =========

 elfsh@WTH $ cat relinject.esh
 #!../../../vm/elfsh

 load main
 load simple.o

 reladd 1 2

 redir main fake_main
 redir __stack_smash_handler fake_stack_smash_handler
 redir __libc_start_main fake_libc_start_main
 redir strcpy fake_strcpy

 save fake_main

 quit

 ========= END EXAMPLE 30 =========


	   Now let's see this in action !


 ========= BEGIN EXAMPLE 31 =========
 elfsh@WTH $ ./relinject.esh


         The ELF shell 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org

 ~load main

 [*] Sun Jul 31 17:24:20 2005 - New object main loaded

 ~load simple.o

 [*] Sun Jul 31 17:24:20 2005 - New object simple.o loaded

 ~reladd 1 2

 [*] ET_REL simple.o injected succesfully in ET_DYN main

 ~redir main fake_main

 [*] Function main redirected to addr 0x00005154 <fake_main>

 ~redir __stack_smash_handler fake_stack_smash_handler

 [*] Function __stack_smash_handler redirected to addr 
     0x00005203 <fake_stack_smash_handler>

 ~redir __libc_start_main fake_libc_start_main

 [*] Function __libc_start_main redirected to addr 
     0x00005281 <fake_libc_start_main>

 ~redir strcpy fake_strcpy

 [*] Function strcpy redirected to addr 0x000051BD <fake_strcpy>

 ~save fake_main

 [*] Object fake_main saved successfully

 ~quit

 [*] Unloading object 1 (simple.o)
 [*] Unloading object 2 (main) *
         .:: Bye -:: The ELF shell 0.65
 
 ========= END EXAMPLE 31 =========


	   What about the result ?


 ========= BEGIN EXAMPLE 32 =========

 elfsh@WTH $ ./fake_main
 fake_libc_start_main
 start_main has been run 0
 I am the main function, I have 1 argc and my argv is BF9A6F54 yupeelala
 fake_main is calling write !
 0x800068c8 main(argc=0xbf9a6e80, argv=0xbf9a6e2c, envp=0xbf9a6e28, 
 	        auxv=0xbf9a6e24) __guard=0xb7f78148
 ssp-all (Stack) Triggering an overflow by copying [20] of data into [10] of space
 The fucker wants to copy 01234567890123456789 at address BF9A6E50
 calling printf from stack smashing handler 0
 Same player play again [damaged = 39383736]
 A second (2) printf from the handler

 elfsh@WTH $ ./fake_main AAAA
 fake_libc_start_main
 start_main has been run 0
 I am the main function, I have 2 argc and my argv is BF83A164 yupeelala
 fake_main is calling write !
 0x800068c8 main(argc=0xbf83a090, argv=0xbf83a03c, envp=0xbf83a038, 
	        auxv=0xbf83a034) __guard=0xb7f09148
 ssp-all (Stack) Copying [4] of data into [10] of space
 The fucker wants to copy AAAA at address BF83A060

 elfsh@WTH $ ./fake_main AAAAAAAAAAAAAAA
 fake_libc_start_main
 start_main has been run 0
 I am the main function, I have 2 argc and my argv is BF8C7F24 yupeelala
 fake_main is calling write !
 0x800068c8 main(argc=0xbf8c7e50, argv=0xbf8c7dfc, envp=0xbf8c7df8, 
                 auxv=0xbf8c7df4) __guard=0xb7f97148
 ssp-all (Stack) Copying [15] of data into [10] of space
 The fucker wants to copy AAAAAAAAAAAAAAA at address BF8C7E20

 ========= END EXAMPLE 32 =========


	No problem there : strcpy, main, libc_start_main and
	__stack_smash_handler are redirected on our own routines
	as the output shows.


---[ C. Extending static executables


        Now we would like to be able to debug static binary the same way 
	we do for dynamics. But we can't inject e2dbg using DT_NEEDED
        dependances. So the idea is to inject e2dbg as an ET_REL as ET_REL
        into ET_EXEC is possible on static binaries. E2dbg as many more
        dependancy than a simple host.c program. So the idea is to inject
        the missing part of static library when it is necessary.

        So we have to resolve dependancy on-the-fly while ET_REL injection
        is performed.

        To be able to find the suitable ET_REL to inject, ELFsh load all
        the ET_REL from static library (.a) then the resolution is done
        using this pool of binary.

        Circular dependancy are solved by using second stage relocation
        when the required symbol is in a file that is being injected.

        A problem is remaining, as for now we had one PT_LOAD by injected
        section, we quickly reach more than 500 PT_LOAD. This seems to be
        a bit too much for a regular ELF static file.

        This technique provide the same features as EXTPLT but for static
        binaries : we can inject what we want (regardless of what the host
        binary contains.

        So here is an smaller (working) example:


 ========= BEGIN EXAMPLE 33 =========

 elfsh@WTH $ cat host.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 int     legit_func(char *str)
 {
   puts("legit func !");
   return (0);
 }

 int main()
 {
   char  *str;
   char  buff[BUFSIZ];
   read(0, buff, BUFSIZ-1);

   puts("First_puts");

   puts("Second_puts");

   fflush(stdout);

   legit_func("test");

   return (0);
 }

 elfsh@WTH $ file a.out
 a.out: ELF 32-bit LSB executable, Intel 80386, statically linked, 
 not stripped

 elfsh@WTH $ ./a.out

 First_puts
 Second_puts
 legit func !

 ========= END EXAMPLE 33 =========

	   
	   The injected file source code is as follow :


 ========= BEGIN EXAMPLE 34 =========

 elfsh@WTH $ cat rel2.c
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <netdb.h>


 int     glvar_testreloc = 42;
 int     glvar_testreloc_bss;
 char    glvar_testreloc_bss2;
 short   glvar_testreloc_bss3;


 int     hook_func(char *str)
 {
   int sd;

   printf("hook func %s !\n", str);

   return (old_legit_func(str));
 }


 int     puts_troj(char *str)
 {
   int   local = 1;
   char  *str2;
   int   fd;
   char  name[16];
   void  *a;

   str2 = malloc(10);
   *str2 = 'Z';
   *(str2 + 1) = 0x00;

   glvar_testreloc_bss  = 43;
   glvar_testreloc_bss2 = 44;
   glvar_testreloc_bss3 = 45;

   memset(name, 0, 16);

   printf("Trojan injected ET_REL takes control now "
          "[%s:%s:%u:%u:%hhu:%hu:%u] \n",
          str2, str,
          glvar_testreloc,
          glvar_testreloc_bss,
          glvar_testreloc_bss2,
          glvar_testreloc_bss3,
          local);

  free(str2);

  gethostname(name, 15);
  printf("hostname : %s\n", name);

  printf("printf called from puts_troj [%s] \n", str);


  fd = open("/etc/services", 0, O_RDONLY);

  if (fd)
    {
      if ((a = mmap(0, 100, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *) -1)
        {
          perror("mmap");
          close(fd);
          printf("mmap failed : fd: %d\n", fd);
          return (-1);
        }
      printf("-=-=-=-=-=- BEGIN /etc/services %d -=-=-=-=-=\n", fd);
      printf("host : %.60s\n", (char *) a);
      printf("-=-=-=-=-=- END   /etc/services %d -=-=-=-=-=\n", fd);
      printf("mmap succeed fd : %d\n", fd);
      close(fd);
    }


   old_puts(str);
   fflush(stdout);
   return (0);
 }

 ========= END EXAMPLE 34 =========
	   

	   The load_lib.esh generated script looks like this :


 ========= BEGIN EXAMPLE 34 =========

 elfsh@WTH $ head -n 10 load_lib.esh
 #!../../../vm/elfsh
 load libc/init-first.o
 load libc/libc-start.o
 load libc/sysdep.o
 load libc/version.o
 load libc/check_fds.o
 load libc/libc-tls.o
 load libc/elf-init.o
 load libc/dso_handle.o
 load libc/errno.o
 
 ========= END EXAMPLE 34 =========


           Here is the injection ELFsh script:


 ========= BEGIN EXAMPLE 35 =========

 elfsh@WTH $ cat relinject.esh
 #!../../../vm/elfsh

 exec gcc -g3 -static host.c
 exec gcc -g3 -static rel2.c -c

 load a.out
 load rel2.o

 source ./load_lib.esh

 reladd 1 2

 redir puts puts_troj
 redir legit_func hook_func

 save fake_aout

 quit

 ========= END EXAMPLE 35 =========


           Stripped output of the injection :


 ========= BEGIN EXAMPLE 36 =========
 elfsh@WTH $ ./relinject.esh

         The ELF shell 0.65 (32 bits built) .::.

         .::. This software is under the General Public License V.2
         .::. Please visit http://www.gnu.org

 ~exec gcc -g3 -static host.c

 [*] Command executed successfully

 ~exec gcc -g3 -static rel2.c -c

 [*] Command executed successfully

 ~load a.out
 [*] Sun Jul 31 16:37:32 2005 - New object a.out loaded

 ~load rel2.o
 [*] Sun Jul 31 16:37:32 2005 - New object rel2.o loaded

 ~source ./load_lib.esh
 ~load libc/init-first.o
 [*] Sun Jul 31 16:37:33 2005 - New object libc/init-first.o loaded

 ~load libc/libc-start.o
 [*] Sun Jul 31 16:37:33 2005 - New object libc/libc-start.o loaded

 ~load libc/sysdep.o
 [*] Sun Jul 31 16:37:33 2005 - New object libc/sysdep.o loaded

 ~load libc/version.o
 [*] Sun Jul 31 16:37:33 2005 - New object libc/version.o loaded

 [[... 1414 files later ...]]

 [*] ./load_lib.esh sourcing -OK-

 ~reladd 1 2

 [*] ET_REL rel2.o injected succesfully in ET_EXEC a.out

 ~redir puts puts_troj

 [*] Function puts redirected to addr 0x080B7026 <puts_troj>

 ~redir legit_func hook_func

 [*] Function legit_func redirected to addr 0x080B7000 <hook_func>

 ~save fake_aout

 [*] Object fake_aout saved successfully

 ~quit

 [*] Unloading object 1 (libpthreadnonshared/pthread_atfork.oS)
 [*] Unloading object 2 (libpthread/ptcleanup.o)
 [*] Unloading object 3 (libpthread/pthread_atfork.o)
 [*] Unloading object 4 (libpthread/old_pthread_atfork.o)

 [[... 1416 files later ...]]

         .:: Bye -:: The ELF shell 0.65

 ========= END EXAMPLE 36 =========

           Does it works ?

 ========= BEGIN EXAMPLE 37 =========

 elfsh@WTH $ ./fake_aout

 Trojan injected ET_REL takes control now [Z:First_puts:42:43:44:45:1]
 hostname : WTH
 printf called from puts_troj [First_puts]
 -=-=-=-=-=- BEGIN /etc/services 3 -=-=-=-=-=
 host : # /etc/services
 #
 # Network services, Internet style
 #
 # Not
 -=-=-=-=-=- END   /etc/services 3 -=-=-=-=-=
 mmap succeed fd : 3
 First_puts
 Trojan injected ET_REL takes control now [Z:Second_puts:42:43:44:45:1]
 hostname : WTH
 printf called from puts_troj [Second_puts]
 -=-=-=-=-=- BEGIN /etc/services 3 -=-=-=-=-=
 host : # /etc/services
 #
 # Network services, Internet style
 #
 # Not
 -=-=-=-=-=- END   /etc/services 3 -=-=-=-=-=
 mmap succeed fd : 3
 Second_puts
 hook func test !
 Trojan injected ET_REL takes control now [Z:legit func !:42:43:44:45:1]
 hostname : WTH
 printf called from puts_troj [legit func !]
 -=-=-=-=-=- BEGIN /etc/services 3 -=-=-=-=-=
 host : # /etc/services
 #
 # Network services, Internet style
 #
 # Not
 -=-=-=-=-=- END   /etc/services 3 -=-=-=-=-=
 mmap succeed fd : 3
 legit func !
 ========= END EXAMPLE 37 ========= 


           Yes, It's working. Now have a look at the fake_aout file:



 ========= BEGIN EXAMPLE 38 =========

 elfsh@WTH $ ../../../vm/elfsh  -f ./fake_aout -s

 [*] Object ./fake_aout has been loaded (O_RDONLY)

 [SECTION HEADER TABLE .::. SHT is not stripped]
 [Object ./fake_aout]

 [000] 0x00000000 -------                              foff:000000 sz:00000
 [001] 0x080480D4 a------ .note.ABI-tag                foff:069844 sz:00032
 [002] 0x08048100 a-x---- .init                        foff:069888 sz:00023
 [003] 0x08048120 a-x---- .text                        foff:69920 sz:347364
 [004] 0x0809CE10 a-x---- __libc_freeres_fn            foff:417296 sz:02222
 [005] 0x0809D6C0 a-x---- .fini                        foff:419520 sz:00029
 [006] 0x0809D6E0 a------ .rodata                      foff:419552 sz:88238
 [007] 0x080B2F90 a------ __libc_atexit                foff:507792 sz:00004
 [008] 0x080B2F94 a------ __libc_subfreeres            foff:507796 sz:00036
 [009] 0x080B2FB8 a------ .eh_frame                    foff:507832 sz:03556
 [010] 0x080B4000 aw----- .ctors                       foff:512000 sz:00012
 [011] 0x080B400C aw----- .dtors                       foff:512012 sz:00012
 [012] 0x080B4018 aw----- .jcr                         foff:512024 sz:00004
 [013] 0x080B401C aw----- .data.rel.ro                 foff:512028 sz:00044
 [014] 0x080B4048 aw----- .got                         foff:512072 sz:00004
 [015] 0x080B404C aw----- .got.plt                     foff:512076 sz:00012
 [016] 0x080B4060 aw----- .data                        foff:512096 sz:03284
 [017] 0x080B4D40 aw----- .bss                         foff:515380 sz:04736
 [018] 0x080B5FC0 aw----- __libc_freeres_ptrs          foff:520116 sz:00024
 [019] 0x080B6000 aw----- rel2.o.bss                   foff:520192 sz:04096
 [020] 0x080B7000 a-x---- rel2.o.text                  foff:524288 sz:04096
 [021] 0x080B8000 aw----- rel2.o.data                  foff:528384 sz:00004
 [022] 0x080B9000 a------ rel2.o.rodata                foff:532480 sz:04096
 [023] 0x080BA000 a-x---- .elfsh.hooks                 foff:536576 sz:00032
 [024] 0x080BB000 aw----- libc/printf.o.bss            foff:540672 sz:04096
 [025] 0x080BC000 a-x---- libc/printf.o.text           foff:544768 sz:04096
 [026] 0x080BD000 aw----- libc/gethostname.o.bss       foff:548864 sz:04096
 [027] 0x080BE000 a-x---- libc/gethostname.o.text      foff:552960 sz:04096
 [028] 0x080BF000 aw----- libc/perror.o.bss            foff:557056 sz:04096
 [029] 0x080C0000 a-x---- libc/perror.o.text           foff:561152 sz:04096
 [030] 0x080C1000 a--ms-- libc/perror.o.rodata.str1.1  foff:565248 sz:04096
 [031] 0x080C2000 a--ms-- libc/perror.o.rodata.str4.4  foff:569344 sz:04096
 [032] 0x080C3000 aw----- libc/dup.o.bss               foff:573440 sz:04096
 [033] 0x080C4000 a-x---- libc/dup.o.text              foff:577536 sz:04096
 [034] 0x080C5000 aw----- libc/iofdopen.o.bss          foff:581632 sz:04096
 [035] 0x00000000 ------- .comment                     foff:585680 sz:20400
 [036] 0x080C6000 a-x---- libc/iofdopen.o.text         foff:585728 sz:04096
 [037] 0x00000000 ------- .debug_aranges               foff:606084 sz:00136
 [038] 0x00000000 ------- .debug_pubnames              foff:606220 sz:00042
 [039] 0x00000000 ------- .debug_info                  foff:606262 sz:01600
 [040] 0x00000000 ------- .debug_abbrev                foff:607862 sz:00298
 [041] 0x00000000 ------- .debug_line                  foff:608160 sz:00965
 [042] 0x00000000 ------- .debug_frame                 foff:609128 sz:00068
 [043] 0x00000000 ------- .debug_str                   foff:609196 sz:00022
 [044] 0x00000000 ------- .debug_macinfo               foff:609218 sz:28414
 [045] 0x00000000 ------- .shstrtab                    foff:637632 sz:00632
 [046] 0x00000000 ------- .symtab                      foff:640187 sz:30192
 [047] 0x00000000 ------- .strtab                      foff:670379 sz:25442

 [*] Object ./fake_aout unloaded

 elfsh@WTH $ ../../../vm/elfsh  -f ./fake_aout -p

 [*] Object ./fake_aout has been loaded (O_RDONLY)

 [Program Header Table .::. PHT]
 [Object ./fake_aout]

 [00] 0x8037000 -> 0x80B3D9C r-x memsz(511388) foff(000000) => Loadable seg
 [01] 0x80B4000 -> 0x80B7258 rw- memsz(012888) foff(512000) => Loadable seg
 [02] 0x80480D4 -> 0x80480F4 r-- memsz(000032) foff(069844) => Aux. info.
 [03] 0x0000000 -> 0x0000000 rw- memsz(000000) foff(000000) => Stackflags
 [04] 0x0000000 -> 0x0000000 --- memsz(000000) foff(000000) => New PaXflags
 [05] 0x80B6000 -> 0x80B7000 rwx memsz(004096) foff(520192) => Loadable seg
 [06] 0x80B7000 -> 0x80B8000 rwx memsz(004096) foff(524288) => Loadable seg
 [07] 0x80B8000 -> 0x80B8004 rwx memsz(000004) foff(528384) => Loadable seg
 [08] 0x80B9000 -> 0x80BA000 rwx memsz(004096) foff(532480) => Loadable seg
 [09] 0x80BA000 -> 0x80BB000 rwx memsz(004096) foff(536576) => Loadable seg
 [10] 0x80BB000 -> 0x80BC000 rwx memsz(004096) foff(540672) => Loadable seg
 [11] 0x80BC000 -> 0x80BD000 rwx memsz(004096) foff(544768) => Loadable seg
 [12] 0x80BD000 -> 0x80BE000 rwx memsz(004096) foff(548864) => Loadable seg
 [13] 0x80BE000 -> 0x80BF000 rwx memsz(004096) foff(552960) => Loadable seg
 [14] 0x80BF000 -> 0x80C0000 rwx memsz(004096) foff(557056) => Loadable seg
 [15] 0x80C0000 -> 0x80C1000 rwx memsz(004096) foff(561152) => Loadable seg
 [16] 0x80C1000 -> 0x80C2000 rwx memsz(004096) foff(565248) => Loadable seg
 [17] 0x80C2000 -> 0x80C3000 rwx memsz(004096) foff(569344) => Loadable seg
 [18] 0x80C3000 -> 0x80C4000 rwx memsz(004096) foff(573440) => Loadable seg
 [19] 0x80C4000 -> 0x80C5000 rwx memsz(004096) foff(577536) => Loadable seg
 [20] 0x80C5000 -> 0x80C6000 rwx memsz(004096) foff(581632) => Loadable seg
 [21] 0x80C6000 -> 0x80C7000 rwx memsz(004096) foff(585728) => Loadable seg

 [SHT correlation]
 [Object ./fake_aout]

 [*] SHT is not stripped

 [00] PT_LOAD            .note.ABI-tag .init .text __libc_freeres_fn .fini
                         .rodata __libc_atexit __libc_subfreeres .eh_frame
 [01] PT_LOAD           .ctors .dtors .jcr .data.rel.ro .got .got.plt .data
                        .bss __libc_freeres_ptrs
 [02] PT_NOTE           .note.ABI-tag
 [03] PT_GNU_STACK
 [04] PT_PAX_FLAGS
 [05] PT_LOAD           rel2.o.bss
 [06] PT_LOAD           rel2.o.text
 [07] PT_LOAD           rel2.o.data
 [08] PT_LOAD           rel2.o.rodata
 [09] PT_LOAD           .elfsh.hooks
 [10] PT_LOAD           libc/printf.o.bss
 [11] PT_LOAD           libc/printf.o.text
 [12] PT_LOAD           libc/gethostname.o.bss
 [13] PT_LOAD           libc/gethostname.o.text
 [14] PT_LOAD           libc/perror.o.bss
 [15] PT_LOAD           libc/perror.o.text
 [16] PT_LOAD           libc/perror.o.rodata.str1.1
 [17] PT_LOAD           libc/perror.o.rodata.str4.4
 [18] PT_LOAD           libc/dup.o.bss
 [19] PT_LOAD           libc/dup.o.text
 [20] PT_LOAD           libc/iofdopen.o.bss |.comment
 [21] PT_LOAD           libc/iofdopen.o.text
 [*] Object ./fake_aout unloaded

 ========= END EXAMPLE 38 =========

         We can notice the ET_REL really injected : printf.o@libc,
         dup.o@libc, gethostname.o@libc, perror.o@libc and
         iofdopen.o@libc.

         Each injected file create several PT_LOAD segments.
         Here it's ok but for injecting E2dbg that's really too much.

         This technique will be improved as soon as possible by reusing
         PT_LOAD entry when this is possible.


-------[ VI. Past and present


	 In the past we have shown that ET_REL injection into 
	 non-relocatable ET_EXEC object is possible. This paper presented 
	 multiple extensions and ports to this residency technique 
	 (ET_DYN and static executables target). Coupled to the EXTPLT 
	 technique that allow for a complete post-linking of the host file,
	 we can add function definitions and use unknown functions in the
	 software extension. All those static injection techniques worse 
	 when all PaX options are enabled on the modified binary. Of course
	 , the position independant and stack smashing protection features
	 of hardened Gentoo does not protect anything when it comes to 
	 binary manipulation.

	 We have also shown that it is possible to debug without using the 
	 ptrace system call, which open the door for new reverse 
	 engineering and embedded debugging methodology that bypass known 
	 anti-debugging techniques. The embedded debugger is not completely
	 PaX proof and it is still necessary to disable the mprotect flag.
	 Even if it does not sound like a problem, we are investigating on 
	 how to put breakpoints (e.g. redirections) without disabling it.

	 Our ground techniques are portable to many architectures (x86, 
	 alpha, mips, sparc) on both 32bits and 64bits files. However our 
	 proof of concept debugger was done for x86 only. We believe that 
	 our techniques are portable enough to be able to port the debugger
	 without much troubles.

	 We wrote that article at the WTH conference in Netherland. Due to 
	 Devhell Labs. machine crash during the meeting, we will publish
	 the e2dbg source code tomorrow evening (August 1st 2005) when we
	 get back at home and reboot the webs server machine. You can find
	 it on : http://elfsh.devhell.org as well as on the official mirror
	 http://elfsh.segfault.net. 

	 Share and enjoy.


-------[ VII. Greetings  


	 We thank all the peoples at the WhatTheHack party 2005 in 
	 Netherland. We add much fun with you guys and again we will come 
	 in the future. Special thanks go to andrewg for teaching us the 
	 sigaction technique, dvorak for his early interest in the 
	 improvement and optimization of the ALTPLT technique on the SPARC
	 architecture, sk from Devhell Labs. for libasm, solar from the 
	 Hardened Gentoo project for providing us the ET_DYN pie/ssp 
	 testsuite, the PaX team for the awesome entertaining kernel 
	 protection patch, the phrack staff for delaying the Phrack #63	
	 electronic release for us. Final shoutouts to s/ash from RTC for 
	 driving us to WTH and the Coconut crew for everything and the 
	 rest, you know who you are.


-------[ VIII. References



 [1] The GNU debugger
     http://www.gnu.org/software/gdb/

 [2] PaX
     http://pax.grsecurity.net/

 [3] Silvio: binary reconstruction from a core image
     http://vx.netlux.org/lib/vsc03.html

 [4] Ripe & Pluf : Antiforensic evolution: Self
     http://www.phrack.org (Phrack #63)

 [5] Zeljko Vbra : Next-Gen. Runtime binary encryption using
                   on-demand function extraction
     http://www.phrack.org (Phrack #63)

 [6] lcamtuf : fenris
     http://lcamtuf.coredump.cx/fenris/

 [7] Ltrace team : ltrace
     http://freshmeat.net/projects/ltrace/

 [8] mammon : The dude (replacement to ptrace)
     http://www.eccentrix.com/members/mammon/Text/dude_paper.txt

 [9] andrewg : Binary protection schemes
     http://felinemenace.org/papers/Binary_protection_schemes-1.00\
     -prerelease.tar.gz

 [10] jp : ET_REL injection in memory
      Secret URL
      
 [11] Hardened Gentoo project
      http://www.gentoo.org/proj/en/hardened/

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH