249 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| Declaration for Linux kernel compatibility
 | |
| */
 | |
| 
 | |
| #include <assert.h>
 | |
| #include <stdarg.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <sys/types.h>
 | |
| #include <sys/ptrace.h>
 | |
| 
 | |
| #include "extra.h"
 | |
| 
 | |
| pid_t victim_pid= -1;
 | |
| char *victim_exe= NULL;
 | |
| 
 | |
| #define TRAP_BIT	(0x80000000)
 | |
| 
 | |
| static struct nlist *exe_nlist;
 | |
| static int exe_nlist_n;
 | |
| 
 | |
| /* unsigned long __get_free_page(int type) { assert(0); } */
 | |
| /* void *kmalloc(size_t size, int type) { assert(0); } */
 | |
| void free_page(unsigned long page) { assert(0); }
 | |
| /* void kfree(void *mem) { assert(0); } */
 | |
| void vfree(void *mem) { assert(0); }
 | |
| 
 | |
| size_t strncpy_from_user(char *addr, const char *user_name, size_t size)
 | |
| { assert(0); return 0; }
 | |
| 
 | |
| /* void lock_kernel(void) { assert(0); } */
 | |
| /* void unlock_kernel(void) { assert(0); } */
 | |
| /* void __asm__(char *str) { assert(0); } */
 | |
| 
 | |
| extern void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot)
 | |
| { assert(0); return NULL; }
 | |
| 
 | |
| #if 0
 | |
| void kallsyms_sections(void *infop,
 | |
| 	int (*fp)(void *token, const char *modname, const char *secname,
 | |
| 	      ElfW(Addr) secstart, ElfW(Addr) secend, ElfW(Word) secflags))
 | |
| { assert(0); }
 | |
| #endif
 | |
| 
 | |
| unsigned long __generic_copy_to_user(void *x, const void *y, unsigned long z)
 | |
| { assert(0); return -1; }
 | |
| unsigned long __generic_copy_from_user(void *x, const void *y, unsigned long z)
 | |
| { assert(0); return -1; }
 | |
| 
 | |
| /* void read_lock(struct lock *lock) { assert(0); } */
 | |
| /* void read_unlock(struct lock *lock) { assert(0); } */
 | |
| void udelay(unsigned long usecs) { assert(0); }
 | |
| int copy_to_user(void * result_record, void *res, size_t size)
 | |
