Using MD5 in kernel space of Linux - c

I am trying to use the kernel space implementation of the md5 algorithm (md5.h and md5.c). It turns out that md5.h does not declare the functions found in md5.c, so I could not simply include md5.h into my c file. I also wanted to avoid altering md5.h to declare the functions, since that could have unintended consequences. Is there any other way to use md5 in kernel space?

Use Crypto API instead of rolling your own.

#include <crypto/hash.h>
bool md5_hash(char *result, char* data, size_t len){
struct shash_desc *desc;
desc = kmalloc(sizeof(*desc), GFP_KERNEL);
desc->tfm = crypto_alloc_shash("md5", 0, CRYPTO_ALG_ASYNC);
if(desc->tfm == NULL)
return false;
crypto_shash_init(desc);
crypto_shash_update(desc, data, len);
crypto_shash_final(desc, result);
crypto_free_shash(desc->tfm);
return true;
}

Beware, the code posted by wande chen will cause kernel heap corruption.
struct shash_desc *desc;
desc = kmalloc(sizeof(*desc), GFP_KERNEL);
desc->tfm = crypto_alloc_shash("md5", 0, CRYPTO_ALG_ASYNC);
This is because md5 engine will use memory past struct shash_desc for storing md5 context.
The correct way to allocate struct shash_desc can be found here.
*shash = crypto_alloc_shash(name, 0, 0);
size = sizeof(struct shash_desc) + crypto_shash_descsize(*shash);
*sdesc = kmalloc(size, GFP_KERNEL);

struct sdesc {
struct shash_desc shash;
char ctx[];
};
static struct sdesc *init_sdesc(struct crypto_shash *alg)
{
struct sdesc *sdesc;
int size;
size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
sdesc = kmalloc(size, GFP_KERNEL);
if (!sdesc)
return ERR_PTR(-ENOMEM);
sdesc->shash.tfm = alg;
return sdesc;
}
static int calc_hash(struct crypto_shash *alg,
const unsigned char *data, unsigned int datalen,
unsigned char *digest)
{
struct sdesc *sdesc;
int ret;
sdesc = init_sdesc(alg);
if (IS_ERR(sdesc)) {
pr_info("can't alloc sdesc\n");
return PTR_ERR(sdesc);
}
ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
kfree(sdesc);
return ret;
}
static int do_md5(const unsigned char *data, unsigned char *out_digest)
{
struct crypto_shash *alg;
char *hash_alg_name = "md5";
unsigned int datalen = strlen(data); // remove the null byte
alg = crypto_alloc_shash(hash_alg_name, 0, 0);
if(IS_ERR(alg)){
pr_info("can't alloc alg %s\n", hash_alg_name);
return PTR_ERR(alg);
}
unsigned char hash[32];
calc_hash(alg, data, datalen, hash);
// Very dirty print of 8 first bytes for comparaison with sha256sum
printk(KERN_INFO "HASH(%s, %i): %02x%02x%02x%02x%02x%02x%02x%02x\n",
data, datalen, hash[0] & 0xFFu, hash[1] & 0xFFu, hash[2] & 0xFFu, hash[3] & 0xFFu, hash[4] & 0xFFu,
hash[5] & 0xFFu, hash[6] & 0xFFu, hash[7] & 0xFFu);
char c[3];
for (int i = 0; i < 16; i++)
{
sprintf( c, "%02x", hash[i] & 0xFFu);
memcpy(out_digest+i*2, c, 2);
}
crypto_free_shash(alg);
return 0;
}
tested.

Related

Monitoring Network Packets Using Network Kernal Extension

