Copy Link
Add to Bookmark
Report

BFi numero 09 anno 3 file 18 di 21

eZine's profile picture
Published in 
Butchered From Inside
 · 5 years ago

  

==============================================================================
-------------[ BFi numero 9, anno 3 - 03/11/2000 - file 18 di 21 ]------------
==============================================================================


-[ REVERSiNG ]----------------------------------------------------------------
---[ KEYGEN REVERSiNG - STUDIAMOCi L'ALGO
-----[ syscalo


Tool
dasm (lo trovate su http://racl.immagika.org sezione tool e risorse)

Allegato
keygen.tgz

Descrizione
Keygen e' un piccolo programmino che ho trovato nella mia distibuzione linux
(/usr/bin/keygen appartenente al package rpm xf86-3.3.5-29)
Il programma genera una chiave pseudo-casuale; a noi interessa vedere
l'algoritmo che hanno utilizzato i programmatori e per fare questo procediamo
disassemblando l'eseguibile.

Iniziamo
Disassembliamo il programma:
rev@rVm:~/keygenRev > dasm keygen keygen.dasm
(tralascio l'output di dasm)

Innanzitutto rechiamoci all'entry point del programma; lo trovate scritto in
chiaro nel disassemblato:
start address 0x080484b0

Ok, ora vediamo un po' di codice: i miei commenti sono indicati tra /* */ o
preceduti da #

Disassembly of section .text: /* Come potete ben vedere siamo giunti al
disassemblato della sezione text che come ben
noto contiene il codice eseguibile del
programma */


/* Tutte queste istruzioni vengono aggiunte dal compilatore per "lanciare" il
codice da noi scritto */

0x080484b0 xorl %ebp,%ebp
0x080484b2 popl %esi
0x080484b3 movl %esp,%ecx
0x080484b5 andl $0xfffffff8,%esp
0x080484b8 pushl %eax
0x080484b9 pushl %esp
0x080484ba pushl %edx
0x080484bb pushl $0x8048688
0x080484c0 pushl $0x80483ac
0x080484c5 pushl %ecx
0x080484c6 pushl %esi
0x080484c7 pushl $0x8048520

Reference to function : __libc_start_main

0x080484cc call 0x08048438 /* E da qui viene "lanciato" il codice che
abbiamo scritto noi */

0x080484d1 hlt

Ma come facciamo a sapere dove inizia il programma vero e proprio? Semplice,
basta guardare l'ultimo valore pushato a __libc_start_main:
0x080484c7 pushl $0x8048520

Il valore 0x8048520 e' l'indizzo della prima istruzione del programma.
Ricerchiamo questo valore nel disassemblato e andiamo a leggere le istruzioni
assembly; ho inserito anche la descrizione delle funzioni chiamate (estratte
dalle pagine di man) per capire meglio cosa fa il programma:

##############################################
##
## Procedura generazione "numeri" casuali
## Estratta dal disassemblato di keygen
## /usr/bin/keygen
##
##############################################

# allocazione stack frame
0x08048520 pushl %ebp
0x08048521 movl %esp,%ebp

# allocazione spazio per var locali
0x08048523 subl $0x50,%esp #50h=80 -> 20 word

# bkp registri a cura della funzione chiamata
# infatti questa parte di programma e' a tutti gli effetti una funzione e
# quindi deve preoccuparsi di salvare i registri
0x08048526 pushl %edi
0x08048527 pushl %esi
0x08048528 pushl %ebx


# INIZIO CHIAMATE A FUNZIONI PER OTTENERE VALORI DA UTILIZZARE COME SEME PER
# LA FUNZIONE RANDOM

# Reference to function : gethostid
#
# #include <unistd.h>
#
# long int gethostid(void);
#
#
# Get a unique 32-bit identifier for the current
# machine.
#

0x08048529 call 0x08048488
0x0804852e movl %eax,%esi #%esi=(#1)

# Reference to function : getuid
#
# #include <unistd.h>
# #include <sys/types.h>
#
# uid_t getuid(void);
#
#
# getuid returns the real user ID of the current process.
#

0x08048530 call 0x08048458
0x08048535 movl %eax,%edi #%edi=(#2)

# Reference to function : getgid
#
# #include <unistd.h>
# #include <sys/types.h>
#
# gid_t getgid(void);
#
# getgid returns the real group ID of the current process.
#

0x08048537 call 0x08048468
0x0804853c movl %eax,0xffffffb4(%ebp) #(%ebp-4Ch)=(#3)

# Reference to function : getpid
#
# #include <unistd.h>
#
# pid_t getpid(void);
#
#
# getpid returns the process ID of the current process.
# (This is often used by routines that generate unique tem-
# porary file names.)
#

0x0804853f call 0x080483e8
0x08048544 movl %eax,%ebx #%ebx=(#4)

# Reference to function : getppid
#
# #include <unistd.h>
#
# pid_t getppid(void);
#
# getppid returns the process ID of the parent of the cur-
# rent process.
#

0x08048546 call 0x08048428
# NON SALVA IL VALORE DI RITORNO - chiamata inutile


# Reference to function : getpgrp
#
# #include <unistd.h>
#
# pid_t getpgrp(void);
#
# getpgid returns the process group ID of the process speci-
# fied by pid. If pid is zero, the process ID of the cur-
# rent process is used.
#
# getpgrp is equivalent to getpgid(0).
#

0x0804854b call 0x080483f8
0x08048550 movl %eax,0xffffffb0(%ebp) #(%ebp-50h)=(#6)

0x08048553 pushl $0x0 #parametro2 per gettimeofday
0x08048555 leal 0xffffffb8(%ebp),%eax #copia ind %ebp-48h in %eax
0x08048558 pushl %eax #parametro1 per gettimeofday

# Reference to function : gettimeofday
#
# #include <sys/time.h>
# #include <unistd.h>
#
# int gettimeofday(struct timeval *tv, struct timezone *tz);
#
# gettimeofday and settimeofday can set the time as well as
# a timezone. tv is a timeval struct, as specified in
# /usr/include/sys/time.h:
#
# struct timeval {
# long tv_sec; /* seconds */
# long tv_usec; /* microseconds */
# };
#
#
# and tz is a timezone :
#
# struct timezone {
# int tz_minuteswest; /* minutes W of Greenwich */
# int tz_dsttime; /* type of dst correction */
# };
#

0x08048559 call 0x08048478

0x0804855e leal 0xffffffc0(%ebp),%eax #copia ind %ebp-40h in %eax
0x08048561 pushl %eax #parametro2 per statfs
# Possible reference to string:
# "."
0x08048562 pushl $0x80486ac #parametro1 per statfs

# Reference to function : statfs
#
# #include <sys/vfs.h>
#
# int statfs(const char *path, struct statfs *buf);
#
#
# statfs returns information about a mounted file system.
# path is the path name of any file within the mounted
# filesystem. buf is a pointer to a statfs structure
# defined as follows:
#
# struct statfs {
# long f_type; /* type of filesystem (see below) */
# long f_bsize; /* optimal transfer block size */
# long f_blocks; /* total data blocks in file system */
# long f_bfree; /* free blocks in fs */
# long f_bavail; /* free blocks avail to non-superuser */
# long f_files; /* total file nodes in file system */
# long f_ffree; /* free file nodes in fs */
# fsid_t f_fsid; /* file system id */
# long f_namelen; /* maximum length of filenames */
# long f_spare[6]; /* spare for later */
# };
#

0x08048567 call 0x08048408

# a questo punto e' terminato il "recupero" dei valori da usare come seme per
# la funzione random.
# ora il programma prende tutti i valori ottenuti e li passa uno alla volta
# alla funzione da me chiamata Call_much (per non dover sempre trascrivere
# l'indirizzo)

0x0804856c pushl %esi #passa (#1)
# chiama Call_much
0x0804856d call 0x08048610

0x08048572 pushl %edi #passa (#2)
# chiama Call_much
0x08048573 call 0x08048610

0x08048578 movl 0xffffffb4(%ebp),%edx #copia ind %ebp-4Ch in %edx (#3)
0x0804857b pushl %edx #passa (#3)
# chiama Call_much
0x0804857c call 0x08048610

0x08048581 pushl %ebx #passa (#4)
# chiama Call_much
0x08048582 call 0x08048610
0x08048587 addl $0x20,%esp #libera lo stack da 8 word

0x0804858a pushl %ebx #passa (#4) -- seconda volta (al posto di #5)
# chiama Call_much
0x0804858b call 0x08048610

0x08048590 movl 0xffffffb0(%ebp),%edx #copia %ebp-50h in %edx (#6)
0x08048593 pushl %edx #passa (#6)
# chiama Call_much
0x08048594 call 0x08048610

0x08048599 movl 0xffffffb8(%ebp),%eax #copia %ebp-48h in %eax (#7)
0x0804859c pushl %eax #passa (#7)
# chiama Call_much
0x0804859d call 0x08048610

0x080485a2 movl 0xffffffbc(%ebp),%eax #copia %ebp-44h in %eax (#7+1)
0x080485a5 pushl %eax #passa (#7+1)
# chiama Call_much
0x080485a6 call 0x08048610

0x080485ab movl 0xffffffc8(%ebp),%eax #copia %ebp-38h in %eax (#8+2)
0x080485ae pushl %eax #passa (#8+2)
# chiama Call_much
0x080485af call 0x08048610

0x080485b4 movl 0xffffffcc(%ebp),%eax #%ebp-34h (#8+3)
0x080485b7 pushl %eax
# chiama Call_much
0x080485b8 call 0x08048610

0x080485bd movl 0xffffffd0(%ebp),%eax #%ebp-30h (#8+4)
0x080485c0 pushl %eax
# chiama Call_much
0x080485c1 call 0x08048610

0x080485c6 movl 0xffffffd4(%ebp),%eax #%ebp-2Ch (#8+5)
0x080485c9 pushl %eax
# chiama Call_much
0x080485ca call 0x08048610

0x080485cf addl $0x20,%esp #libera lo stack di 8 word

0x080485d2 movl 0xffffffd8(%ebp),%eax #%ebp-28h (#8+6)
0x080485d5 pushl %eax
# chiama Call_much
0x080485d6 call 0x08048610

# terminata l'eleborazione procede a stampare la key ottenuta; i valori
# vengono stampati come esadecimali

# passa gli indirizzi dei 4 campi dati per la printf
0x080485db movl 0x80497c4,%eax #ultimo
0x080485e0 pushl %eax
0x080485e1 movl 0x80497c0,%eax #sono nelle locazioni da 0x80497b8
0x080485e6 pushl %eax
0x080485e7 movl 0x80497bc,%eax #a 0x80497c4
0x080485ec pushl %eax
0x080485ed movl 0x80497b8,%eax #primo
0x080485f2 pushl %eax

# stringa di formattazione per la printf
# Possible reference to string:
# "%08lx%08lx%08lx%08lx"
0x080485f3 pushl $0x80486ae #passa il formato della stringa

# Reference to function : printf
0x080485f8 call 0x08048448 #chiama la printf

# ripristino registri e disallocazione stack frame
0x080485fd leal 0xffffffa4(%ebp),%esp
0x08048600 popl %ebx
0x08048601 popl %esi
0x08048602 popl %edi
0x08048603 movl %ebp,%esp
0x08048605 popl %ebp
0x08048606 ret #ritorna dalla chiamata


###############################################################
# Spiegazione della funzione Call_much
#
# La funzione Call_much usa il valore passato come seme per la funzione
# random.
# Poi effettua uno xor dei valori della chiave da ottenere con i valori
# restituiti da random.
#
###############################################################

# Referenced from call at 0804856d ; 08048573 ; 0804857c ; 08048582 ; 0804858b ;
# 08048594 ; 0804859d ; 080485a6 ; 080485af ; 080485b8 ; 080485c1 ; 080485ca ;
# 080485d6 ;

# Call_much:
0x08048610 pushl %ebp
0x08048611 movl %esp,%ebp
0x08048613 pushl %esi
0x08048614 pushl %ebx
# fine allocazione stack frame e salvataggio registri

0x08048615 movl 0x8(%ebp),%eax #copia il parametro passato in %eax
0x08048618 pushl %eax #passa %eax alla funzione srandom

# Reference to function : srandom
#
# #include <stdlib.h>
#
# void srandom(unsigned int seed);
#
#
# The srandom() function sets its argument as the seed for a
# new sequence of pseudo-random integers to be returned by
# random(). These sequences are repeatable by calling sran-
# dom() with the same seed value. If no seed value is pro-
# vided, the random() function is automatically seeded with
# a value of 1.
#


0x08048619 call 0x08048498 #chiama srandom
0x0804861e addl $0x4,%esp #libera lo stack

# %ebx, %esi indirizzi inizio e fine numero da elaborare
0x08048621 movl $0x80497b8,%ebx #copia l'indirizzo in %ebx
# 0x80497b8 locazione dove INIZIA il numero da elaborare

0x08048626 movl $0x80497c4,%esi #copia l'indirizzo in %esi
# 0x80497c4 locazione dove FINISCE il numero da elaborare

0x0804862b nop

# Reference to function : random
# Referenced from jump at 08048638 ;
#
# #include <stdlib.h>
#
# long int random(void);
#
# The random() function uses a non-linear additive feedback
# random number generator employing a default table of size
# 31 long integers to return successive pseudo-random num-
# bers in the range from 0 to RAND_MAX.
#

# call_m1: #etichetta aggiunta da me per avere un riferimento per il salto
0x0804862c call 0x08048418 #chiama la funzione random
# xora il valore ritornato da random con quello puntato da %ebx
0x08048631 xorl %eax,(%ebx)
0x08048633 addl $0x4,%ebx #incrementa %ebx di 4; passa alla word successiva
0x08048636 cmpl %esi,%ebx #confronta %esi con %ebx

# salta a call_m1
0x08048638 jle 0x0804862c #esegue l'elaborazione fino a quando %ebx<=%esi

# ripristina registri e disalloca stack frame per il ritorno dalla chiamata
0x0804863a leal 0xfffffff8(%ebp),%esp
0x0804863d popl %ebx
0x0804863e popl %esi
0x0804863f movl %ebp,%esp
0x08048641 popl %ebp
0x08048642 ret

Ecco spiegato l'algoritmo utilizzato dal programma. A mio avviso e' un buon
metodo per generare chiavi "casuali" per un uso giornaliero 8-)

Riproduciamo l'algoritmo in C:
/*file syskeygen.c*/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/vfs.h>
#include <stdlib.h>

void call_much(long int);

/*array per contenere la key*/
static long int key[4];

void call_much(long int num)
{
int i;
srandom(num);
for(i=0; i<4; i++)
key[i]^=random();
}

main(void)
{
long int hostid, uid, gid, pid, pgrp;

/*parametri per gettimeofday*/
struct timeval *tv;
struct timezone *tz=0;

/*parametri per statfs*/
char path[]=".";
struct statfs *buf;

/*allocazione delle strutture*/
tv=(struct timeval *) malloc(sizeof(struct timeval));
buf=(struct statfs *) malloc(sizeof(struct statfs));

hostid=gethostid();
uid=getuid();
gid=getgid();
pid=getpid();
pgrp=getpgrp();
gettimeofday(tv, tz);
statfs(path, buf);

/* inizio chiamate a call_much */
call_much(hostid);
call_much(uid);
call_much(gid);
call_much(pid);
call_much(pid); /* ripetuta due volte con il valore pid, come nel
disassemblato*/

call_much(pgrp);
call_much(tv->tv_sec);
call_much(tv->tv_usec);
call_much(buf->f_blocks);
call_much(buf->f_bfree);
call_much(buf->f_bavail);
call_much(buf->f_files);
call_much(buf->f_ffree);

printf("\n\033[10G\033[1m\033[31m\033[44m syscalo key generator \033[m\n");
printf("\nkey: %08lx%08lx%08lx%08lx\n", key[0], key[1], key[2], key[3]);

exit(0);
}

Credo non sia il caso di commentare il codice vista la semplicita'.

Note finali
Spero abbiate trovato interessante questo tutorial, nonostante sia abbastanza
semplice; per chi inizia credo possa essere un buon punto di partenza.
Ora potreste sfruttare questo algoritmo per migliorarlo, ottimizzarlo, o
semplicemente prendere spunto per crearne uno vostro.

-x bye to all x-
syscalo


==============================================================================
---------------------------------[ EOF 18/21 ]--------------------------------
==============================================================================

← 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