A forum for reverse engineering, OS internals and malware analysis 

 #31453  by Li Yong
 Mon Apr 16, 2018 12:07 pm
I have search in several places on web some implementation of realloc function to kernel driver development in Windows and pratically nothing was found.

But was found a talk between some driver programmers about this function (including malloc) that can be see in this link and exists a code snnipet about a possible start of a implementation, also not know if this is the right way of make.

In C (not kernel programming) realloc seems like this, second this reader.

Then, i want know if someone already have implemented realloc function in kernel mode and could share here if possible?

Thank you to all.
 #31454  by Vrtule
 Mon Apr 16, 2018 7:49 pm
If you know the size of the buffer being "reallocated", you can use something like this:
Code: Select all
void *CustomRealloc(POOL_TYPE PoolType, const void *Buffer, size_t Size, size_t NewSize)
{
  void *ret = NULL;
  
  ret = ExAllocatePoolWithTag(PoolType, NewSize), Tag);
  if (ret != NULL) {
    memcpy(ret, Buffer, Size);
    ExFreePoolWithTag(Buffer, Tag);
  }
  
  return ret;
}
Well, if the new size is lesser than the old one, there is no need to reallocate, however, such strategy does not free the unsued memory.

If you do not know the buffer size, you may implement your own memory allocator based on ExAllocatePool/ExFreePool routines. You allocator would always know the block size and where the free space is, so it may possibly do real reallocations.

The question is, however, why do you need realloc in kernel mode.
 #31455  by Li Yong
 Mon Apr 16, 2018 8:08 pm
Vrtule wrote: Mon Apr 16, 2018 7:49 pm If you know the size of the buffer being "reallocated", you can use something like this:
Code: Select all
void *CustomRealloc(POOL_TYPE PoolType, const void *Buffer, size_t Size, size_t NewSize)
{
  void *ret = NULL;
  
  ret = ExAllocatePoolWithTag(PoolType, NewSize), Tag);
  if (ret != NULL) {
    memcpy(ret, Buffer, Size);
    ExFreePoolWithTag(Buffer, Tag);
  }
  
  return ret;
}
Well, if the new size is lesser than the old one, there is no need to reallocate, however, such strategy does not free the unsued memory.

If you do not know the buffer size, you may implement your own memory allocator based on ExAllocatePool/ExFreePool routines. You allocator would always know the block size and where the free space is, so it may possibly do real reallocations.

The question is, however, why do you need realloc in kernel mode.
Vrtule, thank you very much by answer.

The reason to this question around realloc function is because i want pass this arraylist to kernel mode (changing value_type to UNICODE_STRING), see on link (the answer) that the "key" to success in this particular case (usermode) (but also i belive that in kernel not is different) is the realloc function.:)
 #31457  by Li Yong
 Tue Apr 17, 2018 5:16 pm
Based in your answer, here was my last attempt, but without success.
Code: Select all
///////////////////////////////////// START ARRAYLIST /////////////////////////////////////////

typedef char* value_type;

typedef struct arraylist{
	size_t size;
	value_type* data;
}arraylist;

///////////////////////////////////////////////////

void free(const void*mem)
{
	if (mem)
	{
		arraylist *base = (arraylist*)(((size_t)mem) - sizeof(arraylist));
		ExFreePool(base);
	}
}

void* malloc(size_t size)
{
	if (sizeof(arraylist) + size < size)
		return NULL; 

	void *base = ExAllocatePoolWithTag(NonPagedPool, sizeof(arraylist) + size, 'MyTG' );
	if (!base)
		return base;

	arraylist *pHeader = (arraylist*)base;
	pHeader->size = size;

	return (void*)(((size_t)base) + sizeof(arraylist));
}

void* realloc(void*oldmem, size_t newsize)
{
	arraylist *pHeader = oldmem ? (arraylist*)(((size_t)oldmem) - sizeof(arraylist)) : NULL;
	size_t oldsize = pHeader ? pHeader->size : 0;
	if (oldsize >= newsize)
		return oldmem;
	void *newmem = malloc(newsize);
	if (newmem)
	{
		memcpy(newmem, oldmem, oldsize);
		free(oldmem);
	}
	return newmem;
}

