I am currently trying to inject code that will print helloworld into a vulnerable program. I have succeeded in injecting the code by storing it in one of the environment variables and overwriting the rip register to point to that code. Here is my assembly and op codes:
0000000000000000 <_start>:
0: eb 17 jmp 19 <stack_setup>
0000000000000002 <execute>:
2: 48 31 c0 xor %rax,%rax
5: b0 01 mov $0x1,%al
7: 48 31 ff xor %rdi,%rdi
a: 48 ff c7 inc %rdi
d: 5e pop %rsi
e: b2 0f mov $0xf,%dl
10: 0f 05 syscall
12: b0 3c mov $0x3c,%al
14: 48 ff cf dec %rdi
17: 0f 05 syscall
0000000000000019 <stack_setup>:
19: e8 e4 ff ff ff callq 2 <execute>
1e: 48 rex.W
1f: 65 gs
20: 6c insb (%dx),%es:(%rdi)
21: 6c insb (%dx),%es:(%rdi)
22: 6f outsl %ds:(%rsi),(%dx)
23: 2c 20 sub $0x20,%al
25: 77 6f ja 96 <stack_setup+0x7d>
27: 72 6c jb 95 <stack_setup+0x7c>
29: 64 21 0a and %ecx,%fs:(%rdx)
2c: 0d .byte 0xd
The opcodes after line 19 are for the instruction db "Hello, world!", 0x0a, 0x0d. After examining the execution of the instructions in lines x2-x10 with gdb, I have noticed that it properly prepared the arguments to print the string Hello, World. However, upon executing the syscall statement, nothing happens. Same is to be said for the instructions from line x12 - x17.
I have also tried to compile and link the assembly code to execute it independently and it works properly. In addition to that, I have compiled the vulnerable program with the options
-fno-stack-protector -z execstack
So that I can run code located in the stack. I have also disabled randomizing_va_space. I want to ask if there is something I did not do to allow me to successfully execute the code I injected?
The reason might be that the write
syscall returns an error code. It could be for many reasons, but maybe rdx
is not all zeros, so you should xor %rdx, %rdx
before loading 15 there (actually you should load 14 only, for "Hello, World!\n"
).
Anyway, the error from write
would be returned in rax
, and be a negative number (-errno
), thus when you do
mov $0x3c,%al
dec %rdi
syscall
That will be an invalid syscall, and errno
38 for ENOSYS
will be returned.
The exit
I got to work anyway by doing
xor %rax, %rax
mov $0x3c,%al
syscall
I recommend that you run the program with strace
and see from its output why exactly the write
is failing.
Here's a version of shell code that works for me:
0000000000000000 <main>:
0: eb 1d jmp 1f <stack_setup>
0000000000000002 <execute>:
2: 48 31 c0 xor %rax,%rax
5: b0 01 mov $0x1,%al
7: 48 31 ff xor %rdi,%rdi
a: 48 ff c7 inc %rdi
d: 5e pop %rsi
e: 48 31 d2 xor %rdx,%rdx
11: b2 0e mov $0xe,%dl
13: 0f 05 syscall
15: 48 31 c0 xor %rax,%rax
18: b0 3c mov $0x3c,%al
1a: 48 ff cf dec %rdi
1d: 0f 05 syscall
000000000000001f <stack_setup>:
1f: e8 de ff ff ff callq 2 <execute>
24: 48 rex.W
25: 65 6c gs insb (%dx),%es:(%rdi)
27: 6c insb (%dx),%es:(%rdi)
28: 6f outsl %ds:(%rsi),(%dx)
29: 2c 20 sub $0x20,%al
2b: 57 push %rdi
2c: 6f outsl %ds:(%rsi),(%dx)
2d: 72 6c jb 9b <stack_setup+0x7c>
2f: 64 21 0a and %ecx,%fs:(%rdx)