Bugtraq: Saying Userland Exec
by Phil Tadros
January 3, 2024

2024-01-02 05:41:27
Bugtraq
Bugtraq
mailing record archives
From: the grugq <grugq () hcunix web>
Date: Thu, 01 Jan 2004 19:02:26 +0000
Hey,
That is an implementation of userland exec, that's, code which replaces
the present course of picture with a brand new one. The accompaning paper explains
the design and implementation of this code. The complete src code can also be
included.
peace, --gq
The Design and Implementation of Userland Exec by the grugq Summary: This paper examines a mechanism to execute a binary with out using the syscall execve(). The design for this mechanism is easy: clear up the handle house; examine for, and cargo, the dynamic linker; load the binary; set up the stack; find the entry level, and switch management of execution. One implemenation of this mechanism is used for example this design. Introduction: Userland exec replaces the present course of picture inside the present handle house with a brand new one. On this, userland exec mimics the habits of the system name execve()*. Nevertheless, as a result of it operates in userland, the kernel course of constructions which describe the method picture stay unchanged. This signifies that the method identify reported by system utilities would be the previous course of identify, and so on. The power to load a brand new course of picture with out the direct assist of the kernel is necessary in lots of situations. For instance: a program (e.g. shellcode) might load a binary off the wire and execute it with out first creating a duplicate on disk; or, a program might extract a binary from an encrypted knowledge retailer and execute it with out making a plain textual content picture on the disk. Userland exec is helpful for any state of affairs the place it's preferable to not create a file on the disk when executing a program. This paper will describe the design and implementation of the userland exec code. First it should talk about how execve() creates a brand new course of picture, and what this course of picture appears like (together with the stack structure). Based mostly on this data the design of the userland exec code might be examined, utilizing the userland exec implementation for example ideas. *) This implementation of userland exec is restricted to ELF binaries on i386 Linux programs, nonetheless the methodology outlined is common throughout Unix-like programs. Background: When a Unix program needs to execute one other program it should use the execve() system name to load the brand new program as a course of picture (creating the brand new course of by way of fork() is ignored right here). The person web page for the exec household of perform calls (execl() and the opposite wrappers for execve()) describes what occurs: "[t]he exec household of features replaces the present course of picture with a brand new course of picture." A extra full image of what occurs when a course of picture is changed might be discovered within the execve() man web page: execve() doesn't return on success, and the textual content, knowledge, bss, and stack of the calling course of are overwritten by that [sic] of this system loaded. Clearly, this system which calls execve() is taken out of reminiscence and the brand new program loaded. When this occurs, the .textual content and .knowledge segments in addition to the heap and the stack are changed. Any implementation of userland exec would must take away the previous course of' textual content, knowledge and heap, and reset the stack. To design a userland exec implementation, a extra detailed description of how execve() operates is required. This extra detailed description of how a brand new course of picture is created from an ELF binary could be: First, execve() cleans the handle house of the present course of by unmapping the entire pages of reminiscence which kind the present picture. If the executable is dynamically linked -- that's, if it makes use of run time libraries supplied by the system -- the dynamic linker is loaded into reminiscence. The primary ELF executable is then mapped into the method handle house. The stack is initialized with the environmental variables and the opposite parameters to foremost(). The stack can also be initialized with arguments for the dynamic linker to permit it to find the binary in reminiscence. Lastly, the kernel determines the proper entry level: both the dynamic linker, whether it is loaded, or the primary binary, whether it is not.The kernel then transfers execution to this entry level. This extra detailed description gives a blueprint for the userland exec implementation. Nevertheless, some particular particulars nonetheless should be clarified: specifically the precise structure of the stack simply after the picture is created. The diagram beneath roughly illustrates this stack structure. ----------------------------------------- [ 0 ] <-- prime of the stack [ envp strings ] [ 0 ] [ argv strings ] [ 0 ] [ auxv ] [ 0 ] [ envp ] [ 0 ] [ argv ] [ argc ] <-- stack pointer ----------------------------------------- On the prime of the stack are the environmental and argument strings. The underside of the stack begins with the argument depend, then come the argument pointerarray and the environmental pointer array. Within the center is the Elf_aux vector. This array of information constructions gives data to the dynamic linker concerning the course of picture, e.g. the situation of this system header desk. The dynamic linker is accountable for relocating the ELF binary, if required, in addition to loading all the required libraries and performing run time image decision. For extra data on dynamic linkers see [Levine 1999], [grugq 2001] and [grugq & scut 2001]. Design: With a transparent understanding of how execve() creates a brand new course of picture, it's doable to enumerate a listing of steps {that a} userland implementation should observe. That record is: 1. Clear out the handle house 2. If the binary is dynamically linked, load the dynamic linker 3. Load the binary 4. Initialize the stack 5. Decide the entry level (i.e. the dynamic linker or the primary executable) 6. Switch execution to the entry level Notice: the second and third step are literally interchangeable. Implementation: Step 0, preserving arguments to foremost() When userland exec is invoked, it accepts arguments to the primary() perform of the brand new program. Whereas constructing the brand new course of picture, userland exec will reset the stack and doubtlessly harm these parameters. Because of this, the very first thing that userland exec should do is protect these arguments for later use. On this implementation, the arguments are saved in tables allotted with mmap(). The contents of those tables can then be copied again into the stack when it's being initialized for the brand new course of picture. Step 1, clear out the handle house To organize the handle house for a brand new course of picture userland exec must clear out solely sure handle ranges, not all the previous picture. The handle vary of major significance is the one to which the brand new program binary has been relocated. On i386 Linux programs, this handle is normally 0x08048000. The .textual content section, and the .knowledge section, of the present course of's binary might be mapped to this location. Following the .knowledge section would be the .bss, and following that, the heap. Userland exec should subsequently map the previous executable down, along with mapping down the previous heap. Relying on the state of the program, the heap might be of various dimension. The userland exec implementation should decide the place the reminiscence vary which includes the .textual content, .knowledge and heap, begins and ends in order that it might probably map the vary down. There are a number of other ways of figuring out this vary. In some situations, for a particular goal, it's doable to hard-code the values. For a extra generic strategy, one strategy could be to register a sign handler and begin probing the handle house, e.g. to find out the top of the heap. Utilizing the exhausting coded begin handle of 0x08048000 and the probed heap dimension, userland exec might map down this vary. On this implementation, userland exec makes use of the method maps file maintained by the kernel to find out the situation and dimension of the method' .textual content and .knowledge segments and the heap. Convieniently, beneath Linux, the primary three traces of the /proc/self/maps file comprise the .textual content section, the .knowledge section and the heap. By mapping down the primary three reminiscence segments listed within the maps file userland exec can clear the vary required for the brand new .textual content and .knowledge segments, and the brand new heap. Step 2, examine for, and cargo, the dynamic linker Figuring out whether or not a given ELF binary requires a dynamic linker, or not, is extremely easy. The execve() man pages describe the precise technique utilized by the kernel (and by userland exec) to examine for a dynamic linker. If the executable is a dynamically-linked ELF executable, the interpreter named within the PT_INTERP section is used to load the wanted shared libraries. The dynamic linker is barely required for these processes which make the most of shared libraries from the system. If a binary requires dynamic linking, the trail to the specified dynamic linker might be saved in a particular program header section: PT_INTERP. By looking out this system header desk of the brand new ELF picture, userland exec can decide whether or not a dynamic linker is required, and, concurrently, which dynamic linker to load. Loading the linker after that is trivial, requiring solely an understanding of how ELF binaries are loaded into reminiscence. The following part will talk about how that is completed. Step 3, load the primary binary The precept for loading an ELF binary is identical no matter whether or not the binary is loaded from a reminiscence buffer or off the disk. For every PT_LOAD section in this system header desk, the loader ensures that the ELF picture from p_offset for p_filesz bytes is copied right into a reminiscence buffer (with p_flags permissions) at p_vaddr of p_memsz (aligned to p_align) bytes. That's, every PT_LOAD section primarily says "this a part of the ELF goes into this a part of the reminiscence picture". The userland exec implementation scans this system header desk and determines the full quantity of reminiscence the loaded ELF will occupy. This merely means aligning the p_memsz values of all of the PT_LOAD segments utilizing p_align, then including them collectively. The userland exec code then allocates a reminiscence vary ranging from the primary PT_LOAD section's p_vaddr for the full size beforehand calculated. With the reminiscence now reserved, all that continues to be is to copy the PT_LOAD segments into their applicable ranges after which set the section permissions primarily based on their p_flags. Step 4, initialize the stack With the primary binary, and any dynamic linker, loaded into reminiscence, the final main activity which nonetheless stays is establishing the stack. The stack, at program begin up, has a strict format examined briefly above. To initialize the stack, userland exec should reset the stack pointer. Performing that is merely a matter of calculating the dimensions of the stack contents (the argv strings, environmental strings, auxv, and so on. and so on.) and subtracting this worth from the stack base. With the house allotted for the brand new parameters, userland exec can start creating the stack structure. To create the stack structure the userland exec implementation should extract the saved parameters for the primary() perform (argc, argv and envp) and replica them to the stack. This will trivially be achieved utilizing the saved parameters from step 0 and a few easy pointer arithmetic. The Elf_Aux vector is the one knowledge construction which requires some rationalization. This vector accommodates knowledge which the dynamic linker wants as a way to combine with the method picture appropriately. There are only some key items of data required by the dynamic linker to carry out its activity. These are: its personal load handle (AT_BASE); the situation of this system header desk (AT_PHDR), in addition to the variety of program headers (AT_PHNUM); the dimensions of a web page of reminiscence (AT_PAGESZ); any flags to change its run time habits (AT_FLAGS), and the entry level for the foremost executable (AT_ENTRY). Step 5, decide entry level Finding the proper entry level for the brand new course of picture could be very straight ahead. If a dynamic linker was loaded, then the entry level is the load handle of the linker plus the e_entry worth, in any other case it's the foremost ELF's e_entry. Step 6, switch management of execution The ultimate step is to start out the brand new course of picture operating by transferring management of execution to the entry level positioned throughout step 5. These six steps are all which might be required to load an arbitrary ELF binary into an handle house and execute it. Conclusion: It has been proven that the execve() system name might be mimicked in userland with a minimal of problem. Creating a brand new course of picture is a straightforward matter of: cleansing out the handle house; checking for, and loading, the dynamic linker; loading the binary; initializing the stack; figuring out the entry level and, transferring management of execution. By following these six steps,a new course of picture might be created and run. Utilizing this implementation as a begin level, it's doable to create each smaller, and likewise extra elaborate,userland exec implementations. Historical past of userland exec: The writer first developed a userland exec implementation in early 2002. The preliminary proof of idea implementation demonstrated that it was certainly doable to imitate execve() in userland. Nevertheless, a number of limitations within the implementation made it unfit for public launch. Just lately, some individuals have posted extremely crude mechanisms for executing a brand new binary in an handle house occupied by one other course of picture. Given the extreme limitations of this method, and the request of a buddy for the previous proof of idea implementation, the writer felt compelled to implement a totally useful model of userland exec. Design and implementation took lower than 48 hours to finish. Acknowledgments: As all the time, the creation of any work will not be doable with out the assistance of different people. Right here, then, is a listing of those that've been concerned in some capability or one other in making userland exec: mammon_; gera; duke, and Grendel, PhD. Moreover because of these ppl who made .sg so fulfilling Halvar & Evelyn, SK, Saumil, Charl and Dave Aitel. And all of the ppl who got here to my speak. Bibliography: http://www.phrack.org/phrack/58/p58-0x05 grugq & scut, 2001 http://downloads.securityfocus.com/library/subversiveld.pdf grugq, 2001 http://www.iecc.com/linker/ levine, 1999
Attachment:
ul_exec-1.1.tar.gz
Description:
Present thread:
- Saying Userland Exec the grugq (Jan 01)
What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0