Buffer Overflow to Modify the Return Address - c

I'm needing to modify the return address so I can call print_good function. I need an offset value, and a hex value to store to do so. The offset that I calculated from using obj is 0xcd, which was gotten 0x40074e(the puts function which I believe prints out try again) minus 400686(The address of the print_good function that I want to call). The hex value that I believe is correct is 400686, which is the address of the print_good value. Putting the offset value I got and the hex value I got doesn't give the correct answer.
I'm pretty sure the hex value is 0x400686, but correct me if I'm wrong. The offset value I believe could be off.
I'm given the code and the executable. I need to find the password which is an offset value and a hex value. I got the addresses using objdump and looking at its code.
If you want to try it yourself to help me, here's the file to download the executable:
The executable:
https://www.mediafire.com/file/disui6pwcb55ing/Ch3_07_CanaryBypass
The c code:
https://www.mediafire.com/file/yu3j3dxg476qy8c/Ch3_07_CanaryBypass.c
The c Code written here:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#define USERDEF 30
char msg[] =
"Stack canaries and non-executable stacks make stack exploitation difficult. Such\n"
"techniques, however, do not protect against return-oriented programming where\n"
"only the return addresses on the stack are targeted. In this level, you control\n"
"a single write into a vulnerable buffer in the function prompt_user. Overflow\n"
"the buffer to modify the return address beyond the stack canary so that it\n"
"points to a function of your choice. The level will prompt you with an offset\n"
"(in decimal) from the beginning of the buffer that will be written into followed\n"
"by a hexadecimal value that will be written there (e.g. scanf(\"%d %x\");).\n"
"The program will then write the hexadecimal value to a location computed\n"
"using the offset. To determine how close you are, examine the pointer\n"
"being used to write into the stack and how far away it is from the value\n"
"of $rsp when the retq instruction at the end of prompt_user is reached.\n\n";
void print_good() {
printf("Good Job.\n");
exit(0);
}
void print_msg() {
printf("%s",msg);
}
void prompt_user() {
char buffer[30];
int offset;
char *user_addr;
char **over_addr;
printf("Enter the password: ");
scanf("%d %lx", &offset, (unsigned long *) &user_addr);
over_addr = (char **) (buffer + offset);
*over_addr = user_addr;
}
int main(int argc, char *argv[]) {
print_msg();
prompt_user();
printf("Try again.\n");
return 0;
}

Related

How to print integers and memory addresses to the console using write()?

I am in a situation where I cannot use printf() to print to the console in C.
It's a university assignment and we're reimplementing malloc, calloc, free and realloc. I am using ubuntu and when I call printf(), it seg faults as printf() uses malloc in its implementation (according to my lecturer), so I can't use it and have to use write() instead.
So if I have a simple program, how can I print an integer and a pointer address to the console using write().
I have tried:
#include <unistd.h>
int main(void) {
int a = 12345;
int* ptr = &a;
// none of the following seem to work
write(2, &a, sizeof(a));
write(2, "\n", 1);
write(2, ptr, sizeof(ptr));
write(2, "\n", 1);
write(2, &ptr, sizeof(ptr));
write(2, "\n", 1);
return 0;
}
The output was
90
90
xZ???
Thanks, Juan
The int value 12345 is equal to 0x0000003039 (assuming 4-byte int).
On a little-endian system (like a standard x86 or x86-64 PC) it's stored in the sequence 0x39 0x30 0x00 0x00 0x00 0x00 0x00 0x00.
In ASCII encoding 0x39 is the character '9' and 0x30 is '0'.
So printing the value 12345 will print the two characters 90, and then some unprintable zeros.
You need to convert the values to text to be able to print them. Perhaps like this:
char value[128];
snprintf(value, sizeof value, "%d", a);
write(STDOUT_FILENO, value, strlen(value));
If you're not allowed to use even snprintf (or sprintf) then you need to come up with some other way to convert the number to text.
Decide on the format you want to output the number. As a hex number? Decimal number? In octal? In base64?
Write a conversion function between uintptr_t to a string. uintptr_t is the type that may be used to convert a pointer to a number.
Convert numbers to string.
Write the string.
The following program:
#include <unistd.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
char *uintptr_to_string(char *dest, size_t n, void *v0) {
uintptr_t v = (uintptr_t)v0;
for (int i = 0; i < sizeof(v) * 2; ++i) {
if (n-- == 0) return NULL;
const short idx = (v >> (sizeof(v) * CHAR_BIT - 4));
const char hex[] = "0123456789abcdef";
*dest++ = hex[idx];
v <<= 4;
}
return dest;
}
int main() {
char string[200];
int a;
char *end = uintptr_to_string(string, sizeof(string), &a);
printf("%018p\n", (void*)&a);
write(STDOUT_FILENO, "0x", 2);
write(STDOUT_FILENO, string, end - string);
write(STDOUT_FILENO, "\n", 1);
}
may output on godbolt:
0x00007ffffd3d0a9c
0x00007ffffd3d0a9c
I am in a situation where I cannot use printf() to print to the console in C. It's a university assignment and we're reimplementing malloc, calloc, free and realloc. I am using ubuntu
You are lucky. Ubuntu is mostly open source software,
So the code of printf, malloc etc... is inside GNU glibc (or musl-libc) whose source code (above syscalls(2) provided by the Linux kernel) you can read and study.
Read of course Advanced Linux Programming and Modern C (and later the C standard n1570).
Use gdb(1) and strace(1) to understand the behavior of your (or others) program.
If you compile with a recent GCC, be sure to use gcc -Wall -Wextra -g to get warnings and DWARF debug information for the GDB debugger. Once your code is correct, add -O2 to get compiler optimizations. If you want some formal proof of your code, consider using Frama-C.
Mention in your assignment the source code that you did actually read. Your teacher would appreciate.
Of course, you need to convert your int a; into a string buffer such as char buf[80];; avoid buffer overflows and other kinds of undefined behavior. You might not be allowed to use snprintf, but you surely can mimic its code and behavior. Converting an int to some ASCII string is an easy exercise (assuming you understand what a decimal number is).
The intuition is that for a small int x between 0 and 9 included, its decimal digit in ASCII is (char)('0'+x) or "0123456789"[x]. To convert a bigger number, use the % modulus and / integral division operators cleverly in a simple loop.
For IBM Z main frames using EBCDIC, it should be similar.
The full code is left as an exercise to the reader.
You need to multiply sizeof() by the size of a byte

C: buffer overflow, changing passed variables

I'm doing some exercises regarding buffer overflows and I am currently stumped as how to proceed further with one of them. This is the program code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
void reverb(char *msg, unsigned int len) {
unsigned char length = (unsigned char) len;
char buffer[250] = "Printed: ";
strcat(buffer + 9, msg);
if ((length > 75) || (length < 15)) {
fprintf(stderr, "Error: invalid string length");
exit(1);
}
else {
fprintf(stdout, "%s\n", buffer);
}
}
int main(int argc, char **argv) {
//argument check
if (argc != 2) {
fprintf(stderr, "Invalid arguments!\n");
return 1;
}
reverb(argv[1], strlen(argv[1]));
return 0;
}
So basically as obvious as it is, this program should just re-print the argument you gave to it. I obviously have to exploit one of the functions used, and I suspect the main culprit here is strcat. However, I'm faced with the issue of the length variable when I want to get my stack smashing done.
To be able to cause a segfault and successfully find a point for the overflow to happen, I need to pass an argument with a length of around 255+ (not sure on the current number right now but it's somewhere around that), which is not doable with my 75 char limit. Using gdb and setting a break point right after strcat, I am able to find the buffer's location in the memory (kinda easy, just the area filled with 0x41 since I spammed it with A's). length's location was kinda trickier, but here's the issue - it's located BEFORE the buffer, meaning I couldn't even overwrite it if I wanted. But, I somehow still need to overwrite it to get into the else branch, I think. And I've been stuck at that point, not seeing a way to proceed properly.
If the string is long - say 256 chars, the Length variable will be wrong. Use the suggestions in the comments to catch it.
The crash: the string copy will then copy all 256 chars onto the end of the string in buffer, which only can hold 250 bytes.
Move the strcpy() into the else.
Additional notes:
I ran this in my debugger (VS2015)
When passing in the 256 byte string and overrunning “buffer”, the variable “length” got clobbered, and its value changes from 0 to 69 (some character in my string). This caused the 75 char limit to fail and the buffer to be printed.

Why is this Overflow Occuring?

In the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_authentication(char *password) {
char password_buffer[16];
int auth_flag = 0;
strcpy(password_buffer, password);
if(strcmp(password_buffer, "brillig") == 0)
auth_flag = 1;
if(strcmp(password_buffer, "outgrabe") == 0)
auth_flag = 1;
return auth_flag;
}
int main (int argc, char *argv[]){
if(argc < 2){
printf("Usage: %s <password>\n", argv[0]);
exit(0);
}
if(check_authentication(argv[1])){
printf("\n-=-=-=-=-=-=-==-=-=-\n");
printf(" Access Granted\n");
printf("-=-=-=-=-=-=-==-=-=-\n");
}
else {
printf("Access Denied\n");
}
}
if I run something such as "AAAAAAAAAAAAAAAAAAAA", somehow something is overflowed and it causes the program to run as access granted. I'm confused because when I ran the gdb debugger, auth_flag was before password_buffer in the memory and it was never overflowed.
EDIT: I understand that the text doesn't fit into the buffer but I am experimenting with buffer overflows and how to exploit them in a controlled manner. Yes, we could make the array bigger but that's not the point of this
I was wondering if someone would be able to tell me why this is happening/what is being overflowed to cause this.
AAAAAAAAAAAAAAAAAAAA has size 20. You are then using strcpy to copy it to an char array of size 16. Try increasing your password_buffer size.
To avoid overflows, the size of the array pointed by destination
shall be long enough to contain the same C string as source (including
the terminating null character), and should not overlap in memory with
source.
http://www.cplusplus.com/reference/cstring/strcpy/
Because you are copying the input into a buffer that is too small (and for no reason). Your method could be implemented (without overflow) like
int check_authentication(const char *password) {
size_t len = strlen(password);
return strncmp(password, "brillig", len) == 0 ||
strncmp(password, "outgrabe", len) == 0;
}
I understand it overflows the buffet, but why would it cause access granted? (auth_flag >0)
Because auth_flag is the next int in memory after char password_buffer[16];. With some compilers (and operating systems), if you overflow password_buffer, there is a high probability that you modify auth_flag.
The memory is stored in the stack in a consecutive manner,
so there's a char[16] and an int that indicates whether the authentication passed successfully.
When you pass in a pointer to a buffer and copies it without boundary checking the local buffer, you risking overflowing your buffer and rewriting your stack variables.
When you input 'A' * 20, the first 16 'A' went into the buffer, and the remaining 4 'A's went into the int (usually sizeof(int) is 4 bytes).
So now, your int is not 0, it's:
auth = 0x41414141
since the ASCII code of 'A' is 0x41.
There's a really great article related to this -
http://insecure.org/stf/smashstack.html
It lays out the basics of stack overflows and gets a little more advanced later on.

Convert int to string in hex format

While I was trying to do a smash-stacking exploit just like this article: http://www.cs.wright.edu/people/faculty/tkprasad/courses/cs781/alephOne.html, I ran across a problem of needing to convert the stack pointer into a string.
I know how to print out an int in a hex format (using printf), but not how to store it as an internal string representation. I need to store it internally as a string so I can pass it into the memcpy function.
The theoretical function I need is "convertFromIntToHexCharStar" below.
unsigned long NOPSledPointer = get_sp() + 150;
char * address = convertFromIntToHexCharStar(NOPSledPointer);
It is intended to work with this function as the argument. It gives the stack pointer.
unsigned long get_sp(void) {
__asm__("movl %esp,%eax");
}
I want to convert the stack pointer into a hex char* so I can do memcpy like this:
char buffer[517];
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);
/* Fill the buffer with appropriate contents here */
memcpy((void*) buffer, (void*) address, 4);
I need to fill in the memory with the address represented in hex, because I know that it has worked in the past.
So, what I'm asking is for help with either converting it to a string, or another easier way to do this NOP sled (that is my real problem I'm trying to solve). I was going to fill in the address multiple times so it increases the odds of overwriting the return address on the stack, but for brevity I only gave one line of code writing "address" into "buffer."
I have already searched stackoverflow & google and couldn't find anything. Thanks in advance for your help!
snprintf solved my problem, since I know the size of the stack pointer in advance to be 4 bytes.
This site helped me:
http://www.cplusplus.com/reference/cstdio/snprintf/
And here is the code solution below, with some print statements that I used to make sure it worked correctly.
#include <stdio.h>
unsigned long get_sp(void)
{
__asm__("movl %esp,%eax");
}
int main()
{
unsigned long numberToConvert = get_sp();
char address[9];
snprintf(address, 9, "%08lX", numberToConvert);
printf("Number To Convert: %lu \n", numberToConvert);
printf("Expected hex number: %08lX \n", numberToConvert);
printf("Actual hex number: %s \n", address);
return 0;
}

