So I am trying to write a uint64_t return address to a buffer and then verify that the correct return address got written to the correct spot. Here is my code.
uint64_t new_ret = ret - 8 - 32 - 32 - 1001 (ret_buffer_offset sizeof(shellcode));
printf("new_ret :%lu\n", new_ret);
snprintf(&buffer[ret_buffer_offset], 8, "%s", new_ret);
// debug code
char buffer_debug[10];
uint64_t* buffer_uint = (uint64_t*)buffer_debug;
bzero(buffer_debug, 10);
strncpy(buffer_debug, &buffer[ret_buffer_offset], 8);
uint64_t ret_debug = *buffer_uint;
printf("ret debug: %lu\n", ret_debug);
the two printfs should output the same thing, but the bottom printf outputs a very different number. I'm not sure if the way I'm writing to the buffer is wrong or if the way I'm getting the value back is wrong. What is the issue here?
Thanks
CodePudding user response:
snprintf(&buffer[ret_buffer_offset], 8, "%s", new_ret);
buffer
now contains the string representation of your original value (or at least the first 8 bytes of the string representation). Your code then takes the first 8 bytes of this string and interprets that binary sequence as if it was a uint64_t
. Step through this chunk of code in a debugger and you'll see exactly where the value changes.
I'm not sure exactly what this code is trying to do, but it seems like it's doing more copying and conversion than necessary. If you have a pointer to where you want the value to go, you should be able to either do memcpy(ptr, &new_ret, sizeof(new_ret))
or possibly even *(uint64_t*)ptr = new_ret
if your platform allows potentially-misaligned writes. To print out the value for debugging, you'd use printf("%"PRIu64, *(uint64_t*)ptr)
.
CodePudding user response:
I like to use union
, but if you make a char
pointer (char*
) to point to the address of uint64_t
it will work.
Using pointer will be:
uint64_t new_ret = ret - 8 - 32 - 32 - 1001 (ret_buffer_offset sizeof(shellcode));
buffer = (char*) &new_ret;
Test the code below to use union and pointer:
#include <stdio.h>
#include <stdint.h>
int main(){
union {
uint64_t u64;
char str[8];
} handler;
handler.u64 = 65;
printf("Using union:\n");
printf(" uint64: %ld\n", handler.u64);
printf(" char*: %s\n", handler.str);
uint64_t u64 = 65;
char *str = (char*)&u64;
printf("Using pointer:\n");
printf(" uint64: %ld\n", u64);
printf(" char*: %s\n", str);
return 0;
}