Copy Link
Add to Bookmark
Report

BFi numero 11 anno 6 file 13 di 15

eZine's profile picture
Published in 
Butchered From Inside
 · 22 Aug 2019

  

==============================================================================
------------[ BFi numero 11, anno 6 - 23/12/2003 - file 13 di 15 ]------------
==============================================================================


-[ HACKiNG ]------------------------------------------------------------------
---[ PTRACE(2) F0R FUN AND PR0FiT
---[ dev-13, 02/11/2002
-----[ xenion <xenion@acidlife.com>



Author: xenion

ptrace(2) for fun and profit
------------------------------------------------------------------------

0x0 ptrace(2), first steps
0x1 Reading and writing child memory
0x2 read(2)/write(2) reference
0x3 Logging the contents of inbound/outbound telnet/ssh sessions
0x4 Injecting commands on a ptraced telnet/ssh session
0x5 Bindshell, the last stage of delirium
0x6 References



0x0 ptrace(2), first steps
------------------------------------------------------------------------

ptrace(2) e' una syscall che offre funzionalita' di debugging/tracing:
Permette di osservare e controllare l'esecuzione di un processo,
modificarne/leggerne l'immagine in memoria ed i registri.
Ecco il prototipo della funzione a userspace:

long int ptrace(enum __ptrace_request request, pid_t pid,
void * addr, void * data)

Evito di dire con altre parole quanto viene gia' spiegato chiaramente
nella Man page, finirei col fare traduzioni grossolane ed inutili :)
Vediamo invece come usare la ptrace(2) con un piccolo esempio: Vogliamo
vedere che syscall vengono utilizzate a runtime da un qualsiasi
eseguibile: <ptrace/scm.c>.

Ora siamo in grado di:
- agganciare un processo
- mantenerne il controllo loggando
- le syscall chiamate
- lo stato dei registri



0x1 Reading and writing child memory
------------------------------------------------------------------------

Mediante richieste di tipo PTRACE_PEEKTEXT e PTRACE_POKETEXT possiamo
rispettivamente leggere o scrivere una WORD (quindi 4 bytes su una
box Linux 32-bit). Scomodo.. Vediamo come implementare un paio di funzioni
che ci permettono di fare queste stesse operazioni su buffer di dimensioni
maggiori:


#define WORD_SIZE 4

// 'x' viene approssimato per eccesso ad un multiplo di 'y'
#define COUNT_OK(x, y) (##x % ##y != 0 ? ##x+(##y - (##x % ##y)) : ##x)

// 'x' viene approssimato per difetto ad un multiplo di 'y'
#define LEN_OK(x, y) (##x-(##x % ##y))


/*
Legge dal processo 'pid' da 'src' 'count' bytes, andando quindi
a scrivere sul buffer puntato da 'dest', buffer di 'len' bytes.
*/

int
memread(pid_t pid, unsigned char *dest, unsigned char *src, long count,
long len)
{
long off;
long res;

if (count < 0 || len < 0)
return (-1);

count = COUNT_OK(count, WORD_SIZE);
len = LEN_OK(len, WORD_SIZE);

if (len < count)
return -1;

for (off = 0; off < count; off += WORD_SIZE) {
res = ptrace(PTRACE_PEEKTEXT, pid, src + off, 0);
if (errno > 0)
return -1;
else
memcpy(dest + off, &res, WORD_SIZE);
}

return count;
}

/*
Scrive sul processo 'pid' in 'src' 'count' bytes, letti
dal buffer puntato da 'dest', buffer di 'len' bytes.
*/

int
memwrite(pid_t pid, unsigned char *dest, unsigned char *src, long count,
long len)
{
long off;
long res;

if (count < 0 || len < 0)
return (-1);

count = COUNT_OK(count, WORD_SIZE);
len = LEN_OK(len, WORD_SIZE);

if (len < count)
return -1;

for (off = 0; off < count; off += WORD_SIZE) {
memcpy(&res, src + off, WORD_SIZE);
if (ptrace(PTRACE_POKETEXT, pid, dest + off, res) < 0)
return -1;
}

return count;
}



0x2 read(2)/write(2) reference
------------------------------------------------------------------------

Ci occorre conoscere con chiarezza parametri e return value di queste
due syscall, ci serviranno in seguito:

read(2):

read up to count bytes from file fd into buffer *buf:

arg:
eax 3
ebx file descriptor
ecx ptr to input buffer
edx buffer size, max. count of bytes to receive
return:
eax no. of bytes received
errors:
eax EAGAIN, EBADF, EFAULT, EINTR, EINVAL, EIO, EISDIR
source:
fs/read_write.c


write(2):

write (up to) count bytes of data from *buf to file fd:

arg:
eax 4
ebx file descriptor
ecx ptr to output buffer
edx count of bytes to send
return:
eax no. of sent bytes (if POSIX conforming f.s.)
errors:
eax EAGAIN, EBADF, EFAULT, EINTR, EINVAL, EIO, ENOSPC, EPIPE
source:
fs/read_write.c



0x3 Logging the contents of inbound/outbound telnet/ssh sessions
------------------------------------------------------------------------

Con ptrace(2) possiamo agganciarci ad un qualsiasi processo esistente (se
siamo root), possiamo quindi vedere cosa passa per la write(2) o la read(2)
senza ricorrere ad un modulo a kernelspace: Questo ci permette di loggare
le sessioni telnet/ssh!
<ptrace/idioteque.c> serve esattamente a questo.. fixati alcuni bug presenti
nella prima release pubblica.



0x4 Injecting commands on a ptraced telnet/ssh session
------------------------------------------------------------------------

Perche limitarsi a loggare? Possiamo modificare o aggiungere
dati nei buffer di I/O, questo ci permette indirettamente
di eseguire codice arbitrario sulla box.. vediamo come:

Quando l'utente esegue un qualche tipo di operazione sulla shell
inserisce una sequenza di caratteri seguita da '\n', sequenza che viene
letta dal client ssh/telnet attraverso un fd. Se la sessione e'
linebuffered sara' sufficiente una sola read(2), una per
carattere nel caso fosse unbuffered.. ci bastera' quindi aspettare una read(2)
da un certo fd che abbia come ultimo byte letto '\n' oltre il quale
inseriremo i nostri comandi. Torniamo alla read(2):
Come sappiamo, viene mandato un segnale di SIGTRAP prima di eseguire
la syscall ed un'altro appena dopo.. i bytes letti saranno disponibili
solo al secondo stop. Andremo quindi a scrivere partendo dalla posizione
ecx+eax, ricordandoci di fixare eax. Dimensione dei buffer di I/O:

| client | length |
+-----------------+--------+
| OpenSSH_3.2.3p1 | 16384 |
+-----------------+--------+
| telnet | 8192 |
+-----------------+--------+

Lo spazio e' limitato, ma sufficiente per qualsiasi cosa, come vedremo
in seguito :)
Una volta aggiornato il registro eax non occorre fare altro se non
rilasciare il controllo al client che si arrangiera' a fare il resto.
Dobbiamo pero' fare i conti con un problema: potrebbe esserci l'echo
dei caratteri, questo complica le cose.. potrebbe infatti tornare
frammentato in piu write(2). L'unica soluzione "veloce" consiste nel
nascondere qualsiasi output all'utente fino a quando non siamo sicuri
di aver nascosto l'echo (e l'output) dei nostri comandi.
..per nascondere l'output occorrera' non scrivere nulla, mettendo edx a 0
al primo stop, ricordandosi di fixare eax al secondo con il vecchio valore
di edx.
Tutto questo in <ptrace/onelove.c>, have fun!