Format String Attack in C

I'm studying a security unit and I'm attempting to understand format string attacks. Could somebody please attempt to explain this to me?
The following code is taken from: http://julianor.tripod.com/bc/tn-usfs.pdf:
/*
* fmtme.c
* Format a value into a fixed-size buffer
*/
#include <stdio.h>
int
main(int argc, char **argv)
{
char buf[100];
int x;
if(argc != 2)
exit(1);
x = 1;
snprintf(buf, sizeof buf, argv[1]);
buf[sizeof buf - 1] = 0;
printf("buffer (%d): %s\n", strlen(buf), buf);
printf("x is %d/%#x (# %p)\n", x, x, &x);
return 0;
}
As I understand it, the %n format specifier is used to read a specified address back into memory, then when printf pops values off the stack, it should read our address. I can't seem to pull this off.
In the document, the following example is provided:
perl -e 'system "./fmtme", "\x58\x74\x04\x08%d%n"'
Where did \x58\x74\x04\x08%d%n come from?
"\x58\x74\x04\x08%d%n" is the "shell code".
The exploit is explained very carefully in that document. I suppose it expects you to have some understanding of the typical layout of stack frames, which also is explained in the table . Keep in mind that stack addresses typically grows downwards, which means that a function call that "pops" more arguments than was actually passed to it will start reading local variables from the stack frame below its own. This is what this shell code exploits.
It puts an address in the first 4 bytes of buf (because snprintf prints it into there) and then it skips the x variable (from the frame below it) and finally reads the address from the first part of buf (but interpreted as a pointer) and write a value to it, via the %n format code.

Resources