Bypassing stack guard- Buffer overflow - c++

I am taking a secure computer system course and I am very new to the subject. I am having a problem with an assignment where I need to get a shell by overflowing the buffer in a target program (target.cc). I cannot make any changes in target.cc but I can send the parameters to the target file.
here is the code.
#include <cstdio>
#include <cstring>
#include <cstdlib>
class SubStringReference
{
const char *start;
size_t len;
public:
SubStringReference(const char *s, size_t l) : start(s), len(l) { }
virtual ~SubStringReference() { }
virtual const char *getStart() const { return start; }
virtual int getLen() const { return len; }
};
void print_sub_string(const SubStringReference& str)
{
char buf[252];
if (str.getLen() >= sizeof buf)
{
// Only copy sizeof(buf) - 1 bytes plus a null
memcpy(buf, str.getStart(), sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0'; // null-terminate
}
else
{
printf("by passed mem check\n");
// The length is less than the size of buf so just string copy.
strcpy(buf, str.getStart());
buf[str.getLen()] = '\0'; // null-terminate to get just the substring
}
puts(buf);
}
int main(int argc, char **argv)
{
if (argc != 4)
{
fprintf(stderr, "Usage: %s STRING START LENGTH\n", argv[0]);
return 1;
}
const char *s = argv[1];
int total_len = strlen(s);
int start = atoi(argv[2]);
int len = atoi(argv[3]);
if (start < 0 || start >= total_len)
{
fputs("start is out of range!\n", stderr);
return 1;
}
if (len < 0 || start + len > total_len)
{
fputs("length is out of range!\n", stderr);
return 1;
}
SubStringReference str(s + start, len);
print_sub_string(str);
return 0;
}
Since this program is stackguard protected the program gets aborted before returning. Is there any other way that i can overflow the buffer and get a shell??
Thanks.
Edit - I am running this on a Qemu arm emulator with g++ compiler

The vulnerability can be exploited by overflowing the buffer and overwriting the address of str.getLen() function so as to point to the shell code. Since the canary check is done at the end of the function, shell is got before the canary is checked.

Related

Using strtok and get "cannot convert 'char*' to 'char**' in assignment"

I am trying to make a program that reads a string from a file in SPIFFS with 4 tab-separated things and then processes it into four char arrays to be used in another function. However, I get the error cannot convert 'char*' to 'char**' in assignment. Is there any idea why? Here's my code:
#include <string.h>
#include "FS.h"
#include "AdafruitIO_WiFi.h"
char *ssid;
char *pass;
char *aiduser;
char *aidkey;
// comment out the following two lines if you are using fona or ethernet
#include "AdafruitIO_WiFi.h"
//AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);
void setupWifi(char* *aiduser, char* *aidkey, char* *ssid, char* *pass){
#define WIFIFILE "/config.txt"
int addr = 0;
bool spiffsActive = false;
if (SPIFFS.begin()) {
spiffsActive = true;
}
File f = SPIFFS.open(WIFIFILE, "r");
String str;
while (f.position()<f.size())
{
str=f.readStringUntil('\n');
str.trim();
}
// Length (with one extra character for the null terminator)
int str_len = str.length() + 1;
// Prepare the character array (the buffer)
char char_array[str_len];
// Copy it over
str.toCharArray(char_array, str_len);
const char s[2] = {9, 0};
/* get the first token */
aiduser = strtok(char_array, s);
aidpass = strtok(NULL, s);
ssid = strtok(NULL, s);
pass = strtok(NULL, s);
/* walk through other tokens
while( token != NULL ) {
printf( " %s\n", token );
token = strtok(NULL, s);
}*/
// RESULT: A thingy
}
void setup(){
setupWifi(&aiduser, &aidkey, &ssid, &pass);
AdafruitIO_WiFi io(aiduser, aidkey, ssid, pass);}
Also, I can't run the setupWifi function unless it is in setup or loop, but I can't make it in another setup because this is #included into another main file.
You get this error because of this:
void setupWifi(char* *aiduser, char* *aidkey, char* *ssid, char* *pass)
{
...
aiduser = strtok(char_array, s);
aidpass = strtok(NULL, s);
ssid = strtok(NULL, s);
pass = strtok(NULL, s);
}
This variables are double pointers, strtok returns a pointer to char, those
are not compatible types.
Because strtok returns char_array + some_offset and char_array is a local
variable in setupWifi, you need to do a copy for each of them and return the
copy instead. You can do it with strdup.
*aiduser = strdup(strtok(char_array, s));
*aidpass = strdup(strtok(NULL, s));
*ssid = strdup(strtok(NULL, s));
*pass = strdup(strtok(NULL, s));
I encourage you to always check the return value of strdup, because it can
return NULL.1
If your system does not have strdup, then you can write your own:
char *strdup(const char *text)
{
if(text == NULL)
return NULL;
char *copy = calloc(strlen(text) + 1, 1);
if(copy == NULL)
return NULL;
return strcpy(copy, text);
}
One last thing:
void setupWifi(char* *aiduser, char* *aidkey, char* *ssid, char* *pass);
It looks really awkward, never seen declaring double pointer this way. Much
easier to read would be
void setupWifi(char **aiduser, char **aidkey, char **ssid, char **pass);
Fotenotes
1While the syntax is correct, I still consider this bad practice,
because you should always check the return values of functions that return
pointers. If they return NULL, you cannot access the memory. This adds a
little bit of more code, but your program will not die of segfaults and it can
recover from the errors.
I'd also change your function to return 1 on success, 0 otherwise:
int parse_and_set(char *txt, const char *delim, char **var)
{
if(delim == NULL || var == NULL)
return 0;
char *token = strtok(txt, delim);
if(token == NULL)
return 0;
token = strdup(token);
if(token == NULL)
return NULL;
*var = token;
return 1;
}
void init_parse(char ***vars, size_t len)
{
for(size_t i = 0; i < len; ++i)
**(vars + i) = NULL;
}
int cleanup_parse(char ***vars, size_t len, int retval)
{
for(size_t i = 0; i < len; ++i)
{
free(**(vars + i));
**(vars + i) = NULL;
}
}
int setupWifi(char **aiduser, char **aidkey, char **ssid, char **pass)
{
if(aiduser == NULL || aidkey == NULL || ssid == NULL || pass == NULL)
return 0;
...
/* get the token token */
char **vars[] = { aiduser, aidkey, ssid, pass };
size_t len = sizeof vars / sizeof *vars;
init_parse(vars, len);
if(parse_and_set(char_array, s, aiduser) == 0)
return cleanup_parse(vars, len, 0);
if(parse_and_set(NULL, s, aidpass) == 0)
return cleanup_parse(vars, len, 0);
if(parse_and_set(NULL, s, ssid) == 0)
return cleanup_parse(vars, len, 0);
if(parse_and_set(NULL, s, pass) == 0)
return cleanup_parse(vars, len, 0);
...
return 1;
}

How do I modify strcat so that it wouldn't edit str1

Why does strcat gives me its version of str1? As far as I know there has to be & thing before paramatater in function prototype and implementation if you want to get it editted, but I don't see it here.
char *strcat( char *str1, const char *str2 );
How do I edit this function so that it would only return new string but leave out the ones I give it?
My try
char *strApp(char *dest, const char *src)
{
size_t i,j;
size_t k = 0;
for (i = 0; dest[i] != '\0'; i++);
char rdest[100];
do {
rdest[k] = dest[k];
} while(++k<=i);
for (j = 0; src[j] != '\0'; j++)
rdest[i+j] = src[j];
rdest[i+j] = '\0';
return rdest;
}
It damages second string. Could anyone give me safe and correct version? Thanks in advance.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strApp(const char *s1, const char *s2)
{
char *pointer = malloc(strlen(s1) + strlen(s2) + 1);
if (pointer == NULL)
{
perror("failed to allocate memory");
exit(EXIT_FAILURE);
}
return strcat(strcpy(pointer, s1), s2);
}
int main()
{
char *s1 = "original";
char *s2 = " modified";
char *s3 = strApp(s1, s2);
printf("%s\n", s1);
printf("%s\n", s2);
printf("%s\n", s3);
free(s3);
return 0;
}
Just trying to point out you don't need to completely rewrite strcat() to get what you want.
strcat is, by definition, altering the target. If you don't want to, you should make a copy yourself in a target memory location you allocate yourself.
You've tagged your question with both C and C++. I'm providing a C solution. Adjustments may be needed for C++.
#include <stdlib.h>
#include <string.h>
char* strdupcat(const char* s1, const char* s2) {
size_t s1_len = strlen(s1);
size_t s2_len = strlen(s2);
char* s = malloc(s1_len + s2_len + 1);
if (s == NULL)
return NULL;
{
char* s_end = s;
s_end = mempcpy(s_end, s1, s1_len);
s_end = mempcpy(s_end, s2, s2_len);
*s_end = '\0';
}
return s;
}
Example usage:
#include <stdio.h>
int main() {
char* s = strdupcat("abc", "def");
if (s == NULL) {
perror("Can't concatenate");
return EXIT_FAILURE;
}
puts(s);
free(s);
return EXIT_SUCCESS;
}
This function is used similarly to strdup.
DESCRIPTION
The strdupcat() function returns a pointer to a new string which is a duplicate of the string s1 with a duplicate of string s2 appended. Memory for the new string is obtained with malloc(3), and can be freed with free(3).
RETURN VALUE
The strdupcat() function returns a pointer to the duplicated string, or NULL if insufficient memory was available.
ERRORS
ENOMEM Insufficient memory available to allocate the new string.
You can use strerror or perror to obtain an error message when strdupcat() returns NULL.
Here's a version that accepts an arbitrary number of arguments:
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
char* strdupcatmany(int dummy, ...) {
#define strdupcatmany(...) strdupcatmany(0, __VA_ARGS__, NULL)
size_t len = 0;
char* s;
char* s_dst;
const char* s_src;
va_list ap;
va_start(ap, dummy);
while (1) {
s_src = va_arg(ap, const char*);
if (s_src == NULL)
break;
len += strlen(s_src);
}
va_end(ap);
s = malloc(len + 1);
if (s == NULL)
return NULL;
s_dst = s;
va_start(ap, dummy);
while (1) {
s_src = va_arg(ap, const char*);
if (s_src == NULL)
break;
s_dst = stpcpy(s_dst, s_src);
}
va_end(ap);
*s_dst = '\0';
return s;
}
For example,
#include <stdio.h>
int main() {
char* s = strdupcatmany("abc", "def", "ghi");
if (s == NULL) {
perror("Can't concatenate");
return EXIT_FAILURE;
}
puts(s);
free(s);
return EXIT_SUCCESS;
}
Note: I don't know how portable __VA_ARGS__ args is.

Readline: How to list all autocomplete matches on double tab?

I'm using "readline" library to create a console interface for my program. I'm able to autocomplete words using tab, but when I have words that share the same prefix like (car, card, carbon) it always chooses the shortest one. Here's my program (mostly taken from link):
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <iostream>
const char *words[] = {"add", "remove", "rm", "update", "child", "children", "wife", "wifes"};
void *xmalloc (int size)
{
void *buf;
buf = malloc (size);
if (!buf)
{
fprintf (stderr, "Error: Out of memory. Exiting.\n");
exit (1);
}
return buf;
}
char *dupstr (const char *str)
{
char *temp;
temp = (char *) xmalloc (strlen (str) + 1);
strcpy (temp, str);
return (temp);
}
char *my_generator (const char *text, int state)
{
static int list_index, len;
const char *name;
if (!state)
{
list_index = 0;
len = strlen (text);
}
while (name = words[list_index])
{
list_index++;
if (strncmp (name, text, len) == 0) return dupstr (name);
}
// If no names matched, then return NULL.
return ((char *) NULL);
}
static char **my_completion (const char *text, int start, int end)
{
char **matches = (char **) NULL;
if (start == 0)
{
matches = rl_completion_matches ((char *) text, &my_generator);
}
else rl_bind_key ('\t', rl_abort);
return matches;
}
int main (int argc, char *argv[])
{
char *buf;
rl_attempted_completion_function = my_completion;
while ((buf = readline(">> ")) != NULL)
{
rl_bind_key ('\t', rl_complete);
if (strcmp (buf, "exit") == 0) break;
else if (buf[0] == '\0') continue;
else
{
std::cout << buf << std::endl;
add_history (buf);
}
}
free (buf);
return 0;
}
Is it possible to list all matches on double tab just like in ubuntu terminal?
I managed to get it to work by commenting out these two lines:
rl_bind_key ('\t', rl_complete);
and:
else rl_bind_key ('\t', rl_abort);
The default completion behaviour of readline works exactly like in ubuntu terminal, one tab to complete and two tabs to list possible completions. Not sure though what's the default completion function that's binded with the tab key, from the documentation i thought it was rl_possible_completions but it didn't give the same results.
Also i added the following line to my_completion function to prevent adding space at the end of the matched word:
rl_completion_append_character = '\0';
I removed dupstrfunction it and replaced it with the native strdup function instead (this has nothing to do with the auto complete problem, it's just to remove unnecessary code).
This is the final code:
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <iostream>
const char *words[] = {"add", "remove", "rm", "update", "child", "children", "wife", "wives"};
// Generator function for word completion.
char *my_generator (const char *text, int state)
{
static int list_index, len;
const char *name;
if (!state)
{
list_index = 0;
len = strlen (text);
}
while (name = words[list_index])
{
list_index++;
if (strncmp (name, text, len) == 0) return strdup (name);
}
// If no names matched, then return NULL.
return ((char *) NULL);
}
// Custom completion function
static char **my_completion (const char *text, int start, int end)
{
// This prevents appending space to the end of the matching word
rl_completion_append_character = '\0';
char **matches = (char **) NULL;
if (start == 0)
{
matches = rl_completion_matches ((char *) text, &my_generator);
}
// else rl_bind_key ('\t', rl_abort);
return matches;
}
int main (int argc, char *argv[])
{
char *buf;
rl_attempted_completion_function = my_completion;
while ((buf = readline(">> ")) != NULL)
{
// rl_bind_key ('\t', rl_complete);
if (strcmp (buf, "exit") == 0) break;
else if (buf[0] == '\0')
{
free (buf);
continue;
}
else
{
std::cout << buf << std::endl;
add_history (buf);
}
free (buf);
buf = NULL;
}
if (buf != NULL) free (buf);
return 0;
}
The answer by razzak is almost correct, but this NULL must be added at the end of array of strings:
const char *words[] = {"add", "remove", "rm", "update", "child", "children", "wife", "wives", NULL};
Some changes for nonwarning compilation in my_generator() function:
while ((name = words[list_index++]))
{
if (strncmp (name, text, len) == 0) return strdup (name);
}

Random Bytes added to an end of a buffer

I was making a re-creation of some System.IO functions from that class.
When I setup a buffer and allocate n number of bytes it'll read bytes to that and then add random bytes to the end of that buffer.
For example:
My Main:
int main(int argc, char *args[])
{
SetConsoleTitle(TEXT("Stream Test."));
cout<<"Press any Key to begin reading.";
cin.get();
const char* data = File::ReadAllBytes(args[1]);
Stream* stream = new Stream(data);
char* magic = new char[8];
stream->Read(magic, 0, 8);
magic[8] = '\0';
cout<<magic<<endl<<endl;
delete[]data;
cout<<"Press any key to quit.";
cin.get();
return 0;
}
and here is my System::IO namespace + stream class:
namespace System
{
namespace IO
{
class File
{
public:
static char* ReadAllBytes(const char *name)
{
ifstream fl(name, ifstream::in|ifstream::binary);
fl.seekg( 0, ifstream::end );
size_t len = fl.tellg();
char* ret = new char[len+1];
ret[len] = '\0';
fl.seekg(0);
fl.read(ret, len);
fl.close();
return ret;
}
//not sure of this use yet.
static size_t fileSize(const char* filename)
{
ifstream in(filename, ifstream::in | ifstream::binary);
in.seekg(0, ifstream::end);
return in.tellg();
}
};
class Stream
{
public:
const char *_buffer;
__int64 _origin;
__int64 _position;
__int64 _length;
__int64 _capacity;
bool _expandable;
bool _writable;
bool _exposable;
bool _isOpen;
static const int MemStreamMaxLength = 2147483647;
Stream()
{
InitializeInstanceFields();
}
Stream(const char *buffer)
{
_buffer = buffer;
_length = strlen(_buffer);
_capacity = _length;
_position = 0;
_origin = 0;
_expandable = false;
_writable = true;
_exposable = true;
_isOpen = true;
}
int ReadByte()
{
if (_position >= _length)
return -1;
return _buffer[_position++];
}
void Read(char* &buffer, int offset, int length)
{
if((_position + offset + length) <= _length)
{
memcpy( buffer, _buffer + (_position + offset), length );
_position += length;
}
}
private:
void InitializeInstanceFields()
{
_origin = 0;
_position = 0;
_length = 0;
_capacity = 0;
_expandable = false;
_writable = false;
_exposable = false;
_isOpen = false;
}
};
}
}
This is what ends up happening:
Can anyone explain why this happens, how I can fix, or anything else? I'm new to C++ so any explanations would help. Also please don't criticize my scripting, I know it may be bad, outdated, deprecated, etc. but I'm open to learning and any helping advice goes for the better. :)
You can only use operator << (char *) on C-style strings, not arbitrary arrays of characters. How would you expect it to know how many characters to output?
I would guess the file was not opened correctly and thus the magic buffer is not set at all which leaves it with initialized junk data:
If the constructor is not successful in opening the file, the object
is still created although no file is associated to the stream buffer
and the stream's failbit is set (which can be checked with inherited
member fail).
http://www.cplusplus.com/reference/fstream/ifstream/ifstream/
Try adding more error checking along the way (using cout), especially when opening and reading the buffer. Perhaps set the magic buffer to zero or something recognizable that is overwritten when successful.

simulate ulltoa() with a radix/base of 36

I need to convert an unsigned 64-bit integer into a string. That is in Base 36, or characters 0-Z. ulltoa does not exist in the Linux manpages. But sprintf DOES. How do I use sprintf to achieve the desired result? i.e. what formatting % stuff?
Or if snprintf does not work, then how do I do this?
You can always just write your own conversion function. The following idea is stolen from heavily inspired by this fine answer:
char * int2base36(unsigned int n, char * buf, size_t buflen)
{
static const char digits[] = "0123456789ABCDEFGHI...";
if (buflen < 1) return NULL; // buffer too small!
char * b = buf + buflen;
*--b = 0;
do {
if (b == buf) return NULL; // buffer too small!
*--b = digits[n % 36];
n /= 36;
} while(n);
return b;
}
This will return a pointer to a null-terminated string containing the base36-representation of n, placed in a buffer that you provide. Usage:
char buf[100];
std::cout << int2base36(37, buf, 100);
If you want and you're single-threaded, you can also make the char buffer static -- I guess you can figure out a suitable maximal length:
char * int2base36_not_threadsafe(unsigned int n)
{
static char buf[128];
static const size_t buflen = 128;
// rest as above