Beispiel #1
0
int inject_shellcode(HIJACK *hijack, unsigned long addr, void *data, size_t sz) {
    return inject_shellcode_freebsd(hijack, addr, data, sz);
}
Beispiel #2
0
int inject_shellcode(HIJACK *hijack, unsigned long addr, void *data, size_t sz)
{
	REGS origregs;

#if defined(FreeBSD)
    return inject_shellcode_freebsd(hijack, addr, data, sz);
#endif
	
	write_data(hijack, addr, data, sz);
	
	if (ptrace(PTRACE_GETREGS, hijack->pid, NULL, &origregs) < 0)
		return SetError(hijack, ERROR_SYSCALL);
	
	/*
		There's a lot of duplicated logic here for x86 and x86_64.
		It used to be unified, but it looked ugly, so I seperated it out.
	*/
	#if defined(i686)
		origregs.esp -= sizeof(unsigned long);
		if (ptrace(PTRACE_SETREGS, hijack->pid, NULL, &origregs) < 0)
			return SetError(hijack, ERROR_SYSCALL);
		
		write_data(hijack, (unsigned long)(origregs.esp), &(origregs.eip), sizeof(unsigned long));
		origregs.eip = (long)addr;
		
		/*
			EIP might need to be adjusted further, depending on if we interrupted a syscall
			More Info: http://fxr.watson.org/fxr/source/arch/i386/kernel/signal.c?v=linux-2.6#L623
			Link valid on 09 April 2009
		*/
		if (origregs.orig_eax >= 0)
		{
			switch (origregs.eax)
			{
				case -514: /* -ERESTARTNOHAND */
				case -512: /* -ERESTARTSYS */
				case -513: /* -ERESTARTNOINTR */
				case -516: /* -ERESTART_RESTARTBLOCK */
					if (IsFlagSet(hijack, F_DEBUG))
						fprintf(stderr, "[*] Adjusting EIP due to syscall restart.\n");
					
					origregs.eip += strlen(SYSCALLSEARCH);
					break;
			}
		}
	#elif defined(x86_64)
		origregs.rsp -= sizeof(unsigned long);
		if (ptrace(PTRACE_SETREGS, hijack->pid, NULL, &origregs) < 0)
			return SetError(hijack, ERROR_SYSCALL);
		
		if (IsFlagSet(hijack, F_DEBUG_VERBOSE))
			fprintf(stderr, "[*] Pushing RIP: 0x%016lx\n", origregs.rip);
		
		write_data(hijack, origregs.rsp, &(origregs.rip), sizeof(unsigned long));
		origregs.rip = (unsigned long)addr;
		
		/* Above comment about adjusting EIP is valid for x86_64, too. */
		if (origregs.orig_rax >= 0)
		{
			switch (origregs.rax)
			{
				case -514: /* -ERESTARTNOHAND */
				case -512: /* -ERESTARTSYS */
				case -513: /* -ERESTARTNOINTR */
				case -516: /* -ERESTART_RESTARTBLOCK */
					if (IsFlagSet(hijack, F_DEBUG))
						fprintf(stderr, "[*] Adjusting RIP due to syscall restart.\n");
					
					origregs.rip += strlen(SYSCALLSEARCH);
					break;
			}
		}
	#endif
	
	if (ptrace(PTRACE_SETREGS, hijack->pid, NULL, &origregs) < 0)
		return SetError(hijack, ERROR_SYSCALL);
	
	return SetError(hijack, ERROR_NONE);
}