How to read & write 1 byte into a particular memory address? - c

I'm trying to read a single byte from a particular memory address of a structure followed by writing that same byte into that same address. My goal is to load 64-byte memory associated with that memory address into the cache line.
I have a structure variable testStructure of size 12584. I tried the following code to read and write back 1 byte into the memory address,
unsigned char *p;
int forEachCacheLine = sizeof(testStructure);
printf("size of forEachCacheLine is %d\n", forEachCacheLine);
for (int i = 0; i<forEachCacheLine ; i+=64) {
printf("i is %d\n",i);
// read 1 byte
p=(unsigned char *)&testStructure+i;
printf("Read from %p byte is %hhx\n", &testStructure+i, p);
// write 1 byte
*(unsigned char *)(&testStructure+i)=p;
printf("Write into %p byte is %hhx\n\n", &testStructure+i, p);
}
upon running the code I get the following output:
size of forEachCacheLine is 12584
i is 0
Read from 0x7f5d42e71f80 byte is 80
Write into 0x7f5d42e71f80 byte is 80
i is 64
Read from 0x7f5d42f36980 byte is c0
Segmentation fault (core dumped)
As the output shows, the writing attempt in the first iteration was successful. However, the second iteration causes a Segfault. Any comments on why I'm getting this Segmentation fault?
I'm not quite sure if this is the correct approach to achieve my goal. But as of now, this is the only way I can think off. If this is an incorrect approach can someone please suggest an alternate approach?

While your for loop only seems to increment i by 64 bytes each iteration, your debug output shows that the second read is 805376 bytes beyond the first - which is out of bounds and likely causing the segfault. 805376 is 64 times 12584. What this means is that each iteration is incrementing p by 64 teststructure's instead of 64 chars.
Try replacing
p=(unsigned char *)&testStructure+i;
with
p=((unsigned char *)&testStructure)+i;
This ensures that &teststructure is a char* and not a teststructure* when we add i to it.
On most modern systems, there is little to no performance gain from explicitly caching memory like this. If you really want the memory in cache though - try using __builtin_prefetch() on each 64 bytes of teststructure. This is a GNU extension that populates a cache line. You should also pay attention to it's optional arguments.

Related

x86 assembly function stack

i am honing my assembly for buffer overflow exploitation.
Machine specs : kali linux 32 bit running in virtual box.
i am running this code
#include <stdio.h>
getinput(){
char buffer[8]; //allocating 8 bytes
gets(buffer); //read input
puts(buffer); // print;
}
main() {
getInput();
return 0 ;
}
My understaning is that when the function getInput() is invoked the following happens :
1 - the address of the next instruction in main is pushed on the stack.
2 - ebp register is pushed on the stack.
3 - 8 bytes are allocated on the stack for the buffer.
That a total of 16 bytes.. but
As you can see in the image , just before reading the input in the getInput() function
it shows a total of 24 bytes of the stack.
specifically, i don't know why there is an extra 0x0000000 on the top of the stack
moreover, when i try to over-write the return address by inputing something like (ABCDABCDABCDABCD[desired address for target program]) it justs over-writes everything.
And if i try to input something like \xab\xab\xab\xab it gives a segementation fault , although this is only 4 bytes and should fit perfectly into the 8 bytes buffer.
Thank you in advance.
In real life buffer overflow attacks, you never know the size of the stack frame. If you discover a buffer overflow bug, it's up to you to determine the offset from the buffer start to the return address. Treat your toy example exactly like that.
That said, the structure of the stack frame can be driven by numerous considerations. The calling convention might call for specific stack alignment. The compiler might create invisible variables for its own internal bookkeeping, which may vary depending on compiler flags, such as the level of optimization. There might be some space for saved caller registers, the number of which is driven by the register usage of the function itself. There might even be a guard variable specifically to detect buffer overflows. In general, you can't deduce the stack frame structure from the source alone. Unless you wrote the compiler, that is.
After diassembling the getInput routin , it turned out that the extra 4 bytes came from the compiler pushing $ebx on the stack for some reason.
After testing with various payloads , it appeared that i was not considering the deceptive null byte that is added at the end of the string. so i only need to add one extra byte to mitigate the effect of the null byte.
The proper payload was : printf "AAAAAAAAAAAAA\xc9\x61\x55\x56" | ./test

Attempting to parse a WAV file, memcpy results are unexpected