| {
 | |
| 	memcpy(result_record, res, size);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void panic(char *str) { assert(0); }
 | |
| 
 | |
| void printk(char *fmt, ...)
 | |
| {
 | |
| 	va_list ap;
 | |
| 
 | |
| 	va_start(ap, fmt);
 | |
| 	vfprintf(stderr, fmt, ap);
 | |
| 	va_end(ap);
 | |
| }
 | |
| 
 | |
| int kallsyms_address_to_symbol(db_expr_t off,
 | |
|     const char * *mod_name, unsigned long *mod_start, unsigned long *mod_end, 
 | |
|     const char * *sec_name, unsigned long *sec_start, unsigned long *sec_end, 
 | |
|     const char * *sym_name, unsigned long *sym_start, unsigned long *sym_end)
 | |
| {
 | |
| 	static char name[64];
 | |
| 
 | |
| 	int i;
 | |
| 	unsigned long btext, etext;
 | |
| 	struct nlist *below, *above;
 | |
| 
 | |
| 	off &= ~TRAP_BIT;
 | |
| 	load_nlist(victim_exe, &btext, &etext);
 | |
| 	below= above= NULL;
 | |
| 	for (i= 0; i<exe_nlist_n; i++)
 | |
| 	{
 | |
| 		if (exe_nlist[i].n_type != N_TEXT)
 | |
| 			continue;
 | |
| 		if (exe_nlist[i].n_value <= off)
 | |
| 		{
 | |
| 			if (!below || exe_nlist[i].n_value > below->n_value)
 | |
| 				below= &exe_nlist[i];
 | |
| 		}
 | |
| 		if (exe_nlist[i].n_value > off)
 | |
| 		{
 | |
| 			if (!above || exe_nlist[i].n_value < above->n_value)
 | |
| 				above= &exe_nlist[i];
 | |
| 		}
 | |
| 	}
 | |
| #if 0
 | |
| 	if (below)
 | |
| 	{
 | |
| 		printf("found '%s' at 0x%x\n", below->n_name, below->n_value);
 | |
| 	}
 | |
| 	if (above)
 | |
| 	{
 | |
| 		printf("found '%s' at 0x%x\n", above->n_name, above->n_value);
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	btext |= TRAP_BIT;
 | |
| 	etext |= TRAP_BIT;
 | |
| 
 | |
| 	*mod_name = victim_exe;
 | |
| 	*mod_start = btext;
 | |
| 	*mod_end = etext;
 | |
| 	*sec_name = ".text";
 | |
| 	*sec_start = btext;
 | |
| 	*sec_end = etext;
 | |
| 
 | |
| 	assert(below && above);
 | |
| 
 | |
| 	strncpy(name, below->n_name, sizeof(name)-1);
 | |
| 	name[sizeof(name)-1]= '\0';
 | |
| 	*sym_name= name;
 | |
| 
 | |
| 	*sym_start= below->n_value | TRAP_BIT;
 | |
| 	*sym_end= above->n_value | TRAP_BIT;
 | |
| 
 | |
| 	return 1;
 | |
| }
 | |
| 
 | |
| struct module *module_list;
 | |
| struct task_struct *task_list;
 | |
| struct lock tasklist_lock;
 | |
| 
 | |
| unsigned long text_read_ul(void *addr)
 | |
| {
 | |
| 	int i;
 | |
| 	unsigned long value;
 | |
| 
 | |
| 	for (i= 0; i<sizeof(value); i++)
 | |
| 	{
 | |
| 		((unsigned char *)&value)[i]= text_read_ub((char *)addr+i);
 | |
| 	}
 | |
| 	return value;
 | |
| }
 | |
| 
 | |
| unsigned char text_read_ub(void *addr)
 | |
| {
 | |
| 	int v;
 | |
| 	unsigned long vaddr;
 | |
| 
 | |
| 	vaddr= (unsigned long)addr;
 | |
| 	vaddr &= ~TRAP_BIT;
 | |
| 	v= ptrace(T_READB_INS, victim_pid, vaddr, 0);
 | |
| 	if (v < 0)
 | |
| 	{
 | |
| 		fprintf(stderr,
 | |
| 	"text_read_ub: trace T_READB_INS failed on pid %d, addr 0x%lx: %s\n",
 | |
| 			victim_pid, vaddr, strerror(errno));
 | |
| 		exit(1);
 | |
| 	}
 | |
| 	return v;
 | |
| }
 | |
| 
 | |
| void text_write_ul(void *addr, unsigned long value)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i= 0; i<sizeof(value); i++)
 | |
| 	{
 | |
| 		text_write_ub((char *)addr+i, ((unsigned char *)&value)[i]);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void text_write_ub(void *addr, unsigned char value)
 | |
| {
 | |
| 	int v;
 | |
| 	unsigned long vaddr;
 | |
| 
 | |
| 	vaddr= (unsigned long)addr;
 | |
| 	vaddr &= ~TRAP_BIT;
 | |
| 	v= ptrace(T_WRITEB_INS, victim_pid, vaddr, value);
 | |
| 	if (v < 0)
 | |
| 	{
 | |
| 		fprintf(stderr,
 | |
| 	"text_read_ub: trace T_WRITEB_INS failed on pid %d, addr 0x%lx: %s\n",
 | |
| 			victim_pid, vaddr, strerror(errno));
 | |
| 		exit(1);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void load_nlist(exe_name, btextp, etextp)
 | |
| char *exe_name;
 | |
| unsigned long *btextp;
 | |
| unsigned long *etextp;
 | |
| {
 | |
| 	int i;
 | |
| 	unsigned long btext, etext;
 | |
| 
 | |
| 	if (!exe_nlist)
 | |
| 	{
 | |
| 		exe_nlist_n= read_nlist(exe_name, &exe_nlist);
 | |
| 		if (exe_nlist_n <= 0)
 | |
| 		{
 | |
| 			if (exe_nlist_n == -1)
 | |
| 			{
 | |
| 				fprintf(stderr,
 | |
| 				"error reading name list from '%s': %s\n",
 | |
| 					exe_name, strerror(errno));
 | |
| 			}
 | |
| 			else
 | |
| 				fprintf(stderr, "no name list in '%s'\n",
 | |
| 					exe_name);
 | |
| 			exit(1);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (!btextp && !etextp)
 | |
| 		return;
 | |
| 
 | |
| 	etext= 0;
 | |
| 	btext= (unsigned long)-1;
 | |
| 	for (i= 0; i<exe_nlist_n; i++)
 | |
| 	{
 | |
| 		if (exe_nlist[i].n_type != N_TEXT)
 | |
| 			continue;
 | |
| 		if (exe_nlist[i].n_value < btext)
 | |
| 			btext= exe_nlist[i].n_value;
 | |
| 		if (exe_nlist[i].n_value > etext)
 | |
| 			etext= exe_nlist[i].n_value;
 | |
| 	}
 | |
| 
 | |
| 	if (btext >= etext)
 | |
| 	{
 | |
| 		fprintf(stderr, "Bad btext (0x%lx) or etext (0x%lx) in %s\n",
 | |
| 			btext, etext, exe_name);
 | |
| 		exit(1);
 | |
| 	}
 | |
| 
 | |
| 	btext |= TRAP_BIT;
 | |
| 	etext |= TRAP_BIT;
 | |
| 
 | |
| 	if (btextp)
 | |
| 		*btextp= btext;
 | |
| 	if (etextp)
 | |
| 		*etextp= etext;
 | |
| }
 | 
