Exploit [Italian] E-Zine - HitNote 0x04

Exploiter

Хакер
34,644
0
18 Дек 2022
EDB-ID
15912
Проверка EDB
  1. Пройдено
Автор
R0B0T82 & DANY15GNI & TURBOCOTOLETTA & D0CT0R
Тип уязвимости
PAPERS
Платформа
MULTIPLE
CVE
N/A
Дата публикации
2011-01-05
Код:
     __  _____________   ______  ____________
    / / / /  _/_  __/ | / / __ \/_  __/ ____/
   / /_/ // /  / / /  |/ / / / / / / / __/
  / __  // /  / / / /|  / /_/ / / / / /___       
 /_/ /_/___/ /_/ /_/ |_/\____/ /_/ /_____/ [0x04 :: December 2010]
                 Hackkappatoio Isn't The Name Of This Ezine

http://hitnote.gotdns.org :: http://unofficialhj.gotdns.org


**********************************************
* HITNOTE 0x04 :: L'officina dei bimbiminkia *
**********************************************

ke kz hai dtt? 
Ehi Cm xi fta l csa xopra la phto?
wlf yeah fuka fuka ohhoh

Li riconoscete questi messaggi? Ebbene, sono tutto ciò che potete trovare su
Facebook andando su un profilo di un qualunque bimbominkia. Stranamente, molti
oggetti discussi su facebook trovati nei vari blog sono copie stra vecchie di
topic trattati in forum di... bbk. Avete rotto con le penne usb ruba dati..
tutte *stronzate* che nei migliori dei casi sono software remoti di controllo
in cui è stato cambiato lo sfondo e il nome... Sinceramente abbiamo bisogno di
tutte 'ste cose quando possiamo andare in edicola e comprare ottime riviste con
incluso un bel cyberenigma e materiale sempre nuovo??? La nostra privacy gettata
       ai quattro venti vale veramente un servizio di host di foto e stronzate? 
Eppure, Facebook è in continua crescita. È innegabile. Noi tutti possiamo essere
Sicuri oramai, che facebook è una grande officina di bimbiminkia.
Una sola domanda: Ne avevamo veramente bisogno?
Credo di no.

Attualmente il mondo gira così. Se volete, incominciate a camminare dalla parte 
       opposta, così sarete pronti per quando girerà in senso inverso.. 

Male che vada vi siete tolti quella mole di grasso da nerd =DDD

E fatti un favore. Cancellati da Faccia Libro.

L |
O V

