Reputation: 179
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[] = \
"\xeb\x13\x48\x31\xc0\x5f\x88\x47\x07\x57\x48\x89\xe6\x50\x48\x89\xe2\xb0\x3b\x0f\x05\xe8\xe8\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x41\x42\x42\x42\x42\x42\x42\x42\x42\x43\x43\x43\x43\x43\x43\x43\x43";
int main(void) {
printf("Shellcode length: %d\n", (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
Upvotes: 1
Views: 1830
Reputation: 47573
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", "\353\23H1\300_\210G\7WH\211\346PH\211\342\260;\17\5\350\350\377\377\377/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.
Upvotes: 2