Giter Site home page Giter Site logo

saruman's People

Contributors

elfmaster avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

saruman's Issues

Saruman crashes host program on first bootstrap instruction

Hello there,

I am unable to run the Saruman correctly due to a really weird bug on my Debian 8:
Linux M 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u2 (2016-10-19) x86_64 GNU/Linux. Saruman crashes the host program right in call_fn(BOOTSTRAP_CODE, ...) at the very first instruction of program's entry point.

Host:

~/devel/infector/saruman2 $ ./launcher `pidof host` ../parasite ""

#include <stdio.h>
int main(void) {
	for(;;) {
		printf("I am a boring program\n");
		sleep(3);
	} 
}

Parasite:

#include <stdio.h>
int main(void){
	int i;
	for (i = 0; i < 10; i++)
		printf("I AM AN EVIL FUCKING PARASITE!!!\n");
}

Launching slightly modified Saruman's code:

[+] Target pid: 389
[+] map_elf_binary(ptr, ../parasite)
[+] Parasite entry point will be main(): 0x400506
[+] Found text segment
[+] Found data segment
[+] Found dynamic segment
[+] Found dynamic string table
[+] Found dynamic symbol table
[+] Found G.O.T
[+] PLT count: 72 entries
[DEBUG]-> get_sym_from_libc() addr of __libc_dl_*: 7f112c69cb00
[+] PT_ATTACHED -> 389
[+] calling bootstrap

-- [RIP - 0x00400000] Single step
rax: 0xfffffffffffffdfc (-516)
rbx: 0x7ffce59de1a0 (140724160815520)
rcx: 0xffffffffffffffff (-1)
rdx: 0x04000000 (67108864)
rsi: 0x000005c8 (1480)
rdi: 0x00c00000 (12582912)
rbp: 0xffffffff (4294967295)
rsp: 0x7ffce59de188 (140724160815496)
r8: 0x7ffce59de2a0 (140724160815776)
r9: 0x7ffce59de0e0 (140724160815328)
r10: 0x00000008 (8)
r11: 0x00000246 (582)
r12: 0x7ffce59de220 (140724160815648)
r13: 0x7ffce59de450 (140724160816208)
r14: 0x00000000 (0)
r15: 0x00000000 (0)
First 12 bytes from RIP:
55 48 89 e5 48 81 ec a0 48 81 ec a0

-- [RIP - 0x003ffffe] Single step
rax: 0x000000db (219)
rbx: 0x7ffce59de1a0 (140724160815520)
rcx: 0xffffffffffffffff (-1)
rdx: 0x04000000 (67108864)
rsi: 0x000005c8 (1480)
rdi: 0x00c00000 (12582912)
rbp: 0xffffffff (4294967295)
rsp: 0x7ffce59de188 (140724160815496)
r8: 0x7ffce59de2a0 (140724160815776)
r9: 0x7ffce59de0e0 (140724160815328)
r10: 0x00000008 (8)
r11: 0x00000246 (582)
r12: 0x7ffce59de220 (140724160815648)
r13: 0x7ffce59de450 (140724160816208)
r14: 0x00000000 (0)
r15: 0x00000000 (0)
First 12 bytes from RIP:
ff ff ff ff ff ff ff ff 89 e5 48 81

[!] Target process has been stopped, something went wrong. Signal: 11 (Segmentation fault)
call_fn(BOOTSTRAP_CODE, ...) failed: Success

One can notice that the second registers dump differs from first one in:

  • RAX being changed
  • RIP being shifted two bytes back
  • bytes at RIP being malformed with 0xff - not to mention, that following bytes: 89 e5 48 ... are shifted even further from RIP - four bytes off.

Here are all modifications made to Saruman (launcher.c):

  • added function display_regs for tracing purposes
  • slightly modified call_fn function to instead of PTRACE_CONT got into PTRACE_SINGLESTEP
  • added a do..while loop with more thorough status interpretation code
  • added failover code for run_bootstrap in main() as saruman should fail when bootstrap did not manage to run.