Turbocotoletta, MMX


   ______________ ___               _____        _____
  |    __________|___|              \    \      /    /
  |   |__  ___ __|___|___  ______    \    \    /    /_____  ___   __ ___ ____
  |    __||   '___/  __  \/  __  \    \    \  /    /  __  \|   | |  |   '___/
  |   |   |   |  |   ____/   ____/     \    \/    /  (__)  |   |_|  |   |
  |___|__ |___|__|\______|\______|______\        / \______/ \_____,_|___|
  |      \/      |   |   \ |   |    __   \      /        _____
  |              |   |    \|   |   |  \   |    /     ,mdMMMMMMMMmm_
  |   |\    /|   |   |         |   |   |  |   /    mMMMMPP"""YPMMMMb.
  |   | \  / |   |   |   |\    |   |__/   |  /   dMMMP'         ``YMMM.
  |___|  \/  |___|___|___| \___|_________/__/  ,MKMP'     _____    `MMMb
                    __                        ,MMM'      /     :     YMMb
                 ,-' _`...,                  ,MMM'      /    __:      YMMb
               ,',-''.....:..___             dMMK       :   /          YMMb
             .','-''            |           ,MEM      __:   :__        `MMM
            ,'`      _,..---...,'           dMME     :         :        YMM[
           /___    ,'                       dMM[     :__     __:        dMM[
         ,'    '''''-..                     dMME        :   :           dMM[
        ,'             `"._                 YMMb        :   :           MMM'
       /       ____ _      \.               `MMw        :   :          JMMP
     ,'       ::'    `'-.    `.              YMMb       :   :          MMM'
    /          |         `.    \              YMML      :___:         dMMF
   /           :     o-----:---:------------   YMMb                 ,dMMF
  '             :..___..-'     /                YMMM.              mMMMP
                `''          ,'                  `YMMMm.       _,mMMMP
                           ,'                      `YMMMMMmmmdMMMMMP'
                       _.-'                           `YPMMMMMPP"'
              _.---''''                                   /mm\
     __,,..--'                                           .MMMM.
  '''                                                    `YMMY'



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Indice:

* 0x00 . I Troll
* 0x01 . Reversing alternativo
* 0x02 . Il sensore di prossimità a luce visibile
* 0x03 . Backup di sistema
* 0x04 . Real Italy
* 0x05 . Programming /dev/dsp For Dummies
* 0x06 . Sistema idroponico per piccole piantagioni di piante domestiche
* 0x07 . PNM drawing
* 0x08 . Riddle
* 0x09 . Ringraziamenti


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


****************************
* 0x00 :: Studio sui troll *
****************************


*INTRODUZIONE*

I troll non piacciono a nessuno, nemmeno agli altri troll. Sono bestiacce
talmente fastidiose che sarebbe preferibile avere uno stronzo fumante sulla
keyboard piuttosto di doverne sopportare uno.
E non ce n'è un solo tipo bensì una moltitudine di specie diverse: dal 
baby-troll che parla a vanvera, al senior-troll che ha una cultura generica,
e fino al super-troll capace anche di replicare una personalità esistente;
ma tutti con una caratteristica in comune: far danni.

*IL COMPORTAMENTO DEL TROLL*

La specie dei troll non mi ha mai interessato più di tanto: danno più
soddisfazione le culture di muffe, spore, e funghi. Ma in tempi recenti è
successo qualcosa che mi ha portato ad iniziare una ricerca sul loro
comportamento, abitudini, habitat: ho trovato un esemplare disponibile 24/7
e così ho potuto cimentarmi in uno studio dal vivo :)
In effetti non è un esemplare molto sano, anzi è mal ridotto... ma prendendo
le dovute precauzioni ho evitato che si disfasse durante i test.
Il suo nick è voldemort, ed è un esemplare di senior-troll classico: nè carne
nè pesce; non sono neanche certo della sua sessualità, dato che mostra
un chiaro atteggiamento bisex anche per questo credo di avere scoperto una
nuova specie: il trollipop (da troll e lollipop). 

Ecco il comportamento di voldemort:
- rimane nei canali in silenzio, ed interviene solamente quando ha 
qualcosa di acido da dire per sfottere e umiliare;
- quando viene interpellato sfrutta gli errori grammaticali altrui per sminuire
 il valore delle argomentazioni;
- cambia istantaneamente l'atteggiamento, da simpatico a scontroso;
- risponde quasi esclusivamente in modo interrogativo e ironico, per non
 fornire info e conservarsi sempre una scappatoia;
- non dimostra nè moralità, nè allineamento spirituale;
- abbonda con l'ipocrisia, e nega l'evidenza dei fatti;
- racconta solo balle, o al massimo evita di dire la verità;
- si finge idiota e pretende sempre la ragione.

*ABITUDINI ALIMENTARI*

Un'esempio delle capacità di voldemort, quando siamo stati soli in chan:
   <d0ct0r> salve!
---dopo circa mezz'ora---
<voldemort> ciao d0ct0r 
   <d0ct0r> hellO!
   <d0ct0r> come va voldemort?
---il resto è silenzio---[cit. Amleto]

Si denota un disinteresse totale da parte del troll. Il suo obiettivo non è il
singolo utente, e nemmeno il flood; il suo obiettivo è il gruppo di utenti:
provocare flame per avere informazioni sulle relazioni e sulle capacità del
gruppo, allo scopo di dividere.
E così ho fatto un test per verificare di cosa abbisognava il troll.
E' noto il fatto che i troll si cibino principalmente di discussioni inutili
e che cerchino sempre un pretesto per accendere un flame.
Ma in questo caso non c'era alcun thread in cui intervenire e così voldemort
si è trincerato nella sua ambiguità:

<voldemort> sono iscritto sul forum
   <d0ct0r> aka?
<voldemort> che importa? :D
<voldemort> se volevo dirlo joinavo con il nick con cui sono registrato no?
   <d0ct0r> che senso ha?XD
<voldemort> potrei dirti un nick qualsiasi
<voldemort> la tua domanda che senso ha?
   <d0ct0r> che senso ha la mia domanda che domanda quale senso abbia il
 senso del tuo nick?
<voldemort> <voldemort> sono iscritto sul forum
<voldemort> <d0ct0r> aka?
<voldemort> questa domanda
   <d0ct0r> è stata la domanda che ha generato la risposta che ha generato una
 discussione equivoca e di difficile comprensione, ma rimane l'interrogativo
  fisso: perchè?
<voldemort> non c'è un perché
   <d0ct0r> c'è un come
   <d0ct0r> fanstastica.
<voldemort> se lo dici tu
   <d0ct0r> potrei dirlo io ma dato che non c'è un perchè ma solo un come la
 risposta non ha un senso compiuto dato che scaturita da un discorso già nato
 senza senso compiuto.
<voldemort> non c'è nemmeno un come
   <d0ct0r> filosofico.
   <d0ct0r> assolutamente illuminante.
<voldemort> già
<voldemort> in cosa sei dottore? in stronzate?
  <ja_tux_> :O
   <d0ct0r> in realtà ho il dottorato in scienza del cazzeggio applicato a
 livello filosofico e sul come agisce tra mente mittente e relazione sociale.
   <d0ct0r> a grandi linee un sì

Il comportamento che ho tenuto è vivamente sconsigliato: io l'ho adottato a
scopo di test.
Si nota come ho dato un sacco di pappa al troll, e come lui l'ha schifata.
I troll generalmente vogliono aver ragione e/o ostentare una certa superiorità,
ma in questo caso particolare voldemort ha dimostrato di preferir consumare
la pappa in gruppo.


*SOCIALIZZAZIONE*

Il troll preferisce avere un branco a cui affiancarsi, molte volte si forma
come un duetto di demenza, come ben risaputo.
Infatti è qui che il troll gioca le sue carte: l'unione fa la forza.
Come un gruppo di formiche laboriose i troll tramano dicendosi cose come:
"haha li freghiamo", "siamo i migliori", "mamma la pasta non mi va più".
la principale occupazione dei troll è detta "appostamento a pecorina",
che consiste nel stare fermi zitti e muti come a pecorina per carpire
più informazioni possibile, solitamente svolgono questa attività a gruppi di
due individui, uno posto "accavallato" all'altro(fonti da confermare).

Bando alle ciancie ecco un po d'azione:

nov 25 21:07:34 <un0>	ragazzi, che ambiente grafico mi consigliate per
                        il mio linux?
nov 25 21:08:04 <d0ct0r>	a me piace fluxbox
nov 25 21:08:06 <black>	gnome
nov 25 21:08:16 <edx>	dwm sbavvvv...
nov 25 21:08:24 <black>	dipende da esperienza e gusti... :)
nov 25 21:08:32 <d0ct0r>	molti mene hanno parlato bene di dwm ma non mi ispira..
nov 25 21:09:04 <r0b0t82>	ho provato dwm ed è fantastico!
nov 25 21:09:07 <voldemort>	quoto d0ct0r :D
nov 25 21:09:13 <un0>	mi serve un ambiente che sia buono per fare hacking
nov 25 21:09:22 <edx>	perchè va personalizzato
nov 25 21:09:44 <black>	un0 flux all'inizio e poi dwm
nov 25 21:09:47 <d0ct0r>	beh ti basta vim, un terminale e voglia
                                di imparare :)
nov 25 21:10:07 <un0>	ah, si può fare hackerare con vim?
nov 25 21:10:33 <d0ct0r>	è un editor di testo puoi farci ciò che vuoi.
nov 25 21:10:46 <un0>	che si può fare di interessante?
nov 25 21:10:56 <d0ct0r>	programmare
nov 25 21:11:17 <un0>	ma per fare hacking bisogna sapere programmare?
nov 25 21:11:23 <un0>	perchè io non so fare molto
nov 25 21:11:25 <r0b0t82>	cosa intendi per hacking?
nov 25 21:11:39 <voldemort>	ownare :D
nov 25 21:11:42 <un0>	r0b0t82: bucare macchine
nov 25 21:11:46 <un0>	bravo voldemort 
nov 25 21:11:46 <d0ct0r>	lol
nov 25 21:12:12 <r0b0t82>	un0, impara a programmare e divertiti.
nov 25 21:12:17 <r0b0t82>	si, per fare quello serve programmare
nov 25 21:12:25 <un0>	ma io non voglio programmare
nov 25 21:12:26 <un0>	voglio bucare
nov 25 21:12:41 <voldemort>	lol
nov 25 21:12:42 <d0ct0r>	lol 
nov 25 21:12:50 <black>	XD
nov 25 21:13:09 <un0>	gli schiavi programmano
nov 25 21:13:27 <r0b0t82>	un0, mi spiace. allora non puoi.
nov 25 21:13:44 <black>	un0, un trapano può servire?
nov 25 21:14:00 <un0>	black: si, il trapano buca
nov 25 21:14:05 <voldemort>	dai per bucare qualcosa in genere basta saper
                                compilare non programmare ehhe
nov 25 21:14:21 <un0>	voldemort: bene
nov 25 21:14:21 <r0b0t82>	questo lo fanno i lamer
nov 25 21:14:28 <un0>	voldemort: ma tu sei hacker?


Possiamo osservare come voldemort appoggiato dal suo fedele cagnolino
si rafforzi.
Mentre prima voldemort sembrava esser colto abbastanza per riproverare
gli altri, ora si è trasformato in un troll di un altro livello.

Ecco il modus operandi:

nov 25 21:14:36 <voldemort>	tanto pure chi sa programmare alla fine rimane
                                inculato se gli passano qualche exploit
nov 25 21:14:42 <voldemort>	tipo blacklight
nov 25 21:14:48 <voldemort>	un0: naah
nov 25 21:14:53 <un0>	ma chi è questo blacklight?
nov 25 21:14:58 <un0>	è un hacker?
nov 25 21:14:59 <r0b0t82>	un gran figo
nov 25 21:15:01 <r0b0t82>	si
nov 25 21:15:04 <r0b0t82>	ma hacker vero
nov 25 21:15:15 <r0b0t82>	afk
nov 25 21:15:16 <voldemort>	perché?
nov 25 21:15:16 <r0b0t82>	a dopo!
nov 25 21:15:38 <un0>	che significa hacker vero?
nov 25 21:15:44 <un0>	è un white hat?
nov 25 21:15:46 <voldemort>	boh non capisco tutto questo hype su blacklight
nov 25 21:16:30 <black>	afk per una ventina di minuti
nov 25 21:16:43 <black>	non credo vi piacerebbe sapere la motivazione XD
nov 25 21:16:59 <un0>	black: vai a bucare qualche server?
nov 25 21:17:22 <black>	ti do un indizio: inizia con d e finisce con iarrea
nov 25 21:18:15 <d0ct0r>	lol
nov 25 21:18:19 <voldemort>	ammazza
nov 25 21:18:25 <voldemort>	20 minuti di diarrea ti disidrati
nov 25 21:19:36 <voldemort>	poi qualcuno mi spieghi perché blacklight è un
                                "vero hacker" thanks :P
nov 25 21:19:59 <un0>	si, anche io voglio sapere chi è blacklight
nov 25 21:20:36 <voldemort>	ti linko il suo sito
nov 25 21:20:45 <voldemort>	http://blacklight.gotdns.org/
nov 25 21:21:18 <edx>	e per sfortuna non c'è più hacknowledge,
                        lì si che c'era roba fica :(
nov 25 21:21:40 <voldemort>	ma
nov 25 21:21:45 <voldemort>	cosa c'era di così fico?
nov 25 21:21:55 <voldemort>	io non mi ricordo niente di fico...
nov 25 21:22:00 <voldemort>	che c'era solo li
nov 25 21:22:00 <un0>	ma è rotto?
nov 25 21:22:17 <un0>	perchè è tutto nero?
nov 25 21:22:32 <voldemort>	un0: black is cool
nov 25 21:24:31 <voldemort>	edx: ?
nov 25 21:25:43 <un0>	ma per caso blacklight è fascista?
nov 25 21:32:07 <voldemort>	tutti morti
nov 25 21:32:48 <un0>	già
nov 25 21:32:54 <un0>	vado ad orinare
nov 25 21:33:43 <voldemort>	per me una shell root 100mbit
nov 25 21:42:16 <voldemort>	avevo letto ordinare!

Il trollaggio è evidente, ma ecco come sbarazzarcene:

nov 25 21:15:15 <r0b0t82>	afk

non dandogli da mangiare loro la smettono e presi dalla noia vanno a marchiare
il loro territorio altrove:

<un0>	vado ad orinare



*HABITAT*

Tutte queste comuni caratteristiche di voldemort inducono una classificazione
di categoria media:
- è un fanca##ista semi-mantenuto che non sà che cosa significhi lavorare
  seriamente IRL (oppure che svolge un'attività lavorativa IRL talmente scarsa 
  e inappagante da provocargli un complesso di inferiorità);
- non ha molto tempo da dedicare alla sua esistenza come troll quindi
  non eccellerà mai, nè farà carriera;
- non ha molta fiducia in se stesso e perciò avrà sempre bisogno di un compagno
  troll che gli faccia da spalla nelle performance più impegnative;
- è molto invidioso e difetta di fantasia e perciò tende ad usare schemi
  ripetitivi e facilmente identificabili.

Un troll mediocre come voldemort trova terreno fertile solo in mezzo a grandi
gruppi; e trova tana solo in Forum con migliaia di iscritti. Lui sà di avere 
buone capacità, ma è deviato dalla propria pigrizia e parassitismo. 
Probabilmente è la mancanza di amore, affetto, e comprensione che lo portano 
a questa effimera esistenza; perciò quando si sente rifiutato non interroga sè 
stesso ma usa i peggiori mezzi di coercizione per vendicarsi.



*RIPRODUZIONE*

"ovvero la principale causa di sovvraccarico della linea adsl esistente
al mondo"(secondo la cultura troll).

Infatti, secondo molte fonti i troll definiscono la riproduzione come:
"L'unico vero e approvato sistema per occupare banda guardando filmati"
Credetemi, i dettagli non li vogliamo sapere e nemmeno voi li volete sapere.
Comunque sia si crede poca o scarsa oppure molta ma solitaria.
(si cerca volontario per ricerca di prove sul campo).

C.R.T. research institute


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


*********************************
* 0x01 :: Reversing alternativo *
*********************************


Eccoci di nuovo ad affrontare un po' di reversing "alternativo", nel senso che
andremo a vedere come utilizzare in maniera ortodossa i nostri strumenti da 
lavoro che siamo abituati a usare secondo procedure più o meno standard.
I procedimenti non saranno sempre validi, ma ci aiuteranno a capire qualcosa di
più e a far vedere che razza di nerd siamo :).

Direi dunque che possiamo iniziare, e come sempre lo facciamo partendo con
il sorgente del nostro crackme del giorno:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void usage () {
	printf ("[!] Usage: ./program <username> <password>\n");
	exit (0);
}

char *gen_pass (char *uname) {
	char *pass;
	int i;
	pass=malloc(strlen(uname));
	for(i=0;i<strlen(uname);i++) 
		pass[i]=uname[i]-(i/2)+((i%2)?2:3);
	pass[i]=0;
	return pass;
}

int main (int argc, char* argv[]) {
	if (argc!=3)
		usage ();
	if (!strcmp (argv[2],gen_pass(argv[1])))
		printf ("[+] Password corretta!\n");
	else
		printf ("[-] Password errata.\n");
	return 0;
}

A parte la funzione gen_pass () che utilizza algoritmi complicatissimi e molto
sicuri per crittare l'username per generare la password possiamo vedere che si
tratta del classico crackme che prende un username e una password, critta l'
username e lo confronta con la password; in caso di esito positivo mostra un
determinato messaggio, in caso contrario ne mostra un altro.
Il nostro scopo è, inutile ricordarlo, fare in modo che il nostro eseguibile
accetti qualunque combinazione username-password.
Per iniziare cominciamo a compilare il sorgente e ad analizzare il contenuto:

darkjoker@localhost:~/rev$ gcc -o a a.c
darkjoker@localhost:~/rev$ objdump -D a
[output tagliato]
0804855d <main>:
 804855d:       55                      push   %ebp
 804855e:       89 e5                   mov    %esp,%ebp
 8048560:       83 e4 f0                and    $0xfffffff0,%esp
 8048563:       83 ec 10                sub    $0x10,%esp
 8048566:       83 7d 08 03             cmpl   $0x3,0x8(%ebp)
 804856a:       74 05                   je     8048571 <main+0x14>
 804856c:       e8 43 ff ff ff          call   80484b4 <usage>
 8048571:       8b 45 0c                mov    0xc(%ebp),%eax
 8048574:       83 c0 04                add    $0x4,%eax
 8048577:       8b 00                   mov    (%eax),%eax
 8048579:       89 04 24                mov    %eax,(%esp)
 804857c:       e8 51 ff ff ff          call   80484d2 <gen_pass>
 8048581:       8b 55 0c                mov    0xc(%ebp),%edx
 8048584:       83 c2 08                add    $0x8,%edx
 8048587:       8b 12                   mov    (%edx),%edx
 8048589:       89 44 24 04             mov    %eax,0x4(%esp)
 804858d:       89 14 24                mov    %edx,(%esp)
 8048590:       e8 47 fe ff ff          call   80483dc <strcmp@plt>
 8048595:       85 c0                   test   %eax,%eax
 8048597:       75 0e                   jne    80485a7 <main+0x4a>
 8048599:       c7 04 24 ab 86 04 08    movl   $0x80486ab,(%esp)
 80485a0:       e8 27 fe ff ff          call   80483cc <puts@plt>
 80485a5:       eb 0c                   jmp    80485b3 <main+0x56>
 80485a7:       c7 04 24 c2 86 04 08    movl   $0x80486c2,(%esp)
 80485ae:       e8 19 fe ff ff          call   80483cc <puts@plt>
 80485b3:       b8 00 00 00 00          mov    $0x0,%eax
 80485b8:       c9                      leave  
 80485b9:       c3                      ret    
 80485ba:       90                      nop
 80485bb:       90                      nop
 80485bc:       90                      nop
 80485bd:       90                      nop
 80485be:       90                      nop
 80485bf:       90                      nop
[output tagliato]
darkjoker@localhost:~/rev$ 

Guardando la nostra funzione main () vediamo che viene chiamata primariamente
la funzione usage (), che possiamo immaginare a cosa serva dal nome, ma per 
toglierci dubbi possiamo andare a vedere il listato relativo a quella funzione,
che è:

080484b4 <usage>:
 80484b4:       55                      push   %ebp
 80484b5:       89 e5                   mov    %esp,%ebp
 80484b7:       83 ec 18                sub    $0x18,%esp
 80484ba:       c7 04 24 80 86 04 08    movl   $0x8048680,(%esp)
 80484c1:       e8 06 ff ff ff          call   80483cc <puts@plt>
 80484c6:       c7 04 24 00 00 00 00    movl   $0x0,(%esp)
 80484cd:       e8 1a ff ff ff          call   80483ec <exit@plt>

Vediamo che viene stampata una stringa e poi viene chiamata la funzione exit(),
a questo punto dovrebbe essere chiaro a cosa serve questa funzione, ma per 
sfizio andiamo a leggere la stringa stampata (useremo revtool.h per velocizzare
il processo :)

#include <revtool.h>

int main () {
	printf ("%s\n",addr2str("a",0x8048680));
	return 0;
}

Compiliamo e eseguiamo:

darkjoker@localhost:~/rev$ gcc -o b b.c
darkjoker@localhost:~/rev$ ./b
[!] Usage: ./program <username> <password>
darkjoker@localhost:~/rev$ 

Esattamente quello che ci aspettavamo, la funzione usage () serve per dare un
alert nel caso in cui non vengono passati i parametri necessari.
Noi possiamo quindi saltare questa parte e dedicarci a quanto segue. Possiamo
vedere che viene chiamata la funzione gen_pass () e in seguito una strcmp (),
che "dirama" il flusso a seconda che l'uguaglianza tra le due stringhe sia 
vera o falsa.

Sappiamo (spero :) che la funzione strcmp () ritorna 0 quando il confronto
tra le stringhe dà esito positivo, mentre ritorna un valore diverso da 0 quando
le stringhe sono diverse (non ci interessa per il nostro articolo quale valore
ritorna strcmp () al variare delle due stringhe, ci basti sapere che ritorna
valori diversi da 0).
Una volta Ritornato il valore esso viene "negato" (!), a questo punto se la
funzione ci ha ritornato 0 avremo un 1, se ci avrà ritornato un valore diverso
da 0 avremo 0. L'if quindi ci mostrerà un messaggio diverso a seconda del 
valore ritornato da strcmp ().
Ora, saremmo tentati dal modificare il jne in un je per invertire i messaggi
mostrati, ma possiamo trovare altre vie.
Una molto semplice può essere, per esempio, forzare la funzione strcmp () a
ritornare sempre 0, per farlo è discretamente banale.

Andiamo a vedere l'etichetta strcmp () che istruzioni contiene:

080483dc <strcmp@plt>:
 80483dc:       ff 25 14 a0 04 08       jmp    *0x804a014
 80483e2:       68 28 00 00 00          push   $0x28
 80483e7:       e9 90 ff ff ff          jmp    804837c <_init+0x30>

Queste poche istruzioni andranno poi a svolgere il compito della funzione
strcmp (), ma prima di tutto vengono eseguite queste.
Cosa accadrebbe se noi al posto di queste istruzioni ne mettessimo solamente
una che ritorna 0?
Appena chiamata strcmp () verrebbe ritornato subito 0, senza avvenire nessun
reale confronto tra le stringhe.

Per vedere come modificare i byte dobbiamo prima avere quelli che ci servono,
ossia quelli per le istruzioni 'mov $0, ret', vediamo quali sono:

.text
	.global main
lab:
	mov	$0, %eax
	ret
main:
	call lab

Queste istruzioni possono essere compilate e "lette" con objdump per ottenere
i byte relativi:

080483b4 <lab>:
 80483b4:       b8 00 00 00 00          mov    $0x0,%eax
 80483b9:       c3                      ret    

080483ba <main>:
 80483ba:       e8 f5 ff ff ff          call   80483b4 <lab>
 80483bf:       90                      nop

Bene, ci serviranno i byte b8 00 00 00 00 c3, ma abbiamo visto che in strcmp ci
sono 16 byte, mente i nostri sono solo 6: gli altri 10 saranno dei NOP (0x90).
Possiamo quindi procedere e sostituire i byte (useremo revtool ma lo stesso 
risultato si ottiene con un classico editor esadecimale):

#include <revtool.h>

int main () {
	int addr=0x080483dc;
	int bytes [] =	{0x90, 0x90, 0x90, 0x90,
			 0x90, 0x90, 0x90, 0x90,
			 0x90, 0x90, 0xb8, 0x00,
			 0x00, 0x00, 0x00, 0xc3};
	replace_bytes ("a",addr,bytes,16);
	return 0;
}

Compiliamo ed eseguiamo:

darkjoker@localhost:~/rev$ gcc -o b b.c
darkjoker@localhost:~/rev$ ./b
darkjoker@localhost:~/rev$ 

A questo punto, se andiamo a controllare strcmp () nel nostro eseguibile lo
vedremo così:

080483dc <strcmp@plt>:
 80483dc:       90                      nop
 80483dd:       90                      nop
 80483de:       90                      nop
 80483df:       90                      nop
 80483e0:       90                      nop
 80483e1:       90                      nop
 80483e2:       90                      nop
 80483e3:       90                      nop
 80483e4:       90                      nop
 80483e5:       90                      nop
 80483e6:       b8 00 00 00 00          mov    $0x0,%eax
 80483eb:       c3                      ret    

A occhio e croce quello che ci aspettavamo...
Proviamo ora ad eseguire:

darkjoker@localhost:~/rev$ ./a
[!] Usage: ./program <username> <password>
darkjoker@localhost:~/rev$ ./a darkjoker password
[+] Password corretta!
darkjoker@localhost:~/rev$ 

Ecco fatto ;)
L'articolo dovrebbe finire così, ma mentre scrivevo l'articolo e mi rileggevo
un po' il listato mi si è accesa una lampadina in testa su un altro metodo
"alternativo" di bypassare la funzione strcmp (): se le stringhe che passiamo
sono uguali.. beh, strcmp () ci ritornerà 0 senza dubbi, no?
Come stringa da confrontare ci potrebbe venire comoda quella che viene usata
dalla funzione usage () e che ha, nel nostro esempio, indirizzo 0x08048680.
A questo punto non ci resta che mettere in cima allo stack due indirizzi uguali
entrambi relativi alla nostra stringa.
Per fare ciò possiamo usare push, vediamo quali sono i byte che ci servono:

.text
	.global main
main:
	push	$0x08048680
	
Compiliamo ed apriamo con objdump:

darkjoker@localhost:~/rev$ gcc -o a a.s
darkjoker@localhost:~/rev$ objdump -D a
[output tagliato]
080483b4 <main>:
 80483b4:       68 80 86 04 08          push   $0x8048680
 80483b9:       90                      nop
 80483ba:       90                      nop
 80483bb:       90                      nop
 80483bc:       90                      nop
 80483bd:       90                      nop
 80483be:       90                      nop
 80483bf:       90                      nop
[output tagliato]
darkjoker@localhost:~/rev$ 

Bene, i nostri byte sono 68 80 86 04 08, che dovremo ripetere due volte dal 
momento che dobbiamo mettere la stringa due volte.
In totale ci serviranno 10 byte, andiamo a vedere nella nostra main dove 
possiamo trovare 10 byte liberi (ossia prenderemo 10 byte che servono per
caricare nello stack gli argomenti "veri" di strcmp ()):

 804856c:       e8 43 ff ff ff          call   80484b4 <usage>
 8048571:       8b 45 0c                mov    0xc(%ebp),%eax
 8048574:       83 c0 04                add    $0x4,%eax
 8048577:       8b 00                   mov    (%eax),%eax
 8048579:       89 04 24                mov    %eax,(%esp)
 804857c:       e8 51 ff ff ff          call   80484d2 <gen_pass>
 8048581:       8b 55 0c                mov    0xc(%ebp),%edx
 8048584:       83 c2 08                add    $0x8,%edx
 8048587:       8b 12                   mov    (%edx),%edx
 8048589:       89 44 24 04             mov    %eax,0x4(%esp)
 804858d:       89 14 24                mov    %edx,(%esp)
 8048590:       e8 47 fe ff ff          call   80483dc <strcmp@plt>
 
Vediamo che se partiamo da 0x08048584 e riscriviamo i 12 byte successivi 
arriveremo subito prima della chiamata a strcmp ().
Facciamo dunque così, ed ecco il nostro sorgente in C che si sporcherà le mani
al posto nostro:

#include <revtool.h>

int main () {
	int bytes [] =	{0x90, 0x90, 0x68, 0x80,
			 0x86, 0x04, 0x08, 0x68,
			 0x80, 0x86, 0x04, 0x08};
	int addr=0x8048584;
	replace_bytes ("a",addr,bytes,12);
	return 0;
}

Compiliamo ed eseguiamo, quindi proviamo a lanciare il nostro crackme:

darkjoker@localhost:~/rev$ gcc -o b b.c
darkjoker@localhost:~/rev$ ./b
darkjoker@localhost:~/rev$ ./a
[!] Usage: ./program <username> <password>
darkjoker@localhost:~/rev$ ./a darkjoker password
[+] Password corretta!
darkjoker@localhost:~/rev$ 

Ottimo direi ;)

Con questo è davvero tutto,

darkjoker


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


****************************************************
* 0x02 :: Il sensore di prossimità a luce visibile *
****************************************************


Nel mio ultimo progetto mi serviva un sensore di distanza (ebbene si, il vecchio
d0ct0r è ancora li che da vita a esseri meccatronici infinitamente stupidi).

Sappiamo bene tutti quanti che i migliori sensori di distanza a portata di tasca
sono quelli ad ultrasuoni, ma purtroppo non sono poi proprio alla portata di 
tutte le tasche.

Secondi in classifica i sensori ad infrarossi: sono ottimi e quasi economici
se li si costruisce da soli diventa praticamente gratuita la cosa...
c'è un ma; i diodi ad infrarossi non si trovano proprio ovunque e quelli 
dei telecomandi (salvo eccezioni) riflettono solamente in maniera perpendicolare
quindi al nostro ricevitore non arriverà nessun segnale a meno che non lo si 
metta dritto in fronte all'emettitore.

Ma veniamo al dunque:
vanno parecchio di moda quelle luci al led quasi accecanti di solito formate 
da una ventina di leds.
Ed ecco l'idea:
usare questa luce con lo stesso principio dei sensori ad infra-rossi, una luce
emessa viene ricevuta dal ricevitore 
(nel nostro caso sarà una fotoresistenza) che ne ricava il
segnale analogico più o meno forte a seconda della vicinanza all'ostacolo.

Vi è un problema:

la fotoresistenza è molto influenzata dalla luce ambientale.

Ecco la soluzione:

mettiamo la nostra fotoresistenza dentro ad una cannuccia resa scura da del 
nastro isolante. In questo modo la luce non verrà ricevuta se non abbastanza 
forte per entrare nella cannuccia. Ora posizioniamo il sensore appena costruito 
sotto alla luce led, nel senso di attaccarlo materialmente al di sotto in 
maniera che quando un oggetto è vicino la luce venga riflessa 
all'interno della cannuccia.

Ecco il nostro bel sensore di prossimità da pochi spiccioli.
Non c'è bisogno di uno schema elettrico poichè è una cosa molto semplice:
basta capirne il principio.
Ma se avete bisogno di maggiori informazioni non esitate a contattarci.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


*****************************
* 0x03 :: Backup di sistema *
*****************************


Object: essere liberi d'installare e sperimentare l'«impossibile» sul PC,
finchè non si ottiene la configurazione preferita XD E poi continuare a godere
ripristinando tutto con «una sola passata», senza ricominciare da zero, ed
applicare finalmente la configurazione collaudata :> Dopodichè, ricominciare a
sperimentare XD 
Cosa c'è di più buono e saggio di un backup integrale del SistemaOperativo del
PC? O magari di tutto/i il/i disk di Sistema?
E per backup integrale intendo un full backup, una copia il più raw possibile,
un clone, cioè un dump del filesystem.
Sperimentando, è vero che in certi casi ci si può togliere dai pasticci (tipo
con: "tar -zTf pacchetto_che_mi_pento_di_aver_scompattato.tar.gz | xargs rm"),
ed è vero che i packages manager sono una gran bella comodità (un esempio per
tutti: "dpkg --get-selections > lista_pacchetti_installati" "dpkg
--set-selections < lista_pacchetti_installati"), ma non c'è pulizia più comoda
e sicura di un ripristino assoluto delle condizioni precedenti :)
Quì non si tratta di stare up grazie ad un RAID-1 (benedetto mirroring). Quì si
tratta di tornare indietro nel tempo, al momento in cui è stato preparato il
backup integrale che è costituito da un file-immagine («copia-di-backup» in cui
viene copiato tutto il contenuto di una partizione o di un intero disk) o da
una «copia al volo» disk-to-disk, ripristinandolo (cioè sovrascrivendo tutto il
filesystem di una partizione o tutto un disk).

L'unico problema è sempre [stato] il money: occorre spazio per backuppare la
partizione/disk di Sistema, ed il popolo informatico è a tutt'oggi restìo ad
adibire a magazzino un secondo drive magari tenendolo "fermo in un cassetto".
E non ci sono alternative equivalenti.

Per creare/ripristinare il file-immagine di una origine (un SO a partizione
singola/multipla, o comunque una qualsiasi partizione/disk) occorre che la
origine stessa sia smontata (per averne accesso esclusivo e quindi evitare
modifiche indesiderate ai file ivi contenuti, durante il procedimento); quindi
un SO non può «dumpare» sè stesso, e occorre una seconda Linux box (o comunque
un'altro SO) che crei/ripristini la copia-di-backup su/da un'altra
partizione/disk montata/o.

In caso di «copie al volo» di interi disk, si hanno tre drive in gioco: quello
di origine, quello di backup, e quello su cui gira la Linux box (o chi per
essa) che fà il lavoro (e che può essere costituito da un
lettore-CD/DVD/BRD/floppy/card o da un HD/SSD su IDE/SATA/E-SATA/USB o da sola
RAM di Sistema o altro). In tutti gli altri casi è logico usare almeno un
secondo drive (magari rimovibile) su/da cui scrivere/leggere i singoli
file-immagine: in caso di guasto del drive della origine, le copie-di-backup
non saranno perse, mentre la Linux box che fà il lavoro può anche essere
installata sul medesimo drive della origine, in una propria partizione, insieme
alle altre partizioni da copiare/ripristinare.

Ovviamente quando si ha a che fare con comandi/applicazioni che non introducono
informazioni aggiuntive insieme ai dati utili da clonare, occorre prestare
sempre attenzione nel ripristinare un file-immagine nella sua giusta relativa
partizione di origine (dalla quale è stato creato il file-immagine stesso): è
possibile ripristinarlo/duplicarlo su un'altra partizione purchè questa sia di
dimensione uguale o maggiore, ed inoltre si deve trattare del giusto filesystem
specificato nella tavola delle partizioni (presente nell'MBR di quello stesso
disk) onde evitare spiacevoli contrattempi coi SO e coi drive stessi.

Detto questo, si passa all'azione :)

Tutti i comandi successivi devono essere eseguiti come root o comunque con
privilegi di root.
Inoltre sarebbe molto più sicuro usare un terminale su un runlevel diverso da
quello del ServerX che fà girare un eventuale DE, così, se dovesse crashare
l'eventuale DE utilizzato, non si interromperebbe il backup/ripristino in
corso; perciò è bene lavorare nei famosi tty1...6 ([Ctrl]+[Alt]+[F1]...[F6]).
Come prima operazione occorre smontare/montare i device interessati (i vari
disk e partizioni); perciò bisogna azionarsi di "sudo", "su", "mount" e
"umount", o DE e GUI preferiti, per preparare i device interessati :)


Usare dd/sdd, gzip/bzip2/lzma, split, cat, per qualsiasi filesystem
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Clonare l'intero device
=======================

Dalla origine "sda" (smontato), al backup "sdx" (smontato):

 dd if=/dev/sda of=/dev/sdx


Ripristinare il clone dell'intero device
========================================

 dd if=/dev/sdx of=/dev/sda

Tutto quì. E' una copia perfetta 1:1, un vero dump.
Il device sdx deve essere di capacità uguale o superiore (meglio superiore:
anche se i drive sono identici ci può essere una differenza in negativo, ergo
occorre controllare bene prima) a quella di sda.
Se sdx è più grosso non ci sono problemi: lo spazio inutilizzato rimasto alla
fine del disk sdx risulterà come spazio non partizionato vuoto; e se si rottama
(che brutto...) sda, si può usare sùbito sdx, e poi con calma utilizzare quello
spazio non partizionato allargando l'ultima partizione presente oppure
creandovene una nuova (tramite "parted", "gparted", o altri).
Ovviamente quando si ripristina da un sdx più grosso di sda, bisognerà
aspettarsi un errore di spazio su disk insufficiente, ma l'importante è che sda
sia stato ri-riempito :)

Inoltre, in caso di presenza di blocchi difettosi (durante la lettura), dd si
fermerebbe se non si specificasse, ad esempio:

 dd if=/dev/sda of=/dev/sdx conv=noerror,sync bs=512 iflag=direct 

dove "noerror" forza dd a continuare dopo un errore di lettura, "bs=512"
specifica la dimensione minima del blocco-dati letto (in questo caso
equivalente alla dimensione minima di un settore su HardDisk), "sync" forza dd
a scrivere tutti i blocchi letti (inclusi quelli con errori, che così non
verranno saltati bensì riempiti con valori a 0), e "iflag=direct" forza il
necessario accesso diretto al device bypassando la cache del Kernel.
Certo è che così, leggendo settore per settore, non si ottimizza molto il
lavoro di un HD; perciò si potrebbe usare, in sostituzione a dd con bs=512,
dc3dd (http://dc3dd.sourceforge.net) che usa bs=32768 di default e scende
automaticamente al minimo bs=512 solo in caso di errori di lettura, donando un
pò di respiro all'HD:

 dc3dd /dev/sda of=/dev/sdx conv=noerror,sync bs=32K iflag=direct

Oltre a ciò, c'è sempre ddrescue
(http://www.gnu.org/software/ddrescue/ddrescue.html), buono per un'analisi
forense :)

Per sapere a che punto è il lavoro effettuato da dd, è sufficiente inviargli un
segnale "USR1" per interrogarlo (man docet). Si può provvedere sùbito ad
assegnare il PID del dd in questione, alla variabile "PIDPIPPO":

 dd if=/dev/sda of=/dev/sdx conv=noerror,sync bs=512 iflag=direct & PIDPIPPO=$!
 
(occhio alla "&" che porta il processo in background nel terminale) e poi
interrogare dd con:

 kill -USR1 $PIDPIPPO; sleep 1

Usando sdd, con il parametro -time, si invia il signal "QUIT":

 sdd if=/dev/sda of=/dev/sdx conv=noerror,sync bs=512 iflag=direct -time &
PIDPIPPO=$!
 ...
 kill -QUIT $PIDPIPPO; sleep 1

Usando dc3dd, si invia il signal "INFO":

 dc3dd /dev/sda of=/dev/sdx conv=noerror,sync bs=32K iflag=direct & PIDPIPPO=$!
 ...
 kill -INFO $PIDPIPPO; sleep 1


«Azzerare» lo spazio libero, prima di usare dd per creare un file-immagine
==========================================================================

Purtroppo il comando dd/sdd non può distinguere tra bit di file utili (negli
used block) e bit di file eliminati (nei free block), però è possibile riempire
tutto lo spazio libero disponibile nella partizione da backuppare (o in
ciascuna partizione esistente nell'intero disk da backuppare) con degli zeri
consecutivi (similmente ad una formattazione completa), affinchè
gzip/bzip2/lzma li possa ridurre ad un nonnulla (altro che valori sparsi e non
consecutivi) :D Perciò basterà creare un punto di montaggio provvisorio e
montare temporaneamente ciascuna partizione da backuppare, ad esempio sda1,
con:

 mkdir /PARTIZIONEDARIEMPIRE

e poi:
 
 mount /dev/sda1 /PARTIZIONEDARIEMPIRE
oppure
 mount -t ext3 /dev/sda1 /PARTIZIONEDARIEMPIRE
oppure
 ntfs-3g /dev/sda1 /mnt/PARTIZIONEDARIEMPIRE
 
(dove "-t ext3" può essere altro: vedasi man mount)
e poi crearvi dentro un file pieno di zeri:

 dd if=/dev/zero of=/PARTIZIONEDARIEMPIRE/fuffa

ovviamente così facendo ad un certo punto avverrà un errore di spazio
insufficiente: la botte è piena.
Per filesystem FAT32 si procede creando tanti file da 4GiB (che è il limite max
per un file in FAT32), cioè ad esempio con una riga in BASH tipo:

 FUFFALOL=1000; while [ $COUNTER -gt 0 ]; do dd if=/dev/zero of=/PARTIZIONEDARI
EMPIRE/fuffa.$FUFFALOL bs=4096 count=1048575; let FUFFALOL=FUFFALOL+1; done

che creerà tanti file di 4294963200Byte (4GiB - 4096B).

Dopo aver riempito la partizione, non rimane che eliminare il file "fuffa",
con:

 rm -vf /PARTIZIONEDARIEMPIRE/fuffa

e infine smontare la partizione, con:

 umount /PARTIZIONEDARIEMPIRE

Questo metodo è il migliore per una eliminazione veramente sicura dei dati nei
filesystem con journaling (in effetti è più sicuro di "sfill" e "srm" (del
pacchetto "secure-delete"), per non parlare di "wipe" (utile solo per piallare
partizioni intere: "wipe -kD /dev/sda1") e "shred"): alternando per 1...3 volte
una passata di numeri casuali et una di zeri ("dd if=/dev/urandom
of=/PARTIZIONEDARIEMPIRE/fuffa" "dd if=/dev/zero
of=/PARTIZIONEDARIEMPIRE/fuffa") si rende impossibile il recupero di dati dai
free block tramite tecnologia MagneticForceMicroscopy; altrimenti (se l'HD non
verrà aperto o se si tratta di SSD) è sufficiente una singola passata di zeri.
L'importante è evitare di farlo nella partizione di Sistema (quella montata in
"/") mentre il SO stesso gira (ergo occorre farlo da distro live o comunque da
altra Linux box). In alternativa a dd è possibile usare sdd, dcfldd, dc3dd :)


Creare un file-immagine di una partizione o dell'intero device
==============================================================
  
Per creare un file-immagine della partizione di origine "sda1" (smontata), e
salvarlo in una partizione di backup "sdx1" (montata, ad esempio, in
"/BACKUP"): 

 sdd if=/dev/sda1 | gzip  -c -9 | split -b 2048M - /BACKUP/backupmio.img.gz.
oppure
 sdd if=/dev/sda1 | bzip2 -c -9 | split -b 2048M - /BACKUP/backupmio.img.bz2.
oppure
 sdd if=/dev/sda1 | lzma  -c -9 | split -b 2048M - /BACKUP/backupmio.img.lzm.

dove sdd (oppure dd se siamo nostalgici) legge tutti i bit della partizione
sda1, e li invia a gzip/bzip2/lzma che li comprime al max con "-9" (default =
"-6", minimo = "-1"; attenzione che col max i tempi di lavoro si possono
decuplicare, ma cmq ho clonato una NTFS di 160GiB in un'ora con un DualCore e
2GiB-RAM), e li invia a split che li suddivide in stream lunghi al max 2048MiB
(= 2GiB = lunghezza max dei file per il filesystem dei DVD, nel caso si preveda
di masterizzare il tutto), e li salva aggiungendo un suffisso al nome del file:
"/BACKUP/backupmio0.img.gz.aa", "/BACKUP/backupmio0.img.gz.ab",
"/BACKUP/backupmio0.img.gz.ac", ecc. (il "." finale, e il nome tutto, è
puramente arbitrario: nessuno ci impedisce di scatenare la "notazione
ungherese" :D ).

Nel caso sdx1 fosse una partizione con FAT32, al max è possibile splittare a
"4096M" (4GiB è la lunghezza max dei file).

A parità di dati utili clonati e di parametro di compressione, lzma dovrebbe
comprimere meglio (e sorprendentemente più in fretta) di bzip2 che dovrebbe
comprimere meglio di gzip; ma in realtà la questione non è così semplice:
vedasi man :)

Volendo creare un file-immagine dell'intero disk "sda", basterà cambiare "sda1"
in "sda".

Volendo creare un file-immagine salvandolo su un device di un altro Sistema
accessibile in una rete sicura, basterà inserire netcat:

 sdd if=/dev/sda1 | gzip -c -9 | nc -q 2 xxx.xxx.xxx.xxx 6699

dove xxx.xxx.xxx.xxx et "6699" sono IP et porta del Sistema ricevente, però il
ricevente deve già essere pronto a ricevere con:

 nc -q 2 -l -p 6699 | split -b 2048M - /BACKUP/backupmio.img.gz.

dove "-l" specifica al netcat del ricevente di stare in ascolto sulla porta, ad
es., 6699.


Senza lo split, la riga diventa:
--------------------------------

 sdd if=/dev/sda1 | gzip -c -9 > /BACKUP/backupmio.img.gz

oppure, nel caso di netcat, sul Sistema ricevente:

 nc -q 2 -l -p 6699 > /BACKUP/backupmio.img.gz


Senza lo split e senza la compressione, la riga diventa:
........................................................

 sdd if=/dev/sda1 of=/BACKUP/backupmio.img

oppure, nel caso di netcat:

 sdd if=/dev/sda1 | nc -q 2 xxx.xxx.xxx.xxx 6699
e
 nc -q 2 -l -p 6699 > /BACKUP/backupmio.img

ed è utile per ottenere un unico file-immagine paragonabile ad una immagine-ISO
e quindi montabile (ad esempio in "/IMMAGINEBACKUP") con:

 mount -o loop,ro /BACKUP/backupmio.img /IMMAGINEBACKUP

dove "-t ext3" non è obbligatorio e indica il filesystem della suddetta sda1, e
"ro" impedisce modifiche accidentali.
Così è possibile accedere al contenuto del file-immagine al fine di ricopiare
(o modificare) qualche file senza dover ripristinare l'intero file-immagine.
 

Ripristinare il file-immagine di una partizione o dell'intero device
====================================================================

Avendo montato (come da esempio suddetto) la partizione di backup sdx1 (che
contiene il file-immagine) in "/BACKUP", e avendo la partizione di origine (su
cui avverrà il ripristino) smontata, basta dare:

 cat /BACKUP/backupmio.img.gz.* | gzip  -dc | sdd of=/dev/sda1
oppure
 cat /BACKUP/backupmio.img.gz.* | bzip2 -dc | sdd of=/dev/sda1
oppure
 cat /BACKUP/backupmio.img.gz.* | lzma  -dc | sdd of=/dev/sda1

dove cat legge i file (in ordine alfabetico), e li invia a gzip/bzip2/lzma che
li decomprime ("-d"), e li invia a sdd che li scrive sulla partizione "sda1".

Volendo ripristinare un file-immagine dell'intero disk "sda", basterà cambiare
"sda1" in "sda".

Volendo ripristinare un file-immagine leggendolo da un device di un altro
Sistema accessibile in una rete sicura, basterà inserire netcat, mettendolo in
attesa di ricevere lo stream sul Sistema ricevente:

 nc -q 2 -l -p 6699 | gzip -dc | sdd of=/dev/hda1

e poi inviando il file-immagine dal netcat dell'altro Sistema:

 cat /BACKUP/backupmio.img.gz.* | nc -q 2 xxx.xxx.xxx.xxx 6699


Senza lo split, la riga diventa:
--------------------------------

 gzip -dc /BACKUP/backupmio.img.gz | sdd of=/dev/sda1

oppure, nel caso di netcat, sul Sistema col file-immagine:

 sdd if=/BACKUP/backupmio.img.gz | nc -q 2 xxx.xxx.xxx.xxx 6699


Senza lo split e senza la compressione, la riga diventa:
........................................................

 sdd if=/BACKUP/backupmio.img of=/dev/sda1

oppure, nel caso di netcat:

 nc -q 2 -l -p 6699 | sdd of=/dev/hda1
e
 sdd if=/BACKUP/backupmio.img | nc -q 2 xxx.xxx.xxx.xxx 6699


Usare ntfsclone per il filesystem di Window$
++++++++++++++++++++++++++++++++++++++++++++

ntfsclone (del pacchetto ntfsprogs) si usa solo per filesystem NTFS ed è
migliore di dd/sdd perchè distingue tra used block e free block (non salva i
free block ed in fase di ripristino, dopo salvataggio verso standard output, li
ricrea con valori zero) quindi non è necessario un «azzeramento» preventivo dei
free block (per migliorare la compressione dei dati) ma è comunque utilissima
una compressione come per dd/sdd.
Insomma ntfsclone+gzip (o bzip2) equivale all'uso di partimage (PartitionImage)
ma è più affidabile ed in più funziona da Sistemi a 64bit; e similmente a
partimage non è possibile montare i suoi file-immagine «speciali» (creati col
parametro "-s") in loopback device; ma se non si sfruttassero i suoi
file-immagine «speciali», tantovarrebbe usare dd invece di ntfsclone.


Creare un file-immagine di una partizione con NTFS
==================================================

Per creare un file-immagine della partizione di origine "sda1" (smontata) con
NTFS, e salvarlo in una partizione di backup "sdx1" (montata, ad esempio, in
"/BACKUP"):

 ntfsclone -s -o - /dev/sda1 | gzip -c -9 > /BACKUP/backupmio.img.gz

dove "-s" salva in un formato speciale, "-o" specifica un nome per il
file-immagine (non preesistente), "-" specifica di usare lo standard output per
poterlo inviare a gzip (oppure bzip2 oppure lzma o altro) che comprime al max
(con "-9").


Ripristinare il file-immagine di una partizione con NTFS
========================================================

Avendo montato la partizione di backup sdx1 (che contiene il file-immagine) in
"/BACKUP", e avendo la partizione di origine con NTFS (su cui avverrà il
ripristino) smontata, basta dare:

 gzip -dc /BACKUP/backupmio.img | ntfsclone -r -O /dev/sda1 -

dove "-r" ripristina il formato speciale, "-O" forza la sovrascrittura, e "-"
specifica d'usare lo standard input.


Usare una live distro dedicata o di rescue
++++++++++++++++++++++++++++++++++++++++++

>>>> Clonezilla, basata su Debian :) Dicono che Clonezilla sia difficilmente
«comprensibile», ma io non lo credo anzi penso che sia la miglior distro live
dedicata alla clonazione di partizioni/disk; perciò ecco il sito di Clonezilla:
http://www.clonezilla.org
Clonezilla sfrutta dd, ntfsclone, partimage, partclone, ed evita di clonare lo
spazio inutilizzato, per i filesystem Ext2, Ext3, Ext4, ReiserFS, Reiser4, UFS,
XSF, JFS, HFS, HFSPlus, HPFS, FAT, NTFS, VMFS; e se occorre clonare filesystem
ZFS o altri non supportati, utilizza comunque dd per clonare tutto quindi
occorre provvedere prima «azzerando» lo spazio non occupato da file utili.
Clonezilla consente di comprimere e splittare i file-immagine ma è molto più di
una semplice GUI (difatti si può utilizzare anche senza la GUI by Ncurses):
oltre a clonare disk-to-disk anche includendo l'eventuale spazio su una
destinazione più grande, clona partition-to-partition anche allargando le
partizioni di destinazione.
Clonezilla è ricco di parametri (e quindi di schermate), ma invece di
ri-passare tutte le schermate per ripetere un lavoro, è possibile
uscire/riavviare alla Shell e ricopiare la riga di comando che Clonezilla
stesso visualizza prima d'iniziare un lavoro.
Insomma, l'unica vera mancanza è l'impossibilità di montare direttamente i
file-immagine di Clonezilla per estrarre dei singoli file.
Per info:
http://drbl.sourceforge.net/faq

>>>> G4L (GhostForLinux), basata su Debian, è un'ottima live dedicata alla
clonazione di dischi o partizioni.
Basta scaricare la ISO da:
http://sourceforge.net/projects/g4l/files/g4l%20ISO%20images/g4l-v0.34.iso/down
load
e masterizzarla su CD-R oppure installarla su pendrive (preventivamente
montato) tramite unetbootin v471 (o superiore).
G4L consente di comprimere e splittare i file-immagine ma è solo una GUI per
altri programmi:
-- in "RAW Mode" usa dd per i generici "Backup" e "Restore", e non distingue
tra spazio occupato da file utili (used block) e spazio occupato da file
eliminati (free block) quindi occorre provvedere prima «azzerando» lo spazio
non occupato da file utili; ma in caso di NTFS è possibile scegliere "NTFSCLONE
Backup" e "NTFSCLONE Restore" per i quali è usato appunto ntfsclone che rende
superfluo il preventivo «azzeramento» dei free block;
-- in "File Mode" usa partimage (PartitionImage) che è utile per creare
file-immagine di partizioni (comprimendo con gzip/bzip2 e splittando il
risultato in file di dimensioni volute) evitando di clonare lo spazio
inutilizzato (per i tipi di filesystem Ext2, Ext3, ReiserFS, HPFS, UFS, XFS,
JFS, FAT, NTFS, HFS).
Purtroppo, non ho ancòra trovato info sul come montare un file-immagine (non
splittato e non compresso) di PartitionImage al fine di poter estrarre dei
file; perciò per ora, in caso di bisogno, ripristino il file-immagine su una
partizione non usata, poi la monto, e infine copio i file che servono; se non è
disponibile una partizione inutilizzata, ma c'è abbastanza spazio in una
partizione utilizzata, creo un file pieno di zeri e lo assegno ad un loopback
device e poi lo formatto al fine di simulare una partizione in cui ripristinare
il file-immagine:
 sdd if=/dev/zero of=/PARTIZIONEUTILIZZATA/FILEZERO bs=1M count=100MB
 losetup /dev/loop69 /PARTIZIONEUTILIZZATA/FILEZERO
 fdisk /dev/loop69
  ...(formattazione)...
 sdd if=/BACKUP/backupmio.img of=/dev/loop69
 mount -o loop,ro /dev/loop69 /IMMAGINEBACKUP
  ...(copia dei file utili)...
 umount /dev/loop69
 losetup -d /dev/loop69
Per info:
http://www.partimage.org

>>>> SystemRescue, basata su Gentoo :) E' una delle migliori rescue live per
riparare e modificare partizioni e MBR, nonchè per creare file-immagine.
Sito:
http://www.sysresccd.org/Main_Page
Download:
https://sourceforge.net/projects/systemrescuecd/files/sysresccd-x86/1.5.8/syste
mrescuecd-x86-1.5.8.iso/download
Per installare la ISO su pendrive, basta creare un punto di montaggio e
montarla in loop:

 mkdir /srcd
 mount -o loop,exec /percorso/completo/systemrescuecd-x86-x.y.z.iso /srcd

poi smontare il pendrive interessato, se è già stato montato, ed eseguire lo
script previsto per l'installazione su pendrive:

 cd /srcd
 ./usb_inst.sh dialog
 
ed infine smontare la ISO:

 cd /
 umount /srcd

In caso di problemi:
http://www.sysresccd.org/Sysresccd-manual-
it_How_to_install_SystemRescueCd_on_an_USB-stick
Tutto ciò perchè unetbootin ha notevoli difficolta ad installare SystemRescueCD
v1.5.x :b

>>>> PartedMagic, basata su Slackware :) Last but not least, ha qualche
strumento in più ed è da preferire a SystemRescue se ha versioni più recenti di
"PartitionImage", "GpartEd", "TestDisk", "ddrescue", "sfdisk", "ntfs-3g", ecc.
ma è altrettando valida per il rescue.
Sito:
http://partedmagic.com
Download:
http://sourceforge.net/projects/partedmagic/files/partedmagic/Parted%20Magic%20
5.2/pmagic-5.2.iso.zip/download  

Ovviamente sono molte le distro utilizzabili per clonare/recuperare; specie
considerando il fatto che nella maggior parte delle situazioni è sufficiente
disporre di un solo specifico tool capace di clonare un solo specifico
filesystem/disk; ma come regola generale vale sempre: vecchio hardware
necessita di vecchio software, ergo conservare il più possibile le ISO/CD delle
vecchie live distro, qualunque esse siano :) Anche perchè le vecchie distro
hanno DE leggerissimi rispetto a quelli odierni, e comunque possono runnare
allegramente con 64MiB-RAM :)
Da mettere nei preferiti:
http://www.livecdlist.com
http://distrowatch.com


Usare tar & company per backuppare a livello di file
++++++++++++++++++++++++++++++++++++++++++++++++++++

E' possibile backuppare tutta una Linux box semplicemente copiandone i file,
magari mentre non runna così ci si avvicina il più possibile alla condizione di
«immagine» del Sistema.
Backuppare a livello di file è utile quando c'è la necessità di recuperare solo
qualche file; perciò è possibile creare un semplice backup non incrementale e
non differenziale con tar (da root) creando un archivio compresso contenente
tutta la radice (meno qualcosina):

 tar -cvp --bzip2 -f /ARCHIVIOBACKUP/BACKUP.tar.bz2 --exclude=/lost+found
--exclude=/sys --exclude=/media --exclude=/tmp --exclude=/home/*/.gvfs
/PUNTO/MONTAGGIO/PARTIZIONE/DA/BACKUPPARE

da fare fuori dalla Linux box interessata; oppure:

 tar -cvp --bzip2 -f /ARCHIVIOBACKUP/BACKUPSYS.tar.bz2
--exclude=/BACKUP.tar.bz2 --exclude=/lost+found --exclude=/proc --exclude=/mnt
--exclude=/sys --exclude=/media --exclude=/tmp --exclude=/var/tmp/*
--exclude=/dev/* --exclude=/home /
 tar -cvp --bzip2 -f /ARCHIVIOBACKUP/BACKUPHOME.tar.bz2 --exclude=/home/*/.gvfs
/home

da fare mentre la Linux box gira.
"--bzip2" è sostituibile da "-j" ma non è universalmente compatibile negli
script. Aggiungere "--exclude" a piacere onde evitare di copiare device e file
che manderebbero in errore tar.
La home è utile metterla in un archivio a parte quand'è «pesante» e/o quando si
trova in un'altra partizione (diversa da quella della radice).
In caso di bisogno è anche possibile ripristinare il tutto, rispettivamente
con:

 tar -xvp --bzip2 -f /ARCHIVIOBACKUP/BACKUP.tar.bz2 -C /DIR/MONT/PART/BACKUP

 tar -xvp --bzip2 -f /ARCHIVIOBACKUP/BACKUPSYS.tar.bz2 -C / 
 tar -xvp --bzip2 -f /ARCHIVIOBACKUP/BACKUPHOME.tar.bz2 -C /home

A seconda delle necessità/preferenze, si può anche usare cpio
(http://wwwcdf.pd.infn.it/AppuntiLinux/a2220.htm#almltitle1374) specie se con
opzione "-k" (http://heirloom.sourceforge.net).
Vedasi anche:
http://wwwcdf.pd.infn.it/AppuntiLinux/a2845.htm#almlindex35026
http://www.pluto.it/files/journal/pj9911/backups.html


Conclusioni
+++++++++++

Si sente la mancanza di un pratico metodo per estrarre dei singoli file da un
file-immagine compresso, senza doverlo decomprimere prima.
Son contento che certi utenti di Window$ possano sfruttare "Acronis True Image"
anche per creare un file-immagine compresso di una partizione con
Ext2/Ext3/..., ma da esso non è possibile estrarre nulla (si può solo
ripristinarlo completamente quindi tantovale usare dd+gzip). E per quanto
riguarda l'hot backup (SO che backuppa sè stesso), non ho mai gradito la
«tecnologia» VSS (VolumeShadowCopyService) dei filesystem NTFS, e non credo che
si tratti di un vero dump del filesystem (dump&restore docet: http://surf.ml.se
ikei.ac.jp/~nakano/dump-restore/dump-restore-mini-HOWTO.en.html e http://dump.s
ourceforge.net/isdumpdeprecated.html).
Preferirei affidarmi a progetti più interessanti e potenti tipo "KDar"
(http://kdar.sourceforge.net basato su "DAR" http://dar.linux.free.fr),
"Bacula" (http://www.bacula.org), "Amanda" (http://www.amanda.org).
 

Byez!

Morbido6868


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


**********************
* 0x04 :: Real Italy *
**********************


Tutto ha un inizio, come nelle più belle favole, con la sola differenza che qui 
non si parla ne dei fratelli Grimm ne di Esopo, qui si parla della vita,
quella vera, quella vissuta giorno dopo giorno... O forse no?! 
Il confine tra ciò che è realtà e ciò che è "finzione" oggigiorno è molto 
sottile, quasi invisibile, e alcuni addirittura ne ignorano l'esistenza.
E' l'esempio di ciò che ho visto ultimamente sugli schermi televisivi, che mi ha
fatto sussultare, e venir voglia di scrivere un articolo a riguardo, ma diverso 
dagli altri che ho letto in qusti giorni ...

E' iniziato tutto in un giorno caldo di fine Agosto, un giorno come tanti, 
una notizia come tante altre al tg, una ragazza sparita dall'oggi al domani nel 
nulla, una madre che giustamente si appella ai media per far luce su una 
scomparsa che fin dall'inizio cela qualcosa di nascosto, qualcosa che qualcuno 
di sicuro sa, ma che probabilmente come nel caso dell'assassino più crudele 
che sputa in faccia al valore intrinseco della vita, non ammetterà mai.

E ha inizio così il tam tam delle notizie, il rincorrersi degli "aggiornamenti"
da un paese che fino a quel momento si trovava in un angolino sperduto sulla 
carta geografica, la ricerca incessante dello scoop...
Così giorno dopo giorno si delinea una storia dentro la storia, la ragazza 
scomparsa forse è scappata, da una realtà che gli stava troppo stretta, 
da una famiglia forse troppo "oppressiva", scappata da sola, 
verso chissà quale helldorado.

L'italiano inizia ad appassionarsi al caso, come se fosse un diretto discendente
di Sherlock Holmes, e intanto col telecomando da un programma di approfondimento
ad un altro, da un telegiornale all'altro, da una conferma di arresto 
ad un'altra, beh... l'italiano che fa?! Zapping, e passa così col suo bel 
telecomando in mano al Grande Fratello: "Chissà che starà facendo Gennaro, 
chissà se si è messo con Clara" pensa...
(Ovviamente sono nomi puramente "casuali")

Poi cambia nuovamente canale (forse c'è la pubblicità, chissà) e scopre che un 
uomo che fino a quel momento sembrava la persona più triste, fragile e buona 
al mondo, diventa Il Mostro, che cede agli inquirenti che lo interrogano in 
Questura, il Mostro che fa ritrovare il cadavere di quella povera ragazza in 
un pozzo, e che ammette addirittura di aver abusato di lei dopo averla uccisa...

Mi fermo qui, ho già detto troppo. 
Mi mi fermo qui perchè non è del caso in se che voglio parlare, 
sappiamo tutti com'è andata, sappiamo tutti che non è finita qui...
Quello di cui vorrei parlare è il mondo in cui ultimamente le notizie ci 
vengono "offerte", il modo in cui siamo costretti a 
leggere o vedere i fatti del giorno...

Una ragazza viene assassinata, ed ecco subito lo spunto per televisioni,
internet, radio e giornali, per riempire quegli spazi sempre più vuoti che 
l'informazione in generale in Italia ha e che vanno di pari passo con le menti 
sempre più vuote di un popolo che sa sempre meno a chi credere. 
Ecco allora lo spunto per non parlare almeno una volta (finalmente) delle donne
del Presidente o del nuovo calendario della show-girl di turno...

È ovvio allora che i media ne approfittino, si buttino a capofitto come delle 
iene affamate su delle prede inermi col telecomando in mano...
È ovvio che i media se ne approfittano e riempiano quegli spazi vuoti citati 
poc'anzi, con programmi e programmi tutti uguali, che dicono le stesse cose, 
con un offerta creata con lo stampino, con il solo scopo di strappare quel 
punticino in più al rivale.

E così su un canale ti trovi la ricostruzione dettagliata di un omicidio, 
magari corredata da un bel plastico, su un altro canale trovi la stessa identica 
cosa (magari senza il plastico, in tempi di crisi forse certe reti televisive 
hanno meno fondi delle altre...), e su un altro ancora il Grande Fratello, 
giunto ormai all'undicesima edizione, che alla fine della fiera, 
fa i suoi 6 milioni di share e batte anche il plastico...



Sarò troppo polemico, troppo retrograda, troppo ossessionato da quel tocco di 
imperfezione che il giornalista deve mettere nella notizia, in quella notizia 
che deve fare sua,dove deve mettere il cuore,dove deve mettere tutto se stesso..

Il mondo mediatico però è sempre più "spietato", e le notizie vengono offerte al
pubblico in una maniera apposita, creata a pennello per fare più ascolti o per 
vendere più copie, tralasciando quella "professionalità" che il prodotto offerto
dovrebbe avere. Ed ecco così che un assassinio come tanti altri (ne abbiamo 
visti di tutti i tipi in Italia, non facciamo i puristi e i moralisti per 
favore!) venir ripreso 24 ore su 24 da ogni televisione possibile, ed ecco che i
giornalisti tutti i giorni scrivono di quella ragazza sui giornali, ed ecco che
ogni giorno che passa l'italiano si appassiona sempre più al "giallo", tutto 
assomiglia tristemente a quel meccanismo che è il reality, e forse purtroppo 
finisce per diventarlo.

Non è finita qui purtroppo, il rincorrersi delle notizie e degli scoop conditi
da improbabili ricostruzioni con attori presi per quattro soldi continueranno a
lungo, e la gente che spesso non ha altro da poter guardare o da poter leggere o
da poter ascoltare, finirà per guardare ancora una volta quel reality sulla vita
che non c'è più di una povera ragazza...

Le coscienze di tutti noi sono nobili, nessuno è inferiore o superiore agli 
altri, basta solo spegnere la tv se ancora ci propone il solito prodotto, basta
non comprare il giornale la mattina, se ancora in prima pagina campeggia la
solita notizia che da due mesi ci viene "offerta", basta spegnere la radio se lo
speaker accenna a quel determinato paesino della Puglia, basta spegnere tutte 
queste cose, e accendere la cosa più importante di tutte, il cervello, 
solo così forse avremo più notizie e meno reality.


dany15gni


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


********************************************
* 0x05 :: Programming /dev/dsp For Dummies *
********************************************

Andiamo a vedere come funziona uno dei files virtuali più fighi di linux:
/dev/dsp

Innanzitutto, come tutti i files in /dev punta a un device fisico e viene
gestito da OSS: la vecchia architettura sonora di linux.

Per fare una prova iniziale, date un semplice

cat /dev/urandom > /dev/dsp

Questo scriverà bytes casuali sulla scheda audio: sentirete un fruscio XD

Prima di passare al codice vero e proprio, tenterò di spiegarvi come funziona
in parole poverissime un altoparlante e un DAC (Digital to Analog Converter) 
di una comune scheda audio.

Premettiamo una parola:
Hz = Hertz = "volte al secondo"

1) Altoparlante audio: ha una semplicissimo bobina dietro alla membrana che,
in base alla tensione su essa, attira o respinge la membrana.
Naturalmente la membrana è tenuta "al centro","in volo" da un secondo magnete :)
Cambiando, ad esempio, 1000 volte al secondo la tensione sulla bobina, 
la membrana vibrerà a 1000 Hz e nell'aria si formerà un'onda a 1000Hz: 
un suono..più precisamente un fischio rompiscatole, o beep :)

2) Il DAC della scheda audio ha il compito di trasformare un segnale digitale 
proveniente dalla motherboard(CPU, alla fine xd) in segnale analogico. 
Naturalmente riuscirà a creare al max una tensione da circa -2 a +2 Volt. 
Poi il segnale verrà amplificato da amplificatori esterni (alla scheda audio)
e arriverà alla bobina della cassa :)

Ora entra in gioco un parametro noioso: la "Frequenza di Campionamento".
Essa rappresenta quante conversioni dovrà eseguire ogni secondo il DAC. 
Naturalmente, se sono 1000 conversioni/s, la frequenza massima che
potrà far uscire la scheda audio sarà di 500 vibrazioni/s!

Per la musica ad alta qualità(CD-Rom compresi) c'è lo standard di 44100 hz di
campionamento: la frequenza massima in uscita sarà 22050hz: il nostro orecchio 
capta fino ai 20000hz, quindi è più che ottima! :P

Altra informazione che vuole il DAC è quanti bit usare per ogni conversione:
Normalmente si può scegliere fra 8 o 16 bit.
Usando 8 bit, si potranno ottenere 2^8(256) livelli di tensione diversi.
Usando 16 bit, si potranno ottenere 2^16(65536) livelli di tensione diversi.
Il che vorrà dire maggiore qualità sonora.

Poi c'è da contare anche il fattore Mono/Stereo: usando lo stereo andranno
usati il doppio dei bytes:

Quindi:
Bytes/s = Freq_di_camp * Byte_per_conv * Numero_di_casse;

Per un semplice secondo di musica su un CD si hanno:
44100 * 2 * 2 = 176.400 bytes = 176.4 kb di dati da inviare alla scheda audio
ogni secondo.

Per comodità, i bytes si scrivono signed: da -127 a +128 oppure 
da -65535 a +65536.

Naturalmente, -127 = -2Volt in uscita; 128 = +2Volt in uscita
come -65535 = -2Volt in uscita; 65536 = +2Volt in uscita.

Ultimo accenno teorico: /dev/dsp è gestito dal vecchio OSS, oramai sovrastato
dalla potenza di ALSA; ma imho è il migliore per imparare a gestire una
scheda audio. :)

Ora che avete capito come funziona la scheda audio in teoria, 
iniziamo a vedere un po' di codice. :P

Per prima cosa apriamo il device /dev/dsp in scrittura.

-----

int fd = open("/dev/dsp", O_WRONLY);
if (fd < 0)
{
	perror("open of /dev/dsp failed");
	exit(1);
}

-----

Ricordatevi che per aprire /dev/dsp in scrittura bisogna lanciare il programma
appartenedo al gruppo 'audio', o in ogni caso *COME ROOT*.

Ora impostiamo tramite ioctl() le varie opzioni :)

un'esempio di uso della ioctl è:

-----

int r;
int dato;
dato = DATO_INIZIALE;
r = ioctl(fd,COMANDO,&dato);
if(r==-1 || dato!=DATO_INIZIALE)
{
	fprintf(stderr,"Cannot set %d = %d\n",COMANDO,dato);
	exit(1);
}

-----

il 'dato' va passato via puntatore: la ioctl ci potrebbe scrivere anche 
dentro un possibile "output". Ma nei nostri casi riscrive lo stesso valore
se è andato tutto bene :)

Detto questo, vi passo una mia funzione che semplifica l'uso delle ioctl con
la scheda audio:

-----

void set_audio(int fd, int op, int arg)
{
    int r,a;
    a = arg; r = ioctl(fd,op,&a);
    if(r==-1 || a!=arg){fprintf(stderr,"Cannot set %d = %d\n",op,arg); exit(1);}
}

-----

e nella main inviamo tre impostazioni alla scheda audio:

-----

set_audio(fd,SOUND_PCM_WRITE_BITS,8); 	 /* 1 byte(8 bit) per ogni conversione*/
set_audio(fd,SOUND_PCM_WRITE_CHANNELS,1);/* mono!!!! [iniziamo dal semplice!] */
set_audio(fd,SOUND_PCM_WRITE_RATE,44100);/* 44100 campionamenti al secondo    */

-----

Il codice risultante sarà:

-----

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>

void set_audio(int fd, int op, int arg)
{
    int r,a;
    a = arg; r = ioctl(fd,op,&a);
    if(r==-1 || a!=arg){fprintf(stderr,"Cannot set %d = %d\n",op,arg); exit(1);}
}

int main()
{
	int fd = open("/dev/dsp", O_WRONLY);
	if (fd < 0)
	{
		perror("open of /dev/dsp failed");
		exit(1);
	}

	set_audio(fd,SOUND_PCM_WRITE_BITS,8); /*1 byte(8 bit) per ogni conversione*/
	set_audio(fd,SOUND_PCM_WRITE_CHANNELS,1); /*mono!![iniziamo dal semplice!]*/
	set_audio(fd,SOUND_PCM_WRITE_RATE,44100); /*44100 campionamenti al secondo*/

	/* scheda audio pronta! */

	close(fd);

	return 0;
}

-----


Benissimo! e ora vediamo come scrivere una funzione che crei il buffer su
misura per far beepare a 1000Hz gli speaker!

Quello che dobbiamo fare noi è creare una sinusoide che ondeggi a 1000Hz.
Quindi... abbiamo 44100 bytes da creare: ogni byte con la posizione
in quell'istante della membrana.

Beh, potremmo usare la funzione matematica sin() :D

Innanzitutto vogliamo far fare 1000 "su e giù"(XD) alla sinusoide al secondo;
Se ogni secondo suona 44100 bytes, dobbiamo fare una sinusoide che completi
il suo giro in 1/1000 secondi: dovrà durare 44100/1000 bytes

Impostiamo una proporzione per portare dai 44100/1000 frames a 360(angolo giro)
i : (44100/1000) = i_gradi : 360
che diventa:
i_gradi = (i * 360) / (44100/1000)
i_gradi = i * 360 / 44100 * 1000

Poi trasformiamo da gradi a radianti
(le funzioni trigonometriche si computano in radianti):

i_gradi:180=i_radianti:PI_GRECO
quindi:
i_radianti = (i_gradi * PI_GRECO) / 180.

La funzione sin, visto che ha un range da 0 a 1,
andrà moltiplicata per il volume(0-128):

Quindi, [usiamo per esempio 70 come volume, volume "medio" XD]
Bytes[i] = sin( i * 360 / 44100 * 1000 * 3.14 / 180 ) * 70;

semplifichiamo 360 con 180:
Bytes[i] = sin( i * 2 * 3.14 * 1000 / 44100 ) * 70;

Ok, quindi, per generare un beep basta questa formula:
Bytes[i] = sin( i * 2 * 3.14 * FREQUENZA / CAMPIONAMENTO) * VOLUME

Semplice! :D

Raccontato al computer:

-----
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h> //necessita di -lm
#include <sys/ioctl.h>
#include <linux/soundcard.h>

void set_audio(int fd, int op, int arg)
{
    int r,a;
    a = arg; r = ioctl(fd,op,&a);
    if(r==-1 || a!=arg){fprintf(stderr,"Cannot set %d = %d\n",op,arg); exit(1);}
}

int main()
{
	char bytes[44100];
	int i, fd;

	/* accede alla scheda audio in modalità scrittura */
	fd = open("/dev/dsp", O_WRONLY);
	if (fd < 0)
	{
		perror("open of /dev/dsp failed");
		exit(1);
	}

	/* imposta le varie opzioni */
	set_audio(fd,SOUND_PCM_WRITE_BITS,8); // 1 byte(8 bit) per ogni conversione
	set_audio(fd,SOUND_PCM_WRITE_CHANNELS,1);//mono!!!! [iniziamo dal semplice!]
	set_audio(fd,SOUND_PCM_WRITE_RATE,44100);//44100 campionamenti al secondo

	/*scheda audio pronta! */

	/*crea il buffer */
	for(i=0;i<44100;i++)
	{
		bytes[i] = sin(i * 2 * 3.14 * 1000 / 44100) * 70;
	}

	/* scrive i bytes nel buffer della scheda audio */
	write(fd,bytes,sizeof(bytes)); 

	/* aspetta finchè non è stato scritto tutto sul DAC / altoparlanti */
	ioctl(fd,SOUND_PCM_SYNC,0);

	/* chiude il file */
	close(fd);

	return 0;
}

-----

Ecco qui il nostro programma bello pronto :)

Ultima nota: per sommare più frequenze assieme basta sommarle "matematicamente".
Esempio:

-----

for(i=0;i<44100;i++)
{
	bytes[i] = sin(i * 2 * 3.14 * 1000 / 44100) * 69;
	bytes[i] += sin(i * 2 * 3.14 * 100 / 44100) * 59;
}

-----

* Attenzione: se la somma dei volumi supera 128, il suono risulterà distorto! *
(in questo caso, 69+59=128 :PP)

Questo creerà un buffer che farà suonare 1000 Hz e 100 Hz assieme :))

Con questo vi saluto e vi auguro buon audio-coding! :D

r0b0t82


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


***************************************************************************
* 0x06 :: Sistema idroponico per piccole piantagioni di piante domestiche *
***************************************************************************


Per chi si trova in ambienti cittadini oppure nella propria camera e vorrebbe
tenere delle pianticelle come la salvia, il rosmarino, il basilico e perchè no,
una pianta di pomodoro, i vasi tradizionali presentano i seguenti vantaggi e
svantaggi:

Vantaggi:
______________________________________,
1| Relativamente semplice da preparare|
2| Si può spostare facilmente         |
3| La pianta tende a restare piccola  |
--------------------------------------'

Svantaggi:
______________________________________.
1| la terra tende a impoverirsi       |
2| Scomodo per piante grosse          |
3| Ha bisogno di molte più cure       |
4| Favorisce il formarsi di parassiti |
5| Rischio di soffocamento (pianta)   |
--------------------------------------'

Un sistema idroponico permette di sopperire a alcune di queste lacune..
ecco i principali vantaggi / svantaggi:

Vantaggi:
_____________________________________,
1| La pianta è perennemente concimata|
2| La pianta è perennemente innafiata|
3| Nessun rischio di soffocamento    | 
4| Crescita 3 o 4 volte più veloce   |
5| Non da problemi di dimensioni     |
-------------------------------------'

Svantaggi:

_____________________________________,
1| Consumo di corrente elettrica     |
2| Rel. complicato da spostare       |
3| Necessità di controlli periodici  |
4| Poco efficente per diverse piante |
-------------------------------------'

Come ben sapete o dovreste sapere le più grandi piantagioni indoor del mondo
sono idroponiche per il più favorevole rapporto vantaggi/svantaggi. in oltre
c'è da dire che essi vengono spesso accostati a impianti di illuminazione..

Ecco le linee di massima per produrre un impianto casalingo funzionale. con esso 
non avrete più problemi ad innaffiare le piante, visto che esse saranno sempre 
in mezzo all'acqua =D

In primo luogo vi serve un recipiente dove far passare le radici. 
Diciamo che per piccole piante, uno spazio di 1-2 dm3 è più che sufficente, 
mentre che se volete puntare a piante che raggiungono i 2 metri 
dovete ingrandire questa misura.

Per "piantagioni" composte da una sola pianta, come in genere si trovano nelle 
cucine o nelle camere ho visto utilizzare anche vaschette vuote del gelato, 
in se basta recuperare un recipiente che non perda (non volete mica una palude!)
con un coperchio.
Nel coperchio dovete Fare dei 4 fori + 1 aggiuntivo per ogni pianta extra che 
volete avere. 
Due fori devono far passare un tubo di gomma forellato che è collegato a una 
pompa d'acquario. per intenderci quelle che buttano fuori aria.
il tubo deve essere attaccato al fondo della vasca, e con un ago fate dei buchi
in modo che l'aria possa uscire in modo uniforme e costante. 
Sul coperchio invece dovete fare agli estremi due buchi per far uscire gli 
estremi del tubicino, in oltre dovete prevedere un buco (con un tappo per 
evitare dell'evaporazione) per aggiungere e controllare il livello dell'acqua, 
il ph ecc.. e in fine un buco per le piante. ecco un disegno ascii 
per farvi capire:

La vasca montata:


| |               ||   Ok, è un aborto ma l'idea la da;
| |               ||  Il perimetro esterno è la vasca. il coso interno è il
|_L=-=-=-=-=-=-=-=I|  tubicino forellato che passa per il fondo.
'''''''''''''''''''' 
   ,--------------,----------------[pompa]
   |         ____ |
,--|---\ /---' '--|--,
|  |   ]&[        |  |  Questo è come *dovrebbe* essere il coperchio.
|      |&|           |  le due strisce collegate alla pompa sono
                        i capi dei tubicini.

                          \ / questo è il "sedime" dove la pianta dovrà essere
                          ]&[ inserita, & è del cotone che va a pescare l'acqua
                          |&| il livello dell'acqua deve essere sempre all'
                              altezza della fine di |&| specialmente nelle prime
                              fasi di sviluppo della pianta.
              _____
L'ultimo buco, ' '  serve a controllare, ad aggiungere acqua e i nutrimenti.

Potete trovare tutte le "formule" di coltivazione idroponica delle principali 
colture su internet. inoltre se aggiungete coloranti o particolari sostanze
nutritive che contengono un determinato pigmento colorato la pianta lo assorbirà
e farà dei fiori o dei frutti colorati. che comunque sconsiglio di mangiare nel
caso sia colorante chimico.


Pensavateche fosse più complesso? ricordatevi che la pianta ha sempre bisogno
di acqua con dentro aria disciolta ( Eh già, le piante [e i pesci] non dividono
l'acqua in idrogeno e ossigieno, semplicemente catturano l'aria sciolta dentro
l'acqua) e nutrimento. Con  un impianto del genere non avrete più problemi,
per chi come me ha il riscaldamento a serpentina, di dover rialzare le piante 
(anche se un minimo fa sempre bene) anzi, il calore del riscaldamento unito al
sistema idroponico farà crescere le vostre piante come funghi.

DECLINO OGNI RESPONSABILITÀ RIGUARDO ALL'USO IMPROPRIO DI QUANTO RIPORTATO QUI 
SOPRA AI FINI DI PRODURRE BOMBE,ARMI E TUTTO IL RESTO CHE NON SIA APPROVATO DAL
REGIME DI COMANDO ATTUALE DELLA TUA NAZIONE.

UNITI PER UN MONDO SENZA POMODORI ASSASSINI.

Su youtube potete vedere vari esempi di quanto espresso in questo articolo..

buona realizzazione e bye

turbocotoletta, MMX


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


***********************
* 0x07 :: PNM drawing *
***********************

Vi piace l'ascii art? Non amate uscire dal terminale? Allora i formati NetPBM 
fanno per voi!

NetPBM è un toolkit sviluppato dal programmatore Jef Poskanzer negli oramai lon-
tani anni ottanta, permette di creare e manipolare immagini e convertirle in nu-
merosi formati. 
Si presentano essenzialmente tre estensioni: PBM, PGM e PPM, più la "metaesten-
sione" PNM, che può sostituire tutte quelle precedentemente elencate.


###LINEE BASE
Un file contenente un'immagine PNM è formato da:
- un header, sempre in caratteri ASCII, contenente:
	- un "descrittore" di due bytes + newline (a capo);
	- commenti preceduti da '#'
	- due numeri interi decimali separati da uno spazio che rappresentano 
	  rispettivamente la largezza e la lungezza del'immagine + newline;
	- se il formato lo richiede, un numero intero decimale che rappresenta 
	  la quantità di colori nella scala, + newline;
- i bytes dell'immagine, in ASCII o in binario, a seconda del tipo di codifica.

Per creare l'immagine basta scrivere i valori con un qualsiesi editor di testo
e salvare il file nel formato corretto (oppure, per i maniaci della consol...
ehm, amanti della semplicità, 'pnmscale 20 | pnmtopng > file.png' e avrete 
direttamente una png :) ).

###I descrittori
Danno al programma indicazioni sul tipo di dati che andrà ad interpretare. 
Sono:
-------------------------------------------------------------------------------
|P1 | File PBM, in bianco e nero, codifica ASCII			      |
|P2 | File PGM, in scala di grigi, codifica ASCII			      |
|P3 | File PPM, a colori, codifica ASCII				      |
-------------------------------------------------------------------------------
Per la codifica binaria:
-------------------------------------------------------------------------------
|P4 | File PBM, in bianco e nero					      |
|P5 | File PGM, in scala di grigi					      |
|P6 | File PPM, a colori						      |
-------------------------------------------------------------------------------

###Height and width
Ogni riga del file corrisponde a un segmento di pixel sull'immagine. La riga
deve contenere tanti caratteri quanti ne sono espressi nell'header, alla fine 
di ogni riga si manda a capo.

Ogni carattere che fa parte del segmento "immagine" è:
- se la codifica è ASCII:
	- un carattere numerico ASCII
	- separato da quello accanto da uno SPAZIO
- se è in binario
	- risulterà leggibile solo alle macchine
	- non ci devo essere spazi


###PBM
Il formato PBM è in più semplice e il primo ad essere sviluppato. SI basa sul
principio 0 = bianco, 1 = nero.
I descrittori per ASCII e binario sono rispettivamente P1 e P4, come intuibile
non necessita del valora della scala.

Esempio:
-------------------------------------------------------------------------------
P1
#commento
29 10
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 0 0 
0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 1 0 0 0
0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0 0 1 0 0 1 1 1 1 1 1 1 0 1 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0
0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0
0 0 0 0 0 1 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-------------------------------------------------------------------------------

###PGM
Il PGM permette invece di usare una scala di grigi per colorare l'immagine. 
La quantità di colori nella scala viene definita da un numero nella riga sotto-
stante alle dimensoni. In questo caso, 0=nero e il massimo valore nella scala 
è il bianco

Esempio:
-------------------------------------------------------------------------------
P2
#commento
29 10
4
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 2 0 0 0 0 0 3 0 0 0 0 0 0 0 4 4 0 0 0 0 
0 0 0 0 1 0 0 0 0 2 0 0 0 0 3 0 3 0 0 0 0 0 4 0 0 4 0 0 0
0 0 0 1 0 0 0 0 0 2 0 0 0 3 0 0 0 3 0 0 0 4 0 0 0 0 4 0 0
0 0 1 0 0 0 0 0 0 2 0 0 3 0 0 0 0 0 3 0 4 0 0 0 0 0 0 4 0
0 0 1 0 0 0 0 0 0 2 0 0 3 3 3 3 3 3 3 0 4 0 0 0 0 0 0 4 0
0 0 0 1 0 0 0 0 0 2 0 0 3 0 0 0 0 0 3 0 0 4 0 0 0 0 4 0 0
0 0 0 0 1 0 0 0 0 2 0 0 3 0 0 0 0 0 3 0 0 0 4 0 0 4 0 0 0
0 0 0 0 0 1 1 0 0 2 0 0 3 0 0 0 0 0 3 0 0 0 0 4 4 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-------------------------------------------------------------------------------

###PPM
Nel "Portable pixmap" cambiano alcune cose. Essendo a colori, ogni pixel è 
rappresentato da una tripletta di valori RGB. Come nel PGM anche qui è necessa-
rio inserire un valore di "fondoscala" (di solito 255).

Esempio (tagliato per problemi di spazio):
-------------------------------------------------------------------------------
P3
#commento
10 10
255
0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  
0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  255 0 0  255 0 0  0 0 0  0 0 0  255 255 0   
0 0 0  0 0 0  0 0 0  0 0 0  255 0 0  0 0 0  0 0 0  0 0 0  0 0 0  255 255 0  
0 0 0  0 0 0  0 0 0  255 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  255 255 0 
0 0 0  0 0 0  255 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  255 255 0
0 0 0  0 0 0  0 255 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  255 255 255 
0 0 0  0 0 0  0 0 0  0 255 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  255 255 255
0 0 0  0 0 0  0 0 0  0 0 0  0 255 0  0 0 0  0 0 0  0 0 0  0 0 0  255 255 255 
0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 255 0  0 255 0  0 0 0  0 0 0  255 255 255  
0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0 
-------------------------------------------------------------------------------


###Utilità
La prima cosa che salta all'occhio studiando il NetPGM è la semplicità di uso
e implementazione. Nel pacchetto sono incluse parecchie utility per operazioni
di base e applicazione di filtri.
Consiglio di usare pnmscale per ingrandire le immagini prodotte a mano:
$ pnmscale 20 file.pnm

Per unire vari comandi si possono usare le pipe. Ad esempio, per mettere un 
contorno roso ad un'immagine png:
$ pngtopnm file.png |pnmmargin -color red 3 | pnmtopng >file2.png

Oppure, per farsi uno screenshot:
$ xwd -root |xwdtopnm | pnmtopng >screen.png

E chi più ne ha, più ne metta!

Con un 'ls /usr/bin |grep pnm' possiamo rapidamente trovare tutti tools che 
NetPNM mette a disposizione, e con le omonime librerie possiamo crearne di 
nuovi. Il limite è solo la fantasia!

###Ma...
Il pgm non prevede alcuna compressione, se non la codifica 
binaria, per questo conviene usarlo per operare solo temporaneamente 
sull'immagine


Sperando di non avervi annoiato,

black


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


******************
* 0x08 :: Riddle *
******************

Lo scorso riddle era abbastanza complicato: abbiamo avuto solo una risposta
per i livelli 'Base' e 'Intermedio':

Il vincitore di entrambi i livelli è Link89 ( http://www.webalice.it/frenky.89 )

Ed ecco le soluzioni:

Livello Base:
******************
Scrivendo su PORTB questa sequenza di bytes (appena arrivati all'ultimo byte, si
reincomincia dal primo) si ottiene un gioco ottico:
0x01,0x40,0x02,0x40   (esattamente accende a,g,d,g)
Saresti capace di crearne altri?
******************
1) 0x01, 0x02, 0x04, 0x08, 0x10, 0x20
   (gira lo 0)

2) 0x01, 0x02, 0x40, 0x10, 0x08, 0x04, 0x40, 0x20  
   (gira l'8)

3) 0x01, 0x22, 0x40, 0x14, 0x08  
   (simula una discesa dei led)

4) 0x01, 0x22, 0x40, 0x14, 0x08, 0x14, 0x40, 0x22, 0x01  
   (simula una discesa e risalita dei led)

5) 0x39, 0x06, 0x77, 0x3F
   (CIAO)

6) 0x76, 0x7B, 0x30, 0x30, 0x3F, 0x00, 0x3E, 0x3F, 0x50, 0x30, 0x5E  
   (HellO UOrld; un sapevo come fa la W e l'ho "italianizzato" XD)

Livello Intermedio:
******************
Se invio su PORTB i seguenti bytes, cosa mi esce scritto sul display?
0x38,0x3f,0x38,0x00,0x74,0x06,0x78,0x54,0x3f,0x78,0x79
******************
0x38 -> 00111000 -> L
0x3F -> 00111111 -> O
0x38 -> 00111000 -> L
0x00 -> 00000000 ->
0x74 -> 01110100 -> h
0x06 -> 00000110 -> i
0x78 -> 01111000 -> t
0x54 -> 01010100 -> n
0x3F -> 00111111 -> O
0x78 -> 01111000 -> t
0x79 -> 01111001 -> E 

* Riddle di questo numero: *

Bene, questa volta tentiamo un image-riddle basandoci su un algoritmo 
simile al PNM. 

Dimensioni 54x5:
01111101111001110111110000110000000110011100110001000001000001000100100100000000
01100000110000100010100100000111000111100010010000000001100100110000100010100100
00010000010000001001000000000011010110000010001001010000011111010000011101111100
000001101100000111001000110000

Il livello è solo uno. Buon divertimento!!!


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


**************************
* 0x09 :: Ringraziamenti *
**************************

Per questo numero si ringrazia, in ordine alfabetico:
black, dany15gni, darkjoker, d0ct0r, r0b0t82, Morbido6868, turbocotoletta

La ezine HITNOTE è a cura dello staff di Unofficial HJ Forum:
http://unofficialhj.gotdns.org

Il sito ufficiale di HITNOTE è:
http://hitnote.gotdns.org

Insultateci, criticateci, inviateci tutto quel che vi passa per la testa a:
[email protected]

Il canale IRC su cui ci incontriamo è:
#hj @ unofficialhj.gotdns.org:6667 [6697 via SSL]
#hjssl @ unofficialhj.gotdns.org:6697 [solo via SSL]


HITNOTE 0x04 [December 2010] -- Released under Creative Commons
 
Источник
www.exploit-db.com

Похожие темы