///////////////////////////////////////////////////

void arraylist_initial(struct arraylist *list) {

	list->size = 0;
	list->data = NULL;
}

int arraylist_get_size(const struct arraylist list) {

	return list.size;
}

void arraylist_set_data_collection(struct arraylist *list, value_type* data) {

	list->data = data;
}

void arraylist_add(struct arraylist *list, value_type value) {

	int size = arraylist_get_size(*list);
	value_type *new_data;

	new_data = realloc(list->data, (size + 1) * sizeof new_data[0]);

	if (new_data)
	{
		new_data[size] = value;
		arraylist_set_data_collection(list, new_data);
		++list->size;
	}
}

value_type arraylist_get(const struct arraylist list, int index) {

	if (index < arraylist_get_size(list)) {
		return list.data[index];
	}
	else {
		return NULL;
	}
}

void arraylist_clear(struct arraylist *list) {
	
	list->size = 0;
	free(list->data);
	list->data = NULL;
}

void arraylist_deallocate(struct arraylist *list) {
	
	if (list->data != NULL)
		free(list->data);
	free(list);
}

int arraylist_indexof(const struct arraylist list, value_type value) {

	int index = 0;
	for (; index != arraylist_get_size(list); ++index) {
		if (strcmp(list.data[index], value) == 0) {
			return index;
		}
	}

	return -1;
}

struct arraylist list;

///////////////////////////////// END ARRAYLIST ///////////////////////////////////

void listUnload(IN PDRIVER_OBJECT DriverObject)
{
	DbgPrint("Goodbye from list!\n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
{

	arraylist_initial(&list);

	arraylist_add(&list, "1");
	arraylist_add(&list, "2");
	arraylist_add(&list, "3");
	arraylist_add(&list, "4");
	arraylist_add(&list, "5");
	arraylist_add(&list, "6");
	arraylist_add(&list, "7");


	int index = 0;
	for (; index != 7; ++index) {
		DbgPrint("CHECK: %s\n", arraylist_get(list, index));

	}

	int my_value = arraylist_indexof(list, "4");

	DbgPrint("size: %d index: %d\n", arraylist_get_size(list), my_value);

	arraylist_clear(&list);
	arraylist_deallocate(&list);

	DriverObject->DriverUnload = listUnload;

	DbgPrint("Hello from list!\n");

	return STATUS_SUCCESS;
}

 #31459  by EP_X0FF
 Wed Apr 18, 2018 7:29 am
This code with small modifications copy-pasted from stackoverflow.

What is the point in this? Vrtule already gave you code for "realloc".

Ex*** memory pool manager does not have this function. You either implement it yourself (which you are unable to do no matter what you copy-paste), or you clarify what you want to do in first and why you need this "realloc" at all.

Let me guess this is related to your previous topic where copy-paste "failures" also take place -> http://www.kernelmode.info/forum/viewto ... =14&t=4974 which is a result of failed port of this http://www.kernelmode.info/forum/viewto ... 438#p31438

It maybe surprise you but you don't need any "IndexOf" or "reallocs" or "StringLists" to do what you want to do. All you need is a primitive linked list, something students learn first when it comes to pointers usage.

Your topics all considered as flood. We don't need here gallery of failed copy-pasted codes from stackoverflow.
 #31461  by Vrtule
 Wed Apr 18, 2018 8:35 pm
The linked lists are a build-in feature in the Windows kernel (see the LIST_ENTRY structure and routines such as InitializeListHead, InsertTailList etc.), so you can just use them, there is no need to reinvent the wheel.

When you are talking about realloc, you should at first ask yourself why do you need such a routine. When resizing an array, realloc is more effecient that the malloc-copy/free approach since it just increased size of the allocated block in question if it is followed byreasonable amount of free space. However, I think you have much bigger problems than performance right now.

I recommend you to read some theory about general structures, such as array, linked list, hash table, n-ary tree, so you would know their advantages and caveats and would understand how they work under the hood.