getdents() syscall implementation for rootkit - c

I plan to hook my own version of getdents() for my rootkit. Code is here:
asmlinkage int new_getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count)
{
int nread;
int bpos;
struct linux_dirent *d;
int (*orig_func)(unsigned int fd, struct linux_dirent *dirp, unsigned int count);
t_syscall_hook *open_hook;
open_hook = find_syscall_hook(__NR_getdents);
orig_func = (void*) open_hook->orig_func;
nread = (*orig_func)(fd, dirp, count);
d = dirp;
for (bpos = 0; bpos < nread;) {
d = (struct linux_dirent *) ((char*)dirp + bpos);
printk(KERN_INFO "%s\n", d->d_name);
bpos += d->d_reclen;
}
return nread;
}
I fail to understand the type cast in this line: d = (struct linux_dirent *) ((char*)dirp + bpos);
Both d and dirp hold memory address for a linux_dirent struct. d_reclen contains length of the entry. If we receive d_reclen as 3, 5, 7, then entries would be present at dirp, dirp+3 /size(linux_dirent), (dirp+3/size(linux_dirent)+5/size(linux_dirent))...
So the line should be something like this then: d = (struct linux_dirent *) ((dirp + bpos)/size(linux_dirent));
Why are we converting into (char *)?
typedef struct {
unsigned long d_ino;
unsigned long d_off;
unsigned short d_reclen;
char d_name[1];
} linux_dirent;

So the line should be something like this then: d = (struct linux_dirent *) ((dirp + bpos)/size(linux_dirent));
No - dirp / sizeof(linux_dirent) makes little sense, the offset of dirp from 0 has no relation to the size of the structure. Dividing memory address by the size of the structure... it's just some unrelated address.
You meant, like, to divide only the offset from the memory location, and then add the resulting pointer to the pointer. Well, along:
(char*)dirp + ((char*)(dirp + bpos) - (char*)dirp)/sizeof(linux_dirent)
^^^^^^^^^^^ = (char*)dirp + bpos * sizeof(linux_dirent)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = bpos * sizoef(linux_dirent)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = bpos
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = (char*)dirp + bpos
But... instead of incrementing the dirp pointer in sizeof(linux_dirent) steps, you can just increment it in 1 bytes steps. That's what the cast to char* is doing. sizeof(char) is always 1. The following is true to the value:
dirp + bpos == (char*)dirp + bpos * sizeof(linux_dirent)
Why are we converting into (char *)?
We are converting to char * to change how many bytes the + operator will increment. Short example:
int *a = 20;
a + 5 == 20 + 5 * sizeof(int)
(char*)a + 5 == 20 + 5 * sizeof(char) // sizeof(char) = 1, so:
(char*)a + 5 == 25
Pointer arithmetic is a good topic to research.

Related

Save a block of data from memory to byte array to restore later the block from byte array

I have the following code:
typedef struct {
struct {
uint64_t key;
uint64_t hash;
uint64_t size;
uint64_t body;
} length;
} block_head;
-----------------------------------------------------
//Block allocation
uint64_t d1, d2, d4; //Lengths for octet strings to be saved in memory block
uint64_t d3; //just for saving a size - integer value
unsigned char **data = (unsigned char**)malloc(sizeof(block_head) + d1 + d2 + d4);
block_head *head = (block_head *)data;
head->length.key = d1;
head->length.hash = d2;
head->length.size = d3;
head->length.body = d4;
-----------------------------------------------------
//Later we fill memory of data block
// get a pointer key buffer location
unsigned char *d = (char *)data + sizeof(secure_head_t);
//Add octet string
FillData1(d);
// get a pointer to the body buffer location
unsigned char *body = (unsigned char *)data + (sizeof(block_head) + head->length.d1 + head->length.d2);
//get the length of the body free space (of a block)
int body_length = head->length.body;
//body is filled with octet string, and length is saved to body_length
FillBody2((unsigned char*)body, &body_length)
// Advance the body pointer to the location of the remaining space, and calculate just how much room is still available.
body += body_length;
// Save another octet string to block
FillBody3((unsigned char *)data + (sizeof(block_head) + head->length.key), &body_length);
Now I need to save the filled block (unsigned char **data) to a byte array, to restore later from array to a block.
I do this but it is not working:
unsigned char **data = some_filled_data;
block_head *head = (block_head *)data;
// convert data to arr
unsigned char *arr = (unsigned char *)malloc( sizeof(block_head) + (head->length.key + head->length.hash + head->length.body));
memcpy(&arr, data, sizeof(block_head) + (head->length.key + head->length.hash + head->length.body));
// convert arr to data
unsigned char *data = (unsigned char*)malloc( sizeof(unsigned char) * strlen(arr));
memcpy(&data, &arr, strlen(arr));
If I try to use the new converted block from arr, then I will get an error, because it is not constructed correctly or something like this
How I should convert correctly data to arr and arr to data, to represent the same block ?
While I could not decipher the description, this answers the title:
typedef struct {
int a;
char b[20];
} Test;
void fillAndBackupTest(char **out) {
Test test;
test.a = 20;
strcpy(test.b, "Hello!");
*out = (char*) malloc(sizeof Test);
memcpy(*out, &test, sizeof Test);
}
void restoreAndPrintTest(char *in) {
Test test;
memcpy(&test, in, sizeof Test);
printf("a: %d, b: %s\n", test.a, test.b);
}
int main()
{
char *blob;
fillAndBackupTest(&blob);
restoreAndPrintTest(blob);
free(blob);
return 0;
}
A structure type, Test is defined, fillAndBackupTest() creates one, fills its fields and stores a "copy" of it into a buffer it allocates for itself (it is a char* for now, but actually it could very well remain being void*), then restoreAndPrintTest() restores a (different) Test instance from this buffer and prints its contents.
What you do with malloc-ing a sum of a size and some arbitrary numbers (key? body?) does not seem to be a good idea, and strlen can not measure the length of a binary blob either.