0x5 Bindshell, the last stage of delirium
------------------------------------------------------------------------

Attraverso qualche echo -ne rediretto possiamo uppare qualsiasi tipo
di file.. anche un piccolo eseguibile di 268 byte, sufficiente per una
bindshell:) Il sorgente si trova in <ptrace/bind.s>, vediamo come compilarlo
ed ottimizzarne la dimensione:

# compiliamo..
gate$ gcc -Wall -s -nostartfiles -nostdlib bind.s -o bind
# quanti byte?
gate$ wc -c bind
496 bind
# bene, rimuoviamo ora tutto il non essenziale dall'eseguibile
gate$ sstrip bind
# quanti byte?
gate$ wc -c bind
268 bind
gate$

Ora che abbiamo il nostro piccolo ELF, non ci resta che trasformarlo
in un unico echo utilizzando <ptrace/ech.c>: <ptrace/cmdfiles/_bindshell>



0x6 References
------------------------------------------------------------------------

[1] Man page of ptrace(2)
[2] strace(2) sources
[3] http://www.phrack.org/phrack/59/p59-0x0c.txt
[4] http://www.linuxgazette.com/issue81/sandeep.html
[5] http://linuxassembly.org
[6] http://www.lxhp.in-berlin.de/lhpsyscal.html
[7] http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html


==============================================================================
--------------------------------[ EOF 13/15 ]---------------------------------
==============================================================================

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT