$ programa --version
pues no puedo entrar a cada máquina, aunque si puedo ver su sistema de archivos. Tampoco hay un gestor de aplicaciones al cual consultar, incluso pueden haber programas instalados sin el uso de un usuario privilegiado, como puede ser un portable o compilado localmente.
Supongamos que tenemos el ejecutable identificado, como ejemplo usaré chrome.
En linux Mint y supongo Ubuntus está en:
/opt/google/chrome/chrome
En windows lo he hallado en lugares como:
C:\Program Files (x86)\Google\Chrome\Application\
C:\Users\XXXXX\AppData\Local\Google\Chrome\Application\
Primero hay que tener varias versiones identificadas:
chrome.lin.78.0.3904.97
chromium-browser.lin.65.0.3325.181
chrome.win32.24.0.1312.57
chrome.win.44.0.2403.155
chrome.win.51.0.2704.84
chrome.win.57.0.2987.133
chrome.win.62.0.3202.75
chrome.win.78.0.3904.97
chrome.win.44.0.2403.155
chrome.win.51.0.2704.84
chrome.win.57.0.2987.133
chrome.win.62.0.3202.75
chrome.win.78.0.3904.97
Las de linux se obtienen descomprimiento el deb que se consigue en
http://security.ubuntu.com/ubuntu/pool/universe/c/chromium-browser/
¡Qué féo ese http sin la s!
Con grep vamos viendo si esos números están almacenados.
$ grep 3904 chrome.*
Binary file chrome.lin.78.0.3904.97 matches
Binary file chrome.win.78.0.3904.97 matches
con -a le decimos a grep que los tome como archivos de texto pese a que son binarios. De pado limitamos el contexto de match con -o y con ".{32}".
$ grep -a -o '.\{32\}78\.0\.3904\.97.\{32\}' chrome.*
chrome.lin.78.0.3904.97:brtc/pc/peer_connection.cc:609778.0.3904.97id-smime-mod-ets-eSigPolicy-97
chrome.win.78.0.3904.97:test-child-processvvmodule78.0.3904.97GCM Store
chrome.win.78.0.3904.97:mblyIdentity type="win32" name="78.0.3904.97" version="78.0.3904.97" languag
Mmmm, ese último me gustó, probemos con algo más específico y sin -o
$ grep -a 'version="78.0.3904.97"' chrome.*
chrome.win.78.0.3904.97:<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly></dependency><dependency><dependentAssembly><assemblyIdentity type="win32" name="78.0.3904.97" version="78.0.3904.97" language="*"></assemblyIdentity></dependentAssembly></dependency><trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"><security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo><compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS><supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS><supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></supportedOS><supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></supportedOS></application></compatibility></assembly>( ;J�=I�=I�?L�@L�AM�BM�DP�AN�L]�DO�BO�CO�DP�EQ�FR�DR�GR�GS�OwdHT�IT�IU�Qo�IV�LW�Q\�Wb�[� [� >e�@e�]� ?f�[� \� >f�@g�]� ]�8]� Z�#^� _�[]� _� _� _� a�(`� `� a� b� b� c� ��Ie�!g�)��Jd�!��L��Mi�)Su�n�/��YZ�A��[��^P��J��O��<��?���ç�Ĩ�ĩ�Ū>��������D���Ѱ[��E��@���ձA��B��A��B��C��@��A��B��C��D��E��R��S��������������hhhhhhhhhhhhhhhhhhhhhh BQUhhhhhhhhhh FZYWhhhhhhh,&&#")TZY\hhhhh-**((>9E[ZYXhhhh//.@VJJRS[ZYhhh2113dC:7Af`[Z]hh455+L<::7Jc[Z]hh;60 L=<::Jb`[^hh;8 PD=<Cgaa_]hhh'
Me gusta cada vez más, quedémonos con la parte interesante de ese xml con identación para mejorar la lectura:
<assembly ...
<assemblyIdentity
type="win32"
name="78.0.3904.97"
version="78.0.3904.97"
language="*"
>
</assemblyIdentity> ...
</assemblyIdentity> ...
</assembly>
Y repitamos para las otras versiones con un nuevo grep ajustado:
$ grep -a -o "<assemblyIdentity type=\"win32\" name=\".\{16\}" chrom*
chrome.win.44.0.2403.155:<assemblyIdentity type="win32" name="44.0.2403.155" v
chrome.win.51.0.2704.84:<assemblyIdentity type="win32" name="51.0.2704.84" versio
chrome.win.57.0.2987.133:<assemblyIdentity type="win32" name="Microsoft.Window
chrome.win.57.0.2987.133:<assemblyIdentity type="win32" name="57.0.2987.133" v
chrome.win.62.0.3202.75:<assemblyIdentity type="win32" name="Microsoft.Window
chrome.win.62.0.3202.75:<assemblyIdentity type="win32" name="62.0.3202.75" ve
chrome.win.78.0.3904.97:<assemblyIdentity type="win32" name="Microsoft.Window
chrome.win.78.0.3904.97:<assemblyIdentity type="win32" name="78.0.3904.97" ve
chrome.win.78.0.3904.97:<assemblyIdentity type="win32" name="Microsoft.Window
chrome.win.78.0.3904.97:<assemblyIdentity type="win32" name="78.0.3904.97" ve
Se me cayó linux, luego vemos. Para windows con esta regla ya estamos:
- Si tiene información de versión
- Y esa información no coincide con la versión que deseo
Dicho en yara:
rule ChromeWin
{
strings:
$version = "<assemblyIdentity type=\"win32\" name=\""
$version78 = "<assemblyIdentity type=\"win32\" name=\"78."
condition:
$version and not $version78
}
y su ejecución:
$ yara ruleChrome.yara .
ChromeNot78 ./chrome.win.51.0.2704.84
ChromeNot78 ./chrome.win.44.0.2403.155
ChromeNot78 ./chrome.win.57.0.2987.133
ChromeNot78 ./chrome.win.62.0.3202.75
Y así tenemos un modo que aunque dependiente del programa es independiente de las versiones menores y revisiones para identificarla estáticamente. Tambien pudimos usar un hash, pero hace falta identificar todos los casos.
Si sólo dejamos $version78, igual funciona, pero si hay otros programas los halla tambien.
Uh, uh, qué difícil, no?
Quizás con linux suframos un poco más, veamos que tenemos:
$ grep -a -o ".\{16\}65.0.3325.181.\{16\}"chromium-browser.lin.65.0.3325.181
lurl_template65.0.3325.181BREAKPAD_DUMP_L
lurl_template65.0.3325.181BREAKPAD_DUMP_L
$ grep -a -o ".\{16\}78.0.3904.97.\{16\}" chrome.lin.78.0.3904.97
nection.cc:609778.0.3904.97id-smime-mod-e
Está en el medio de la nada, ni siquiera es un null terminated string, nos puede servir hallar en que section se encuentra, comenzando por el offset en el archivo:
$ hexdump -C chrome.lin.78.0.3904.97 | grep 3904
01039040 2f 76 69 64 65 6f 5f 62 69 74 72 61 74 65 5f 61 |/video_bitrate_a|
010db670 37 38 2e 30 2e 33 39 30 34 2e 39 37 00 69 64 2d |78.0.3904.97.id-|
01139040 64 65 66 69 6e 65 64 2e 00 72 65 71 75 69 72 65 |defined..require|
010db670 37 38 2e 30 2e 33 39 30 34 2e 39 37 00 69 64 2d |78.0.3904.97.id-|
01139040 64 65 66 69 6e 65 64 2e 00 72 65 71 75 69 72 65 |defined..require|
Ahora hay que buscar donde cae el offset 010db670, tiene que estar en la zona amarilla, en realidad en la sección anterior a la valor inmediatamente mayor.
$ readelf -S --wide chrome.lin.78.0.3904.97
There are 38 section headers, starting at offset 0x91713c8:
Section Headers:
[Nr] Name Type Address Off Size Flg
There are 38 section headers, starting at offset 0x91713c8:
Section Headers:
[Nr] Name Type Address Off Size Flg
[ 0] NULL 00000000 000000 000000
[ 1] .interp PROGBITS 000002e0 0002e0 00001c A
[ 2] .note.ABI-tag NOTE 000002fc 0002fc 000020 A
[ 3] .note.gnu.build-id NOTE 0000031c 00031c 000024 A
[ 4] .dynsym DYNSYM 00000340 000340 009ab0 A
[ 5] .gnu.version VERSYM 00009df0 009df0 000ce4 A
[ 6] .gnu.version_r VERNEED 0000aad4 00aad4 0003b0 A
[ 7] .gnu.hash GNU_HASH 0000ae88 00ae88 0001dc A
[ 8] .dynstr STRTAB 0000b064 00b064 007ab9 A
[ 9] .rela.dyn RELA 00012b20 012b20 e16a68 A
[10] .rela.plt RELA 00e29588 e29588 009210 A
[11] .rodata PROGBITS 00e32800 e32800 c047bf AMS
[12] protected_memory PROGBITS 01a36fc0 1a36fc0 0001f8 A
[13] .gcc_except_table PROGBITS 01a371b8 1a371b8 001aac A
[14] .eh_frame_hdr PROGBITS 01a38c64 1a38c64 007c44 A
[15] .eh_frame PROGBITS 01a408a8 1a408a8 01c464 A
[16] .text PROGBITS 01a5d000 1a5d000 7028912 AX
[17] .init PROGBITS 08a85914 8a85914 000017 AX
[18] .fini PROGBITS 08a8592c 8a8592c 000009 AX
[19] malloc_hook PROGBITS 08a85940 8a85940 000556 AX
[ 2] .note.ABI-tag NOTE 000002fc 0002fc 000020 A
[ 3] .note.gnu.build-id NOTE 0000031c 00031c 000024 A
[ 4] .dynsym DYNSYM 00000340 000340 009ab0 A
[ 5] .gnu.version VERSYM 00009df0 009df0 000ce4 A
[ 6] .gnu.version_r VERNEED 0000aad4 00aad4 0003b0 A
[ 7] .gnu.hash GNU_HASH 0000ae88 00ae88 0001dc A
[ 8] .dynstr STRTAB 0000b064 00b064 007ab9 A
[ 9] .rela.dyn RELA 00012b20 012b20 e16a68 A
[10] .rela.plt RELA 00e29588 e29588 009210 A
[11] .rodata PROGBITS 00e32800 e32800 c047bf AMS
[12] protected_memory PROGBITS 01a36fc0 1a36fc0 0001f8 A
[13] .gcc_except_table PROGBITS 01a371b8 1a371b8 001aac A
[14] .eh_frame_hdr PROGBITS 01a38c64 1a38c64 007c44 A
[15] .eh_frame PROGBITS 01a408a8 1a408a8 01c464 A
[16] .text PROGBITS 01a5d000 1a5d000 7028912 AX
[17] .init PROGBITS 08a85914 8a85914 000017 AX
[18] .fini PROGBITS 08a8592c 8a8592c 000009 AX
[19] malloc_hook PROGBITS 08a85940 8a85940 000556 AX
...
Key to Flags:
W (write), A (alloc), X (execute), M (merge),
S (strings), l (large), I (info), L (link order),
G (group), T (TLS), E (exclude), x (unknown),
O (extra OS processing required),
o (OS specific), p (processor specific)
Lo cual es razonable pues hasta donde entiendo los strings como este en .rodata deben estar.
$ objdump -s -j .rodata chrome.lin.78.0.3904.97 \
| grep 3904 -A 2 -B 2
10db650 62727463 2f70632f 70656572 5f636f6e brtc/pc/peer_con
10db660 6e656374 696f6e2e 63633a36 30393700 nection.cc:6097.
10db670 37382e30 2e333930 342e3937 0069642d 78.0.3904.97.id-
10db680 736d696d 652d6d6f 642d6574 732d6553 smime-mod-ets-eS
10db690 6967506f 6c696379 2d393700 69642d73 igPolicy-97.id-s
10db650 62727463 2f70632f 70656572 5f636f6e brtc/pc/peer_con
10db660 6e656374 696f6e2e 63633a36 30393700 nection.cc:6097.
10db670 37382e30 2e333930 342e3937 0069642d 78.0.3904.97.id-
10db680 736d696d 652d6d6f 642d6574 732d6553 smime-mod-ets-eS
10db690 6967506f 6c696379 2d393700 69642d73 igPolicy-97.id-s
más arriba cuando había dicho ni siquiera es un null terminated string me equivoqué, ahí está clarito el null.
Pero esto seguro cambia de versión en versión.
$ objdump -s -j .rodata chromium-browser.lin.65.0.3325.181 \
| grep 65\.0\.3325 -A 2 -B 2
6d32960 00636872 6f6d6500 7469746c 65007465 .chrome.title.te
6d32970 78740075 726c0075 726c5f74 656d706c xt.url.url_templ
6d32980 61746500 0036352e 302e3333 32352e31 ate..65.0.3325.1
6d32990 38310042 5245414b 5041445f 44554d50 81.BREAKPAD_DUMP
6d329a0 5f4c4f43 4154494f 4e005061 796d656e _LOCATION.Paymen
6d32960 00636872 6f6d6500 7469746c 65007465 .chrome.title.te
6d32970 78740075 726c0075 726c5f74 656d706c xt.url.url_templ
6d32980 61746500 0036352e 302e3333 32352e31 ate..65.0.3325.1
6d32990 38310042 5245414b 5041445f 44554d50 81.BREAKPAD_DUMP
6d329a0 5f4c4f43 4154494f 4e005061 796d656e _LOCATION.Paymen
Ok, quizás buscando un string de cuatro enteros separados por puntos entre dos nulos funcione... demasiado, trae toda dirección IP
$ grep -a -o -P \
"\x00[1-9][0-9]*\.[0-9]+\.[0-9]+\.[0-9]+\x00" \
chromium-browser.lin.65.0.3325.181 \
chrome.lin.78.0.3904.97
chromium-browser.lin.65.0.3325.181:6.5.254.41
chromium-browser.lin.65.0.3325.181:65.0.3325.181
chromium-browser.lin.65.0.3325.181:239.255.255.250
chromium-browser.lin.65.0.3325.181:127.0.0.1
chrome.lin.78.0.3904.97:78.0.3904.97
chrome.lin.78.0.3904.97:7.8.279.23
chrome.lin.78.0.3904.97:4.10.1582.1
chrome.lin.78.0.3904.97:127.0.0.1
chrome.lin.78.0.3904.97:224.0.0.251
chrome.lin.78.0.3904.97:239.255.255.250
chrome.lin.78.0.3904.97:127.0.0.1
chrome.lin.78.0.3904.97
chromium-browser.lin.65.0.3325.181:6.5.254.41
chromium-browser.lin.65.0.3325.181:65.0.3325.181
chromium-browser.lin.65.0.3325.181:239.255.255.250
chromium-browser.lin.65.0.3325.181:127.0.0.1
chrome.lin.78.0.3904.97:78.0.3904.97
chrome.lin.78.0.3904.97:7.8.279.23
chrome.lin.78.0.3904.97:4.10.1582.1
chrome.lin.78.0.3904.97:127.0.0.1
chrome.lin.78.0.3904.97:224.0.0.251
chrome.lin.78.0.3904.97:239.255.255.250
chrome.lin.78.0.3904.97:127.0.0.1
¡Qué problema! El orden no significa nada, sólo podríamso descartar algunas IPs muy evidentes como 127.0.0.1 y 239.255.255.250,pero nos empieza a obligar a tener una lista de versiones más estrictas.
No es tan terrible. para cada programa candidato, obtenemos la lista de strings potenciales y si alguna coincide con versiones correctas o incorrectas.
Esta parte de linux ha sido para practicar lo aprendido en el libro Practical Binary Analysis, cuya reseña en pocas semanas publicaré.
No hay comentarios:
Publicar un comentario