I am building NKE(Network Kernal Extension) for filtering and modifying the packets on the fly. myipfilter_output_redirect callback gives mbuf_t pointer and based on the researched knowledge it has every information related to the network call.
I want to read the html from this mbuf_t and inject one css/html into it. how can I achieve it?
static errno_t myipfilter_output(void* cookie, mbuf_t* data, ipf_pktopts_t options) {
if (data)
log_ip_packet(data, kMyFiltDirOut);
return 0;
}
static errno_t myipfilter_input(void* cookie, mbuf_t* data, int offset, u_int8_t protocol) {
if (data)
log_ip_packet(data, kMyFiltDirIn);
return 0;
}
static void myipfilter_detach(void* cookie) {
/* cookie isn't dynamically allocated, no need to free in this case */
struct myfilter_stats* stats = (struct myfilter_stats*)cookie;
printf("UDP_IN %lu UDP OUT: %lu TCP_IN: %lu TCP_OUT: %lu ICMP_IN: %lu ICMP OUT: %lu OTHER_IN: %lu OTHER_OUT: %lu\n",
stats->udp_packets[kMyFiltDirIn],
stats->udp_packets[kMyFiltDirOut],
stats->tcp_packets[kMyFiltDirIn],
stats->tcp_packets[kMyFiltDirOut],
stats->icmp_packets[kMyFiltDirIn],
stats->icmp_packets[kMyFiltDirOut],
stats->other_packets[kMyFiltDirIn],
stats->other_packets[kMyFiltDirOut]);
g_filter_detached = TRUE;
}
static struct ipf_filter g_my_ip_filter = {
&g_filter_stats,
"com.xxx.NetworKext",
myipfilter_input,
myipfilter_output_redirect, // myipfilter_output,
myipfilter_detach
};
kern_return_t MyIPFilter_start () {
printf("MyIPFilter_start called");
int result;
result = ipf_addv4(&g_my_ip_filter, &g_filter_ref);
return result;
}
kern_return_t MyIPFilter_stop () {
printf("MyIPFilter_stop called");
ipf_remove(g_filter_ref);
return KERN_SUCCESS;
}
static errno_t myipfilter_output_redirect(void* cookie, mbuf_t* data, ipf_pktopts_t options)
{
// not printing all html and css tags
printf("myipfilter_output_redirect called");
unsigned char* dataString = NULL;
for (mbuf_t mb = *data; mb; mb = mbuf_next(mb))
{
dataString = mbuf_data(mb);
size_t len = mbuf_len(mb);
for (size_t i = 0; i < len; i++)
{
printf("%c", dataString[i]);
}
}
printf("dataString: %s", dataString);
}
I have made a sample repo if you can help here anything.
you should choose socket filter and in order to retrieve HTML payload you should read mbuf_t using mbuf_t data. Below method prints every bytes from the starts so put it in your sf_data_in_func call back.
print_mbuf_data(*data);
This would work for you.
static void print_mbuf_data(mbuf_t mb){
// unsigned char *tmp_buffer = (unsigned char *) mbuf_datastart(mb);
unsigned char *tmp_buffer = (unsigned char *) mbuf_data(mb);
unsigned long line = 0, index = 0, character = 0, hex_length = 0x80; // hex_length has limit of 64 decimal
unsigned long length = mbuf_len(mb);
unsigned char hex_temp [0x80]; // buffer has limit of 64 decimal
for (index = 0; index < length; index += 0x80)
{
memset(hex_temp, 0, hex_length);
line = length - index > 0x80 ? 0x80 : length - index;
for (character = 0; character < line; character++)
{
snprintf(((char *) hex_temp + strlen((char *) hex_temp)),
hex_length - strlen((char *) hex_temp), "%c", tmp_buffer[index + character]);
}
printf("%s", hex_temp);
}
}

retrieve information from a structure with ptrace