Reading a value of a short from file data

I have a file (pointed to by *data) which begins with a struct.
I would like to get to the value of nsectionheaders in memory so that I can use it.
I've tried this, but it's returning a strangely large negative value. How do I get it to return the right value?
void read_file_header(void *data) {
int offset = (sizeof(char) * 16) + (sizeof(int) * 4) + sizeof(int) + (sizeof(short) * 6);
char *pointer = (char *) data + offset;
short num_sec_headers = 0;
memcpy(&num_sec_headers, &pointer, sizeof(short));
printf("The number of headers is %d\n", num_sec_headers);
}
The line
memcpy(&num_sec_headers, &pointer, sizeof(short));
is incorrect. You are taking the address of the pointer, instead of just using pointer:
memcpy(&num_sec_headers, pointer, sizeof(short));
You have a secure offsetof in the standard (include stddef.h):
void read_file_header(void *data) {
int offset = offsetof(ElfFileHeader, nsectionheaders);
short num_sec_headers;
memcpy(&num_sec_headers, (char *)data + offset, sizeof(short));
printf("The number of headers is %d\n", num_sec_headers);
}

Memcpy or struct assignment?

I have the following code and am unsure of whether to use structure alignment or memcpy to copy struct A onto the custom "stack" char/byte array.
Is there anything advantageous/disadvantageous about the following two options of code or anything that is just flat out wrong?
The necessary struct/functions.
struct B {
int type;
struct B *prev;
}
struct A {
struct B base;
int n;
struct B *another;
char name[1]; /* Struct hack */
};
void align(char **ptr, int n) {
intptr_t addr = (intptr_t)*ptr;
if(addr % n != 0) {
addr += n - addr % n;
*ptr = (char *)addr;
}
}
Option 1: Struct Assignment
void struct_assignment() {
char *stack = malloc(400*1000);
char *top_of_stack = stack + 3149; /* Just an example */
struct A *var = (struct A *)top_of_stack;
align((char **)&var, sizeof(struct B)); /* Most restrictive alignment member in struct A */
var->base.type = 1;
var->base.prev = NULL;
var->another = (struct base *)var;
char *name = "test";
var->n = strlen(name) + 1;
strcpy(var->name, name);
top_of_stack = (char*)var + sizeof(*var)+ (var->n - 1); /* -1 for name[1] */
}
Option 2: memcpy
void memcpying() {
char *stack = malloc(400*1000);
char *top_of_stack = stack + 3149; /* Just an example */
struct A var;
var.base.type = 1;
var.base.prev = NULL;
var.another = NULL;
char *name = "test";
var.n = strlen(name) + 1;
strcpy(var.name, name);
char *aligned_ptr = top_of_stack;
align(&aligned_ptr, sizeof(struct B)); /* Most restrictive alignment member in struct A */
memcpy(aligned_ptr, &var, sizeof(var) + (var.n - 1); /* -1 for name[1] */
struct A *var_ptr = (struct A*)aligned_ptr;
var_ptr->another = (struct B *)var_ptr;
top_of_stack = aligned_ptr + sizeof(var)+ (var.n - 1); /* -1 for name[1] */
}
Is option 1 even struct assignment?
Will both options result in the same padding and alignment?
Will the endianness of the target architecture affect option 1?
I don't think that this can be called struct assignment. You are assigning to the individual fields.
struct assingment in your case where you are merely interested in initialization of the object on the stack that you are "reserving" could use a temporary:
struct base tmp = {
.type = 1,
.prev = NULL,
// whatever other fields you want to initialize
};
var->base = tmp;
or even more consise by using a compound literal:
var->base = (struct base){
.type = 1,
.prev = NULL,
// whatever other fields you want to initialize
};
Both methods have the advantage of initializing all fields that you
might have forgotten to 0. The for the copy operation itself, let the compiler chose whatever the compiler designer saw fit. Don't mess around with such things unless some careful benchmarking tells you that there is a real problem.

What is the behavior of the plus plus (++) operator when applied to a struct?

I'm trying to learn C by playing with an Arduino Uno. I'm reviewing the code for the Colorduino library on github. I'm wondering how ++ works when applied to a struct.
There is a PixelRGB struct defined in Colorduino.h:
typedef struct pixelRGB {
unsigned char r;
unsigned char g;
unsigned char b;
} PixelRGB;
In Colorduino.cpp there is a bit of code that applies the ++ operator to a PixelRGB pointer. How does this work?
for (unsigned char y=0;y<ColorduinoScreenWidth;y++) {
for(unsigned char x=0;x<ColorduinoScreenHeight;x++) {
p->r = R;
p->g = G;
p->b = B;
p++;
}
}
Note, that this code increments pointer to PixelRGB, not the struct itself.
So, the result of ++ when applied to pointer, is just incrementing its value by sizeof(PixelRGB)
p is a pointer, not a struct, so it works like pointer arithmetic does on any type. The pointer's value is an address. So when, for example, you add n to a pointer, it's value changes and points to a new address n * sizeof type away. So...
char *p = malloc(SOME_NUMBER * sizeof char);
p++; // p = p + sizeof char
p += 4; // p = p + sizeof char * 4
And if you have a struct...
typedef struct {
int a;
} foo;
/* ... */
foo *fp = malloc(SOME_NUMBER * sizeof foo);
fp++; // fp = fp + sizeof foo;
fp += 4; // fp = fp + sizeof foo * 4;

how to malloc for this structure

typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char *macsStrList[MAC_ADDR_STR_LEN];
} testMsg_t;
Number of elements in macsStrList is m_Count.
I know following is not correct:
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
This is correct, given the structure you have done
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
However you are probably confused to the meaning of *arr[dimension] -- which is an array length dimension of pointers to chars -- reading between the lines,
MAC_ADDR_STR_LEN
Is probably ment to the legth of the string representation of a mac address (say <20 bytes?)
However your struct gives you 20 char pointers, and the character pointers still have to be initializaed to point to valid memory.
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) );
pInput->macsStrList[0] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
pInput->macsStrList[1] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
pInput->macsStrList[2] = (char *) malloc( MAC_ADDR_STR_LEN+1 );
...
or redefine your struct to
typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char macsStrList[NUMBER_OF_MAC_ADDRESSES][MAC_ADDR_STR_LEN];
} testMsg_t;
To avoid having to deal with multiple number of allocations.
ADDITION;
As per comments, given that the number of mac addresses are dynamically determined, you could also define the struct as;
typedef struct testMsg_ {
unsigned char opCode;
unsigned int Count;
char macsStrList[1][MAC_ADDR_STR_LEN];
} testMsg_t;
and then allocate it using
testMsg_t *pInput = (testMsg_t *) malloc(sizeof(testMsg_t) + (countOfMacsAddresses * MAC_ADDR_STR_LEN) );
That would have the added over a solution with pointers of that you could use realloc to resize the array dynamically if you needed to do that as well.....
I think what you're looking for is maybe (ok, Soren got in first, but I'll show a way to allocate a single contiguous chunk):
/* assuming we only need macStrList[0] ... [Count-1] */
struct testMsg
{
unsigned char opCode;
unsigned int Count;
char *macsStrList[];
};
struct testMsg *allocate_testMsg(int count)
{
char *string_storage;
struct testMsg *msg;
size_t size = sizeof(struct testMsg) /* base object */
+ (count * sizeof(char *)) /* char* array */
+ (count * (MAC_ADDR_STR_LEN+1)) /* char storage */
;
msg = malloc(size);
msg->Count = count;
string_storage = (char *)&(msg->macStrList[count]);
/* note msg->macStrList points to UNINITIALIZED but allocated storage.
it might be sensible to zero-fill string_storage, depending on how you'll
initialize it
*/
for (count=0; count < msg->Count;
++count, string_storage += (MAC_ADDR_STR_LEN+1))
{
msg->macStrList[count] = string_storage;
}
return msg;
}
Of course it is. You allocate a pointer to a testMsg_t which is an alias for struct testMsg_. However you need to initialize this object yourself.
(And you don't need to cast the allocated pointer in C).

Resources