├── LICENSE ├── README.md ├── packer.c ├── payload.c └── run.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Alexandre-Xavier Labonté-Lamoureux 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A packer that executes a second (embedded) ELF 2 | 3 | The license is MIT 4 | 5 | It's a GNU/Linux program that makes many system calls and launches a second ELF file that's embedded. 6 | 7 | Many ELFs can be embedded inside the same packer. 8 | 9 | This could be used for malware. The embedded ELF should at least be XORed. 10 | -------------------------------------------------------------------------------- /packer.c: -------------------------------------------------------------------------------- 1 | // A packer that executes a second (embedded) ELF 2 | // 3 | // Copyright (c) 2018 Alexandre-Xavier Labonté-Lamoureux 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 | #include 24 | #include 25 | #include // memcpy 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | // Use "SYS_memfd_create", because the wrapper doesn't exist until Linux 4.10 33 | // The "memfd_create" system call was added to Linux 3.17 so "syscall" can be used to call it 34 | #include 35 | 36 | int main(int argc, char* argv[], char** envp) 37 | { 38 | int pid = getpid(); 39 | printf("My PID is: %d\n", pid); 40 | printf("My filename is: %s\n", argv[0]); 41 | 42 | // Find the size of the file using 43 | struct stat st; 44 | stat(argv[0], &st); 45 | size_t size = st.st_size; 46 | 47 | printf("My size is: %u\n", size); 48 | 49 | char procstring[32]; 50 | sprintf(procstring, "%s%d%s", "/proc/", pid, "/exe"); 51 | 52 | printf("Location (copy): %s\n", procstring); 53 | 54 | int filedesc = open(procstring, O_RDONLY); 55 | if (filedesc < 0) 56 | { 57 | printf("Invalid file descriptor for /proc: %d\n", filedesc); 58 | return 1; 59 | } 60 | 61 | // Delete self 62 | unlink(argv[0]); 63 | if (access(argv[0], F_OK) < 0) 64 | printf("I successfully deleted myself.\n"); 65 | else 66 | printf("Couldn't erase myself from the filesystem.\n"); 67 | 68 | // The real business starts here 69 | char* entirefile = (char*)malloc(size); 70 | read(filedesc, entirefile, size); 71 | 72 | // Yeah... use arbitrary values here. 73 | for (int i = size - 10; i > 1000; i--) 74 | { 75 | // The goal is to find the second ELF header 76 | if (entirefile[i] == 0x7F && entirefile[i + 1] == 'E' && entirefile[i + 2] == 'L' && entirefile[i + 3] == 'F') 77 | { 78 | printf("Second ELF header found at: 0x%x\n", i); 79 | 80 | // Create a buffer for this second ELF 81 | int newsize = size - i; 82 | char* newelf = (char*)malloc(newsize); 83 | 84 | // Copy ELF to buffer 85 | memcpy(newelf, entirefile + i, newsize); 86 | 87 | // It's in memory! Create a file descriptor. 88 | int memfd = syscall(SYS_memfd_create, "hidden", 0); 89 | 90 | if (memfd < 0) 91 | { 92 | printf("Invalid memfd %d.\n", i); 93 | free(newelf); 94 | return 1; 95 | } 96 | else 97 | printf("memfd is: %d\n", memfd); 98 | 99 | // Write ELF to temporary memory file 100 | write(memfd, newelf, newsize); 101 | 102 | // Deploy the payload as a different process 103 | fork(); 104 | int newpid = getpid(); 105 | if (newpid != pid) 106 | { 107 | // Execute the in-memory ELF 108 | int ret = fexecve(memfd, argv, envp); 109 | // The above function will only return if there's an error 110 | printf("ERROR EXECUTING PAYLOAD: Return value: %d. Errno is: ret %d\n", ret, errno); 111 | } 112 | else 113 | printf("The packer is done deploying the payload.\n"); 114 | 115 | free(newelf); 116 | } 117 | } 118 | 119 | // Free the resources 120 | free(entirefile); 121 | close(filedesc); 122 | 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /payload.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("Hello world!\n"); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Build the file to embed 4 | gcc -O2 payload.c -o payload 5 | strip payload 6 | 7 | # Build the packer and embed the payload 8 | gcc packer.c -o emb && cat payload >> emb && ./emb 9 | --------------------------------------------------------------------------------