Universidad Politécnica de Madrid Escuela Técnica Superior...
Transcript of Universidad Politécnica de Madrid Escuela Técnica Superior...
Universidad Politécnica de Madrid
Escuela Técnica Superior de Ingenieros deSistemas Informáticos
Grado en Ingeniería de Computadores
DETECCIÓN DE MALWARE DE LINUX CON MÉTODOS DEAPRENDIZAJE AUTOMÁTICO APLICADOS A DATOS DE ANÁLISIS
ESTÁTICO
Autor: Jose Antonio Quevedo Muñoz
Director: Luis Miguel Pozo Coronado
Madrid, 10 de julio de 2018
DETECCIÓN DE MALWARE DE LINUX CON MÉTODOS DEAPRENDIZAJE AUTOMÁTICO APLICADOS A DATOS DE ANÁLISIS
ESTÁTICO
Autor: Jose Antonio Quevedo MuñozDirector: Luis Miguel Pozo Coronado
Departamento de Matemática Aplicada a las TICEscuela Técnica Superior de Ingenieros de Sistemas Informáticos
Universidad Politécnica de Madrid
10 de julio de 2018
Dedicatoria
A mi padre, al son de las trompetas.
“Si logré ver más lejos fue porque subí a hombros de gigantes”
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático C
Agradecimientos
Perdonadme porque me es imposible nombraros a todos.
Os doy las gracias.
A los compañeros, con los que he compartido y aprendido cada día.
A los profesores que tuve, cuyo esfuerzo diario ha hecho que este camino haya valido la pena.A los profesores del Departamento de Matemática Aplicada a las TIC de esta escuela:
Alfonsa, Luis Miguel, Maria Ángeles, Jose Ignacio, ..Y de otros departamentos:
José Luis, Carola, Frank, Pedro Pablo, Jorge Enrique, Paco, Agustín, Marta, Paula, Pablo, ..No tengo palabras.
A los amigos que son apoyo en los momentos difíciles y alegría en las victorias.
A Esther, mi pareja, que parece mentira que tras tantas aventuras aún me apoye con una sonrisa.A su familia, que es la mía, juntos hacemos un gran equipo.
A mi familia, que siempre me apoyó en llevar mi vocación adelante.
A todos los que me apoyasteis en el camino.Este trabajo, que representa el fin de una etapa y el comienzo de otra, también es vuestro.
Gracias.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático E
Resumen
Resumen —
En este proyecto se aplican técnicas de aprendizaje automático supervisado sobre dos conjuntos deficheros binarios compuestos por goodware y malware. Partiendo de sus informes de análisis estático, sepretende de detectar si un fichero es malware o no.
Se ha tomado como goodware dos conjuntos de ficheros pertenecientes a la distribución DebianGNU/Linux[1] arquitectura amd64 e i386, y como malware los 3565 ficheros binarios del dataset demalware de Linux de Virushare [2].
Estos conjuntos de datos se han unido de manera que conforman dos datasets, los mismos binarios demalware, distintos binarios de goodware, uno para cada arquitectura. Sobre estos datasets se ha realizadoun análisis estático para obtener los informes, los cuales han sido parseados para elaborar una lista contodas las palabras que aparecen en cada uno de ellos junto con su número de apariciones. La selección decaracterísticas se ha hecho eliminando en primer lugar las palabras con menor varianza en su número deapariciones, y luego se han escogido las k-mejores características utilizando el criterio específico de filtradopara clasificación χ2. Estos procesos de filtrado de características se han hecho tomando las decisionessobre el subconjunto de entrenamiento para evitar fugas de datos y obtener así un resultado fiable.Finalmente, se han entrenado varios modelos de clasificación, se han validado y medido sus resultadospara, por último, compararlos.
A raíz de los resultados obtenidos, se ha realizado una investigación hacia atrás para identificar lascaracterísticas que producen dichos resultados. Esto nos ha permitido obtener un conocimiento másprofundo de los criterios basados en datos que están utilizando los algoritmos para tomar las decisionesde clasificación.
Palabras clave — aprendizaje automático supervisado, detección de malware, análisis estático,Debian, Linux, selección de características
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático i
Abstract
Abstract — This project applies supervised machine learning tecniques over two binary files datasetscomposed by goodware and malware. Starting from their static analysis reports, the goal is to detect ifa binary file is malware or not.
Two sets of binary files of the Debian GNU/Linux distribution [1] based on amd64 and i386 architectureshave been chosen as goodware data, as well as 3565 binary files from the Virushare Linux malware dataset[2] as the malware side.
This datasets have been joined to become two datasetsOver this dataset, the same malware files withdifferent goodware files for each architecture. Over this data a static analysis was carried out to get thestatic analysis reports, which were then parsed to elaborate a list containing all the words appearingin the reports along their repetitions. The feature selection was fulfilled through a two feature selectioncombination: in the first place the less variance features were removed, and then the K best featuresfollowing the χ2 criteria have been selected. This feature selection stage took place after having splitted thedataset into training and test subsets, in order to avoid any data leakage effect. Finally, some classificationmodels were trained and evaluated, and their results were compared between themselves and with thepreviously achieved ones in the academic literature.
Due to the obtained results, a backward research was performed to identify which features producethe previously reached results. This provided a deeper knowledge on the data based criteria used by thealgorithms to form the resolutions.
Key words — supervised machine learning, malware detection, static analysis, Debian, Linux, featureselection
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático iii
iv Trabajo de Fin de Grado
Índice general
1. Introducción 11.1. Objetivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2. Tecnologías utilizadas 52.1. Scikit-Learn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.2. Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2.1. Gitflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.3. Python 3.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.4. Bash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.5. Debian GNU/Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.6. Latex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.6.1. Texstudio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.7. Emacs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3. Estado del Arte 133.1. Análisis de malware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.1.1. Análisis estático . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.1.2. Análisis dinámico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2. Malware en Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.2.1. Antivirus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.3. Aprendizaje automático . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.3.1. Tipología . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.4. Librerías de aprendizaje automático . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213.5. Estudios previos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4. Marco teórico 234.1. Algoritmos utilizados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.1.1. Algoritmo Naïve Bayes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244.1.2. Algoritmo KNN - Nearest Neighbors . . . . . . . . . . . . . . . . . . . . . . . . . . 244.1.3. Algoritmo SVM Lineal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254.1.4. Algoritmo RBF SVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254.1.5. Algoritmo de Árbol de Decisión . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264.1.6. Algoritmo de Bosques Aleatorios . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274.1.7. Algoritmo Red Neuronal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274.1.8. Algoritmo AdaBoost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.2. Fugas de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5. Metodología y diseño 295.1. Requisitos funcionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295.2. Requisitos software. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305.3. Proceso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315.4. Del dato al modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.4.1. Fase 1: Eleccción del dataset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático v
ÍNDICE GENERAL
5.4.2. Fase 2: Elección de las herramientas a utilizar . . . . . . . . . . . . . . . . . . . . . 335.4.3. Fase 3: Análisis estático . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335.4.4. Fase 4: Selección de características . . . . . . . . . . . . . . . . . . . . . . . . . . . 345.4.5. Fase 5: Selección de las K mejores características . . . . . . . . . . . . . . . . . . . 365.4.6. Fase 6: Entrenamiento de los modelos estadísticos, predicción y validación de
resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385.4.7. Fase 7: Análisis crítico sobre los resultados obtenidos . . . . . . . . . . . . . . . . . 40
5.5. Del modelo al dato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405.5.1. Fase 8: Reiteración de las fases 5, 6 y 7 con diferente número de K-mejores
características . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405.5.2. Fase 9: Identificación de las características utilizadas. . . . . . . . . . . . . . . . . . 405.5.3. Fase 10: Conclusiones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
6. Datasets 416.1. ¿Por qué Linux? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416.2. ¿Por qué Debian? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436.3. Criterios de selección de ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
7. Desarrollo 477.1. Fases ejecutables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
7.1.1. Fase 1: obtención de las repeticiones de palabras para cada fichero binario. . . . . 477.1.2. Fase 2: obtención del universo de palabras existente en el dataset. . . . . . . . . . 477.1.3. Fase 3: obtención de los subconjuntos de entrenamiento y test. . . . . . . . . . . . 487.1.4. Fase 4: Filtro por chi², entrenamiento y validación de los modelos. . . . . . . . . . 507.1.5. Fase 5: identificación de las características utilizadas en la fase 4. . . . . . . . . . . 51
7.2. Instalación del programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517.3. Cómo ejecutar el programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
7.3.1. Parámetros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527.3.2. Ejemplos de ejecución . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
8. Resultados 558.1. Criterio de evaluación de los modelos en el contexto de malware . . . . . . . . . . . . . . . 568.2. Tabla comparativa - Dataset amd64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578.3. Tabla comparativa - Dataset i386 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
9. Conclusiones 61
Bibliografía 63
Apéndices 65
A. Anexos 67A.1. Fichero de Configuración . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67A.2. Implementación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69A.3. Fichero requirements.txt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
A.3.1. Contenido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99A.4. Matrices de Confusión - Dataset amd64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
A.4.1. Algoritmo Naïve Bayes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100A.4.2. Algoritmo Nearest Neighbors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101A.4.3. Algoritmo Árbol de decisión . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102A.4.4. Algoritmo Bosque Aleatorio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103A.4.5. Algoritmo SVM Lineal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104A.4.6. Algoritmo RBF SVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
vi Trabajo de Fin de Grado
ÍNDICE GENERAL
A.4.7. Algoritmo Red Neuronal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106A.4.8. Algoritmo AdaBoost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
A.5. Matrices de Confusión - Dataset i386 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108A.5.1. Algoritmo Naive Bayes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108A.5.2. Algoritmo Nearest Neighbors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109A.5.3. Algoritmo Decision Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110A.5.4. Algoritmo Random Forest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111A.5.5. Algoritmo Linear SVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112A.5.6. Algoritmo RBF SVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113A.5.7. Algoritmo Neural Net . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114A.5.8. Algoritmo AdaBoost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático vii
Índice de figuras
1.1. Tipos e impacto de de incidentes digitales (Allianz). . . . . . . . . . . . . . . . . . . . . . 21.2. Riesgos más preocupantes de la digitalización . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.1. Scikit-learn logo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.2. Git logo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.3. Python logo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.4. Bash logo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.5. Debian logo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.6. The LaTeX project logo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.7. Emacs logo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.1. Productos con mayor número de vulnerabilidades en la historia (CVEDetails.com). . . . . 163.2. Productos con mayor número de vulnerabilidades en 2018 (CVEDetails.com). . . . . . . . 163.3. Tabla comparativa de Antivirus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.4. Infografía de lenguajes y librerías de aprendizaje automático . . . . . . . . . . . . . . . . . 21
4.1. Ejemplo gráfico del algoritmo SVM Lineal . . . . . . . . . . . . . . . . . . . . . . . . . . . 254.2. Expansión del espacio de características del kernel para σ=1 . . . . . . . . . . . . . . . . . 26
5.1. Flujo de trabajo de aprendizaje automático supervisado . . . . . . . . . . . . . . . . . . . 315.2. Forma de una matriz de confusión . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
6.1. Cuota de mercado global de Sistemas Operativos . . . . . . . . . . . . . . . . . . . . . . . 426.2. Cuota de mercado de servidores web por sistema operativo . . . . . . . . . . . . . . . . . 426.3. Evolución de los sistemas operativos en el top 500 de supercomputación . . . . . . . . . . 436.4. Cuota de mercado de Servidores web Linux . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.1. Distribución de palabras por número de repeticiones en el dataset . . . . . . . . . . . . . . 48
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático ix
Índice de tablas
8.1. Comparativa de algoritmos con dataset amd64 . . . . . . . . . . . . . . . . . . . . . . . . 578.2. Comparativa de algoritmos con dataset i386 . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático xi
1Introducción
Malware es todo aquel fichero o código informático que al ser ejecutado produce en el sistema efectos
no deseados. El malware es capaz de engañar, robar datos personales y profesionales de las empresas
y permite a un atacante emprender una cantidad innumerable de acciones tales como invasión de la
privacidad, suplantación de identidad, fraude, robo de propiedad intelectual, extorsión, interrupción de
servicios, etc. Su principal vía de transmisión es internet, utilizan ingeniería social, correos masivos e
incluso interceptan datos que el usuario intercambia con una entidad de su confianza.
La aparición de las redes sociales, el auge de los sistemas distribuidos y el IoT Internet of Things (IoT)
son factores que hacen que la seguridad digital sea una preocupación que afecta a la sociedad a todos los
niveles. Se estima que actualmente hay un 55% de la población con posibilidad de acceso a internet, un
53% de usuarios activos en la red y un 42% de usuarios activos en redes sociales [3]. El Malware se ha
convertido hoy en día en una de las principales amenazas, tanto para empresarios como para los usuarios
individuales de la red de redes, debido a la gran penetración que tiene internet en la sociedad a nivel
mundial [4] y a las consecuencias que una vulnerabilidad digital puede causar.
Según avanzamos en la era digital, cada día surgen nuevas formas de malware cada vez más sofisticado
[5], que hace que sea necesario aplicar nuevas políticas de seguridad capaces de anticiparse a éstas nuevas
amenazas y la ciberguerra entre analistas de seguridad y desarrolladores de malware se mantiene abierta y
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 1
CAPÍTULO 1. INTRODUCCIÓN
Figura 1.1: Tipos e impacto de de incidentes digitales (Allianz).
en constante evolución. Cada año se caracteriza por la aparición de, al menos, una nueva amenaza grave
[6], por ejemplo, durante el año 2017 las amenazas más preocupantes que surgieron de tipo malware
fueron las catalogadas como ransomware y cryptojacking. Informes como los de AV Test y CVE Details
mencionan un alarmante aumento de los ataques por malware en los últimos años [7] y aunque desde el
año 2014 se observa un descenso en la cantidad de malware creado por año, los ataques cada vez son más
sofisticados y destructivos [8].
Figura 1.2: Riesgos más preocupantes de la digitalización
Según Marketshare, compañía especializada en estadísticas de tecnologías de internet, en la historia
reciente el sistema operativo más instalado en los ordenadores domésticos y corporativos de todo el
mundo ha sido Microsoft Windows, razón por la cual ha sido el sistema operativo más atacado, pero
ningún sistema operativo está a salvo de los ataques de malware y, en estos últimos años, se ha visto
incrementado el número de ataques sobre sistemas operativos de Linux y macOS.
Parece lógico este aumento de ataques, si tenemos en cuenta que el sistema operativo Linux lidera el
mercado de servidores en internet y el de las supercomputadoras y a que además su presencia está teniendo
un crecimiento progresivo en computadoras de escritorio, portátiles, router, videojuegos, smartphones y
2 Trabajo de Fin de Grado
CAPÍTULO 1. INTRODUCCIÓN
tablets [9].
El tipo de gestión de software que ofrece Linux es altamente confiable y goza de una gran reputación,
por este motivo existe una idea muy extendida de que en Linux no hay malware. Llama la atención el bajo
número de estudios sobre malware de Linux comparado con otros sistemas operativos. Aunque es cierto
que las características de diseño de Linux dificulta la labor de un atacante, no está libre de un descuido
por parte de un usuario o de un bug de seguridad que pudiera aparecer en alguna pieza de software.
Aunque los repositorios de las distribuciones Linux cuentan con una gran cantidad de software, es posible
que un usuario descargue un programa fuera de los repositorios oficiales y ejecute un binario que suponga
una amenaza al sistema. También puede suceder que un atacante aproveche una vulnerabilidad en los
puertos abiertos a la red y le permita hacer una escalada de privilegios, lo cual puede conseguir por medio
de un rootkit u otra técnica similar.
Hasta la fecha, la manera más habitual de luchar contra el malware ha consistido en mantener un gran
conjunto de ejemplos con los que comparar cada fichero y así identificar los ficheros maliciosos. [10] Esta
estrategia, aunque útil para no ser infectado por segunda vez, es totalmente ineficaz para amenazas tipo
0-Day. Lo cual, deja como única medida de protección alternativa del sistema, la defensa por protección
del perímetro. Si un atacante supera la defensa de perímetro y consigue que un malware 0-Day sea
ejecutado, habrá conseguido su objetivo. Se estima que alrededor del 30% del malware detectado en
2016 fue clasificado como 0-day porque no fue detectado por los antivirus habituales. Sin una solución de
prevención de ataques que identifique proactivamente el malware por medio de técnicas modernas, casi
una tercera parte del malware pasará desapercibido para las compañías [11].
Este dato confirma que la capacidad de los cibercriminales para automáticamente reempaquetar o
modificar su malware ha superado la habilidad de la industria para conseguir, con suficiente velocidad, la
cantidad de firmas necesarias para detectar eficazmente el malware. Este tipo de malware reempaquetado
es lo que conocemos como malware polimórfico y es difícil de detectar por los antivirus, ya que cada
reempaquetado del mismo malware asegura al menos un sistema infectado. Es por este motivo que se
esté empezando a plantear el uso de la inteligencia artificial, tanto en sus formas de deep learning como
aprendizaje automático, para resolver los complejos procesos de clasificación y encontrar así, un sistema
eficaz de reconocimiento de patrones aplicado a este campo para conseguir mitigar este tipo de ataques.
La idea es utilizar técnicas similares a las que ya se han utilizado con éxito sobre el correo electrónico para
evitar el spam recibido por los usuarios, el cual se ha conseguido reducir en un 99,9% [12]. En este contexto
se plantea el aprendizaje automático como la técnica que puede ayudar a detectar vulnerabilidades que
a día de hoy son aún desconocidas.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 3
CAPÍTULO 1. INTRODUCCIÓN
1.1. Objetivo
El propósito de este proyecto es desarrollar un programa capaz de aplicar técnicas de aprendizaje
automático sobre un conjunto de datos en bruto para conseguir que un ordenador adquiera la habilidad
de reconocer si un fichero binario es malware o no.
4 Trabajo de Fin de Grado
2Tecnologías utilizadas
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 5
CAPÍTULO 2. TECNOLOGÍAS UTILIZADAS
2.1. Scikit-Learn
Figura 2.1: Scikit-learn logo
Scikit-learn es una librería de aprendizaje automático para el lenguaje de programación Python.
Implementa varios algoritmos de clasificación, regresión y clustering incluyendo máquinas de vectores
soporte, bosque de árboles aleatorios, aumento de gradiente, k-means y DBSCAN, y ha sido diseñado
para interoperar con las librerías numericas y científicas de python NumPy y SciPy.
6 Trabajo de Fin de Grado
CAPÍTULO 2. TECNOLOGÍAS UTILIZADAS
2.2. Git
Figura 2.2: Git logo
Es un software de control de versiones distribuido diseñado por Linus Torvalds, pensando en la eficiencia
y la confiabilidad del mantenimiento de versiones de aplicaciones cuando éstas tienen un gran número de
archivos de código fuente. Su propósito es llevar registro de los cambios en archivos de computadora y
coordinar el trabajo que varias personas realizan sobre archivos compartidos.
2.2.1. Gitflow
Se ha utilizado Git siguiendo el flujo de trabajo Gitflow, tanto para
la gestión del código como para la redacción de la documentación
de la memoria.
Este flujo de trabajo consiste en crear una rama paralela a Master
llamada Develop.
La rama Develop se utiliza para que el equipo de trabajo mergee
las ramas de cada feature de desarrollo, y una vez que esté
estabilizada, se hayan resuelto los conflictos que pudiera existir y
pase todos los tests, se hace merge con la rama master para,
finalmente, obtener la versión release que se llevará a producción.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 7
CAPÍTULO 2. TECNOLOGÍAS UTILIZADAS
2.3. Python 3.6
Figura 2.3: Python logo
Python es un lenguaje de programación interpretado, multiparadigma y multiplataforma que usa tipado
dinámico y conteo de referencias para la administración de memoria y cuya filosofía hace hincapié en una
sintaxis que favorece la legibilidad del código.
Es administrado por la Python Software Foundation. Posee una licencia de código abierto denominada
Python Software Foundation License que es compatible con la Licencia pública general de GNU a partir
de la versión 2.1.1, e incompatible en ciertas versiones anteriores.
8 Trabajo de Fin de Grado
CAPÍTULO 2. TECNOLOGÍAS UTILIZADAS
2.4. Bash
Figura 2.4: Bash logo
Bash (Bourne-again shell) es intérprete de comandos y un lenguaje de consola. Es una shell de Unix
compatible con POSIX y el intérprete de comandos por defecto en la mayoría de las distribuciones
GNU/Linux y macOS. También se ha portado a otros sistemas como Windows y Android.
Su nombre es un acrónimo de Bourne-again shell ("shell Bourne otra vez") haciendo un juego de
palabras (born-again significa "nacido de nuevo") sobre la Bourne shell (sh), que fue uno de los primeros
intérpretes importantes de Unix.
Hacia 1978, Bourne era el intérprete distribuido con la versión del sistema operativo Unix Versión 7.
Stephen Bourne, por entonces investigador de los Laboratorios Bell, escribió la versión original. Brian Fox
escribió Bash para el proyecto GNU en 1987 como sustituto libre de Bourne.12 y en 1990, Chet Ramey
se convirtió en su principal desarrollador.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 9
CAPÍTULO 2. TECNOLOGÍAS UTILIZADAS
2.5. Debian GNU/Linux
Figura 2.5: Debian logo
El Proyecto Debian [13] es una asociación de personas que han hecho causa común para crear un
Sistema Operativo (SO) libre y Debian es el sistema operativo resultante.
Los sistemas Debian actualmente usan el núcleo de Linux o de FreeBSD. FreeBSD es un sistema
operativo que incluye un núcleo y otro software.
Aunque lo más común es utilizarlo junto con el kernel Linux, actualmente se está trabajando para
ofrecer la distribución con otros núcleos, en especial Hurd. Hurd es una colección de servidores que se
ejecutan sobre un micronúcleo (como Mach) para implementar las distintas funcionalidades. Hurd es
software libre producido por el proyecto GNU.
Una gran parte de las herramientas básicas que completan el sistema operativo, vienen del proyecto
GNU; de ahí los nombres: GNU/Linux, GNU/kFreeBSD, y GNU/Hurd.
10 Trabajo de Fin de Grado
CAPÍTULO 2. TECNOLOGÍAS UTILIZADAS
2.6. Latex
Figura 2.6: The LaTeX project logo
LaTeX es un sistema de preparación de documentos para escritura de alta calidad. En su mayoría es
utilizado para documentos científicos o técnicos de tamaño medio o grande pero puede ser utilizado par
casi cualquier tipo de publicación.
LaTeX no es un procesador de texto. En su lugar anima a los autores a no preocuparse demasiado de
la apariencia de sus documentos sino en concentrarse en enriquecer el contenido.
Se basa en la idea de que es mejor dejar el diseño a los diseñadores de documentos, y a los autores el
contenido de los mismos.
2.6.1. Texstudio
TeXstudio es un entorno de escritura integrado de
fuentes abiertas para la creación de documentos
LaTeX. Su objetivo es hacer que la escritura con
LaTeX sea tan fácil y cómoda como se aposible. Por
lo tanto, TexStudio tiene muchas características
como sintaxis resaltada, visor integrado, gestor de
referencias y varios asistentes.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 11
CAPÍTULO 2. TECNOLOGÍAS UTILIZADAS
2.7. Emacs
Figura 2.7: Emacs logo
Emacs es un editor de texto con una gran cantidad de funciones, muy popular entre programadores
y usuarios técnicos. GNU Emacs es parte del proyecto GNU y la versión más popular de Emacs con
una gran actividad en su desarrollo. El manual de GNU Emacs lo describe como “un editor extensible,
personalizable, auto-documentado y de tiempo real”.
El EMACS original significa, Editor MACroS para el TECO, y fue escrito por Richard Stallman junto
con Guy Steele en 1975.
12 Trabajo de Fin de Grado
3Estado del Arte
Al revisar el estado del arte de cualquier trabajo de investigación debemos ser cuidadosos a la hora
de elegir las fuentes que utilizamos ya que son estas las que fijan los conceptos sobre los que basamos el
trabajo. Y es que bien sea porque el artículo de investigación se publicó fuera de fecha sin tener en cuenta
los últimos resultados publicados o porque la metodología aplicada no haya sido del todo exhaustiva, el
resultado puede ser que se genere literatura con conclusiones erróneas [10].
Por eso en este trabajo se ha hecho especial hincapié en explicar qué se ha hecho y por qué, para ayudar
al lector a detectar este tipo de errores, en caso de haberlos, o aspectos mejorables.
3.1. Análisis de malware
El objetivo del análisis de malware es proporcionar la información necesaria para detectar y responder
a una potencial intrusión en un sistema.
Los métodos de detección de malware se pueden clasificar según el tipo de reconocimiento utilizado:
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 13
CAPÍTULO 3. ESTADO DEL ARTE
3.1.1. Análisis estático
El análisis estático se basa en estudiar el fichero sospechoso sin ejecutarlo. Es el tipo de detección de
malware más utilizado por los programas antivirus.
La detección de malware basado en firmas tiene dos métodos fundamentales: basado en extracción de
características binarias y basado en características ensamblador.
Ventajas
No requiere de una laboratorio especializado.
Las herramientas necesarias son fácilmente accesibles.
El riesgo es mínimo porque el programa no se ejecuta.
Requiere poca capacidad de cómputo.
Desventajas
Respecto al análisis estático en general:
Los resultados pueden ser muy distintos según el fichero infectado, aún para el mismo código
malicioso.
Supone una alta tasa de fallo en la detección de malware polimórfico.
Respecto a las soluciones de detección de malware basadas firmas:
Para el malware conocido, el comportamiento de las soluciones antivirus es predecible.
Poco eficaz con malware polimórfico.
Ineficaz para malware de tipo 0-Day.
El crecimiento de la base de datos de firmas sigue el mismo ritmo que el de la creación de malware,
el cual hasta hace poco años ha sido exponencial.
14 Trabajo de Fin de Grado
CAPÍTULO 3. ESTADO DEL ARTE
3.1.2. Análisis dinámico
El análisis dinámico se basa en ejecutar el fichero y ver cómo se comporta el sistema en el cual se ha
ejecutado.
Ventajas
Proporciona información detallada sobre el comportamiento del malware.
Es un buen método para detectar malware tipo 0-day y polimórfico.
Desventajas
Requiere un entorno de pruebas especializado y cuidadosamente configurado.
Es computacionalmente caro.
Se puede evadir por medio de técnicas de detección de máquinas virtuales, esto es debido a que en
el análisis dinámico el malware se ejecuta en entornos virtuales, aislados y controlados, fácilmente
replicables, por lo que, si el virus detecta que está en el entorno virtual, este puede ocultar su
comportamiento dando lugar a en un falso negativo en el análisis.
3.2. Malware en Linux
En esta situación, ¿por qué nos fijamos en los sistemas Linux para detectar malware si su cuota de
mercado es tan baja en comparación con otros sistemas operativos? Y la respuesta es simple: por la
importancia que tiene cada uno de los sistemas que gobierna.
Como se puede ver en la figura 3.2, las plataformas con mayor número de vulnerabilidades en 2018
están siendo las plataformas Android y Linux, concretamente Debian. [7]
Actualmente, el número de malware dirigido a Linux está creciendo especialmente en entornos de
escritorio, donde el reputado sistema de gestión de software deja de ser efectivo en el momento en que
un usuario decide ejecutar un fichero descargado desde un sitio distinto a los servidores oficiales de su
distribución.
Hay otros factores que hacen muy recomendable hacer periódicamente un análisis anti-malware de
cualquier sistema operativo, como el hecho de que el administrador del sistema finalmente es un ser
humano y puede cometer errores, o que el software que está actualmente instalado en el servidor puede
tener algún bug de seguridad que aún no conocemos y que por lo tanto no ha sido solucionado.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 15
CAPÍTULO 3. ESTADO DEL ARTE
Figura 3.1: Productos con mayor número de vulnerabilidades en la historia (CVEDetails.com).
Figura 3.2: Productos con mayor número de vulnerabilidades en 2018 (CVEDetails.com).
De hecho, el escenario en el cual un intruso se cuela en un sistema, deja abierta la puerta a que instale
malware de cualquier tipo. Si esto sucede, querremos saberlo cuanto antes para, de este modo, poder
solucionarlo y minimizar los daños.
En este escenario, los mecanismos de control de integridad y análisis de los sistemas siguen siendo
necesarios.
16 Trabajo de Fin de Grado
CAPÍTULO 3. ESTADO DEL ARTE
3.2.1. Antivirus
Existe una amplia gama de antivirus para los SO basados en Linux [14].
Figura 3.3: Tabla comparativa de Antivirus
Uno de las primeros datos que saltan a la vista es que el hecho de utilizar un antivirus de una casa
conocida y con licencia de pago no implica una alta tasa de detección como sucede con F-Prot, Comodo
y McAfee. Por otro lado, el hecho de que la herramienta sea de fuentes abiertas tampoco garantiza
excelentes resultados. ClamAV obtiene un resultado que lo sitúan en la mitad de la tabla comparativa
con un 66% de acierto en la detección. Finalmente encontramos 7 soluciones con maś de un 95% de
virus detectados, de los cuales solo uno, Kaspersky Endpoint Security 8.0 for Linux, consigue el 100% de
detección.
En el caso de las soluciones comerciales que no son de fuentes abiertas, no sabemos qué estrategia
han seguido para implementar la detección de virus. En el caso de ClamAV, al ser de fuentes abiertas,
sabemos que utiliza un sistema de análisis estático con reconocimiento de malware basado en firmas.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 17
CAPÍTULO 3. ESTADO DEL ARTE
3.3. Aprendizaje automático
El aprendizaje automático es una rama de la inteligencia artificial que permite crear programas capaces
de generalizar comportamientos y reconocer patrones en los datos a través de información no estructurada
proporcionada en forma de muestras [15].
Se entiende como aprendizaje automático al área de estudio que proporciona a los ordenadores la
capacidad de aprender a hacer una tarea sin haber sido explícitamente programados para realizarla.
En general se dispone de un conjunto de datos X (registros o instancias) y se trata de predecir los valores
de una variable respuesta Y a partir de los valores de un conjunto de variables predictoras (atributos o
características). El conjunto de instancias se suele dividir en dos partes, una de ellas, denominada conjunto
de entrenamiento, se utiliza para que el sistema aprenda un modelo y la otra, denominada conjunto test,
se usa para evaluar el modelo.
En el caso de que la variable respuesta sea binaria y tome dos posibles valores (positivo y negativo), al
predecir el resultado para una muestra de prueba, se producen cuatro resultados posibles:
Verdadero positivo, resultado realmente positivo y cuya predicción también es positiva,
Verdadero negativo, resultado realmente negativo y cuya predicción también es negativo,
Falso negativo, resultado realmente positivo y cuya predicción es positiva, y
Falso positivo. resultado realmente negativo y cuya predicción es positiva.
3.3.1. Tipología
Según la salida que proporcionan
Supervisado: Se caracterizan porque se conocen los valores de la variable respuesta para los datos
de entrenamiento. Este tipo de algoritmos producen una función que establece una correspondencia
entre entradas y salidas del sistema. experiencia o conocimiento previo en la que nos podemos
apoyar para tomar decisiones y hacer predicciones.
El objetivo del aprendizaje supervisado es usar las características de un objeto para identificar a
qué clase o grupo pertenece.
Por ejemplo, un sistema de control del spam en el cual el usuario indica qué correos electrónicos
son spam, gracias a lo cual el sistema puede aprender de dichas indicaciones para en un futuro ser
capaz de identificar correos similares.
La selección de características utilizadas para el entrenamiento del algoritmo en un entorno de
aprendizaje automático supervisado es fundamental para el correcto funcionamiento de un modelo
18 Trabajo de Fin de Grado
CAPÍTULO 3. ESTADO DEL ARTE
de predicción. Una selección inadecuada de las características hará que el aprendizaje sea más lento
o que incluso no llegue a producirse nunca.
No supervisado: Es un método de aprendizaje automático donde el modelo se ajusta a las
observaciones. A diferencia del aprendizaje supervisado, no hay un conocimiento a priori. Se
caracteriza porque el algoritmo descubre en los datos de entrada, de manera autónoma, las diferentes
características, regularidades, correlaciones y categorías. Así, el aprendizaje no supervisado trata
los objetos de entrada como un conjunto de variables aleatorias, construyéndo así un modelo de
densidad para el conjunto de datos.
Un ejemplo de una aplicación interesante de estos algoritmos es la segmentación de clientes, donde
podemos agrupar los clientes en grupos de forma automática en función de ciertas características
comunes.
Algunos de los algoritmos más representativos de aprendizaje no supervisado son:
• K-means: es un método de agrupamiento, que tiene como objetivo la partición de un conjunto
de n observaciones en k grupos en el que cada observación pertenece al grupo cuyo valor medio
es más cercano.
• Detección de anomalías: consiste en detectar anomalías a partir de una clara definición de
lo que es normal. Es una técnica que genera facilmente falsos positivos por la dificultad que
entraña definir la condición normal. Existen dos tipos de detección de anomalías: estadística
y no estadística.
Semisupervisado: combinación de los anteriores, en las que se tienen en cuenta datos marcados y
no marcados.
Por refuerzo: su información de entrada es el feedback que obtiene como respuesta a sus acciones;
se basa en el método de ensayo y error.
Transducción: similar al aprendizaje supervisado, pero no construye una función como tal. Trata
de predecir categorías de los futuros ejemplos a partir de ejemplos ya dados.
Multitarea: usan el conocimiento previamente aprendido por el sistema, basándose en enfrentarse
a lo que ya a visto previamente.
Según el tipo de tarea
Según el tipo de tarea, los tipos de aprendizaje automático se pueden agrupar en: tipo productivo
(clasificación y regresión) o de tipo descriptivo (clustering y asociación).
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 19
CAPÍTULO 3. ESTADO DEL ARTE
Clasificación: El objetivo es asignar los valores de clase a registros no clasificados a partir de ejemplos
de entrenamiento. La variable respuesta es de tipo categórica, es decir, toma un conjunto finito de
valores.
Regresión: El objetivo es asignar un valor real a un atributo de un registro a partir de los valores
del resto de los atributos del registro. La variable respuesta es cuantitativa y puede tomar infinitos
valores.
Clustering: dividir el conjunto de registros, de tal manera que los registros incluidos en uno de los
clusters se caracterizan por su gran similitud o cercanía, mientras que entre grupos hay una mayor
distancia.
Asociación: identificar relaciones no explícitas entre atributos categóricos de registros no clasificados.
Se pretenden identificar aquellas relaciones que se establecen en función de la ocurrencia conjunta
de varios atributos.
Tipos de modelos
Los modelos creados se pueden clasificar como [16]:
Geométricos: se construyen en el espacio de las instancias y pueden tener múltiples dimensiones.
Pueden tener un borde de decisión linear entre varias clases.
Probabilísticos: intentan determinar la distribución de probabilidades descriptivas de la función que
relaciona los valores de los nuevos registros con unos valores determinados. Se aplica en aquellos
casos en los que la relación entre el conjunto de atributos y la categoría de la clase no es determinista.
Suele deberse al ruido o a la propia naturaleza de los valores. El más conocido es el de Naïve Bayes,
el cual almacena como descripción conceptual la previa probabilidad de cada clase y la probabilidad
condicional de cada atributo dado por la clase.
Lógicos: expresan las probabilidades en reglas organizadas en formas de árboles de decisión.
Según su linealidad
Dentro de los métodos de clasificación y regresión, se distinguen por su linealidad dos tipos:
Lineales: La función que se utiliza para predecir la variable respuesta a partir de las variables
predictoras es una aplicación lineal.
Las características de un objeto son típicamente presentadas en un vector llamado vector de
características.
20 Trabajo de Fin de Grado
CAPÍTULO 3. ESTADO DEL ARTE
Destacan por su velocidad de cómputo, especialmente cuando el vector x es disperso, aunque
los árboles de decisión pueden ser más rápidos. Además, los clasificadores lineales con frecuencia
funcionan muy bien cuando el número de dimensiones del vector x es grande, como en clasificación
de documentos, donde típicamente cada elemento en en el vector x es el número de apariciones de
una palabra en un documento. En tales casos, el clasificador debe estar bien regularizado.
No lineales: Construyen superficies arbitrarias que permiten separar clusters muy cercanos o que
incluso se solapan.
3.4. Librerías de aprendizaje automático
Hay 3 lenguajes con buen soporte al aprendizaje automático: R, Python y Scala.
Figura 3.4: Infografía de lenguajes y librerías de aprendizaje automático
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 21
CAPÍTULO 3. ESTADO DEL ARTE
R es un lenguaje específicamente diseñado para el desarrollo estadístico y suele ser el favorito de los
programadores que proceden de entornos matemáticos. Cuenta con un conjunto de herramientas para
investigación reproducible. Es tan específico que puede no ser la elección óptima en caso de ser necesario
resolver un caso de propósito general. Por su parte, Python es un lenguaje de propósito general y suele ser
el escogido por aquellos desarrolladores que provienen de otros entornos de programación. Por otro lado,
Scala es un lenguaje con grandes capacidades en entorno clusterizados pero carece de las herramientas
de visualización de datos con las que sí cuentan Python y R.
Existe una cantidad muy parecida de librerías, tanto para Python como para R, y en este aspecto
ambos lenguajes cuentan con un soporte parecido.
Para nuestro caso se ha elegido Python porque es uno de los dos lenguajes que cumplen con los requisitos
necesarios para llevar adelante el proyecto, y es el que ofrece una curva de aprendizaje más rápida.
3.5. Estudios previos
Alireza Sohuri y Rahil Hosseini en su informe sobre el estado del arte del año 2018 [10] compararon
40 métodos de detección de malware y se observó que el 40% de los estudios se habían realizado sobre
sistemas tipo Android y un 23% sobre Windows [10], algunos sobre datasets variados, pero ninguno
con datasets solo de Linux. Fuera de este State of Art (SoA) hemos encontrado un único artículo sobre
detección de malware sobre Linux [17].
Se observa que en la mayoría de los estudios publicados se consiguen niveles de detección en su mayoría
por encima del 95% salvo alguna excepción con un 85%.
Los métodos de clasificación más utilizados son:
29% Máquinas de vectores soporte (SVM)
17% J48
14% Árboles de decisión
10% Naive Bayes.
La mayor exactitud alcanzada hasta ahora en este campo fue la obtenida por Zahoor-Ur-Rehman,
Sidra Nasim Khan y su equipo en el año 2017 [18] con un 99,81% y una exhaustividad (recall o TPR) del
100%, utilizando el algoritmo KNN a partir de datos obtenidos de análisis híbrido de malware: estático
y dinámico.
22 Trabajo de Fin de Grado
4Marco teórico
Para la detección de malware nos interesa centrarnos especialmente en algoritmos de clasificación para
diferenciar si un fichero es malware o no.
4.1. Algoritmos utilizados
Para que estos algoritmos puedan funcionar correctamente debemos ser capaces de suministrarles un
conjunto de datos de entrenamiento con suficiente cantidad y calidad como para conseguir así un nivel
de acierto elevado.
En nuestro caso nos centramos en algoritmos de clasificación.
Denotamos por X al vector de variables predictoras, por Y la matriz de variables respuesta, y por Cj
a los posibles valores de la variable respuesta.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 23
CAPÍTULO 4. MARCO TEÓRICO
4.1.1. Algoritmo Naïve Bayes
Naïve Bayes es uno de los clasificadores más utilizados por su simplicidad y rapidez.
Se trata de una técnica de clasificación y predicción supervisada que construye modelos que predicen
la probabilidad de posibles resultados.
Está basada en el Teorema de Bayes, también conocido como teorema de la probabilidad condicionada,
el cual responde a la pregunta de qué probabilidad hay de que suceda un hecho asociado a una probabilidad
que depende de que suceda otro hecho asociado a otra probabilidad.
Presupone que la aparición o no de un atributo en un caso no influye en la aparición del resto
de atributos. [19] Permite sólo variables categóricas. Las variables continuas deben ser categorizadas
previamente a la construcción del modelo.
La salida es, para cada etiqueta de la clase seleccionada, se asigna una puntuación de probabilidad
(normalmente un logaritmo) proporcional a la auténtica probabilidad estimada.
Se utiliza para detección de spam, clasificación de textos, detección de fraudes en seguros.
4.1.2. Algoritmo KNN - Nearest Neighbors
Es un método de clasificación supervisada que sirve para estimar la función de densidad F(x/Cj) de
las características predictoras x por cada clase Cj.
Es un método de clasificación no paramétrico, que estima el valor de la función de densidad de
probabilidad o directamente la probabilidad a posteriori de que un elemento x pertenezca a la clase
Cj a partir de la información proporcionada por el conjunto de prototipos. En el proceso de aprendizaje
no se hace ninguna suposición acerca de la distribución de las variables predictoras.
En el reconocimiento de patrones, el algoritmo KNN es usado como método de clasificación de elementos
basado en un entrenamiento mediante ejemplos cercanos en el espacio de los elementos. KNN es un tipo
de aprendizaje perezoso (lazy learning), donde la función se aproxima solo localmente y todo el cómputo
es diferido a la clasificación.
Se establece una distancia en el espacio vectorial de las variables predictoras (por ejemplo la distancia
euclídea). Para clasificar un elemento se buscan los k registros más cercanos y se clasifica de acuerdo con
la clase mayoritaria entre estos k datos.
24 Trabajo de Fin de Grado
CAPÍTULO 4. MARCO TEÓRICO
4.1.3. Algoritmo SVM Lineal
Los algoritmos SVM pertenecen a la familia de los clasificadores lineales.
Dado un conjunto de puntos, subconjunto de un conjunto mayor (espacio), en el que cada uno de ellos
pertenece a una de dos posibles categorías, un algoritmo basado en SVM construye un modelo capaz de
predecir si un punto nuevo (cuya categoría desconocemos) pertenece a una categoría o a la otra.
Los datos de entrada (los puntos) son vistos como un vector p-dimensional.
La SVM busca un hiperplano que separe de forma óptima a los puntos de una clase de la de otra, que
eventualmente han podido ser previamente proyectados a un espacio de dimensionalidad superior.
Figura 4.1: Ejemplo gráfico del algoritmo SVM Lineal
En ese concepto de “separación óptima” es donde reside la característica fundamental de las SVM: este
tipo de algoritmos buscan el hiperplano que tenga la máxima distancia (margen) con los puntos que estén
más cerca de él mismo. Por eso también a veces se les conoce a las SVM como clasificadores de margen
máximo. De esta forma, los puntos del vector que son etiquetados con una categoría estarán a un lado
del hiperplano y los casos que se encuentren en la otra categoría estarán al otro lado.
Los modelos basados en SVMs están estrechamente relacionados con las redes neuronales. Usando
una función kernel, resultan un método de entrenamiento alternativo para clasificadores polinomiales,
funciones de base radial y perceptrón multicapa.
4.1.4. Algoritmo RBF SVM
El algoritmo de SVM con Función de Base Radial (siglas en inglés RBF) es un tipo de algoritmo de
Máquinas de Vectores Soporte (SVM).
Las funciones de base radial (RBF)son también conocidas como funciones Gaussianas.
El kernel RBF sobre dos muestras x y x’, representado como vector de características en un espacio de
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 25
CAPÍTULO 4. MARCO TEÓRICO
entrada, se define como:
K(x, x′) = exp
(−||x− x
′||2
2σ2
)
|x-x’|² es el cuadrado de la distancia Euclídea entre dos vectores de características. σ es un parámetro
libre. Una definición equivalente pero más simple involucra el parámetro γ = 1/(2*σ²)
K(x, x′) = exp(−γ||x− x′||2
)Como el valor del kernel RBF decrece con la distancia y su valor se encuentra entre 0 y 1, ya se
encuentra preparado para una interpretación de similitud. La característica espacio del kernel tiene un
numero infinito de dimensiones, para σ=1.
Figura 4.2: Expansión del espacio de características del kernel para σ=1
4.1.5. Algoritmo de Árbol de Decisión
Utiliza un árbol de decisión como un modelo predictivo que mapea observaciones sobre un artículo a
conclusiones sobre el valor objetivo del artículo.
Los modelos de árbol, donde la variable de destino puede tomar un conjunto finito de valores se
denominan árboles de clasificación. En estas estructuras de árbol, las hojas representan etiquetas de clase
y las ramas representan las conjunciones de características que conducen a esas etiquetas de clase. Los
árboles de decisión, donde la variable de destino puede tomar valores continuos (por lo general números
reales) se llaman árboles de regresión.
En análisis de decisión, un árbol de decisión se puede utilizar para representar visualmente y de forma
explícita decisiones y toma de decisiones. En minería de datos, un árbol de decisión describe datos, pero
no las decisiones; más bien el árbol de clasificación resultante puede ser un usado como entrada para la
toma de decisiones.
4.1.6. Algoritmo de Bosques Aleatorios
Random forest (o random forests) también conocidos en castellano como “Bosques Aleatorios” es una
combinación de árboles predictores tal que cada árbol depende de los valores de un vector aleatorio
26 Trabajo de Fin de Grado
CAPÍTULO 4. MARCO TEÓRICO
probado independientemente y con la misma distribución para cada uno de estos. Es una modificación
sustancial de bagging que construye una larga colección de árboles no correlacionados y luego los promedia.
El método combina la idea de bagging de Breiman y la selección aleatoria de atributos para construir
una colección de árboles de decisión con variación controlada.
En muchos problemas el rendimiento del algoritmo de bosque aleatorio es muy similar a la del boosting,
y es más simple de entrenar y ajustar. Por estos motivos es un algoritmo muy popular y ampliamente
utilizado.
4.1.7. Algoritmo Red Neuronal
Basado en un gran conjunto de unidades neuronales simples (neuronas artificiales), de forma
aproximadamente análoga al comportamiento observado en los axones de las neuronas en los cerebros
biológicos. Cada unidad neuronal está conectada con muchas otras y los enlaces entre ellas pueden
incrementar o inhibir el estado de activación de las neuronas adyacentes empleando funciones de suma.
Cada neurona se comporta como una función cuyo resultado se propaga a las demás neuronas.
4.1.8. Algoritmo AdaBoost
AdaBoost es, entre los algoritmos de boosting, el más popular y quizá también el más importante
históricamente ya que fue la primera formulación de un algoritmo que pudo aprender a partir de los
clasificadores débiles.
El algoritmo AdaBoost para categorización binario, en general, funciona de la siguiente manera:
1. Forma un conjunto grande de características sencillas
2. Inicializa pesos para entrenar imágenes
3. Para T iteraciones:
a) Normalización de pesos,
b) Para las características disponibles del conjunto, entrenamiento de un clasificador utilizando
solo una característica y evaluación del error de formación
c) Selección del clasificador con el error más bajo,
d) Actualización los pesos de las imágenes de formación: aumenta el peso si el clasificador clasifica
de forma errónea el objeto, disminuye si lo hace correctamente
4. Formación de un clasificador final robusto como la combinación lineal de los T clasificadores.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 27
CAPÍTULO 4. MARCO TEÓRICO
4.2. Fugas de datos
La fuga de datos, o en inglés data leakage, es la creación de información adicional e inesperada en
los datos de entrenamiento, permitiendo a un modelo de aprendizaje automático hacer predicciones
excesivamente optimistas. Las fugas de datos hacen parecer que un modelo es muy preciso hasta que llega
el momento de probarlo en la realidad, momento en el cual se comprueba que es altamente impreciso.
Pueden ser producidos por fallos humanos o mecánicos. Las fugas de datos se pueden producir: por el
tipo de características utilizadas o por un indebido manejo de datos.
Tipos de fugas de datos:
Por el tipo de características utilizadas:
Se produce cuando las características utilizadas para predecir los resultados contienen datos con los
que es imposible contar en el momento de hacer la predicción.
Un ejemplo es si queremos predecir el precio que va a tener un producto con un mes de antelación
y utilizamos una variable que indica qué precio tendrá el producto 2 semanas antes.
Por un manejo incorrecto de los datos:
Este tipo de fuga de datos se produce cuando tomamos decisiones en función de los datos de test o
de las predicciones.
Esto sucede cuando se hace un filtrado de características entrenando dicho filtro con el conjunto
completo de datos, o con subconjuntos de datos de los que no dispondríamos en un escenario real.
La manera correcta de manejar los datos es:
1. Dividir las características que forman el conjunto de datos en subconjunto de características
predictoras (X) y características a predecir (y).
2. Dividir las muestras que forman el conjunto de datos en subconjunto de muestras de
entrenamiento (X_train e y_train) y subconjunto de muestras de test (X_test e y_test),
3. El filtro de características se entrena utilizando las características predictoras de X_train.
4. Una vez se ha entrenado el filtro, se aplica la transformación que produce a las características
predictoras de los subconjuntos de entrenamiento y test.
De esta manera habremos aplicado el filtro de características tomando las decisiones de filtrado
basándonos únicamente en las características predictoras del subconjunto de entrenamiento.
28 Trabajo de Fin de Grado
5Metodología y diseño
Para llevar a cabo el estudio objeto de este proyecto se ha implementado una herramienta que cumple
los siguientes requisitos:
5.1. Requisitos funcionales
El programa es capaz de:
Leer el conjunto de ficheros binarios de goodware y malware,
Hacer el análisis estático de cada uno de los ficheros binarios,
Traducir los reportes de análisis estático de cada fichero binario a vector numéricos,
Entrenar varios modelos de aprendizaje automático supervisado diferentes,
Obtener de cada modelo sus predicciones,
Medir para cada modelo: precisión, exhaustividad, f1 y recall.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 29
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
El programa cumple la anterior funcionalidad siguiendo los siquientes requisitos:
Tener probada su ejecución en un sistema Debian GNU/Linux.
Comportamiento configurable por medio de un fichero de configuración.
Permitir configurar el comportamiento del programa en función de una etiqueta introducible por
argumento que coincide con una etiqueta del fichero de configuración,
No existen valores mágicos dentro del código, a lo sumo en constantes definidas al principio del
código.
5.2. Requisitos software.
La funcionalidad descrita en los requisitos funcionales se consigue con un software que cumple las
siguientes especificaciones:
se escribe en lenguaje Python 3.6,
puede hacer uso de las herramientas del sistema que se consideren convenientes, como es el caso de
readelf y file.
lee la configuración de un fichero de configuración que contará con las siguientes secciones:
• sección de valores por defecto.
• sección de configuraciones especificas que el usuario puede elegir en el momento de ejecutar el
programa a través de un argumento de entrada.
utiliza un logger para los mensajes informativos o de error que deban guardarse en un fichero de
log,
contiene la clase Dataset, la cual describe la forma y funcionalidad que necesita tener nuestro
dataset.
contiene la clase Binary_file, la cual describe la forma y funcionalidad que representa cada fichero
binario.
funcionalidad probada en el mismo sistema del cual procede el dataset analizado, es decir, un sistema
Debian GNU/Linux Buster.
30 Trabajo de Fin de Grado
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
5.3. Proceso
Para la realización de este proyecto se han seguido dos caminos que se pueden considerar inversos: del
dato al modelo y del modelo al dato.
El flujo habitual de un proyecto de aprendizaje automático es el descrito en 5.1 y corresponde a lo que
en este proyecto se ha llamado del dato al modelo.
Figura 5.1: Flujo de trabajo de aprendizaje automático supervisado
Del dato al modelo:
1. Elección del dataset.
2. Elección de las herramientas a utilizar.
3. Análisis estático y generación de submatrices de características.
4. Filtrado de características por limitaciones de computabilidad por el criterio de menor varianza.
5. Selección de las K mejores características para clasificación por el criterio de Chi².
6. Entrenamiento de los modelos estadísticos elegidos, predicción y validación de resultados.
7. Análisis critico sobre los resultados obtenidos.
Además se ha realizado un camino lógicamente inverso, al cual hemos llamado del modelo al dato,
que ha consistido en identificar qué características o palabras corresponden a unos ciertos vectores de
características. Este proceso se ha hecho con el objetivo de conocer mejor la información basada en datos
utilizada por los algoritmos para su toma de decisiones. Este procedimiento permitirá llegar a un modelo
de detección de malware.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 31
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
Del modelo al dato:
8. Reiteración de las fases 5, 6 y 7 con diferente número de K-mejores características.
9. Identificación de las características utilizadas.
10. Conclusiones.
5.4. Del dato al modelo
5.4.1. Fase 1: Eleccción del dataset
Se ha elegido un dataset en el que, tanto malware como goodware, proporcionen fiabilidad de los datos,
buscando que se trate de ficheros etiquetados y bien conocidos por la comunidad de análisis de malware.
Goodware: Debian GNU/Linux Buster
Se ha descargado la distribución de Debian GNU/Linux Buster completa para dos arquitecturas
diferentes, amd64 e i386, por medio de las 3 imágenes ISO de DVD disponibles para descarga en la
web oficial de la distribución por torrent en el servidor de la página oficial de la distribución debian.org
[13]. Se ha montado cada una en un directorio. A continuación, utilizando el script bajo estas lineas, se
han descomprimido para cada arquitectura todos los ficheros *.deb en otro directorio, de manera que
obtenemos una organización de ficheros en directorio destino equivalente a la obtenida al instalar los
paquetes. Esto es así debido al formato de los paquetes Debian *.deb.
#!/bin/bash
# #########################################################################
# Descripcion: Busca todos los ficheros *.deb existentes a partir del
# directorio en el cual se ejecuta este script y se descomprime cada uno
# de ellos en el directorio definido por la variable $destdir.
# #########################################################################
set -e
srcdir="./"
destdir="out"
32 Trabajo de Fin de Grado
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
mkdir -p $destdir
while IFS= read -rd $'\0' file; do
echo $file
dpkg -x $file out
done < <( find "$srcdir" -iname '*.deb' -print0 )
Malware: VirusShare, colección de malware Linux
Se pusieron los 9482 ficheros de malware del dataset de Linux de VirusShare [2] en un directorio. De
este conjunto de ficheros se seleccionaron los que cumplen con la definición de fichero binario que se
describe más adelante en la sección de análisis estático 5.4.3, resultando con esta característica un total
de 3565 ficheros binarios.
5.4.2. Fase 2: Elección de las herramientas a utilizar
Se ha elegido las herramientas del sistema file y readelf, la primera para detectar si el fichero es un
fichero binario o no, y la segunda para analizar el fichero en caso de tratarse de un binario.
El lenguaje utilizado para la programación de la herramienta ha sido Python3 y como lenguaje de
apoyo y para el manejo de ficheros Bash script. El primero se eligió por la agilidad que permite en el
desarrollo, versatilidad y soporte con que cuenta para aprendizaje automático. El segundo por ser la shell
standard de los sistemas Linux y por su eficiencia a la hora de manejar ficheros.
Scikit-learn es la librería principal de aprendizaje automático utilizada en este proyecto, la cual utiliza
a su vez librerías más populares para este entorno como son numpy y pandas, y además cuenta con una
muy buena documentación.
5.4.3. Fase 3: Análisis estático
Se han considerado como ficheros potencialmente binarios y candidatos para ser utilizados para el
análisis estático todos aquellos ficheros que, formando parte del dataset, estuvieran almacenados en un
directorio cuyo nombre termina en las letras “bin”.
Finalmente, se ha considerado como fichero binario aquel sobre el cual, al ejecutar la herramienta File,
devolviera por salida estándar un resultado que contuviera la cadena “ELF” y no contuviera la cadena
“not an ELF”.
Una vez se ha decidido que un fichero es binario, se ejecuta sobre él la herramienta readelf, la cual
hace un análisis estático del mismo. Dicho resultado se transforma en una lista de instancias de clase
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 33
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
Binary_file, la cual contiene el diccionario asociado al reporte readelf donde las claves son las palabras y
el valor asociado a la clave es la cantidad de veces que dicha palabra se ha repetido en el informe readelf
de ese fichero binario.
Una vez decididos los criterios procedemos a parsear los informes estáticos para obtener 2 informaciones
principales:
Para cada binario, qué palabras aparecen y cuantas veces.
Para el conjunto completo de todos los binarios, qué palabras aparecen y cuantas veces.
5.4.4. Fase 4: Selección de características
Una selección de las características adecuada eliminará ruido en los datos y acelerará el aprendizaje
del modelo estadístico.
Cada fichero binario está definido por un vector que representa las repeticiones de cada palabra en el
reporte generado en su análisis estático. Todos los vectores completos apilados forman la matriz completa
de características.
Como ejemplo tomaremos en dataset formado por los binarios amd64 + malware, de manera que el
tamaño de esta matriz se puede calcular de la siguiente manera:
Tamaño total de la matriz de características sin filtrado = nº de muestras * nº de características *
tamaño de cada componente del vector de características.
Siendo:
nº de muestras: 9896 ficheros binarios teniendo en cuenta goodware y malware,
nº de características: 12.384.366 palabras distintas generadas por todos los reportes estáticos de los
binarios,
tamaño de cada componente del vector de características: dado que cada componente es almacenado
en un Dataframe Pandas el cual esta coompuesto por variables de tipo float64, las cuales están
compuestas por: 52 bits de mantisa + 11 bits de exponente + 1 bit de signo = 64 bits = 8 bytes.
De esta manera, el tamaño resultante es: 9896 * 12.384.366 * 8 bytes = 980.445.487.488 bytes =
486815038,475 Kbytes = 475.405,31101 Mbytes = 464,262999034 Gbytes
Esta matriz, debido a su tamaño, es inmanejable por el equipamiento informático con el que contamos
para hacer este trabajo.
34 Trabajo de Fin de Grado
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
Para solventar esta situación se ha procedido a dividir la matriz en submatrices, y a cada una de estas
submatrices se le ha aplicado un filtrado por varianza, con idea de eliminar aquellas caracteristicas que,
o aparecen en practicamente todos los reportes de análisis estático o en casi ninguno.
Partición del dataset: datos de entrenamiento y test
Antes de proceder a tomar decisiones de filtrado de características sobre cada submatriz, se ha procedido
a dividir el dataset completo en subconjuntos de entrenamiento y test. El motivo se hacer esta separación
antes de tomar ninguna decisión sobre el conjunto de los datos es evitar el efecto de fuga de datos o,
como se conoce en inglés, data leakage.
Para seleccionar las mismas muestras en cada submatriz, el procedimiento de particionado del dataset
se hace por medio de la función split, pero utilizando siempre el mismo valor para la semilla aleatoria
random_state. El código aplicado para esta operación se encuentra en la función datasets2finalDataset :
X_train , X_test , y_train , y_test = train_test_split(
X_unfiltered , y, test_size=test_size , random_state =42)
El tamaño del conjunto de test se ha fijado en un 33% de las muestras, de manera que para
entrenamiento se utiliza un 67%. Más adelante se hará validación cruzada sobre el conjunto total
de muestras, pero las características utilizadas serán las seleccionadas en función del subconjunto
de entrenamiento. Toda transformación o selección de características se hace sobre el conjunto de
entrenamiento y después se traslada sobre el subconjunto de test.
Límites impuestos a las submatrices
El equipo utilizado cuenta con 12Gb de RAM y una partición de 16 Gb de Memoria SWAP. Por este
motivo se ha aplicado un filtrado de características secuencial a cada submatriz que compone la matriz
total.
Se han impuesto las siguientes restricciones:
Cada submatriz utilizada del conjunto de datos a tratar debe contar como máximo con 5000
características.
La matriz resultante del filtrado tendrá como máximo 15.000 características.
Una vez definidos estos limites podemos aplicar los criterios de selección de características.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 35
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
Eliminación de características con baja varianza
Se ha procedido a filtrar las características con menor varianza a cada submatriz hasta conseguir una
matriz formada por un máximo de 15.000 características .
Para ello se ha segmentado el dataset completo y se ha creado una lista de listas de palabras, de
manera que en la primera posición se almacena la lista de palabras que se repiten 1 vez, en la 2ª posición
se encuentra la lista de palabras que se repiten 2 veces, y así sucesivamente.
Una vez hemos obtenido esta lista de listas, seleccionamos aquellos intervalos que acumulen menos
de 5000 palabras formando subconjuntos de palabras que, cuando se traduzcan las submatrices, estas
se ajusten a los límites definidos en el apartado anterior. Seguidamente extraemos la información del
conjunto total de ficheros binarios para obtener la submatriz de características que contenga, para todas
las muestras, sólo las características seleccionadas en este subconjunto.
A cada submatriz de características le aplicamos un filtro de baja varianza, empezando en una varianze
del 99% reduciendose en un 1% cada vez que la matriz resultante excede el tamaño máximo definido para
ella fijado en 15.000. La nueva varianza se aplica a la matriz resultante hasta el momento para asegurar
que se aplica el mismo filtro por varianza a todo el dataset. Este procedimiento se repite sucesivamente
hasta haber conseguido que la matriz resultante se ajuste al máximo de características admitidas o hasta
que la varianza aplicada llegue al 50%. Se impone este valor de 50% porque filtrar por varianza por 51%
es equivalente a filtrar por el 49%. Siguiendo esa misma lógica, todos los filtros por varianza por debajo
del 50% se encontrarían ya realizados en los filtrados superiores al 50%.
Este filtro, aunque parezca inicialmente laxo, elimina las palabras demasiado comunes y las que son
extremadamente específicas, como las direcciones de memoria que utilizan unos pocos binarios.
En nuestro caso la varianza final aplicada ha sido 96% y las 12.169 caracteristicas obtenidas tras este
filtrado.
5.4.5. Fase 5: Selección de las K mejores características
A la matriz de características filtrada por varianza del paso anterior se le ha aplicado la selección de
las K mejores características por el criterio de Chi².
El test de Chi² mide la dependencia entre variables estocásticas, por lo que utilizar esta función elimina
las características que más probablemente sean independientes de la clase y, en consecuencia, las más
irrelevantes para clasificación.
La función encargada de hacer este filtrado es remove_worst_features_by_chi2():
def remove_worst_features_by_chi2(X_train, X_test, y_train, num_kbest_features):
36 Trabajo de Fin de Grado
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
selector = SelectKBest(chi2, k=num_kbest_features)
X_train = selector.fit_transform(X_train, y_train)
X_test = selector.transform(X_test)
return X_train, X_test
Internamente la clase selectKbest utiliza la función chi2 la cual recibe por argumento.
Las hipótesis son:
H0 (hipótesis nula): El vector de características no es dependiente linealmente del vector de
respuestas y.
H1 (hipótesis alternativa): El vector de características sí es dependiente linealmente del vector de
respuestas y.
Para cada vector de características obtiene su p_valor y las ordena de menor a mayor p_valor. A menor
valor reciba p_valor, mayor dependencia de la variable respuesta y. La función selectKbest.fit_transform()
entrena el filtro interno de la clase y lo aplica a las características de X_train, el cual seguidamente
aplicaremos a X_test con la función selectKbest.transform() (sin fit_) para no utilizar los datos de test
para entrenar el filtro y de este modo evitar fugas de datos. Estas funciones devuelven las K características
más dependientes del vector respuesta y.
En nuestro caso, para hacer una estimación de la cantidad de características a utilizar, se hizo el
siguiente experimento:
1. Se desactivó el barajado del dataset a la hora de filtrar las características,
2. Se repitió el filtrado de las k mejores características varias veces comparando los resultados obtenidos
con un algoritmo arbitrario diferente a los utilizados en el estudio como es el algoritmo de regresión
lineal. Aplicando la regla del sandwich, por puro prueba y error, se obtuvo que el filtrado que
mayor precisión ofrecía al test era seleccionar las 3332 mejores características partiendo de las
15000 filtradas por baja varianza.
3. Una vez terminado el experimento se volvió a activar el barajado del dataset en el filtrado.
Por este motivo se ha fijado la cantidad de características filtradas en este filtro como 3332, aunque
sabemos que debido a la aleatoriedad que hay en el proceso de barajado del dataset, esta cifra no va a
ser la óptima en todos los casos, aún así es de esperar que ofrezca buenos resultados.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 37
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
5.4.6. Fase 6: Entrenamiento de los modelos estadísticos, predicción y
validación de resultados
Una vez hemos seleccionado las características, procedemos a entrenar los modelos, generar una
predicción y validar los resultados.
Para entrenar los modelos utilizamos las matrices X_train e y_train, que contienen los vectores de
características y el vector de respuestas esperadas respectivamente. Para evaluar la predicción utilizamos
el subconjunto de test X_test e y_test, que corresponde al 33% de las muestras del dataset. Con estos
datos calculamos una predicción y, a partir de esta, generamos la matriz de confusión y calculamos los
siguientes valores que nos servirán para medir la efectividad del mismo: precisión, exactitud, exhaustividad
y F1.
Matriz de Confianza
Los resultados de un modelo de predicción se puede mostrar visualmente por medio de lo que se conoce
como matriz de confusión.
Figura 5.2: Forma de una matriz de confusión
En una matriz de confusión podemos ver:
Verdaderos negativos: resultados negativos que el modelo ha detectado como negativos.
Verdaderos positivos: resultados positivos que el modelo ha detectado como positivos.
Falsos negativos: resultados positivos que el modelo ha detectado como negativos.
Falsos positivos: resultados negativos que el modelo ha detectado como positivos.
En nuestras evaluaciones consideramos el hecho de que un binario sea malware como un resultado
positivo, y el hecho de que un fichero binario sea goodware como un resultado negativo.
38 Trabajo de Fin de Grado
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
Métricas de evaluación
Para valorar este algoritmo, además, se ha tenido en cuenta las siguientes medidas [20]:
Precisión: representa el porcentaje de instancias evaluadas como como verdaderos positivos entre
el total de positivos.
Precision =V erdaderos positivos
V erdaderos positivos+ Falsos positivos
Accuracy (exactitud): representa la fracción de predicciones que el modelo realizó correctamente.
Exactitud =N de predicciones correctas
N total de predicciones
O lo mismo escrito de otra manera:
Exactitud =V P + V N
V P + V N + FP + FN
Exhaustividad o sensibilidad (recall): Representa el porcentaje de instancias de verdaderos positivos
entre el total real de positivos, es decir, verdaderos positivos y falsos negativos.
Recall =V erdaderos Positivos
V erdaderos Positivos+ Falsos Negativos
F1: una medida de la exactitud del test. Es la media armónica de la precisión y la exhaustividad
(precision y recall).
F1 = 2 ∗ Precision ∗ ExhausitividadPrecision + Exhausitividad
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 39
CAPÍTULO 5. METODOLOGÍA Y DISEÑO
5.4.7. Fase 7: Análisis crítico sobre los resultados obtenidos
En este punto del proceso podemos hacer observaciones sobre la efectividad de los algoritmos y discernir
cuales son mejores para nuestro caso concreto.
5.5. Del modelo al dato
5.5.1. Fase 8: Reiteración de las fases 5, 6 y 7 con diferente número de K-
mejores características
Se procede a repetir los pasos 5, 6 y 7 correspondientes al filtrado de las k-mejores características
por chi², entrenamiento, y validación de los modelos, y análisis crítico de los resultados obtenidos para
comprobar de qué manera afecta la cantidad de características elegidas para entrenar los algoritmos.
5.5.2. Fase 9: Identificación de las características utilizadas.
Para conocer qué características, y en consecuencia, criterios concretos están utilizando los los
algoritmos para discernir entre malware y goodware, se procede a identificar las características utilizadas
por los mismos.
Este procedimiento requiere de una investigación hacia atrás sobre las características utilizadas, debido
a que la librería Scikit-learn trabaja con matrices en lugar de otro tipo de dato que contenga los índices
de fila y columna como por ejemplo los Dataframes de Pandas. Consecuentemente, en el momento de
transformar el conjunto de datos en matrices, aunque la información de qué vector corresponde a qué
tipo de fichero se mantiene en las matrices X (características) e y (resultado), se pierde la información de
que característica corresponde a qué columna de la matriz, así como a qué fila corresponde a qué fichero
binario.
5.5.3. Fase 10: Conclusiones.
Una vez que tenemos tanto los valores que describen los modelos: precisión, exhaustividad, F1 y recall,
como las características que llevan a conseguir estos resultados, podemos valorar los resultados obtenidos
y su ámbito de aplicación.
40 Trabajo de Fin de Grado
6Datasets
Se han utilizado dos datasets formados por los ficheros binarios de la distribución Debian GNU/Linux
Buster de las arquitecturas amd64 e i386 para goodware, y como malware los ficheros binarios de malware
de Linux de VirusShare [2].
Los siguientes apartados se explica por qué este SO y los criterios de selección de los ficheros utilizados.
6.1. ¿Por qué Linux?
El sistema operativo Linux cuenta hasta la fecha con una presencia muy desigual según el tipo de
mercado en el que nos fijemos.
En ordenadores de escritorio a nivel mundial su presencia se encuentra en aproximadamente el 2.5%, y
si lo enmarcamos en el total de dispositivos en el mundo su presencia es casi anecdótica siendo esta de poco
más del 1% del total de ordenadores activos en el mundo. Sin embargo, en entornos de supercomputación
y servidores, los sistemas basados en GNU/Linux copan el mercado.
Con la aparición de los dispositivos móviles, la tendencia ha sido que los servicios se alberguen en la
nube y que cada usuario ejecute las aplicaciones en su móvil, o navegador web en el caso de SO’s de
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 41
CAPÍTULO 6. DATASETS
Figura 6.1: Cuota de mercado global de Sistemas Operativos
escritorio, mientras que almacena sus datos en la nube.
Si un sistema operativo de un ordenador de escritorio o dispositivo móvil tiene una vulnerabilidad de
seguridad y un usuario malintencionado consigue el control de ese dispositivo, habrá conseguido acceder
a la información de 1 persona.
Sin embargo, si un usuario malintencionado de un sistema operativo de un servidor o supercomputador,
toma el control de dicho sistema, habrá conseguido acceder a la información de todos los usuarios de todos
los servicios que se encuentren alojados en ese servidor.
Por lo tanto, de esto deducimos que: si bien Linux significa el 1% de los dispositivos del mundo, y por
lo tanto debería ser prácticamente el último SO a proteger, dado que cada servidor es utilizado por miles
o millones de personas, por el impacto que produce una única vulnerabilidad se convierte de facto en el
primer punto más importante a proteger.
Figura 6.2: Cuota de mercado de servidores web por sistema operativo
En el gráfico 6.2 podemos ver diferencias importantes dependiendo de la fuente que escojamos. En este
caso diremos que los sistemas operativos con kernel Linux representan entre un 67% y un 98% de la
cuota de mercado, de los cuales la mitad son de un sistema operativo de una distribución conocida, lo
que significa que entre un 34% y el 97% del mercado global de sistemas operativos para servidores web
42 Trabajo de Fin de Grado
CAPÍTULO 6. DATASETS
correspondiente a una distribución de Linux conocida.
Figura 6.3: Evolución de los sistemas operativos en el top 500 de supercomputación
A fecha de noviembre de 2017, los 500 supercomputadores más potentes del mundo utilizan Linux.
6.2. ¿Por qué Debian?
Como se puede ver en la figura 6.4, un 26% de los servidores linux funcionan con Debian. Ahora bien,
si tenemos en cuenta las distribuciones derivadas de Debian, como por ejemplo Ubuntu, nos encontramos
con que más del 60% de los servidores web del mundo utilizan Debian como SO.
Estos datos, junto con los del apartado anterior, permiten concluir que al menos el 20% de los servidores
del mundo funcionan con una distribución Debian o alguno de sus derivados.
Figura 6.4: Cuota de mercado de Servidores web Linux
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 43
CAPÍTULO 6. DATASETS
Una de las características más reseñables de este sistema operativo, es la alta fiabilidad que proporciona
su sistema de distribución de software.
Esta fiabilidad viene dada por dos motivos:
1. Transparencia: el software distribuido por Debian en su repositorio principal (main) es software
libre. Esto quiere decir, entre otras cosas, que cualquiera puede descargar el código fuente que
forma parte del software que está instalando en su equipo. Es decir, que en cualquier momento
cualquiera, incluso uno mismo, puede ver qué lineas de código está ejecutando exactamente su
máquina.
2. Confianza: Las distribuciones de Linux, como su propio nombre indica, son las responsables de
distribuir el software de sus sistemas en forma de paquetes, y lo hacen por medio de repositorios de
paquetes. Antes de poner el paquete de software a disposición del usuario de la distribución, dicho
paquete es firmado con una clave privada GPG cuya clave pública se encuentra dentro del anillo de
claves de confianza de la distribución. Esto significa que dichos paquetes han sido supervisados por
alguien en quien el responsable de la distribución confía. Además, el uso de GPG en el proceso de
distribución de paquetes asegura la integridad del paquete una vez que éste ha llegado al ordenador
donde se va a instalar y, si el anillo de claves gpg no ha sido manipulado por un atacante, nos
asegura que el paquete proviene de la distribución de origen.
6.3. Criterios de selección de ficheros
Consideramos que un fichero es un fichero binario si al ejecutar la herramienta del sistema file sobre
el fichero, la salida obtenida contiene la cadena “ELF” y al mismo tiempo no contiene la cadena “not an
ELF”.
Los ficheros binarios se han elegido por cumplir las siguientes condiciones:
Goodware:
Ficheros binarios de la distribución de Debian GNU/Linux de entre los que se encuentran ubicados
en el sistema en un directorio cuyo nombre termina en la cadena “bin”. Ejemplo de directorio:
/usr/bin
Para el caso de la arquitectura amd64, está formado por: Total ficheros posibles: 13564 Total ficheros
binarios: 6331
Para el caso de la arquitectura i386, está formado por:
Total ficheros posibles: 13506 Total ficheros binarios: 6266
44 Trabajo de Fin de Grado
CAPÍTULO 6. DATASETS
Malware:
ficheros binarios contenidos en el dataset de virus de linux de VirusShare [2]
Total ficheros posibles: 9482 Total ficheros binarios: 3565
A partir de estos subconjuntos de ficheros binarios se han formado los siguientes datasets:
1. Dataset amd64: Goodware amd64 + Malware = 6331 goodware + 3565 malware = 9896
ficheros binarios Los datos resultantes de este dataset son los siguientes:
• Proporción: Goodware = 63.9753435732%; Malware = 36.0246564268%
• Número de características o palabras diferentes: 12.384.366
• Varianza final aplicada: 96%
• Número de características o palabras tras filtro por varianza: 12.169.
2. Dataset i386: Goodware i386 + Malware = 6266 goodware + 3565 malware = 9831 ficheros
binarios
• Proporción: Goodware = 63.7371579697%; Malware = 36.2628420303%
• Número de características o palabras diferentes: 8.905.965
• Varianza final aplicada: 97%
• Número de características o palabras tras filtro por varianza: 14509.
Ambos datasets con una proporción goodware-malware muy similar 63-36.
Partiendo de estos datos, una precisión inferior al porcentaje del tipo de dato más alto se consideraría un
resultado del todo inútil, ya que podríamos decir que todos los datos son goodware y tener un 63.97%
de acierto.
Siguiendo con el proceso, para llegar a aplicar el algoritmo de clasificación es necesario convertir
los ficheros binarios en un conjunto de datos comprensible por el ordenador, esto es una matriz
de características booleanas o numéricas, en nuestro caso usaremos una matriz numérica porque
consideramos que contiene más información.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 45
7Desarrollo
7.1. Fases ejecutables
Al ejecutar el programa podemos ejecutar una fase en concreto. Las fases ejecutables por el programa
son las mismas descritas en el apartado de 5 a diferencia de que en el programa se han organizado de la
siguiente manera:
7.1.1. Fase 1: obtención de las repeticiones de palabras para cada fichero
binario.
Esta fase es la encargada de: - Diferenciar entre ficheros binarios y no binarios, - Obtener los reportes
de análisis estático de los ficheros binarios, - Parseo de los reportes de análisis estático en palabras, -
Conteo de las repeticiones de palabras para cada reporte.
7.1.2. Fase 2: obtención del universo de palabras existente en el dataset.
En esta fase se obtiene una lista con el universo completo de palabras existentes en el dataset.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 47
CAPÍTULO 7. DESARROLLO
7.1.3. Fase 3: obtención de los subconjuntos de entrenamiento y test.
En esta fase se realizan las siguientes acciones: - Obtención de las repeticiones de todas las palabras
en el dataset, - Obtención de los minidatasets:
Se ha hecho una lista de listas de palabras en función del número de veces que aparecen repetidas en
total en el universo de palabras.
Figura 7.1: Distribución de palabras por número de repeticiones en el dataset
Como se puede ver en 7.1, la mayoría de las palabras se repiten 1-2 veces. Esto es debido a que en los
análisis readelf muchas direcciones de memoria aparecen solo una vez en uno de los informes, y por lo
tanto son demasiado específicas para un único binario. Por otro lado tambien nos interesa eliminar las
palabras que son tan comunes que aparecen en la mayoría de los binarios. Por este motivo consideramos
que aportan poca información y por eso tambien procuraremos eliminarlas del conjunto de palabras Para
esta tarea nos servirá el filtrado por baja varianza que aplicaremos más adelante.
A continuación se han tomado los subconjuntos de características cuyo número total de palabras es
muy cercano a 5.000 que es el máximo fijado para que el ordenador lo pueda computar, y se han formado
submatrices del conjunto total formadas por estas características para todos los binarios. A cada una de
estas submatrices se le ha llamado minidataset.
- Partición y filtrado por varianza de cada minidataset.
El tamaño del dataset y la capacidad limitada de cómputo ha obligado a hacer un prefiltrado de
características. En esta fase, como en todas, se ha tenido en cuenta no producir fugas de datos para no
obtener falsas conclusiones. Es en este punto del programa donde se hace la conversión de los datos del
48 Trabajo de Fin de Grado
CAPÍTULO 7. DESARROLLO
tipo Dataframe de Pandas, que incluye un índice para filas y otro para columnas que nos permiten en
cualquier momento conocer qué características se están utilizando y qué binarios, a matriz numérica de de
numpy, la cual no incluye dichos índices. Para ello se ha dividido cada minidataset siempre de la misma
manera y se ha procedido a entrenar un filtro varianza con los datos de entrenamiento, para seguidamente
aplicar dicho filtro tanto al conjunto de entrenamiento como al conjunto de test.
Esto se puede observar en la siguiente sección de código de la función datasets2finalDataset().
''' Dataset split: Ejecutamos el mismo split sobre los datos para cada submatriz
(representando cada una un minidataset). Se obtienen las mismas muestras cada vez
porque utilizamos el mismo valor para random_state.
'''
X_train, X_test, y_train, y_test = train_test_split(
X_unfiltered, y, test_size=test_size, random_state=42)
X_train, X_test = remove_features_w_low_variance(X_train, X_test, variance)
En primer lugar dividimos cada submatriz siempre de la misma manera. Esto se consigue utilizando
para cada submatriz la misma semilla aleatoria que en nuestro caso hemos fijado arbitrariamente en
42. De este modo tomamos las mismas filas o ficheros binarios para cada una de ellas, obteniendo los
subconjuntos de entrenamiento X_train e y_train, y los subconjuntos de test X_test e y_test. Los
subconjuntos X significan características y los subconjuntos y significan resultado.
A continuación se procede a filtrar las características por baja varianza tal como se puede ver en la
función remove_features_w_low_variance().
def remove_features_w_low_variance(X_train, X_test, minimum_variance=0.8):
'''Variance: defines minimium percentage of variance allowed for a column (default 80%).
This is, if a column have the 81% of its values set to the same value (1 or 0), it will be removed from the features selected.
'''
# Filtro por varianza - 1 para cada submatriz (minidataset)
# Para un 80%: sel = VarianceThreshold(threshold=(.8 * (1 - .8)))
selector = VarianceThreshold(threshold=(minimum_variance * (1 - minimum_variance)))
# Utilizamos los datos de entrenamiento para decidir el filtro por varianza
# y despues aplicamos el mismo filtro a los datos de test, pero en ningún caso
# se decide el filtro con X_test sino solo con X_train. X_test solo recibe el filtro.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 49
CAPÍTULO 7. DESARROLLO
X_train = selector.fit_transform(X_train)
X_test = selector.transform(X_test)
return X_train, X_test
Como se puede ver, primero se entrena el filtro con los datos de entrenamiento, y después se aplica el
mismo filtro a ambos subconjuntos, lo que quiere decir que las decisiones de filtrado se están tomando
partiendo únicamente de los datos de entrenamiento.
Cada submatriz filtrada se concatena a una matriz resultado. Si dicha matriz resultado supera en
número de columnas (características o palabras) el número fijado por limitaciones hardware en 15.000,
se reduce la varianza en un 1%, se aplica la nueva varianza a la matriz resultante y se continua el
proceso hasta que no queden más submatrices por filtrar e incorporar al resultado o hasta que la varianza
aplicada baje del 50%. Se pone el límite del 50% porque se entiende que los filtros inferiores al 50% son
equivalentes a los filtros superiores a 50%, ya que es lo mismo filtrar por 60% que por 40%.
Al terminar esta fase obtenemos los conjuntos X_train, y_train, X_test, y_test filtrados por varianza
y conocemos también la varianza final aplicada.
7.1.4. Fase 4: Filtro por chi², entrenamiento y validación de los modelos.
La fase 3 nos proporciona el mayor número de características que nuestro ordenador puede procesar,
pero nosotros ahora queremos optimizar el proceso de aprendizaje para lo cual aplicamos un filtro de
características por el criterio de chi² que es un criterio específico para algoritmos de clasificación. El
numero de k mejores características a utilizar se puede elegir por medio del argumento -f de entrada al
programa. En nuestro estudio hemos utilizado 1 y 3332 características.
Para validar el modelo se han aplicado 2 métodos:
1. Validación cruzada sobre subconjunto de test: se obtiene la exactitud resultante de la validación
cruzada del modelo sobre los datos de test X_test e y_test, se hace esta validación por medio del
funcionamiento por defecto de la función cross_val_score de la libreria Scikit-learn. Es decir, se
divide el conjunto en 3 subconjuntos y se toma cada vez 2 de ellos para entrenar el modelo y el
restante para comprobar los resultados. Este proceso se repite tomando para test cada uno de los
subconjuntos.
2. Validación simple detallada utilizando conjunto de entrenamiento y test:
para cada modelo se hacen las siguientes acciones: se entrena con las matrices X_train e y_train, y
se obtienen las valoraciones de Exhaustividad, precisión, F1 y exactitud utilizando los subconjuntos
de test X_test e y_test.
50 Trabajo de Fin de Grado
CAPÍTULO 7. DESARROLLO
7.1.5. Fase 5: identificación de las características utilizadas en la fase 4.
Esta es la fase que hace el proceso explicado anteriormente como del modelo a los datos ya que en esta
fase vamos a recorrer el camino desde el vector de características a qué característica o características se
corresponden con dicho vector. Se implementa esta fase con la intención de saber en qué información se
basa el algoritmo para tomar decisiones. La información obtenida en esta fase ha sido especialmente útil
para conocer mejor los resultados obtenidos para 1 característica en el caso del dataset de amd64.
En esta fase se toma la matriz de características utilizada en el modelo, que es la resultante del filtro de
k mejores características por el criterio de chi² obtenida en la fase 4, y se obtienen la o las características
que satisfacen ese vector de características.
7.2. Instalación del programa
El programa está pensado para ser ejecutado directamente desde cualquier directorio que posea el
usuario.
Para configurar el equipo haremos lo siguiente:
1. Es necesario tener instaladas las dependencias. Este es el único comando para el que neceitaremos
permisos de root. Para ello, desde la terminal ejecutamos:
sudo apt -get install pip3 python3 readelf file
2. Desde la terminal, estando en el mismo directorio donde tenemos los ficheros requirements.txt,
ejecutamos el siguiente comando:
pip3 install -r requirements.txt
Los paquetes python a instalar se encuentran definidos en el fichero requirements.txt A.3. Esto
instalará las dependencias en el directorio de configuración local de python 3 y ya estaremos listos
para ejecutar el programa.
7.3. Cómo ejecutar el programa
El programa para llevar a cabo una correcta ejecución requiere que se lance en el mismo directorio en
el que se encuentra ubicado y que el fichero de configuración se encuentre también en el mismo directorio.
Es requisito imprescindible que el fichero de configuración esté correctamente configurado y que no
falten valores por definir.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 51
CAPÍTULO 7. DESARROLLO
El programa se puede ejecutar con o sin parámetros. Si se ejecuta sin parámetros su ejecución utilizará
los valores por defecto.
7.3.1. Parámetros
Los parámetros con que se puede ejecutar son:
usage: ml_mw_analyzer.py [-h] [--version] [-l config_label]
[-s STAGE]
optional arguments:
-h, --help show this help message and exit
--version show program 's version number and exit
-l config_label The config file label used to get the configuration.
Default: malwarelab
-f NUM_KBEST_FEATURES , --features NUM_KBEST_FEATURES
defines the k-best features used to train the
algorithms in stage 4.
-s STAGE , --stage STAGE
defines the stage number to run. i.e: 4
7.3.2. Ejemplos de ejecución
Se recomienda ejecutar el programa desde una consola del sistema, no se necesita ni se recomienda su
ejecución con permisos de administrador. Cabe recordar que el programa se ejecuta en 5 fases. Estando
en el directorio donde se encuentra el programa se puede ejecutar de las siguientes maneras:
Ejemplo 1: Sin argumentos
Esta llamada ejecutará la fase 1 del programa. La configuración que se utiliza en este caso es la
configuración por defecto, que es la que está etiquetada en el fichero de configuración como ’malwarelab’.
./ ml_mw_analyzer.py
Cabe señalar el programa está probado para una ejecución sin problemas en un sistema con 12Gb
de Random Access Memory (RAM) si se ejecuta fase a fase. En caso de querer ejecutar todas las fases
seguidas será conveniente disponer de un ordenador con más RAM o debemos esperar que el sistema
utilice la memoria Memoria SWAP, ralentizando sobremanera el proceso.
52 Trabajo de Fin de Grado
CAPÍTULO 7. DESARROLLO
Ejemplo 2: Aplicando una configuración personalizada.
Podemos crear otra configuración, específica para el ordenador que estemos utilizando, simplemente
clonando la sección por defecto del fichero de configuración y dandole el nombre que queramos.
Normalmente un nombre que identifique el ordenador o el dataset que vayamos aplicar.
./ ml_mw_analyzer.py -l nombre_de_mi_configuracion_especial
Ejemplo 3: Ejecutando una fase específica
En lugar de hacer todas las fases seguidas de una vez, nos puede interesar más ejecutar el proceso
a partir de una fase concreta. En ese caso podemos utilizar el argumento -s para especificar qué fase
queremos ejecutar.
./ ml_mw_analyzer.py -s 3
Este comando ejecutará únicamente la fase 3.
Es necesario que la fase anterior se haya terminado con éxito para poder realizar las siguientes con
éxito.
Ejemplo 4: Ejecutando la fase 4 con K mejores características por argumento
Para ejecutar la fase 4 del software descrita en la sección 7.1.4 con un número de k mejores características
concreto, ejecutamos:
./ ml_mw_analyzer.py -l nombre_de_mi_configuracion_especial -s 4 -f 2000
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 53
8Resultados
Para evaluar la bondad de un algoritmo hay que tener en cuenta el contexto en el que lo estamos
aplicando, en nuestro caso hablamos de detección de malware, donde una sola brecha de seguridad puede
causar graves daños en el sistema o corporación que estamos defendiendo.
Debido a esto le damos mucha importancia a que un resultado no proporcione falsos negativos, porque
en este contexto un falso negativo es un fichero malware clasificado como goodware, lo que implicaría que
el atacante consiguiera su objetivo que es ejecutar un 0-Day en el sistema.
La siguientes tablas de resultados resumen los resultados obtenidos para los modelos estudiados para
dos subconjuntos de características: 1 y 3332. Dichos resultados se pueden ver de manera gráfica a en los
apéndices adjuntos al final de este documento.
Atendiendo a los criterios descritos en 8.1 tendremos en cuenta, en este orden: Exhaustividad (recall),
precisión, F1 y Exactitud (Accuracy).
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 55
CAPÍTULO 8. RESULTADOS
8.1. Criterio de evaluación de los modelos en el contexto de
malware
El valor más importante en nuestra comparativa es la exhaustividad o recall que, como ya se explicó en
la sección 4 del marco teórico, indica qué proporción de verdaderos positivos se identificó correctamente.
Un valor en este apartado inferior al 100% indicaría que se habría marcado un fichero de malware como
goodware, y esto es lo último deseable. En nuestro caso vamos a priorizar el recall por encima de cualquier
otro valor ya que cada caso implica una potencial brecha de seguridad.
El siguiente valor más importante en nuestro contexto es la precisión, la cual responde a la pregunta
de qué proporción de verdaderos positivos es correcta entre los verdaderos positivos y los falsos positivos.
Este valor lo interpretaremos como una molestia para el usuario o administrador del sistema ya que cuanto
más se aleje este valor del 100%, más ficheros de goodware estarán siendo etiquetados como malware,
tras lo cual el usuario o administrador tendrá que hacer un análisis más profundo de la situación para
comprobar si es realmente goodware o malware. En nuestro contexto este será el segundo valor más
importante a tener en cuenta.
A partir de aquí, una vez hemos considerador exhaustividad o recall y precisión, los demás valores
podemos despreciarlos, pero en caso de tenerlos en cuenta el orden seria, en tercer lugar el valor F1,
que es una media armónica entre el recall y la precisión, y en cuarto lugar la exactitud o accuracy, que
representa la proporción del número de predicciones correctas entre el número de predicciones realizadas.
Por último consideraremos el tiempo de entrenamiento como el último factor determinante para elegir el
mejor modelo.
56 Trabajo de Fin de Grado
CAPÍTULO 8. RESULTADOS
8.2. Tabla comparativa - Dataset amd64
Tabla 8.1: Comparativa de algoritmos con dataset amd64Algoritmo\Métrica Muestras Validación cruzada
(Accuracy) Exhaustividad Precisión F1 Exactitud Tiempo deCómputo
Naïve Bayes 3332 0.9960 0.9896 0.98618 0.98788 0.99140 1.778521 0.9770 1.0 0.9232 0.96006 0.970534 0.00917
Nearest Neighbors 3332 0.9972 0.99306 0.99825 0.99565 0.99693 23.907391 0.9770 1.0 0.9232 0.96006 0.9705 0.09252
Decision Tree 3332 0.9991 0.999133 0.9974 0.998268 0.99877 1.524871 0.977 1.0 0.9232 0.960066 0.97053 0.01062
Random Forest 3332 0.9853 0.82582 0.9916 0.90118 0.93585 0.651081 0.977 1.0 0.9232 0.96006 0.97053 0.09507
Linear SVM 3332 0.9985 0.99740 0.99913 0.99826 0.998772 7.979931 0.977 1.0 0.9232 0.960066 0.97053 0.07799
RBF SVM 3332 0.7305 0.29462 1.0 0.45515 0.750153 384.406111 0.9770 1.0 0.9232 0.96006 0.970534 1.46092
Neural Net 3332 0.9988 0.99826 0.998266 0.998266 0.9987722 87.196741 0.9770 1.0 0.9232 0.96006 0.970534 2.25822
AdaBoost 3332 0.9997 1.0 0.9982 0.9991 0.99938 27.740011 0.9770 1.0 0.9232 0.96006 0.970534 2.05079
Según los criterios descritos en la sección 8.1 se observa que es el modelo de AdaBoost entrenado con
3332 features el mejor modelo a utilizar para este caso, ya que proporciona un 100% de exhaustividad,
y un 99.82% de precisión. Esto significa que es capaz de detectar todos los ficheros de malware del
subconjunto considerado, con una mínima molestia para el usuario, habiendo detectado únicamente 2
ficheros de goodware como malware, en un conjunto formado por un total de 3258 ficheros que forman el
subconjunto de test.
Cabe señalar el resultado obtenido utilizando una sola característica para entrenar el modelo. Y es
que utilizando la k-mejor característica se consigue un recall del 100% y una precisión superior al 92%.
Debido a este resultado se ha procedido a identificar dicha característica, obteniéndose no una sino 2
posibles palabras que pueden corresponder al mismo vector de características. Se ha procedido a repetir
la evaluación de los modelos utilizando las 2 mejores características, confirmándose el resultado ya que
los valores obtenidos para cada modelo son exactamente los mismos que para 1 característica.
Las palabras que corresponden a estos vectores de características son: “000000000008” y
“R_X86_64_RELATIVE”. Estas palabras aparecen la misma cantidad de veces en los mismos ficheros
binarios, y cuando aparecen los modelos identifican el fichero como goodware. Sin embargo, hay ficheros
que no son malware y que tampoco contienen estas palabras. Esto es lo que produce los valores de recall
y precisión tan llamativos.
A día de hoy, no sabemos el significado de estas palabras en los informes estáticos readelf. Podemos
lanzar una hipótesis que asocia estas palabras al hecho de que el dataset escogido proviene de una
distribución de ficheros binarios Debian compilada específicamente para arquitectura amd64, y es probable
que los ficheros binarios de malware contenidos en el dataset estén compilados para una arquitectura más
compatible como es la i386, dado que un binario de 32 bits se puede ejecutar en un sistema de 64 bits
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 57
CAPÍTULO 8. RESULTADOS
pero no al revés. Esto tiene sentido dado que el objetivo de un desarrollador de malware está más cercano
a conseguir una alta compatibilidad de su malware que de una alta eficiencia a la hora de ejecutarlo.
Por lo tanto, en caso de ser esta hipótesis cierta, estaríamos diciendo que el resultado obtenido ha
dependido en gran medida del tipo de dataset tomado como goodware.
Esto nos hace plantear la idea de que es más fácil conseguir buenos resultados de detección sobre un
conjunto de datos bien definido y acotado que sobre un conjunto de datos más genérico y global.
Esto quiere decir que a la hora de utilizar técnicas de aprendizaje automático para la detección de
malware, el camino con más probabilidades de conseguir una alta valoración de recall y precisión sea
preparar modelos de detección específicos para el sistema a proteger o incluso el tipo de fichero a analizar.
58 Trabajo de Fin de Grado
CAPÍTULO 8. RESULTADOS
8.3. Tabla comparativa - Dataset i386
Tabla 8.2: Comparativa de algoritmos con dataset i386Algoritmo\Métrica Muestras Validación cruzada
(Accuracy) Exhaustividad Precisión F1 Exactitud Tiempo deCómputo
Naïve Bayes 3332 0.9926 0.99573 0.97656 0.986058 0.989805 3.237201 0.5036 0.986348 0.427831 0.596799 0.5174544 0.00899
Nearest Neighbors 3332 0.9901 0.991467 0.994012 0.992738 0.9947482 33.49141 0.8570 0.787542 0.801215 0.794320 0.852332 0.02385
Decision Tree 3332 0.9954 1.0 0.987363 0.993641 0.995366 2.838111 0.8715 0.726109 0.871926 0.792365 0.862218 0.01437
Random Forest 3332 0.8959 0.983788 0.973817 0.978777 0.984553 1.539341 0.8709 0.733788 0.897703 0.807511 0.873339 0.11728
Linear SVM 3332 0.9963 0.996587 0.996587 0.996587 0.9975285 10.80331 0.7967 0.733788 0.706075 0.719665 0.7930182 2151.95
RBF SVM 3332 0.7090 0.297781 1.0 0.458908 0.7457522 414.2141 0.8832 0.774744 0.873917 0.821347 0.8779734 3.06417
Neural Net 3332 0.9978 0.997440 0.988165 0.992781 0.9947482 83.74641 0.8514 0.691979 0.886338 0.777192 0.8563484 1.46863
AdaBoost 3332 0.9978 1.0 1.0 1.0 1.0 32.61201 0.8638 0.719283 0.893955 0.797163 0.8674698 0.51344
Para una característica ningún modelo consigue una exhaustividad ni exactitud superior al 90%. La
precisión más habitual está entre 70% y 80% a excepción de Naïve Bayes con un 98%. En cualquier
caso, la exhaustividad obtenida hace que los modelos entrenados con una característica no sean útiles
para detección de malware.
La k mejor característica es la correspondiente a la palabra: “00000000”, lo cual actualmente no nos
indica nada en concreto ya que aparentemente muestra un comportamiento linealmente independiente
con el vector de respuestas, tal y como indican los bajos valores obtenidos en los diferentes valoraciones
para una característica.
Para 3332 características encontramos resultados muy variados. Al igual que se observó con el dataset
de amd64, el mejor modelo obtenido es otra vez Adaboost con 3332 características. Consigue un 100%
en todos los valores. El valor de validación cruzada de exactitud que no llega al 100% es poco relevante
ya que es el valor menos significativo y además está muy cercano al 100%.
El algoritmo que peores resultados obtienen con 3332 características es RBF SVM. A pesar de contar
con una precisión del 100%, el 29% en exhaustividad lo descarta de facto como una buena opción.
Los demás algoritmos consiguen buenos resultados siendo de mejor a peor: Árbol de decisión, Red
neuronal, SVM lineal, Naïve Bayes, Nearest Neighbors y Bosque aleatorio. Aunque estos algoritmos no
muestren el mejor resultado de la comparativa, esto no quiere decir que con una selección de características
diferente no puedan conseguir un resultado excelente como la del algoritmo Adaboost.
El algoritmo de Bosque aleatorio ha obtenido la peor valoración cruzada para 3332 características pero
muy buena valoración en la prueba detallada simple. Esto hace pensar que ha tenido suerte en la partición
del conjunto de datos y que en condiciones reales podría fallar más que el resto de algoritmos.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 59
9Conclusiones
Se ha llevado a cabo un proyecto de aprendizaje automático utilizando dos conjuntos de datos de
goodware con un conjunto de datos de malware lo cual nos ha permitido comparar los resultados de varios
algoritmos de clasificación en el entorno de detección de malware. Se ha implementado una herramienta
software realiza todo el proceso de análisis desde el dato en crudo hasta la evaluación de cada modelo
obtenido, pasando por la vectorización de los datos y el filtrado de características, procurando en todo
momento hacer un buen manejo al tratar los datos para prevenir errores por fuga de datos.
Los valores obtenidos en el dataset de amd64 con una característica, y la palabra que corresponde a
dicha característica, nos hace pensar que el malware existente en nuestro dataset está compilado para
la arquitectura i386. Esto tiene sentido porque los binarios de i386 son ejecutables en amd64 pero no
al revés, y parece lógico pensar que un desarrollador de malware elija que sus desarrollos tengan una
mayor compatibilidad entre sistemas antes que una mayor eficiencia de ejecución compilando para una
arquitectura menos compatible como es amd64.
Además observamos que el resultado obtenido al valorar los diferentes modelos entrenados ha sido
dispar, lo que nos ha permitido discutir y decidir qué criterio es el que más conviene aplicar según el
objetivo que nos marque el contexto sobre el que estamos haciendo el proyecto, en nuestro caso detección
de malware.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 61
CAPÍTULO 9. CONCLUSIONES
Además, los resultados obtenidos nos permiten concluir que, entre los algoritmos considerados, el
conjunto de características que mejores resultados ha dado ha sido el de 3332 K-mejores características,
y que tras evaluar y comparar varios algoritmos de clasificación, el algoritmo que peores resultados ha
obtenido ha sido RBF SVM con una exhaustividad del 29% y el que mejor resultados ha dado ha sido
Adaboost, que ha obtenido un 100% en exhaustividad, precisión, F1 y exactitud en la prueba simple, y
una valoración superior al 99% en la validación cruzada de exactitud.
Este resultado, junto con el hecho de que el entrenamiento de la prueba simple se ha hecho con un
67% del conjunto completo de datos, nos hace concluir que el algoritmo Adaboost se muestra como
un algoritmo muy interesante para implementar un detector de malware capaz de detectar malware
polimórfico a partir del análisis estático de ficheros binarios.
Para terminar, los resultados obtenidos en estudios similares en este campo, las precauciones tomadas
en el manejo del dataset y la naturaleza del mismo, nos hacen pensar que los resultados obtenidos no
se ven afectados por efectos no deseados como las fugas de datos, lo que quiere decir que se trata de
resultados fiables en el ámbito de detección de ficheros binarios ejecutables de malware en Linux.
62 Trabajo de Fin de Grado
Bibliografía
[1] Debian.org.Debian Buster. Accedido en 12-06-2018 a urlhttps://cdimage.debian.org/cdimage/buster_di_alpha2/amd64/iso-
cd/debian-buster-DI-alpha2-amd64-netinst.iso. 2018.
[2] VirusShare_Linux_20160715. Accedido en 15-03-2018 a urlhttps://tracker.virusshare.com:7000/torrents/VirusShare_Linux_20160715.zip.torrent.
2016.
[3] Global Digital Report 2018. 2018. url: https://wearesocial.com/blog/2018/01/global-
digital-report-2018.
[4] Informe mobile en Espania y en el mundo 2017. 2017. url: https://www.amic.media/media/
files/file_352_1289.pdf.
[5] Allianz Risk Barometer 2017 - Top risks in focus: Cyber incidents. url: https://www.agcs.
allianz.com/insights/expert-risk-articles/allianz-risk-barometer-2017-top-risks-
cyber-incidents/.
[6] La historia del malware, actualizada: un breve repaso. 24 de oct. de 2016. url: https://www.
welivesecurity.com/la-es/2016/10/24/historia-del-malware-actualizada/.
[7] Malware: van en aumento los ataques a macOS y Linux. url: https://andro2id.com/malware-
van-aumento-ataques/.
[8] titlG Data: menos malware pero más complejo y peligroso. 25 de sep. de 2012. url: https://www.
muyseguridad.net/2012/09/25/g-data-menos-malware-pero-mas-complejo-peligroso/.
[9] Aplicaciones GNU/Linux. url: https://es.wikipedia.org/wiki/GNU/Linux\#Aplicaciones.
[10] Alireza Souri y Rahil Hosseini. «A state-of-the-art survey of malware detection approaches using
data mining techniques». En: Human-centric Computing and Information Sciences 8.1 (2018),
pág. 3. issn: 2192-1962. doi: 10.1186/s13673-018-0125-x. url: https://doi.org/10.1186/
s13673-018-0125-x.
[11] WatchGuard Launches New Quarterly Internet Security Report. 30 de mar. de 2017. url: https:
//www.watchguard.com/wgrd-about/press-releases/watchguard-launches-new-quarterly-
internet-security-report.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 63
BIBLIOGRAFÍA
[12] Pedram Hayati y Vidyasagar Potdar. «Evaluation of spam detection and prevention frameworks
for email and image spam - a state of art». En: (ene. de 2008).
[13] Debian.org. Debian Project. Accedido en 09-07-2018 a urlhttps://www.debian.org/. 2018.
[14] AV-Test Lab tests 16 Linux antivirus products against Windows and Linux malware. url: https:
//www.csoonline.com/article/2989137/linux/av-test-lab-tests-16-linux-antivirus-
products-against-windows-and-linux-malware.html.
[15] Raquel Noblejas Sampedro. «Estudio de algoritmos de detección de anomalías y su aplicación a
entornos de ciberseguridad». Madrid, 2016. url: http://oa.upm.es/40490/.
[16] An Introduction to Machine Learning Theory and Its Applications: A Visual Tutorial with Examples.
url: http : / / www . toptal . com / machine - learning / machine - learning - theory - an -
introductory-primer.
[17] Shiguang Mu Jinrong Bai Yanrong Yang y Yu Ma. «Malware Detection Through Mining Symbol
Table of Linux Executables». En: (2013).
[18] Zahoor Rehman y col. «Machine learning-assisted signature and heuristic-based detection of
malwares in Android devices». En: (dic. de 2017).
[19] EMC Education Services. Data Science and Big Data Analytics: Discovering, Analyzing, Visualizing
and Presenting Data. Wiley, 2015. isbn: 9781118876138. url: https://books.google.es/books?
id=QLblBQAAQBAJ.
[20] Accuracy, Precision, Recall or F1? 15 de mar. de 2018. url: https://towardsdatascience.com/
accuracy-precision-recall-or-f1-331fb37c5cb9.
64 Trabajo de Fin de Grado
Apéndices
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 65
AAnexos
A.1. Fichero de Configuración
[commons]
# Directorio donde se almacenan los ficheros de persistencia. Tanto resultados parciales como finales.
persistence_dir=persistence
# Nombres de fichero según la fase a la que pertenecen.
persistence_stage1_filename=stage1_dwords
persistence_stage1_goodware_filename=stage1_goodware_dwords
persistence_stage1_malware_filename=stage1_malware_dwords
persistence_stage2_filename=stage2_all_different_words_but_commons
persistence_stage3_filtered_dword_filename=stage3_filtered_dword
persistence_stage3_filtered_words_filename=stage3_filtered_words
persistence_stage3_filtered_dataset_filename=stage3_filtered_dataset
persistence_stage3_X_train_filename=stage3_X_train
persistence_stage3_X_test_filename=stage3_X_test
persistence_stage3_y_train_filename=stage3_y_train
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 67
APÉNDICE A. ANEXOS
persistence_stage3_y_test_filename=stage3_y_test
persistence_stage3_minidataframes_filename=stage3_minidataframes
persistence_stage3_y_filename=stage3_y
persistence_stage4_x_train_filtered_filename=stage4_x_train_filtered
persistence_stage4_x_test_filtered_filename=stage4_x_test_filtered
#persistence_stage4_filename=stage4_csv
persistence_stage5_filename=stage5_cual
# Indica si la matriz de características final se obtendrá con forma de resultado booleano.
boolean_result = False
# Indica si la matriz de características final se devolverá con los valores booleanos en forma de entero: '0' o '1'.
transform_bool_to_int = True
# Minimum variance applied at the begining
variance = 0.99
[malwarelab]
# Goodware directory
goodware_dir_base = /home/jose/Downloads/ISO/out
# Malware directory
malware_dirs = /home/jose/src/UPM/TFG/data/MALWARE/VirusShare/Linux/Virus_bin
[franky]
goodware_dir_base = /mnt/1/TFG_jaqm/ISOs/DEBIAN/out
malware_dirs = /mnt/1/TFG_jaqm/Dataset/VirusShare/Linux/Virus
[azubu]
goodware_dir_base = /home/jose/out
malware_dirs = /mnt/TFG/Virus_bin
68 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
A.2. Implementación
#!/usr/bin/env python3
# coding: utf-8
"""
package.module
~~~~~~~~~~~~~
This program receives 1 set of binary files at a time: goodware + malware.
Performs a static analysis over those binaries getting the reports,
parse the reports into words and transform that data into Binary_files instances.
Those instances are analyzed through machine learning and, finally,
an accuracy report is generated for each applied algorithm.
:copyright: 2018-06-20, Jose Antonio Quevedo Muñoz <[email protected]>
:license: GPL v3.0, see LICENSE for more details
"""
__version__ = "0.0.3"
import sys
import argparse
import logging
import configparser
import os
import cloudpickle
import itertools
import time
from subprocess import run, check_output, getoutput, STDOUT, PIPE
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import seaborn as sns
import numpy as np
from sklearn import metrics
from sklearn.metrics import average_precision_score, f1_score, recall_score, accuracy_score, precision_score
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 69
APÉNDICE A. ANEXOS
from sklearn.feature_selection import VarianceThreshold, SelectKBest, chi2
from sklearn.model_selection import train_test_split, ShuffleSplit, cross_val_score, cross_validate
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_moons, make_circles, make_classification
from sklearn.neural_network import MLPClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.gaussian_process.kernels import RBF
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis
## Inner variables that may be moved to the config file
# Amount of features at the end of the low variance features filter at stage3.
prefiltered_num_features = 15000
# Amount of features stored in memory for each iteration
default_num_features = 5000
# Amount of chi2 features at the end of stage3
num_best_features = int(prefiltered_num_features * (2/3))
# Amount of splits the dataset will be splitted for cross validation
default_num_splits = 3
##
names = [
"Naive Bayes",
"Nearest Neighbors",
"Decision Tree",
"Random Forest",
"Linear SVM",
"RBF SVM",
"Neural Net",
"AdaBoost"
70 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
]
classifiers = [
GaussianNB(),
KNeighborsClassifier(3),
DecisionTreeClassifier(max_depth=5),
RandomForestClassifier(max_depth=5, n_estimators=10, max_features=1),
SVC(kernel="linear", C=0.025),
SVC(gamma=2, C=1),
MLPClassifier(alpha=1),
AdaBoostClassifier()
]
commons_config_label = 'commons'
default_config_label = 'malwarelab'
test_size = 1/default_num_splits
not_considered_features = ['']
module = None
if hasattr(sys.modules['__main__'], '__file__'):
module = sys.modules['__main__'].__file__
log = logging.getLogger(module)
#bf_data = None
malware_flagname = "Malware_Flag"
cpkl_extension = ".cpkl"
def timing(f):
'''Función decorador utilizada para medir el tiempo que lleva ejecutar una función
'''
def wrap(*args):
time1 = time.time()
ret = f(*args)
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 71
APÉNDICE A. ANEXOS
time2 = time.time()
print('Tiempo de cómputo: %0.5f s' % ((time2-time1)*1))
return ret
return wrap
class Binary_file(object):
def __init__(self, filename, directory, malware_flag=None):
self.filepath = os.path.join(directory, filename)
_info_file_ = getoutput("file " + directory + "/" + filename)
self.is_elf = 'ELF' in _info_file_ and "Not an ELF file" not in _info_file_
if self.is_elf:
self.filename = filename
self._directory_ = directory
self.malware_flag = malware_flag
_info_readelf_ = run(
("readelf -a " + self.filepath).split(" "),
stderr=STDOUT,
stdout=PIPE
)
_info_readelf_ = str(_info_readelf_.stdout)
_readelf_words_ = _info_readelf_.replace("\n", " ").split(" ")
# Obtiene el diccionario de las palabras { palabra: repeticiones }
# a partir del output de readelf.
self.dword = self._gen_dword(_readelf_words_)
self.dword[malware_flagname] = self.malware_flag
def _gen_dword(self, list_of_words):
dword = {x: 0 for x in set(list_of_words) - set(not_considered_features)}
list_of_words = list(set(list_of_words) - set(not_considered_features))
for word in list_of_words:
if word not in not_considered_features:
dword[word] += 1
72 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
return dword
class DataSet_Config(object):
def __init__(self, config_filepath='config.ini', config_label=default_config_label):
self._config = configparser.ConfigParser()
self._config.read(config_filepath)
self._config_label = config_label
self.persistence_dir = self._config[commons_config_label]['persistence_dir']
__persistence_stage1_filename = \
self._config[commons_config_label]['persistence_stage1_filename'] + "_" + config_label
__persistence_stage2_filename = \
self._config[commons_config_label]['persistence_stage2_filename'] + "_" + config_label
__persistence_stage3_filtered_dword_filename = \
self._config[commons_config_label]['persistence_stage3_filtered_dword_filename']
__persistence_stage3_filtered_words_filename = \
self._config[commons_config_label]['persistence_stage3_filtered_words_filename']
__persistence_stage3_filtered_dataset_filename = \
self._config[commons_config_label]['persistence_stage3_filtered_dataset_filename']
__persistence_stage3_X_train_filename = \
self._config[commons_config_label]['persistence_stage3_X_train_filename']
__persistence_stage3_X_test_filename = \
self._config[commons_config_label]['persistence_stage3_X_test_filename']
__persistence_stage3_y_train_filename = \
self._config[commons_config_label]['persistence_stage3_y_train_filename']
__persistence_stage3_y_test_filename = \
self._config[commons_config_label]['persistence_stage3_y_test_filename']
__persistence_stage3_minidataframes_filename = \
self._config[commons_config_label]['persistence_stage3_minidataframes_filename']
__persistence_stage3_y_filename = \
self._config[commons_config_label]['persistence_stage3_y_filename']
__persistence_stage4_x_train_filtered_filename = \
self._config[commons_config_label]['persistence_stage4_x_train_filtered_filename']
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 73
APÉNDICE A. ANEXOS
__persistence_stage4_x_test_filtered_filename = \
self._config[commons_config_label]['persistence_stage4_x_test_filtered_filename']
# Filepaths
self.stage1_filepath = os.path.join(
self.persistence_dir, __persistence_stage1_filename + ".cpkl")
self.stage1_goodware_filepath = \
os.path.join(self.persistence_dir,
self._config[commons_config_label]['persistence_stage1_goodware_filename'] +
cpkl_extension)
self.stage1_malware_filepath = \
os.path.join(self.persistence_dir,
self._config[commons_config_label]['persistence_stage1_malware_filename'] +
cpkl_extension)
self.stage2_filepath = os.path.join(
self.persistence_dir, __persistence_stage2_filename + cpkl_extension)
self.stage3_X_train_filepath = os.path.join(
self.persistence_dir, __persistence_stage3_X_train_filename + cpkl_extension)
self.stage3_X_test_filepath = os.path.join(
self.persistence_dir, __persistence_stage3_X_test_filename + cpkl_extension)
self.stage3_y_train_filepath = os.path.join(
self.persistence_dir, __persistence_stage3_y_train_filename + cpkl_extension)
self.stage3_y_test_filepath = os.path.join(
self.persistence_dir, __persistence_stage3_y_test_filename + cpkl_extension)
self.stage3_minidataframes_filepath = os.path.join(
self.persistence_dir, __persistence_stage3_minidataframes_filename + cpkl_extension)
self.stage3_y_filepath = os.path.join(
self.persistence_dir, __persistence_stage3_y_filename + cpkl_extension)
self.stage3_filtered_dword_filepath = os.path.join(
self.persistence_dir, __persistence_stage3_filtered_dword_filename + cpkl_extension)
self.stage3_filtered_words_filepath = os.path.join(
self.persistence_dir, __persistence_stage3_filtered_words_filename + cpkl_extension)
self.stage3_filtered_dataset_filepath = os.path.join(
self.persistence_dir, __persistence_stage3_filtered_dataset_filename + cpkl_extension)
self.stage3_groups_of_columns_filepath = os.path.join(
74 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
self.persistence_dir, "groups_of_columns.cpkl")
self.stage4_x_train_filtered_filepath = os.path.join(
self.persistence_dir, __persistence_stage4_x_train_filtered_filename + cpkl_extension)
self.stage4_x_test_filtered_filepath = os.path.join(
self.persistence_dir, __persistence_stage4_x_test_filtered_filename + cpkl_extension)
self.goodware_bf_dir = self._config[config_label]['goodware_dir_base'].split(" ")
self.malware_bf_dir = self._config[config_label]['malware_dirs'].split(" ")
self.boolean_result = self._config[commons_config_label]['boolean_result']
self.transform_bool_to_int = self._config[commons_config_label]['transform_bool_to_int']
class Dataset(object):
def __init__(self, config_filepath='config.ini',
config_label='malwarelab'):
self._load_config(config_filepath, config_label)
self.goodware_bf = None
self.malware_bf = None
# bf_data: The original binary_files. Malware + Goodware, all together.
self.bf_data = None
self.filtered_dword = None
self.all_different_words = None
# count_words: { word: repetitions } in all the binary_files.
self.count_words = None
# filtered_dataset: the {word: repetitions}
self.filtered_dataset = None
# df: Dataframe
self.df = None
# grouped_words: a list of lists of words
self.groups_of_columns = None
def _load_config(self, config_filepath='config.ini',
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 75
APÉNDICE A. ANEXOS
config_label='malwarelab'):
self.config = DataSet_Config(config_filepath, config_label)
def _get_elf_files_from_dir(self, bin_dir, malware_flag):
bf_data = []
num_files = 0
if os.path.exists(bin_dir):
counter = 0
all_files_iterator = os.walk(bin_dir)
num_files = 0
num_binaries = 0
for walk_info in all_files_iterator:
''' Walk devuelve uniterador sobre todos los subdirectorios de un directorio
walk_info=(dirpath, dirnames, filenames)
'''
bin_dir = walk_info[0]
if 'bin' == bin_dir[-3:] or malware_flag == True:
for filename in walk_info[2]:
try:
num_files += 1
bf = Binary_file(filename, bin_dir, malware_flag)
if bf.is_elf:
num_binaries += 1
bf_data.append(bf)
except Exception as e:
log.error(os.path.join(bin_dir, filename) + ": " + e)
counter = print_marks(counter)
print(bin_dir + " -- hecho. Ficheros totales:"
+ str(num_files) + ". Binarios: " + str(num_binaries))
print()
print(bin_dir + ": ")
print("Total ficheros: " + str(num_files))
print("Total binarios: " + str(num_binaries))
else:
76 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
log.error("ERROR: el directorio no existe. Dir: " + bin_dir)
return bf_data
def _get_elf_files(self, bf_directories, malware_flag=None):
'''
Returns the ELF filenames binary_files_directory in the directory
'''
bf_data = []
for bin_dir in bf_directories:
bf_data += self._get_elf_files_from_dir(bin_dir, malware_flag)
return bf_data
def _run_elfs_analysis(self):
self.goodware_bf = self._get_elf_files(self.config.goodware_bf_dir,
malware_flag=False)
self.malware_bf = self._get_elf_files(self.config.malware_bf_dir, malware_flag=True)
self.bf_data = self.goodware_bf + self.malware_bf
print("#Binarios goodware: " + str(len(self.goodware_bf)))
print("#Binarios malware: " + str(len(self.malware_bf)))
print("#TOTAL Binarios: " + str(len(self.bf_data)))
def _get_values_in_range(self, minimum=None, maximum=None, words=None):
'''Opposite method to _remove values. It does the same, in a different way.
Devuelve un nuevo diccionario coteniendo las parejas claves-valor cuya clave
tambien está en el diccionario de palabras filtradas cuyos valores son inferiores a minimum y mayores que maximum.
Recorre las lista de palabras contadas devolviendo un diccionario con las palabras
filtradas por numero de repeticiones.
'''
result = {}
words = words if words else self.count_words
for word, value in words.items():
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 77
APÉNDICE A. ANEXOS
if value >= minimum and value < maximum:
result[word] = value
return result
def _str2value(self, value):
'''Convierte el valor recibido como value de tipo string o booleano, en un valor según las
variables de configuración del programa.
'''
result = None
if isinstance(value, str):
if self.boolean_result:
result = int(value) > 0
else:
result = int(value)
elif isinstance(value, bool):
if self.transform_bool_to_int:
if value:
result = 1
else:
result = 0
else:
result = value
elif isinstance(value, int):
result = value
else:
log.error("ERROR: convirtiendo tipos. Check value")
return result
def _apply_filter(self, filtered_dword=None):
'''Recibe un diccionario de dwords y un diccionario de palabras y repeticiones.
Devuelve el contenido de data, conteniendo únicamente las palabras
que hay en filtered_dword.
'''
78 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
result = {}
filtered_dword = filtered_dword if filtered_dword else self.filtered_dword
counter = 0
for bf in self.bf_data:
counter = print_marks(counter)
result[bf.filename] = {
word: self._str2value(bf.dword[word])
for word in set(filtered_dword.keys()) & set(bf.dword.keys())
}
if result[bf.filename] == {}:
log.info("_Apply_filter(): Diccionario Vacio: " + binary_filename)
print()
return result
def _get_all_different_words(self):
all_different_words = None
counter = 0
for bf in self.bf_data:
counter = print_marks(counter)
all_different_words = set(
bf.dword) if not all_different_words else all_different_words | set(bf.dword)
print()
return all_different_words
def _count_words(self, words=None):
'''Returns a dword containing the { word: repetitions }
of the words in the binary_files within bf_data
If no words provided, then all the words are count.
'''
words = words if words else self.all_different_words
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 79
APÉNDICE A. ANEXOS
result_dword = {word: 0 for word in words}
counter = 0
for bf in self.bf_data:
counter = print_marks(counter)
for word in bf.dword:
result_dword[word] += bf.dword[word]
print()
return result_dword
def get_filtered_dataset(self, filtered_dword=None):
'''Recibe un diccionario de palabras y devuelve el diccionario de
ficheros finarios con las palabras que aparecen en filtered_dword.
Es la salida ideal para despues hacer un Dataframe.
'''
filtered_dword = filtered_dword if filtered_dword else self.filtered_dword
intersect = {}
for bf in self.bf_data:
intersect[bf.filename] = {}
for word in bf.dword:
if word in filtered_dword:
intersect[bf.filename][word] = bf.dword[word]
return intersect
def get_groups_of_words_by_repetition(self, save_image=True):
max_length = len(self.count_words)
result = [[] for i in range(max_length)]
minimum = 0
for word, value in self.count_words.items():
if value >= max_length-1:
result[max_length-1].append(word)
80 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
else:
result[value].append(word)
if save_image:
# Representación gráfica del numero de palabras para el número de repeticiones en el dataset
X = [i for i, item in enumerate(result) if len(item) > 0 and 2 < i < 100]
y = [len(item) for i, item in enumerate(result) if len(item) > 0 and 2 < i < 100]
plt.plot(X, y)
plt.xlabel("Número de repeticiones")
plt.ylabel("Número de palabras")
plt.savefig("groups_of_words.png")
return result
def groups_of_marks_of_equal_size(self, numColumns=default_num_features):
'''Devuelve las posiciones o tamaños de palabras, los cuales dan agrupaciones de
poco más de numColumns palabras.
'''
accum_size = 0
result = []
first = None
last = None
maximum_size_of_group_accepted = numColumns
for pos, group in enumerate(self.groups_of_words):
group_size = len(group)
if not first:
if group_size < numColumns*(2/3):
first = pos
accum_size = group_size
else:
last = pos
accum_size += group_size
if accum_size > numColumns:
result.append((first, last))
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 81
APÉNDICE A. ANEXOS
first = None
last = None
accum_size = 0
if last:
result.append((first, last))
return result
def get_groups_of_columns(self):
'''Devuelve conjuntos de palabras de default_num_features palabras
'''
self.groups_of_words = self.get_groups_of_words_by_repetition()
self.groups_of_marks_of_equal_size = self.groups_of_marks_of_equal_size()
groups_of_columns = [[] for mark in self.groups_of_marks_of_equal_size]
for word, repetitions in self.count_words.items():
for pos, (minimum, maximum) in enumerate(self.groups_of_marks_of_equal_size):
if repetitions >= minimum and repetitions <= maximum:
groups_of_columns[pos].append(word)
break
return groups_of_columns
def get_minidatasets(self):
'''Devuelve mini conjuntos de datasets de default_num_features features.
'''
self.groups_of_words = self.get_groups_of_words_by_repetition()
self.groups_of_marks_of_equal_size = self.groups_of_marks_of_equal_size()
lista_de_palabras = [{} for mark in self.groups_of_marks_of_equal_size]
for word, repetitions in self.count_words.items():
for pos, (minimum, maximum) in enumerate(self.groups_of_marks_of_equal_size):
if repetitions >= minimum and repetitions <= maximum:
lista_de_palabras[pos][word] = repetitions
break
minidatasets = [self.get_filtered_dataset(filtered_dword)
82 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
for filtered_dword in lista_de_palabras]
return minidatasets
def datasets2finalDataset(self, minidatasets):
'''
Input: Minidatasets, con forma de diccionario, pero de un tamaño manejable por 1 ordenador.
Output:
- Matriz de características, tipo numpy.array, conteniendo menos de default_num_features columnas
y filtradas con una varianza mínima de 90.
- y, target (columna Malware_flag)
- variance, la varianza final aplicada a la matriz de características.
'''
result_train = None
result_test = None
variance = float(self.config._config[commons_config_label]['variance'])
done = False
features, y = minidatasets2list_of_X_and_y(minidatasets)
while (not hasattr(result_train, 'shape') or len(result_train[0, :]) > prefiltered_num_features) and variance >= 0.5:
if not hasattr(result_train, 'shape'):
for X_unfiltered in features:
try:
''' Dataset split: Ejecutamos el mismo split sobre los datos para cada submatriz
(representando cada una un minidataset). Se obtienen las mismas muestras cada vez
porque utilizamos el mismo valor para random_state.
'''
X_train, X_test, y_train, y_test = train_test_split(
X_unfiltered, y, test_size=test_size, random_state=42)
X_train, X_test = remove_features_w_low_variance(X_train, X_test, variance)
# Actualizamos los resultados acumulados
result_train = X_train if not hasattr(result_train, 'shape') \
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 83
APÉNDICE A. ANEXOS
else np.concatenate((result_train, X_train), axis=1)
result_test = X_test if not hasattr(result_test, 'shape') \
else np.concatenate((result_test, X_test), axis=1)
# Aplicamos filtrado sobre todo el conjunto de features acumulado
# en caso de superar el tamaño permitido.
if len(result_train[0, :]) > prefiltered_num_features and variance >= 0.5:
variance -= 0.01
result_train, result_test = remove_features_w_low_variance(
result_train, result_test, variance)
except ValueError as e:
log.info(e)
else:
variance -= 0.01
result_train, result_test = remove_features_w_low_variance(
result_train, result_test, variance)
return result_train, result_test, y_train, y_test, variance
# STAGES -- BEGIN
def stage1(self):
print("Stage 1: Start..")
self._run_elfs_analysis()
save_obj(self.goodware_bf, self.config.stage1_goodware_filepath)
save_obj(self.malware_bf, self.config.stage1_malware_filepath)
save_obj(self.bf_data, self.config.stage1_filepath)
print("Stage 1: Completed.")
if stage > 0:
exit(0)
def stage2(self):
try:
84 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
self.bf_data = self.bf_data if self.bf_data else load_obj(
self.config.stage1_filepath)
except Exception as e:
if not self.bf_data:
log.error(
"Error cargando el fichero completo del dataset. Intentando cargar los datos desde los ficheros de goodware y malware.")
self.bf_data = load_obj(self.config.stage1_goodware_filepath) + \
load_obj(self.config.stage1_malware_filepath)
else:
log.error(e)
print("Procesando Stage 2..")
print('Todas las palabras diferentes..')
self.all_different_words = self._get_all_different_words()
save_obj(self.all_different_words, self.config.stage2_filepath)
print("Stage 2: Completed.")
def stage3(self):
print("Procesando Stage 3..")
# Carga de datos desde disco duro si no estuvieran en memoria
self.bf_data = self.bf_data if self.bf_data else load_obj(
self.config.stage1_filepath)
self.all_different_words = self.all_different_words \
if self.all_different_words \
else load_obj(self.config.stage2_filepath)
if not (hasattr(self, 'config')):
self._load_config(config_label=config_label)
# Procesamiento
print("Diccionario de todas las palabras y sus repeticiones..")
self.count_words = self.count_words if self.count_words else self._count_words()
minidatasets = self.get_minidatasets()
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 85
APÉNDICE A. ANEXOS
self.X_train, self.X_test, self.y_train, self.y_test, self.final_variance = self.datasets2finalDataset(
minidatasets)
print("Num Palabras diferentes: " + str(len(self.all_different_words)))
print("Num Features tras filtro con varianza " + str(self.final_variance) + ": "
+ str(len(self.X_train[0, :])))
# Para fase 5
minidataframes, y = minidatasets2list_of_X_and_y(minidatasets, convert_to_numpy=False)
save_obj(minidataframes, self.config.stage3_minidataframes_filepath)
save_obj(y, self.config.stage3_y_filepath)
# Para fase 4
save_obj(self.X_train, self.config.stage3_X_train_filepath)
save_obj(self.X_test, self.config.stage3_X_test_filepath)
save_obj(self.y_train, self.config.stage3_y_train_filepath)
save_obj(self.y_test, self.config.stage3_y_test_filepath)
# Free memory
self.bf_data = None
print("Stage 3: Completed.")
def stage4(self, num_kbest_features):
print("Procesando Stage 4..")
self.X_train = load_obj(self.config.stage3_X_train_filepath)
self.X_test = load_obj(self.config.stage3_X_test_filepath)
self.y_train = load_obj(self.config.stage3_y_train_filepath)
self.y_test = load_obj(self.config.stage3_y_test_filepath)
print("Aplicando FILTROS..")
# Filtro chi2
self.X_train, self.X_test = remove_worst_features_by_chi2(
self.X_train, self.X_test, self.y_train, num_kbest_features)
86 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
print("Num best Features chi2 : "
+ str(len(self.X_train[0, :])))
save_obj(self.X_train, self.config.stage4_x_train_filtered_filepath)
save_obj(self.X_test, self.config.stage4_x_test_filtered_filepath)
image_dir = os.path.join(self.config.persistence_dir, "screenshots")
compare_algorithms(self.X_train, self.X_test, self.y_train, self.y_test, image_dir)
print("Stage 4: Completed.")
def stage5(self):
print("Procesando Stage 5: Qué features se utilizaron en stage4?")
y_train = load_obj(self.config.stage3_y_train_filepath)
X_train_filtered = self.X_train if hasattr(self, "X_train") and self.X_train else load_obj(
self.config.stage4_x_train_filtered_filepath)
self.bf_data = self.bf_data if self.bf_data else load_obj(
self.config.stage1_filepath)
for bf in self.bf_data:
for item in not_considered_features:
bf.dword.pop(item, None)
features = which_features_are_these_vectors(self.bf_data, X_train_filtered)
print("Stage 5: Completed.")
def get_list_of_repetitions_binaries(bf_data, feature_value):
'''Returns a list containing the binary files which have at least 1 word with this feature_value
'''
binaries_list = [bf for bf in bf_data if feature_value in bf.dword.values()]
return binaries_list
@timing
def which_features_are_these_vectors(bf_data, features_matrix):
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 87
APÉNDICE A. ANEXOS
'''Recibe la matriz de características y la información completa de características.
Devuelve la o las características que corresponden a los vectores de características contenidos en la matriz de características.
'''
features_matrix[::-1].transpose().sort()
all_features = []
for i, feature_vec in enumerate(features_matrix.T):
features = get_features_with_the_same_feature_vector(bf_data, feature_vec)
print_marks(i)
print("Features encontradas para vector " + str(i) + ": " + str(features))
all_features.append(features)
return all_features
def get_features_with_the_same_feature_vector(bf_data, feature_vec):
features = []
lista_tuples_repetitions_binaries = []
last_feature = -1
for i, feature_value in enumerate(feature_vec):
if feature_value > 0:
if last_feature != feature_value:
last_feature = feature_value
# Get the possible_features for this feature_value
possible_features_for_this_f_value, binaries_list = get_possible_features(
bf_data, feature_value)
if not features:
features = possible_features_for_this_f_value
else:
features = list(set(features) & set(possible_features_for_this_f_value))
# To check if the feature_vec is satisfactible
88 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
binaries_list.pop()
else:
if binaries_list:
binaries_list.pop()
else:
log.error("Unsatisfactible feature_vector")
print_marks(i)
return features
def get_possible_features(bf_data, feature_value):
'''Returns the possible features for this feature_value and the list of possible binaries
'''
# lista con los binarios que contienen alguno feature con este número de apariciones.
possible_binary_list = get_list_of_repetitions_binaries(
bf_data, feature_value)
# feature_value_info is a list containing: bf_filename, kind_of_binary, features_for_binary
feature_value_info = get_features_of_binaries(
possible_binary_list, feature_value)
# Join al the possible features and takes them all only one time
possible_features = [x[2] for x in feature_value_info]
possible_features = list(set(list(itertools.chain.from_iterable(possible_features))))
return possible_features, possible_binary_list
def get_common_features(feature_value_info):
'''Returns the common features for the binary_list within feature_info.
'''
features = []
# Filter binaries which doesn't contain any possible feature
for i, feature_info in enumerate(feature_value_info):
bf_filename = feature_info[0]
bf_features_for_value = feature_info[2]
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 89
APÉNDICE A. ANEXOS
if i == 0:
features = bf_features_for_value
else:
# Filter list of features
for f in features:
if f not in bf_features_for_value:
features.remove(f)
return features
def get_features_of_binaries(binaries_list, feature_value):
'''
Input:
- binaries_list: a list of Binary_file instances.
- feature_value: a value for a feature
Returns:
a list of 3 items tuples, containing:
- the filename,
- malware_flag, is this file malware or not?
- the features with the same feature_value
'''
result = []
for bf in binaries_list:
current_features = []
kind_of_binary = bf.dword['Malware_Flag']
for word, repetitions in bf.dword.items():
if repetitions == feature_value and word not in not_considered_features:
current_features.append(word)
result.append((bf.filename, kind_of_binary, current_features))
return result
def remove_worst_features_by_chi2(X_train, X_test, y_train, num_kbest_features):
selector = SelectKBest(chi2, k=num_kbest_features)
90 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
X_train = selector.fit_transform(X_train, y_train)
X_test = selector.transform(X_test)
return X_train, X_test
def df2Xy(df, target_feature=malware_flagname):
'''Input: Dataframe
Returns: The features and target
'''
# Target
target_column_name = 'Malware_Flag'
target = [target_column_name]
target_feature = df[target]
y = pd.Series.ravel(target_feature)
# Características
features_wo_target = df.columns.tolist()
features_wo_target.remove(target_column_name)
source_features = df[features_wo_target]
if 'Unnamed: 0' in source_features.columns:
source_features = source_features.set_index('Unnamed: 0')
return source_features, y
def minidatasets2list_of_X_and_y(minidatasets, convert_to_numpy=True):
df = None
features = []
y = None
for ds in minidatasets:
df = pd.DataFrame(ds)
# Transpone la matriz. Nos interesa usar filas para ficheros binarios y columnas para características.
df = df.transpose()
df = df.fillna(0) # Rellena con 0's los valores desconocidos
if malware_flagname in df.columns:
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 91
APÉNDICE A. ANEXOS
X, y = df2Xy(df)
else:
X = df
if convert_to_numpy:
features.append(X.values)
else:
features.append(X)
return features, y
def confusion_matrix(y_test, predictions, score, algorithm_name, image_dir):
'''A partir de los datos de target y sus predicciones, genera
una imagen que muestra la cantidad de prediciones acertadas y falladas,
y en qué sentido. Este matriz es lo que se conoce como matriz de confusión.
'''
cm = metrics.confusion_matrix(y_test, predictions)
plt.figure(figsize=(8, 8))
sns.heatmap(cm, annot=True, fmt=".3f", linewidths=.5, square=True, cmap='Blues_r')
plt.ylabel('Actual label')
plt.xlabel('Predicted label')
all_sample_title = 'Accuracy Score: {0}'.format(score)
plt.title(all_sample_title, size=15)
image_filename = algorithm_name.replace(" ", "_").lower()
image_filepath = image_dir + "/" + image_filename + ".png"
if not os.path.exists(image_dir):
os.mkdir(image_dir)
plt.savefig(image_filepath)
return image_filename
92 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
def compare_algorithms(X_train, X_test, y_train, y_test, image_dir):
num_cpus = 1
# iterate over models
for name, clf in zip(names, classifiers):
y_pred, cross_val_score_var, precision, accuracy, recall, f1 = \
get_datamodel_stats(clf, X_train, X_test, y_train, y_test)
show_datamodel_stats(y_test, y_pred, name, cross_val_score_var,
num_splits, precision, accuracy, recall, f1, image_dir)
def show_datamodel_stats(y_test, y_pred, name, cross_val_score_var, num_splits, precision, accuracy, recall, f1, image_dir):
image_filename = confusion_matrix(y_test, y_pred, accuracy, name, image_dir)
test_size = 1/num_splits
figname = image_filename.replace(".png", "")
fig_path = "graphics/"+figname
print("\section{Algoritmo " + name + "}")
print("\\begin{minipage}{0.6\\textwidth}")
print("\centering")
print("\includegraphics[width=1\\linewidth]{"+fig_path+"}")
print("%\caption{}")
print("\label{fig:"+figname+"}")
print("\end{minipage}")
print("\hfill")
print('\\begin{minipage}{0.5\\textwidth}\\raggedright')
print("Validación cruzada:")
print("\\begin{itemize}")
print("\item Accuracy over X\_test (Shuffle - " + str(num_splits) +
" splits): %0.4f (+/- %0.4f)" % (cross_val_score_var.mean(), cross_val_score_var.std() * 2))
print("\end{itemize}")
print("Validación detallada simple:")
print("\\begin{itemize}")
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 93
APÉNDICE A. ANEXOS
print("\item Test size = %0.4f" % (test_size))
print("\item Recall: " + str(recall))
print("\item Precision: " + str(precision))
print("\item F1: " + str(f1))
print("\item Accuracy: " + str(accuracy))
print("\end{itemize}")
print("\end{minipage}")
print()
@timing
def get_datamodel_stats(datamodel, X_train, X_test, y_train, y_test, num_cpus=1, num_splits=default_num_splits):
cv = ShuffleSplit(n_splits=num_splits, test_size=1/num_splits, random_state=68)
cross_val_score_var = cross_val_score(datamodel, X_test, y_test, cv=cv, n_jobs=num_cpus)
datamodel.fit(X_train, y_train)
y_pred = datamodel.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
return y_pred, cross_val_score_var, precision, accuracy, recall, f1
def save_obj(obj, filepath):
dirname = os.path.dirname(filepath)
if not os.path.exists(dirname):
os.mkdir(dirname)
with open(filepath, 'wb') as f:
cloudpickle.dump(obj, f)
def load_obj(filepath):
with open(filepath, 'rb') as f:
94 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
return cloudpickle.load(f)
def get_y_score(datamodel, x_test):
if hasattr(datamodel, "decision_function"):
y_score = datamodel.decision_function(x_test)
else:
y_score = datamodel.predict_proba(x_test)[:, 1]
return y_score
def parse_command_line(argv):
"""Parse command line argument. See -h option
:param argv: arguments on the command line must include caller file name.
"""
formatter_class = argparse.RawDescriptionHelpFormatter
parser = argparse.ArgumentParser(description=module,
formatter_class=formatter_class)
parser.add_argument("--version", action="version",
version="%(prog)s {}".format(__version__))
parser.add_argument("-v", "--verbose", dest="verbose_count",
action="count", default=0,
help="increases log verbosity for each occurence.")
parser.add_argument('-l', metavar="config_label",
help="The config file label used to get the configuration. Default: malwarelab")
parser.add_argument("-s", "--stage", dest="stage",
action="store", default=0,
help="defines the stage to run. i.e. 4")
parser.add_argument("-f", "--features", dest="num_kbest_features",
action="store", default=1,
help="defines the k-best features used to train the algorithms in stage 4.")
arguments = parser.parse_args(argv[1:])
# Sets log level to WARN going more verbose for each new -v.
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 95
APÉNDICE A. ANEXOS
log.setLevel(max(3 - arguments.verbose_count, 0) * 10)
return arguments
def merge_two_dicts(x, y):
z = x.copy() # start with x's keys and values
z.update(y) # modifies z with y's keys and values & returns None
return z
def get_common_words(bf_data):
''' returns the common words to all the binary files dwords in bf_data.
'''
common_words = None
for bf in bf_data:
common_words = set(bf.dword) if not common_words else common_words & set(bf.dword)
return common_words
def print_marks(counter):
if counter % 1000 == 0:
print(str(int(counter/1000)), end='')
elif counter % 100 == 0:
print(".", end="")
sys.stdout.flush()
return counter+1
def remove_features_w_low_variance(X_train, X_test, minimum_variance=0.8):
'''Variance: defines minimium percentage of variance allowed for a column (default 80%).
This is, if a column has the 81% of its values set to the same value (1 or 0),
it will be removed from the features selected.
'''
# Filtro por varianza - 1 para cada submatriz (minidataset)
96 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
# Original: sel = VarianceThreshold(threshold=(.8 * (1 - .8)))
selector = VarianceThreshold(threshold=(minimum_variance * (1 - minimum_variance)))
# Utilizamos los datos de entrenamiento para decidir el filtro por varianza
# y despues aplicamos el mismo filtro a los datos de test, pero en ningún caso
# se decide el filtro con X_test sino solo con X_train. X_test solo recibe el filtro.
X_train = selector.fit_transform(X_train)
X_test = selector.transform(X_test)
return X_train, X_test
def main():
"""Main program. Sets up logging and do some work."""
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG,
format='%(name)s (%(levelname)s): %(message)s')
try:
arguments = parse_command_line(sys.argv)
config_label = arguments.l if arguments.l else default_config_label
stage = int(arguments.stage) if int(arguments.stage) else 0
num_kbest_features = int(arguments.num_kbest_features) if int(
arguments.num_kbest_features) else 0
ds = Dataset(config_label=config_label)
# STAGES
if stage == 1:
ds.stage1()
elif stage == 2:
ds.stage2()
elif stage == 3:
ds.stage3()
elif stage == 4:
ds.stage4(num_kbest_features)
elif stage == 5:
ds.stage5()
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 97
APÉNDICE A. ANEXOS
except KeyboardInterrupt:
log.error('Program interrupted!')
finally:
logging.shutdown()
if __name__ == "__main__":
sys.exit(main())
98 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
A.3. Fichero requirements.txt
A.3.1. Contenido
pandas
scikit-learn
seaborn
cloudpickle
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 99
APÉNDICE A. ANEXOS
A.4. Matrices de Confusión - Dataset amd64
A.4.1. Algoritmo Naïve Bayes
Features: 3332
Validación cruzada X_test (Shuffle - 3 splits):
Accuracy over: 0.9960 (+/- 0.0017)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9896013864818024
Precision: 0.9861830742659758
F1: 0.9878892733564014
Accuracy: 0.9914057704112953
Tiempo de cómputo: 1.77852 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9770 (+/- 0.0054)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 0.9232
F1: 0.9600665557404326
Accuracy: 0.9705340699815838
Tiempo de cómputo: 0.00917 s
100 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
A.4.2. Algoritmo Nearest Neighbors
Features: 3332
Validación cruzada X_test (Shuffle - 3 splits):
Accuracy: 0.9972 (+/- 0.0015)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9930675909878682
Precision: 0.9982578397212544
F1: 0.9956559513466551
Accuracy: 0.9969306322897483
Tiempo de cómputo: 23.90739 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9770 (+/- 0.0054)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 0.9232
F1: 0.9600665557404326
Accuracy: 0.9705340699815838
Tiempo de cómputo: 0.09252 s
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 101
APÉNDICE A. ANEXOS
A.4.3. Algoritmo Árbol de decisión
Features: 3332
Validación cruzada X_test (Shuffle - 3 splits):
Accuracy: 0.9991 (+/- 0.0015)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9991334488734835
Precision: 0.9974048442906575
F1: 0.9982683982683983
Accuracy: 0.9987722529158993
Tiempo de cómputo: 1.52487 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9770 (+/- 0.0054)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 0.9232
F1: 0.9600665557404326
Accuracy: 0.9705340699815838
Tiempo de cómputo: 0.01062 s
102 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
A.4.4. Algoritmo Bosque Aleatorio
Features: 3332
Validación cruzada X_test (Shuffle - 3 splits):
Accuracy: 0.9853 (+/- 0.0084)
Validación detallada simple:
Test size = 0.3333
Recall: 0.8258232235701907
Precision: 0.991675338189386
F1: 0.9011820330969267
Accuracy: 0.9358502148557397
Tiempo de cómputo: 0.65108 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9770 (+/- 0.0054)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 0.9232
F1: 0.9600665557404326
Accuracy: 0.9705340699815838
Tiempo de cómputo: 0.09507 s
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 103
APÉNDICE A. ANEXOS
A.4.5. Algoritmo SVM Lineal
Features: 3332
Validación cruzada X_test (Shuffle - 3 splits):
Accuracy: 0.9985 (+/- 0.0031)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9974003466204506
Precision: 0.9991319444444444
F1: 0.9982653946227233
Accuracy: 0.9987722529158993
Tiempo de cómputo: 7.97993 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9770 (+/- 0.0054)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 0.9232
F1: 0.9600665557404326
Accuracy: 0.9705340699815838
Tiempo de cómputo: 0.07799 s
104 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
A.4.6. Algoritmo RBF SVM
Features: 3332
Validación cruzada X_test (Shuffle - 3 splits):
Accuracy: 0.7305 (+/- 0.0151)
Validación detallada simple:
Test size = 0.3333
Precision: 1.0
Recall: 0.29462738301559793
F1: 0.4551539491298528
Accuracy: 0.7501534683855126
Tiempo de cómputo: 384.40611 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9770 (+/- 0.0054)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 0.9232
F1: 0.9600665557404326
Accuracy: 0.9705340699815838
Tiempo de cómputo: 1.46092 s
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 105
APÉNDICE A. ANEXOS
A.4.7. Algoritmo Red Neuronal
Features: 3332
Validación cruzada X_test (Shuffle - 3 splits):
Accuracy: 0.9988 (+/- 0.0017)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9982668977469671
Precision: 0.9982668977469671
F1: 0.9982668977469671
Accuracy: 0.9987722529158993
Tiempo de cómputo: 87.19674 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9770 (+/- 0.0054)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 0.9232
F1: 0.9600665557404326
Accuracy: 0.9705340699815838
Tiempo de cómputo: 2.25822 s
106 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
A.4.8. Algoritmo AdaBoost
Features: 3332
Validación cruzada X_test (Shuffle - 3 splits):
Accuracy: 0.9997 (+/- 0.0009)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 0.9982698961937716
F1: 0.9991341991341991
Accuracy: 0.9993861264579497
Tiempo de cómputo: 27.74001 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9770 (+/- 0.0054)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 0.9232
F1: 0.9600665557404326
Accuracy: 0.9705340699815838
Tiempo de cómputo: 2.05079 s
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 107
APÉNDICE A. ANEXOS
A.5. Matrices de Confusión - Dataset i386
A.5.1. Algoritmo Naive Bayes
Features: 3332Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9926 (+/- 0.0055)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9957337883959044
Precision: 0.9765690376569037
F1: 0.9860583016476553
Accuracy: 0.989805375347544
Tiempo de cómputo: 3.23720 sFeatures: 1
Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.5036 (+/- 0.0155)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9863481228668942
Precision: 0.42783123612139157
F1: 0.5967991739803821
Accuracy: 0.5174544331170837
Tiempo de cómputo: 0.00899 s
108 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
A.5.2. Algoritmo Nearest Neighbors
Features: 3332Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9901 (+/- 0.0061)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9914675767918089
Precision: 0.9940119760479041
F1: 0.992738146091414
Accuracy: 0.9947482236638863
Tiempo de cómputo: 33.49140 sFeatures: 1
Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.8570 (+/- 0.0297)
Validación detallada simple:
Test size = 0.3333
Recall: 0.787542662116041
Precision: 0.8012152777777778
F1: 0.7943201376936317
Accuracy: 0.852332406549274
Tiempo de cómputo: 0.02385 s
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 109
APÉNDICE A. ANEXOS
A.5.3. Algoritmo Decision Tree
Features: 3332Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9954 (+/- 0.0045)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 0.987363100252738
F1: 0.9936413734633319
Accuracy: 0.995366079703429
Tiempo de cómputo: 2.83811 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.8715 (+/- 0.0309)
Validación detallada simple:
Test size = 0.3333
Recall: 0.7261092150170648
Precision: 0.8719262295081968
F1: 0.792364990689013
Accuracy: 0.8622181031819586
Tiempo de cómputo: 0.01437 s
110 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
A.5.4. Algoritmo Random Forest
Features: 3332Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.8959 (+/- 0.0733)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9837883959044369
Precision: 0.9738175675675675
F1: 0.9787775891341257
Accuracy: 0.9845535990114304
Tiempo de cómputo: 1.53934 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.8709 (+/- 0.0267)
Validación detallada simple:
Test size = 0.3333
Recall: 0.7337883959044369
Precision: 0.8977035490605428
F1: 0.807511737089202
Accuracy: 0.8733395118937287
Tiempo de cómputo: 0.11728 s
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 111
APÉNDICE A. ANEXOS
A.5.5. Algoritmo Linear SVM
Features: 3332Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9963 (+/- 0.0030)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9965870307167235
Precision: 0.9965870307167235
F1: 0.9965870307167235
Accuracy: 0.9975285758418289
Tiempo de cómputo: 10.80337 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.7967 (+/- 0.0147)
Validación detallada simple:
Test size = 0.3333
Recall: 0.7337883959044369
Precision: 0.7060755336617406
F1: 0.7196652719665272
Accuracy: 0.7930182267531665
Tiempo de cómputo: 2151.95321 s
112 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
A.5.6. Algoritmo RBF SVM
Features: 3332Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.7090 (+/- 0.0160)
Validación detallada simple:
Test size = 0.3333
Recall: 0.2977815699658703
Precision: 1.0
F1: 0.4589086127547666
Accuracy: 0.7457522397281433
Tiempo de cómputo: 414.21432 sFeatures: 1
Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.8832 (+/- 0.0120)
Validación detallada simple:
Test size = 0.3333
Recall: 0.7747440273037542
Precision: 0.8739172281039461
F1: 0.8213478064224332
Accuracy: 0.8779734321902997
Tiempo de cómputo: 3.06417 s
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 113
APÉNDICE A. ANEXOS
A.5.7. Algoritmo Neural Net
Features: 3332Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9978 (+/- 0.0009)
Validación detallada simple:
Test size = 0.3333
Recall: 0.9974402730375427
Precision: 0.9881656804733728
F1: 0.9927813163481953
Accuracy: 0.9947482236638863
Tiempo de cómputo: 83.74647 sFeatures: 1
Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.8514 (+/- 0.0227)
Validación detallada simple:
Test size = 0.3333
Recall: 0.6919795221843004
Precision: 0.8863387978142077
F1: 0.7771921418303785
Accuracy: 0.8563484708063022
Tiempo de cómputo: 1.46863 s
114 Trabajo de Fin de Grado
APÉNDICE A. ANEXOS
A.5.8. Algoritmo AdaBoost
Features: 3332Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.9978 (+/- 0.0017)
Validación detallada simple:
Test size = 0.3333
Recall: 1.0
Precision: 1.0
F1: 1.0
Accuracy: 1.0
Tiempo de cómputo: 32.61207 s
Features: 1Validación cruzada:
Accuracy over X_test (Shuffle - 3 splits):
0.8638 (+/- 0.0227)
Validación detallada simple:
Test size = 0.3333
Recall: 0.7192832764505119
Precision: 0.8939554612937434
F1: 0.7971631205673758
Accuracy: 0.8674698795180723
Tiempo de cómputo: 0.51344 s
Detección de malware de Linux con métodos de aprendizaje automático aplicados a datos de análisis estático 115