user1918858
user1918858

Reputation: 1208

Spawning a shell using ASM

I have the following code in asm to spawn a shell - but it crashes giving Segmentation Fault. Can you please suggest what could be the issue.

jmp short mycall               ; Immediately jump to the call instruction

shellcode:

    pop        esi                ; Store the address of "/bin/sh" in ESI
    xor        eax, eax           ; Zero out EAX
    mov byte   [esi + 7], al      ; Write the null byte at the end of the string

    mov dword  [esi + 8],  esi    ; [ESI+8], i.e. the memory immediately below the string
                                  ;   "/bin/sh", will contain the array pointed to by the
                                  ;   second argument of execve(2); therefore we store in
                                  ;   [ESI+8] the address of the string...
    mov dword  [esi + 12], eax    ; ...and in [ESI+12] the NULL pointer (EAX is 0)
    mov        al,  0xb           ; Store the number of the syscall (11) in EAX
    lea        ebx, [esi]         ; Copy the address of the string in EBX
    lea        ecx, [esi + 8]     ; Second argument to execve(2)
    lea        edx, [esi + 12]    ; Third argument to execve(2) (NULL pointer)
    int        0x80               ; Execute the system call

mycall:

    call       shellcode          ; Push the address of "/bin/sh" onto the stack
    db         "/bin/sh"

Upvotes: 0

Views: 2360

Answers (1)

scottt
scottt

Reputation: 7228

Your shell code is correct. It segfaults on the instruction that tries to NULL terminate the string because .text sections are now read-only on all operating systems including Linux.

To successfully run your code, you'd either need to make the .text section writable or make the stack or some other data memory executable. Here I demonstrate the later to emulate a buffer overflow attack:

buggy.c

#include <string.h>
#include "shellcode.h"

int main()
{
    char buf[512];
    memcpy(buf, shellcode_bin, shellcode_bin_len);
    ((void(*)(void))buf)();
    return 0;
}

GNUmakefile

CFLAGS := -Os -Wall -g3 -I.

NASM_FLAGS := -g -f elf

PROGRAMS := $(basename $(wildcard *.asm *.c))

.PHONY: all clean
all: $(PROGRAMS)
%.o: %.asm
    nasm $(NASM_FLAGS) $< -o $@
clean:
    rm -f $(PROGRAMS) *.o core.* shellcode.bin shellcode.h

.DELETE_ON_ERROR:

shellcode: LDFLAGS := -m32 -nostdlib
shellcode.bin: shellcode
    objcopy --only-section=.text -O binary $< $@

shellcode.h: shellcode.bin
    xxd -i $< > $@

buggy: shellcode.h
buggy: CFLAGS += -m32
buggy: buggy.c
    $(CC) $(CFLAGS) $< $(LDFLAGS) -o $@
    execstack -s $@

Building the Code

$ make
nasm -g -f elf shellcode.asm -o shellcode.o
cc -m32 -nostdlib  shellcode.o   -o shellcode
objcopy --only-section=.text -O binary shellcode shellcode.bin
xxd -i shellcode.bin > shellcode.h
cc -Os -Wall -g3 -I. -m32 buggy.c -o buggy
execstack -s buggy
rm shellcode.o

Sample Session

$ ./buggy
sh-4.3$ 

Notes

  • execstack -s buggy sets the executable stack flag on the ELF binary
  • The xxd program comes installed with the VIM editor. It's in the vim-common package on most Linux distributions.

Upvotes: 2

Related Questions