Beispiel #1
0
static void* get_unused_xblock(CTX ctx)
{
	if (unlikely(xfreelist == NULL)) {
		unsigned char *xmem = (unsigned char*)knh_xmalloc(ctx, 1);
		assert(xmem != NULL);
		knh_xblock_t *p = (knh_xblock_t*)knh_malloc(ctx, XBLOCK_NUMBER * sizeof(knh_xblock_t));
		size_t idx = 0;
		for (idx = 0; idx < XBLOCK_NUMBER - 1; idx++) {
			p[idx].block = &(xmem[idx * XBLOCK_SIZE]);
			p[idx].next = &(p[idx + 1]);
			//			fprintf(stderr, "idx:%d, p:%p, block:%p, next:%p\n", idx, &(p[idx]), p[idx].block, p[idx].next);
		}
		p[idx].block = &(xmem[idx * XBLOCK_SIZE]);
		p[idx].next = NULL;
		xfreelist = p;
	}
	if (xfreelist->next == NULL) {
		unsigned char *xmem = (unsigned char*)knh_xmalloc(ctx, 1);
		knh_xblock_t *p = (knh_xblock_t*)knh_malloc(ctx, XBLOCK_NUMBER * sizeof(knh_xblock_t));
		size_t idx = 0;
		for (idx = 0; idx < XBLOCK_NUMBER - 1; idx++) {
			p[idx].block = &(xmem[idx * XBLOCK_SIZE]);
			p[idx].next = &(p[idx + 1]);
		}
		p[idx].block = &(xmem[idx * XBLOCK_SIZE]);
		p[idx].next = NULL;
		xfreelist->next = p;
	}
	assert(xfreelist->next != NULL);
	knh_xblock_t *ret = xfreelist;
	xfreelist = ret->next;
	return ret;
}
Beispiel #2
0
void* knh_copyCallbackFunc(CTX ctx, void *func, knh_Func_t *fo)
{
  void *f = NULL;
#if !defined(K_USING_WINDOWS) && !defined(K_USING_BTRON)
  f = (void*)(knh_uchar_t*)knh_xmalloc(ctx, FUNC_SIZE);
  int i, marker = -1;
  for (i = 0; i < FUNC_SIZE; i++) {
	if (*(int*)&f[i] == -1) {
	  marker = i;
	  i += 3;
	}
  }
#endif
  return f;
}
Beispiel #3
0
static void *knh_generateCallbackFunc64(CTX ctx, void *tmpl, void *dest, kFunc *fo)
{
	kchar_t *function = NULL;
#if !defined(K_USING_WINDOWS) && !defined(K_USING_BTRON)
	function = (kchar_t*)tmpl;
	// search -1 (0xfffffff0fffffff0)
	int i, marker = -1, jmp_pos = -1;
	enum last_inst lastInst = call_leave_ret;
	for (i = 0; i < FUNC_SIZE; i++) {
		if (*(intptr_t*)&function[i] == 0xfffffff0fffffff0 && marker == -1) {
			marker = i;
			i += 8;
		}
		// XXX ??? function[i] == 0xe8 && 0x66
		/* jmp instruction
		 * e8 00 00 00  */
		if (function[i] == 0xe8 /*&& function[i] == 0x66*/) {
			jmp_pos = i;
		}
		// jmppos for x86_64
		// c9 : leave
		// e9 xxxxxxxx : jmp xxxxxxxx
		if(function[i] == 0xc9 && function[i + 1] == 0xe9) {
			lastInst = leave_jmp;
			jmp_pos = i + 1;
			i += 4; // rel address is 4 bytes
			break; 
		}
		//linux amd64
		if (function[i] == 0xe9 && *(int*)&function[i+1] < 0) {
			lastInst = jmp_only;
			jmp_pos = i;
			i += 5 + 4;
			break;
		}

		// typical epilogue.
		if (function[i] == 0xc9 && function[i+1] == 0xc3) {
			i += 2;
			break;
		}
	}
	// copy function
	size_t funcsize = i;
	function = (kchar_t*)knh_xmalloc(ctx, funcsize);
	memcpy(function, tmpl, i);
	if (marker > 0) {
		memcpy(&function[marker], &fo, sizeof(void*));
	}
	// now, patch
	if (jmp_pos > 0) {
		//linux
		// happend to use rax
		// movq 0x(dest) %rax
		function[jmp_pos+0] = 0x48;
		function[jmp_pos+1] = 0xb8;
		union {
			unsigned char code[sizeof(intptr_t)];
			intptr_t v;
		} code;
		code.v = (intptr_t) dest;
		memcpy(function+(jmp_pos+2), code.code, sizeof(code));

		size_t seekidx = jmp_pos + 2 + sizeof(intptr_t);
		// call
		switch (lastInst) {
		case leave_jmp:
			/* leave */
			//function[seekidx++] = 0xc9;
			/* fall through */
		case jmp_only: /*case leave_jmp:*/
			/* jmp *%rax */
			function[seekidx+0] = 0xff;
			function[seekidx+1] = 0xe0;
			break;
		case call_leave_ret:
			/* callq *%rax */
			function[seekidx+0] = 0xff;
			function[seekidx+1] = 0xd0;
			/* leave */
			function[seekidx+2] = 0xc9;
			/* ret */
			function[seekidx+3] = 0xc3;
			break;
		}
	}

#endif /* tron, lkm */
	return function;
}
Beispiel #4
0
static void *knh_generateCallbackFunc32(CTX ctx, void *tmpl, void *dest, kFunc *fo)
{
  kchar_t *function = NULL;
#if !defined(K_USING_WINDOWS) && !defined(K_USING_BTRON)
  function = (kchar_t*)tmpl;
  //search -1
  int i, marker = -1, jmp_pos = -1, shrink_pos = -1;
  for (i = 0; i < FUNC_SIZE; i++) {
	//	fprintf(stderr, "dump:%02x\n", *(int*)&function[i]);
	if (*(int*)&function[i] == -1 && marker == -1) {
	  marker = i;
	  i += 3;
	}

	// for thunk.bx, they call thunk, and add.
	if (function[i] == 0xe8 && function[i+5] == 0x81 && function[i+6] == 0xc3){
	  shrink_pos = i;
	  continue;
	} else 	if (function[i] == 0xe8 && *(int*)&function[i+1] < 0 && jmp_pos < 0) {
	  jmp_pos = i;
	}
	// loop condition
	if (function[i] == 0x5d && function[i + 1] == 0xc3) {
	  i += 14;
	  break;
	}
	if (i != 0 && function[i] == 0x55 && function[i + 1] == 0x89 && function[i+2] == 0xe5) {
	  // next prologue
	  i -= 1;
	  break;
	}
  }
  //  fprintf(stderr, "i=%d\n", i);
  function = (kchar_t*)knh_xmalloc(ctx, i);
  memcpy(function, tmpl, i);
  //  fprintf(stderr, "marker:%d, jmp:%d, shrink:%d\n", marker, jmp_pos, shrink_pos);
  kchar_t buf[FUNC_SIZE]={0};
  //  dumpBinary(function, 48);
  size_t funcsize = i;
  if (shrink_pos > 0) {
	// shrinking call xxx, add xxx
	// they always moving ebx;
	memcpy(buf, &function[shrink_pos + 11], funcsize - (shrink_pos + 11));
	function[shrink_pos] = 0x90;
	memcpy(&function[shrink_pos + 1], buf, funcsize - (shrink_pos + 11));
	marker -= 10;
	jmp_pos -= 10;
	funcsize -= 10;
	//	fprintf(stderr, "marker:%d, jmp:%d, shrink:%d\n", marker, jmp_pos, shrink_pos);
  }

  if (marker > 0){
	*(intptr_t*)&function[marker] = (intptr_t)fo;
  }


  //  fprintf(stderr, "jpos:%x\n", *(int*)&function[jmp_pos]);
  if (jmp_pos > 0) {
	//	int disp =  (intptr_t)dest - (intptr_t)&function[jmp_pos + 5];
	// it is too far.. make far calling
	function[jmp_pos] = 0xb8;
	*(intptr_t*)&function[jmp_pos+1] = (intptr_t)dest;
	memcpy(buf, &function[jmp_pos + 5], funcsize - (jmp_pos + 5));
	// insert 2 values;
	//before jmp!
	size_t seekidx = jmp_pos + 5;
	function[seekidx] = 0x90;
	function[seekidx+1] = 0xff;
	function[seekidx+2] = 0xd0;
	// shift the rest;
	memcpy(&function[seekidx+3], buf, funcsize - (seekidx+3));
	//	dumpBinary(function, 48);
  }

#endif
  return function;
}