Assume that I have a small WAV file I've opened and dumped as a array of char for processing.
Right now, I am attempting to memcpy the fmt chunk ID into a 4 byte buffer.
char fmt[4];
memcpy(fmt_chunk_id, raw_file + 12, sizeof(char) * 4);
From my understanding of memcpy, this will copy the 4 bytes starting at offset 12 into fmt. However, when I go to debug the program I get some very strange output:
It seems to copy the fmt section correctly, but now for some reason I have a bunch of garbage after it. Interestingly, this garbage comes before format at offset bytes 0 (RIFF), and 8 (WAVE). It is a little endian file (RIFF).
I can't for the life of me figure out why I'm getting data from the beginning of the buffer at the end of this given that I only copied 4 bytes worth of data (which should exactly fit the first 4 characters f m t and space).
What is going on here? The output seems to indicate to me I'm somehow over-reading memory somewhere - but if that was the case I'd expect garbage rather than the previous offset's data.
EDIT:
If it matters, the data type of raw_file is const char* const.
The debugger is showing you an area of memory which has been dynamically allocated on the stack.
What is in all probability happening is that you read data from the file, and even if you asked to read, say, 50 bytes, the underlying system might have decided to read more (1024, 2048, or 4096 bytes usually). So those bytes passed around in memory, likely some on the stack, and that stack is being reused by your function now. If you asked to read more than those four bytes, then this is even more likely to happen.
Then the debugger sees that you are pointing to a string, but in C strings run until they get terminated by a zero (ASCIIZ). So what you're shown is the first four bytes and everything else that followed, up to the first 0x00 byte.
If that's important to you, just
char fmt[5];
fmt[4] = 0;
// read four bytes into fmt.
Now the debugger will only show you the first four bytes.
But now you see why you should always scrub and overwrite sensitive information from a memory area before free()ing it -- the data might remain there and even be reused or dumped by accident.

Read memory in C

I work on a microcontroller,
and I want to read the contents of the memory after the execution of a code.
I know the address of the memory to read and the size
I tried this method:
const volatile unsigned char *const mem_start = 0xd0000000;
#define size ((ptrdiff_t)0x1c000)
unsigned char buff[size];
ptrdiff_t j;
for(j =0 ; j< sizeof(buff) ; j++)
buff[i]= *(mem_start + j);
I am looking for another method to read the memory without copying it in a buffert, in the same memory that I want to read it, risk crushing what I'm looking for. and that the buff may overlap for lack of space
In the statement
...= *(mem_start + j);
you are reading memory. So what more do you want ?
By the way, why didn't you use
mem_start[j]; ??
You can allocate memory with malloc(), or as you have, on the stack. There is no overlap between the two. memmove() can be used if you do have overlap between source and destination; otherwise, memcpy() will suffice.
The expression:
*(mem_start + j)
or the more conventional
mem_start[j]
is a 'read' operation, when it is used, say, on the right-hand side of an assignment, or as a parameter in a function call.
So, instead of your own code line:
buff[j] = *(mem_start + j); // I'm assuming 'buff[i]' was a typo
which reads from one memory location into another, you could do something like:
printf("%hhx", mem_start[j]);
which will read the byte from mem_start at offset j and output it to stdout as a hexadecimal representation of the byte value. Put that in a loop (like you already have it) and you will effectively read from memory, without copying what you are reading into a 2nd buffer.
Based on some of your comments, I'm assuming that having the memory contents displayed on screen will suit your needs. And based on what you say the memory that you want to display will be, I'm assuming that hexadecimal output is suitable. But there are other choices, like reading from the source memory buffer into a file, or outputting the raw byte values (instead of a representation of those values), etc.
Note that not every combination of input and output is useful, though. Outputting raw byte values to the terminal screen is likely to produce less-than-useful results, and depending on what you want to do with the data you read out, a file full of hexadecimal representation of the source bytes might not be useful either. Pick the output destination and output format to suit your needs.

Character array in C(Puts vs printf)

I have some doubts regarding character array in C, I have a character array of size 1, logic says that when I input more than 2 characters, I should be getting a segmentation fault, However puts prints out the array properly whereas printf prints some parts of the array along with garbage value, Why is this happening
#include<stdio.h>
int main()
{
int i;
char A[1];
printf("%d\n",(int)sizeof(A));
gets(A);
puts(A);
for(i=0;i<8;i++)
{
printf("%c\n",A[i]);
}
}
O/P:
1
abcdefg
abcdefg
a
f
g
To add to this I have to type in multiple characters of the array size in the program to throw a segmentation fault. Is it because of the SFP in the stack? The size of SFP is 4 bytes Please correct me if I'm wrong
1
abcdefghijklmnop
abcdefghijklmnop
a
f
g
h
Segmentation fault
OK, others explained it in high-level language and elder's expierence.
I would like to explain your situations in the assembly layer.
You know why your first situation ran without accident?
Because your buffers overflow does NOT destory other processes's memory, So the OS does't signal a Segmentation fault to your process.
And why your stack's length is more than your array's size?
Because of the aligning. Many OS reqiures a stack frame aligning x bytes to implement efficient addressing.
x is machine-dependent.
e.g, If x is 16 bytes.
char s[1] will lead the stack to 16 byte;
char s[17] will lead the stack to 32byte.
Actually even when you write only one character, it's still buffer overflow, because gets() will write a null character to the array.
Buffer overflow doesn't necessarily mean segmentation fault. You can't rely on undefined behavior in any ways. Possibly it just took the program several times to break the memory that it shouldn't write.
It seems that you have known that gets() is dangerous and should be avoided, I added this just in case.