Here, I explain my problem, I am a beginner on the ptrace function and I would like to succeed in recovering the hard information of a structure.
For example with this command, I will have strace -e trace = fstat ls
a line: fstat (3, {st_mode = ..., st_size = ...}
and I would like to successfully retrieve the contents of the structure (st_mode) and (st_size).
I try this but to no avail:
int buffer(unsigned long long addr, pid_t child, size_t size, void *buffer)
{
size_t byte = 0;
size_t data;
unsigned long tmp;
while (byte < size) {
tmp = ptrace(PTRACE_PEEKDATA, child, addr + byte);
if ((size - byte) / sizeof(tmp))
data = sizeof(tmp);
else
data = size % sizeof(tmp);
memcpy((void *)(buffer + byte), &tmp, data);
byte += data;
}
}
and in params :
struct stat stat_i;
buffer(addr, pid, sizeof(stat_i), &stat_i);
printf("%lu", stat_i.st_size); -> fake value :/
Thank'ks !
From the man page,
PTRACE_PEEKTEXT, PTRACE_PEEKDATA
Read a word at the address addr in the tracee's memory,
returning the word as the result of the ptrace() call. Linux
does not have separate text and data address spaces, so these
two requests are currently equivalent. (data is ignored; but
see NOTES.)
Thus you must understand that tmp would hold the actually value that was read.
Your checks are wrong - you should set errno = 0 before the call and then check if it has changed. If it has - you've got an error. If it hasn't - you can be assured that tmp has the word from the remote process.
Try something like this:
int buffer(unsigned long long addr, pid_t child, size_t size, void *buffer)
{
size_t byte = 0;
size_t data;
unsigned long tmp;
// support for word aligned sizes only
if (size % sizeof(long) != 0)
return -1;
long * buffer_int = (long*) buffer;
while (byte < size) {
errno = 0;
tmp = ptrace(PTRACE_PEEKDATA, child, addr + byte);
if (errno)
return -1;
buffer_int[byte / sizeof(long)] = tmp;
byte += sizeof(long);
}
}

Send message through Ring (Circular) Buffer between Threads (in C)

I need to send a message from Main thread to my Created Thread using WinAPI and Ring Buffer.
I defined structures and wrote functions for my Ring buffer.
Ring Buffer - it contains head, tail, size and pointer to the structure Descriptor which has length of Data and data itself. As I need to send 2 parameters to CreateThread function, I created the third structure ThreadParams to keep 2 parameters.
I want to leave this structures how they are now, not changeable.
typedef struct _Descriptor
{
uint32_t dataLen;
void * data;
} Descriptor;
typedef struct _ringBuffer
{
Descriptor *bufferData;
int head;
int tail;
int size;
} ringBuffer;
typedef struct _ThreadParams
{
void * ptr1;
void * ptr2;
} ThreadParams;
There are my realisations of Ring Buffer functions:
void bufferFree(ringBuffer *buffer)
{
free(buffer->bufferData);
}
void ringInitialization(ringBuffer *buffer, int size)
{
buffer->size = size;
buffer->head = 0;
buffer->tail = 0;
buffer->bufferData = (Descriptor*)malloc(sizeof(Descriptor) * size);
}
int pushBack(ringBuffer *buffer, void * data) // fill buffer
{
buffer->bufferData[buffer->tail++] = *(Descriptor*)data;
if (buffer->tail == buffer->size)
{
buffer->tail = 0;
}
return 0;
}
int popFront(ringBuffer *buffer)
{
if (buffer->head != buffer->tail)
{
buffer->head++;
if (buffer->head == buffer->size)
{
buffer->head = 0;
}
}
return 0;
}
My main: I checked that I can send a few bytes (the memory is shared between threads), now I need to send a big message (> BUFF_SIZE) though Ring Buffer what I'm trying to do in while() cycle. Here is the question: how should I do it? My thing doesn't work because I catch an exception in printf() function (memory acces violation).
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <strsafe.h>
#include <stdint.h>
#define RING_SIZE 256
#define BUFFER_SIZE 1024
DWORD WINAPI HandleSendThread(LPVOID params);
uint8_t * getPointer(uint8_t *buffer, uint32_t index)
{
uint8_t * ptr = ((uint8_t*)buffer) + index * BUFFER_SIZE;
return ptr;
}
int main(int argc, char * argv[])
{
//Descriptor * ringData = (Descriptor *)malloc(sizeof(Descriptor) * RING_SIZE);
ringBuffer ring;
ringInitialization(&ring, RING_SIZE);
void * packetBuffer = malloc(BUFFER_SIZE * RING_SIZE);
uint8_t * currentBuffer = getPointer(packetBuffer, 0);
uint8_t * str = "Mr. and Mrs. Dursley, of number four, Privet Drive, were proud to say that they were perfectly normal, thank you very much. They were the last people you'd expect to be involved in anything strange or mysterious, because they just didn't hold with such nonsense. Mr.Dursley was the director of a firm called Grunnings, which made drills.He was a big, beefy man with hardly any neck, although he did have a very large mustache.Mrs.Dursley was thin and blonde and had nearly twice the usual amount of neck, which came in very useful as she spent so much of her time craning over garden fences, spying on the neighbors.The Dursleys had a small son called Dudley and in their opinion there was no finer boy anywhere.";
strcpy(currentBuffer, str);
ring.bufferData[0].data = currentBuffer;
ring.bufferData[0].dataLen = strlen(str);
int currentSize = 0;
int ringSize = RING_SIZE;
while(ring.bufferData[0].data != '\0')
{
for (int i = currentSize; i < ringSize; i + RING_SIZE)
{
pushBack(&ring, currentBuffer);
printf("h = %s, tail = %s, dataBuffer = %s\n", (char*)ring.head, (char*)ring.tail, (char*)ring.bufferData[i].data);
}
currentSize = ringSize;
ringSize = 2 * ringSize;
popFront(&ring);
}
ThreadParams params = { &ring, packetBuffer };
HANDLE MessageThread = 0;
MessageThread = CreateThread(NULL, 0, HandleSendThread, &params, 0, NULL);
if (MessageThread == NULL)
{
ExitProcess(MessageThread);
}
WaitForSingleObject(MessageThread, INFINITE);
CloseHandle(MessageThread);
system("pause");
return 0;
}
And my CreateThread function:
DWORD WINAPI HandleSendThread(LPVOID params)
{
ringBuffer * ring = ((ThreadParams*)params)->ptr1;
void * buffer = ((ThreadParams*)params)->ptr2;
//ring->bufferData[0].dataLen = sizeof(buffer) + sizeof(ring->bufferData[0])*1024;
printf("Shared memory check: ringBuffer data = \"%s\", \nlength = %d\n", (char*)ring->bufferData[0].data, ring->bufferData[0].dataLen);
return 0;
}
Your most immediate problem is the inconsistency between the code in pushBack(), which expects data to point to a Descriptor, and the code in your main function, which passes in a pointer to a string instead.
If you had declared pushBack() properly, i.e.,
void pushBack(ringBuffer *buffer, Descriptor * data)
{
buffer->bufferData[buffer->tail++] = *data;
if (buffer->tail == buffer->size)
{
buffer->tail = 0;
}
}
Then the compiler would have been able to warn you about the discrepancy.
You also have an infinite loop here:
for (int i = currentSize; i < ringSize; i + RING_SIZE)
You probably meant
for (int i = currentSize; i < ringSize; i += RING_SIZE)
... although it still doesn't look to me like it will do anything sensible. Nor do I understand the purpose of the outer loop, which compares a pointer to a character.
Found a solution
int main(int argc, char * argv[])
{
ringBuffer ring;
ringInitialization(&ring, RING_SIZE);
void * packetBuffer = malloc(BUFFER_SIZE * RING_SIZE);
Descriptor temp = { 0 };
uint8_t * currentBuffer = getPointer(packetBuffer, 0);
uint8_t * str = "Mr. and Mrs. Dursley, of number four, Privet Drive, were proud to say that they were perfectly normal, thank you very much. They were the last people you'd expect to be involved in anything strange or mysterious, because they just didn't hold with such nonsense. Mr.Dursley was the director of a firm called Grunnings, which made drills.He was a big, beefy man with hardly any neck, although he did have a very large mustache.Mrs.Dursley was thin and blonde and had nearly twice the usual amount of neck, which came in very useful as she spent so much of her time craning over garden fences, spying on the neighbors.The Dursleys had a small son called Dudley and in their opinion there was no finer boy anywhere.";
strcpy(currentBuffer, str);
temp.dataLen = strlen(str);
temp.data = currentBuffer;
pushBack(&ring, &temp);
ThreadParams params = { &ring, packetBuffer };
HANDLE MessageThread = 0;
MessageThread = CreateThread(NULL, 0, HandleSendThread, &params, 0, NULL);
if (MessageThread == NULL)
{
ExitProcess(MessageThread);
}
WaitForSingleObject(MessageThread, INFINITE);
CloseHandle(MessageThread);
system("pause");
return 0;
}
DWORD WINAPI HandleSendThread(LPVOID params)
{
ringBuffer * ring = ((ThreadParams*)params)->ptr1;
void * buffer = ((ThreadParams*)params)->ptr2;
Descriptor * temp = &ring->bufferData[ring->head];
for (int i = 0; i < temp->dataLen; i++)
{
printf("%c", ((char*)temp->data)[i]);
}
printf("\n");
return 0;
}

Memory comparison causes system halt

I am working on a kernel module and I need to compare two buffers to find out if they are equivalent. I am using the memcmp function defined in the Linux kernel to do so. My first buffer is like this:
cache_buffer = (unsigned char *)vmalloc(4097);
cache_buffer[4096] = '/0';
The second buffer is from a page using the page_address() function.
page = bio_page(bio);
kmap(page);
write_buffer = (char *)page_address(page);
kunmap(page);
I have printed the contents of both buffers before hand and not only to they print correctly, but they also have the same content. So next, I do this:
result = memcmp(write_buffer, cache_buffer, 2048); // only comparing up to 2048 positions
This causes the kernel to freeze up and I cannot figure out why. I checked the implementation of memcmp and saw nothing that would cause the freeze. Can anyone suggest a cause?
Here is the memcmp implementation:
int memcmp(const void *cs, const void *ct, size_t count)
{
const unsigned char *su1, *su2;
int res = 0;
for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
if ((res = *su1 - *su2) != 0)
break;
return res;
}
EDIT: The function causing the freeze is memcmp. When I commented it out, everything worked. Also, when I did I memcmp as follows
memcmp(write_buffer, write_buffer, 2048); //comparing two write_buffers
Everything worked as well. Only when I throw the cache_buffer into the mix is when I get the error. Also, above is a simplification of my actual code. Here is the entire function:
static int compare_data(sector_t location, struct bio * bio, struct cache_c * dmc)
{
struct dm_io_region where;
unsigned long bits;
int segno;
struct bio_vec * bvec;
struct page * page;
unsigned char * cache_data;
char * temp_data;
char * write_data;
int result, length, i;
cache_data = (unsigned char *)vmalloc((dmc->block_size * 512) + 1);
where.bdev = dmc->cache_dev->bdev;
where.count = dmc->block_size;
where.sector = location << dmc->block_shift;
printk(KERN_DEBUG "place: %llu\n", where.sector);
dm_io_sync_vm(1, &where, READ, cache_data, &bits, dmc);
length = 0;
bio_for_each_segment(bvec, bio, segno)
{
if(segno == 0)
{
page = bio_page(bio);
kmap(page);
write_data = (char *)page_address(page);
//kunmap(page);
length += bvec->bv_len;
}
else
{
page = bio_page(bio);
kmap(page);
temp_data = strcat(write_data, (char *)page_address(page));
//kunmap(page);
write_data = temp_data;
length += bvec->bv_len;
}
}
printk(KERN_INFO "length: %u\n", length);
cache_data[dmc->block_size * 512] = '\0';
for(i = 0; i < 2048; i++)
{
printk("%c", write_data[i]);
}
printk("\n");
for(i = 0; i < 2048; i++)
{
printk("%c", cache_data[i]);
}
printk("\n");
result = memcmp(write_data, cache_data, length);
return result;
}
EDIT #2: Sorry guys. The problem was not memcmp. It was the result of memcmp. When ever it returned a positive or negative number, the function that called my function would play with some pointers, one of which was uninitialized. I don't know why I didn't realize it before. Thanks for trying to help though!
I'm no kernel expert, but I would assume you need to keep this memory mapped while doing the comparison? In other words, don't call kunmap until after the memcmp is complete. I would presume that calling it before will result in write_buffer pointing to a page which is no longer mapped.
Taking your code in the other question, here is a rough attempt at incremental. Still needs some cleanup, I'm sure:
static int compare_data(sector_t location, struct bio * bio, struct cache_c * dmc)
{
struct dm_io_region where;
unsigned long bits;
int segno;
struct bio_vec * bvec;
struct page * page;
unsigned char * cache_data;
char * temp_data;
char * write_data;
int length, i;
int result = 0;
size_t position = 0;
size_t max_size = (dmc->block_size * 512) + 1;
cache_data = (unsigned char *)vmalloc(max_size);
where.bdev = dmc->cache_dev->bdev;
where.count = dmc->block_size;
where.sector = location << dmc->block_shift;
printk(KERN_DEBUG "place: %llu\n", where.sector);
dm_io_sync_vm(1, &where, READ, cache_data, &bits, dmc);
bio_for_each_segment(bvec, bio, segno)
{
// Map the page into memory
page = bio_page(bio);
write_data = (char *)kmap(page);
length = bvec->bv_len;
// Make sure we don't go past the end
if(position >= max_size)
break;
if(position + length > max_size)
length = max_size - position;
// Compare the data
result = memcmp(write_data, cache_data + position, length);
position += length;
kunmap(page);
// If the memory is not equal, bail out now and return the result
if(result != 0)
break;
}
cache_data[dmc->block_size * 512] = '\0';
return result;
}

libjpeg crash in jpeg_read_scanlines

When I run this code to load a jpeg file I get a crash in jpeg_read_scanlines
I'm using windows 7 64 bit with VC++ 2010
The image I'm loading is a 100x75 jpg image.
If you need any more details just ask
The crash message is:
Unhandled exception at 0x012db29e in LibTest.exe: 0xC0000005: Access violation writing location 0xcdcdcdcd.
void JPG_Load (const char *path, image_t *img)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
int infile;
JSAMPARRAY buffer;
int row_stride;
unsigned char *out;
infile = fopen(path,"rb");
if (infile == 0) {
memset (img, 0, sizeof(image_t));
return;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, (FILE *)infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
row_stride = cinfo.output_width * cinfo.output_components;
out = malloc(cinfo.output_width*cinfo.output_height*cinfo.output_components);
img->pixels = out;
img->width = cinfo.output_width;
img->height = cinfo.output_height;
img->bytesPerPixel = cinfo.out_color_components;
while (cinfo.output_scanline < cinfo.output_height) {
buffer = (JSAMPARRAY)out+(row_stride*cinfo.output_scanline);
jpeg_read_scanlines(&cinfo, buffer, 1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
}
image_t is defined as:
typedef struct {
int width;
int height;
int bytesPerPixel;
byte *pixels;
} image_t;
Don't do this.
buffer = (JSAMPARRAY)out+(row_stride*cinfo.output_scanline); // WRONG
You are casting to JSAMPARRAY, which is basically void **. The result is garbage, since that's not the kind of data you have: you have an array of bytes.
The jpeg_read_scanlines function, if you look at the documentation, does not take a pointer to your buffer. It takes a pointer to an array of scanlines, and each scanline is a pointer to row data.
while (cinfo.output_scanline < cinfo.output_height) {
unsigned char *rowp[1];
rowp[0] = (unsigned char *) out + row_stride * cinfo.output_scanline;
jpeg_read_scanlines(&cinfo, rowp, 1);
}
Recommendation: Adding a cast to fix a compiler error only works if you know the cast is correct. Don't cast to any type unless you know what the type is.

Resources