Skip to content
Advertisement

GDB – Assembly program returns /bin/sh: 0: Can’t open �

I am presently learning 64-bit assembly language from the related Pentester Academy course. The code I’m working on creates the following error when ran in GDB:

/bin/sh: 0: Can’t open � [Inferior 1 (process 4049) exited with code 0177]

I have googled the error and exit code and haven’t found anything helpful. I tried analyzing the code in GDB over and over, but all the right values seem to be in the right registers. I can’t seem to find what’s wrong.

You can find the code below. My goal is simply to invoke the execve syscall using the jump-call-pop technique.

global _start
section .text

_start:

jmp bash

code:

xor rax, rax
pop rdi
mov [rdi +7], al    

push rdi
mov rsi, rsp
push rax
mov rdx, rsp
mov al, 59
syscall 

bash:

call code 
string:     db      '/bin/shABBBBBBBBCCCCCCCC' 

EDIT:

Here is how I built the program:

nasm -f elf64 -o execve_stack_jcp.o execve_stack_jcp.asm 
ld -o execve_stack_jcp execve_stack_jcp.o

I then use objdump -M intel -d execve_stack_jcp to output the disassembly which I then input in this c program:

#include <stdio.h>
#include <string.h>

unsigned char code[] = 
"xebx13x48x31xc0x5fx88x47x07x57x48x89xe6x50x48x89xe2xb0x3bx0fx05xe8xe8xffxffxffx2fx62x69x6ex2fx73x68x41x42x42x42x42x42x42x42x42x43x43x43x43x43x43x43x43";

int main(void) {

printf("Shellcode length: %dn", (int)strlen(code));

int (*ret)() = (int(*)())code;

ret();

return 0;
}

Finally, I compile the c program using:

gcc -fno-stack-protector -z execstack -o shellcode shellcode.c

Advertisement

Answer

execve in Linux is defined this way:

int execve(const char *filename, char *const argv[], char *const envp[]);

[snip]

argv is an array of argument strings passed to the new program. By convention, the first of these strings (i.e., argv[0]) should contain the filename associated with the file being executed. envp is an array of strings, conventionally of the form key=value, which are passed as environment to the new program. The argv and envp arrays must each include a null pointer at the end of the array.

If you were to run your program through strace ./shellcode you’d probably see something similar to this:

execve(“/bin/sh”, [“/bin/sh”, “270”, “1”, “35323H1300_210G7WH211346PH211342260;175350350377377377/bin/s”…], [/* 0 vars */]) = 0

You’ll notice the second argument argv has a bunch of extra entries in the array. This is because you didn’t NULL terminate the argv array. To correct this you could modify your code by pushing 0 (via RAX) onto the stack like this:

xor rax, rax 
pop rdi
mov [rdi +7], al

push rax      ; NULL terminates the `argv` array
push rdi
mov rsi, rsp
push rax
mov rdx, rsp

If you were to run this change through strace again you’d see something like:

execve(“/bin/sh”, [“/bin/sh”], [/* 0 vars */]) = 0

This should end up being a successful execve call.

Advertisement