Need help with malloc in C programming. It is allocating more space than expected

Let me preface this by saying that i am a newbie, and im in a entry level C class at school.
Im writing a program that required me to use malloc and malloc is allocating 8x the space i expect it to in all cases. Even when just to malloc(1), it is allocation 8 bytes instead of 1, and i am confused as to why.
Here is my code I tested with. This should only allow one character to be entered plus the escape character. Instead I can enter 8, so it is allocating 8 bytes instead of 1, this is the case even if I just use a integer in malloc(). Please ignore the x variable, it is used in the actual program, but not in this test. :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (int argc ,char* argv[]){
int x = 0;
char *A = NULL;
A=(char*)malloc(sizeof(char)+1);
scanf("%s",A);
printf("%s", A);
free(A);
return 0;
}
A=(char*)malloc(sizeof(char)+1);
is going to allocate at least 2 bytes (sizeof(char) is always 1).
I don't understand how you are determining that it is allocating 8 bytes, however malloc is allowed to allocate more memory than you ask for, just never less.
The fact that you can use scanf to write a longer string to the memory pointed to by A does not mean that you have that memory allocated. It will overwrite whatever is there, which may result in your program crashing or producing unexpected results.
malloc is allocating as much memory as you asked for.
If you can read more than the allocated bytes (using scanf) it's because scanf is reading also over the memory you own: it's a buffer overflow.
You should limit the data scanf can read this way:
scanf( "%10s", ... ); // scanf will read a string no longer than 10
Im writing a program that required me
to use malloc and malloc is allocating
8x the space i expect it to in all
cases. Even when just to malloc(1), it
is allocation 8 bytes instead of 1,
and i am confused as to why.
Theoretically speaking, the way you do things in the program, is not allocating 8 bytes.
You can still type in 8 bytes (or any number of bytes) because in C there is no check, that you are still using a valid place to write.
What you see is Undefined Behaviour, and the reason for that is that you write in memory that you shouldn't. There is nothing in your code that stops the program after n byte(s) you allocated have been used.
You might get Seg Fault now, or later, or never. This is Undefined Behaviour. Just because it appears to work, does not mean it is right.
Now, Your program could indeed allocate 8 bytes instead of 1.
The reason for that is because of Alignment
The same program might allocate a different size in a different machine and/or a different Operating System.
Also, since you are using C you don't really need to cast. See this for a start.
In your code, there is no limit on how much data you can load in with scanf, leading to a buffer overflow (security flaw/crash). You should use a format string that limits the amount of data read in to the one or two bytes that you allocate. The malloc function will probably allocate some extra space to round the size up, but you should not rely on that.
malloc is allowed to allocate more memory than you ask for. It's only required to provide at least as much as you ask for, or fail if it can't.
using malloc or creating a buffer on the stack will allocate memory in words.
On a 32-bit system the word size is 4 bytes, so when you ask for
A=(char*)malloc(sizeof(char)+1);
(which is essentially A=(char*)malloc(2);
the system will actually give you 4 bytes. On a 64-bit machine you should get 8 bytes.
The way you use scanf there is dangerous as it will overflow the buffer if a string greater than the allocated size leaving a heap overflow vulnerability in your program. scanf in this case will attempt to stuff a string of any length in to that memory so using it to count the allocated size will not work.
What system are you running on? If it's 64 bit, it is possible that the system is allocating the smallest possible unit that it can. 64 bits being 8 bytes.
EDIT: Just a note of interest:
char *s = malloc (1);
Causes 16 bytes to be allocated on iOS 4.2 (Xcode 3.2.5).
If you enter 8 if will just allocate 2 bytes sizeof(char) == 1 (unless you are on some obscure platform) and you will write you number to that char. Then on printf it will output the number you stored in there. So if you store the number 8 it'll display 8 on the command line. It has nothing to do with the count of chars allocated.
Unless of course you looked up in a debugger or somewhere else that it is really allocating 8 bytes.
scanf has no idea how big the target buffer actually is. All it knows is the starting address of the buffer. C does no bounds checking, so if you pass it the address of a buffer sized to hold 2 characters, and you enter a string that's 10 characters long, scanf will write those extra 8 characters to the memory following the end of the buffer. This is called a buffer overrun, which is a common malware exploit. For whatever reason, the six bytes immediately following your buffer aren't "important", so you can enter up to 8 characters with no apparent ill effects.
You can limit the number of characters read in a scanf call by including an explicit field width in the conversion specifier:
scanf("%2s", A);
but it's still up to you to make sure that target buffer is large enough to accomodate that width. Unfortunately, there's no way to specify the field width dynamically as there is with printf:
printf("%*s", fieldWidth, string);
because %*s means something completely different in scanf (basically, skip over the next string).
You could use sprintf to build your format string:
sprintf(format, "%%%ds", max_bytes_in_A);
scanf(format, A);
but you have to make sure the buffer format is wide enough to hold the result, etc., etc., etc.
This is why I usually recommend fgets() for interactive input.

Resources