[...]
void display_regs(pid_t pid, struct user_regs_struct *pt_reg ) {

    long word[3] = {0};
    char *buf = (char*)word;

    word[0] = ptrace(PTRACE_PEEKTEXT, pid, pt_reg->rip, NULL);
    word[1] = ptrace(PTRACE_PEEKTEXT, pid, pt_reg->rip+4, NULL);
    word[2] = ptrace(PTRACE_PEEKTEXT, pid, pt_reg->rip+8, NULL);
    
    printf("\n-- [RIP - 0x%08lx] Single step \n"
            "rax: 0x%08lx (%ld)\nrbx: 0x%08lx (%ld)\nrcx: 0x%08lx (%ld)\n"
            "rdx: 0x%08lx (%ld)\nrsi: 0x%08lx (%ld)\nrdi: 0x%08lx (%ld)\n"
            "rbp: 0x%08lx (%ld)\nrsp: 0x%08lx (%ld)\nr8: 0x%08lx (%ld)\n"
            "r9: 0x%08lx (%ld)\nr10: 0x%08lx (%ld)\nr11: 0x%08lx (%ld)\n"
            "r12: 0x%08lx (%ld)\nr13: 0x%08lx (%ld)\nr14: 0x%08lx (%ld)\n"
            "r15: 0x%08lx (%ld)\n"
            "First 12 bytes from RIP:\n"
            "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
            pt_reg->rip,
            pt_reg->rax, pt_reg->rax, pt_reg->rbx, pt_reg->rbx, pt_reg->rcx, pt_reg->rcx,
            pt_reg->rdx, pt_reg->rdx, pt_reg->rsi, pt_reg->rsi, pt_reg->rdi, pt_reg->rdi, 
            pt_reg->rbp, pt_reg->rbp, pt_reg->rsp, pt_reg->rsp, pt_reg->r8, pt_reg->r8,
            pt_reg->r9, pt_reg->r9, pt_reg->r10, pt_reg->r10, pt_reg->r11, pt_reg->r11,
            pt_reg->r12, pt_reg->r12, pt_reg->r13, pt_reg->r13, pt_reg->r14, pt_reg->r14,
            pt_reg->r15, pt_reg->r15, 
            buf[0] & 0xff, buf[1] & 0xff, buf[2] & 0xff, buf[3] & 0xff, buf[4] & 0xff, 
            buf[5] & 0xff, buf[6] & 0xff, buf[7] & 0xff, buf[8] & 0xff, buf[9] & 0xff, buf[10] & 0xff, buf[11] & 0xff);
}

/*
 * call_fn() allows one to inject a function
 * (select by functionPayloads_t) into the remote
 * process, and execute it. The return value for
 * the function is stored in payloads.function[func].retval
 */
#define SLACK_SIZE 32
int call_fn(functionPayloads_t func, handle_t *h, uint64_t ip)
{

[...]

case 6:
            pt_reg->rdi = (uintptr_t)h->payloads.function[func].args[0];
                        pt_reg->rsi = (uintptr_t)h->payloads.function[func].args[1];
                        pt_reg->rdx = (uintptr_t)h->payloads.function[func].args[2];
                        pt_reg->rcx = (uintptr_t)h->payloads.function[func].args[3];
                        pt_reg->r8 =  (uintptr_t)h->payloads.function[func].args[4];
            pt_reg->r9 =  (uintptr_t)h->payloads.function[func].args[5];
            break;
    }

    display_regs(h->tasks.pid, pt_reg);
    
    if (ptrace(PTRACE_SETREGS, h->tasks.pid, NULL, pt_reg) < 0)
        return -1;
    
    //if (ptrace(PTRACE_CONT, h->tasks.pid, NULL, NULL) < 0)
    //    return -1;

    do {
        ptrace(PTRACE_SINGLESTEP, h->tasks.pid, 0, 0);
		if (waitpid(h->tasks.pid, &status, 0) == -1) {
			perror("waitpid");
            return -1;
		}

        if (ptrace(PTRACE_GETREGS, h->tasks.pid, NULL, pt_reg) < 0) {
            perror("PTRACE_GETREGS");
            return -1;
        }
        
        display_regs(h->tasks.pid, pt_reg);

		if (WIFEXITED(status)) {
			fprintf(stderr, "\n[!] Target process has exited, something went wrong. Status: %d\n", WEXITSTATUS(status));
			return -1;
		} else if (WIFSIGNALED(status)) {
			fprintf(stderr, "\n[!] Target process has been killed, something went wrong. Signal: %d (%s)\n", WTERMSIG(status), strsignal(WTERMSIG(status)));
			if (WCOREDUMP(status)) {
				fprintf(stderr, "\tChild process has produced a core dump. Damn it.\n");
			}
			return -1;
		} else if (WIFSTOPPED(status)) {
			fprintf(stderr, "\n[!] Target process has been stopped, something went wrong. Signal: %d (%s)\n", WSTOPSIG(status), strsignal(WSTOPSIG(status)));
			return -1;
		} else if (WIFCONTINUED(status)) {
		}

	} while (!WIFEXITED(status) && !WIFSIGNALED(status));
    
    /* Get return value */
    if (ptrace(PTRACE_GETREGS, h->tasks.pid, NULL, pt_reg) < 0) {
        perror("PTRACE_GETREGS");
        return -1;
    }

    h->payloads.function[func].retval = (pt_reg_t)pt_reg->rax;
    
    return 0;

}

[...]

int main(int argc, char **argv)
{
[...]
if(run_bootstrap(&parasite) < 0) {
        goto done;
    }

As can be seen, there is a really strange behaviour that I don't understand going on in host's body:

  1. First, host get's saruman's bootstrap code injected, which gets injected fine - as it can be seen from registers (RIP, and so on) also from first 12 bytes dumped from RIP:
55 push $rsp
48 89 mov $rsp, $rbp
...
  1. Then, after a single step, where push $rsp should occur, out of the sudden we land at 2 bytes before entry point (0x3ffffe), RAX modified, and bytes at RIP malformed.

  2. Host gets it's SIGSEGV and it's life is over.

I don't understand that course of action, neither how it can be traced or fixed.
Any ideas?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.