tag:blogger.com,1999:blog-61483708344565160132024-03-14T05:19:41.371-03:00Seguridad AgileCarlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.comBlogger285125tag:blogger.com,1999:blog-6148370834456516013.post-14312401536970832102024-01-29T12:47:00.003-03:002024-02-01T15:19:49.118-03:00Análisis de entrega de material ciberciruja<p>Un poco como actualización de <a href="https://seguridad-agile.blogspot.com/2015/03/wipe.html">wipe</a>, donde explico cómo disponer de modo seguro y eficiente de medios magnéticos y señalo lo ineficiente que me resultó donar material de computación, cosa sobre la cual reflexiono y vuelvo a recalcar en <a href="https://seguridad-agile.blogspot.com/2023/03/cyberciruja-2023.html">cyberciruja 2023</a>, a raiz de la experiencia del domingo 2024-01-28, reviso un poco esas ideas.<br /></p><p><br /></p><p>Por motivos personales tuve que hacer una purga y disponer de bastante material, calculo que un tercio de metro cúbico, detallado en <a href="https://seguridad-agile.blogspot.com/p/material-cyberciruja.html">material cyberciruja</a> (Listado de la purga 2024/01/28)</p><p> </p><p></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1L53Kx2_V8IRMwQbsse4kXoyWsyAHyqTnkyEOM6jmwSq3eiyUWKBFiuScGB8CFNqKVuGWi5teCSSc1f7HnBTxmwgj49y11kyrEAfwrK4aVGcgz-1TdJRNAkdP3GH-B7McEblJ6_kNLS2jvU-IyjFUMj6KcQ-MvXQRI-jP0go-T42V-4231WgXPOwm3vdz/s1599/purga02.jpeg" style="margin-left: auto; margin-right: auto;"><img alt="Parte del lote" border="0" data-original-height="899" data-original-width="1599" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1L53Kx2_V8IRMwQbsse4kXoyWsyAHyqTnkyEOM6jmwSq3eiyUWKBFiuScGB8CFNqKVuGWi5teCSSc1f7HnBTxmwgj49y11kyrEAfwrK4aVGcgz-1TdJRNAkdP3GH-B7McEblJ6_kNLS2jvU-IyjFUMj6KcQ-MvXQRI-jP0go-T42V-4231WgXPOwm3vdz/w400-h225/purga02.jpeg" title="Parte del lote" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Parte del lote<br /></td></tr></tbody></table><br /> <p></p><p><br /></p><p>El método consiste en preparar el lote (algún detalle extra más abajo en "Actividad común a cualquier metodología de donación"), coordinar con el grupo cyberciruja ubicación y fecha/hora, conseguir transporte, solicitar la ayuda de una o dos personas, llevar todo, explicar a quien manifieste interés por cada pieza qué es, para qué sirve y su estado y listo.<br /></p><p><br /></p><p>En comparación a experiencias anteriores, resultó muy eficiente. Para cada pieza de <a href="https://seguridad-agile.blogspot.com/2015/03/wipe.html">wipe</a> calculo que le habré dedicado dos horas promedio pese a que cada una podía ser más interesante que cualquiera del lote actual y llevó meses en tiempo bruto. En este caso mi esfuerzo invertido fué más o menos este:</p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Tiempo bruto</h2><h2 style="text-align: left;"> </h2><p>Desde que me decidí hasta que ocurrió dos semanas, pero pudo haber sido una.</p><p></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Tiempos netos</h2><h2 style="text-align: left;"> </h2><p>Menos de 10 horas, incluyendo la disposición segura<br /></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Conseguir cajas</h3><h3 style="text-align: left;"> </h3><p>20 minutos repartido en varios días<br /></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Elegir que purgar</h3><h3 style="text-align: left;"> </h3><p>2 horas, la clave es elegir poco, si hay algo que es muy interesante, como por ejemplo una dataset de commodore o unas netbooks del gobierno de las primeras y hace falta hacer el borrado seguro, descartar y dejar para otra oportunidad.<br /></p><p></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Coordinar en el grupo</h3><h3 style="text-align: left;"> </h3><p>menos de 2 horas, es avisar "tengo todo esto, ayúdenme, cuándo podemos?"<br /></p><p></p><p></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Llevar todo al parque</h3><h3 style="text-align: left;"> </h3><p>1 hora, depende de la distancia y el volumen de cosas....<br /></p><p></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Explicar y repartir</h3><h3 style="text-align: left;"> </h3><h3 style="text-align: left;"></h3><p>2 horas, compartido por las personas presentes. Primero hay que atender al cyberciruja. Segundo hay que avisarle a quien pasa que el material está disponible y sus condiciones de gratuitidad. En ambos casos, explicar lo que sepas de la pieza en cuestión, si funciona, si es a probar o reparar.<br /></p><p></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Actividad común a cualquier metodología de donación</h3><h3 style="text-align: left;"><br /></h3><p>Y ahí es dónde entra al seguridad, es el tema de que los medios magnéticos no deben contener información. Esto implica borrado "seguro" o destrucción.</p><p>En este caso hubo un solo borrado de un ide de 80GB.</p><p>Tenía unos diez discos rígidos que no funcionaban asi que no se podían borrar, pero al ignorar que información tenían, no podía tampoco entregarlos. Puede parecer medio estúpido pero así funciona mi mente.</p><p>Lo que hice fué desarmarlos (de ahí salió "montón boards de discos rígidos") para quedarme con los platos, los motores y los imanes. Esto me llevó unas dos horas.<br /></p><p>Los imanes suelen estar pegados a una chapita, basta con retorcer la chapita con dos pinzas para que el adhesivo falle y quedarse con el imán. Estas chapas junto a las carcazas se las entregué en mano a un cartonero con carrito en cualquier otro momento.<br /></p><p>Respecto a cd/dvd, entregué todos los que tenían drivers o programas, un poco confiando en que los grabados por mí no tuvieran información. De todos modos los únicos que suscitaron interés fueron los "impresos", tipo encarta 2000.</p><p>De souvenir exclusivo para cybercirujas, repartí unos discos ópticos locos, confiando en que no tenían nada y que nadie tiene el lector.</p><p>Los diskettes elegí que no tuvieran etiquetas o estuvieran en blanco, confiando....</p><p><br /></p><h2 style="text-align: left;">Anécdotas</h2><p><br /></p><p>Una persona estaba muy interesada en recuperación de componentes electrónicos, en particular motores, se llevó entre otras cosas:</p><ul><li>componente lectora triple de cd</li><li>componente dual deck <br /></li></ul><p> </p><p>Gran interés tuvieron:</p><ul><li>trafo original atari 110v</li><li>gabinete de la alarma casera</li><li>tablet coby</li><li><span class="matching-text-highlight">dock</span> thinkpad con fuente y llave</li><li>tv philips 40 <a href="https://seguridad-agile.blogspot.com/2019/03/jugando-con-los-rayos-0-intro.html" target="_blank">tocado por un rayo</a></li></ul><p> </p><p>Este tipo de evento, aunque en esta ocasión tuvo un fuerte protagonismo de una persona, puede ser más "cada uno lleva un poco". De hecho algunas personas trajeron alguna cosita y el encuentro también sirvió para intercambiar cosas que estaban esperado a cambiar de manos. <br /></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Conclusión</h2><h2 style="text-align: left;"> </h2><p></p><p>Aunque quizás no séa óptima la reutilización por componente, capaz que alguien se llevó un componente útil para sacarle el cobre, el método presentado, entre los extremos posibles, es más eficiente para quien se está deshaciendo de material que la donación pieza por pieza con seguimiento por un lado y por el otro, probablemente genere menos residuos tirados en la calle que tirar todo en la basura.<br /></p><p><br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbB-XtfXD0XnL-z54Qd3ckP8HrmsqU8bodiv2EOpqtSkAqlzf5qfnXzS6N1Vjehfl85T09Xdp1ZxDa95U7hyphenhyphenxPq6iMzcMO6V4PliOp7Ptag4twfB-4v2Tx_64rkGpKKRw5rNwb1qJDkAbRyifxyVNLr_hDG_KUJ-1HhyphenhyphengMm2Cv4sfX4IgqTQnQQUSfVHl1/s1280/purga01.jpeg" style="margin-left: auto; margin-right: auto;"><img alt="El equipo desde un árbol" border="0" data-original-height="1280" data-original-width="960" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbB-XtfXD0XnL-z54Qd3ckP8HrmsqU8bodiv2EOpqtSkAqlzf5qfnXzS6N1Vjehfl85T09Xdp1ZxDa95U7hyphenhyphenxPq6iMzcMO6V4PliOp7Ptag4twfB-4v2Tx_64rkGpKKRw5rNwb1qJDkAbRyifxyVNLr_hDG_KUJ-1HhyphenhyphengMm2Cv4sfX4IgqTQnQQUSfVHl1/w240-h320/purga01.jpeg" title="El equipo desde un árbol" width="240" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">El equipo desde un árbol<br /></td></tr></tbody></table><br /><p><br /></p><p><br /></p><br />Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-72832324958558657762023-12-03T11:21:00.001-03:002023-12-03T11:24:45.407-03:00Para leer Emerging Topics in Hardware Security - General<p>Esta nota es el resultado de la lectura atenta del libro <i><b>Emerging Topics in Hardware Security</b></i>, registro mis opiniones, inquietudes y hallazgos, apuntando a que sea útil para mí como memoria y para tí como disparador.</p><p>Desde hace meses sino años, tengo una pila de libros para leer, pero todos tienen alguna parte que es mejor practicar, incompatible con vacaciones, transporte público. Al ser este libro muy teórico, me basta con la lectura atenta y tomar notas... estas son las notas.</p><p> </p><p>Empecemos con que no es un libro, es un compendio de papers. <br /></p><p>En general, los artículos son, tal como insinúa el título, temas en la cresta de la ola y además de un nivel técnico muy alto y de temas muy específicos. Eso hace que el lector, Charly, por momentos quede un poco afuera. No es que no haya ocurrido con otros libros, pero en los otros no tuve la siguiente sensación:</p><p>Parecen escritos por personas que no dominan el idioma inglés, no lo digo porque los nombres de todos los autores parezcan ser de la India, sino porque efectivamente hay expresiones, formas de armar la frase y algunas cosas que me parecen que son errores gramaticales. También hay errores de sintaxis.</p><p></p><p>No señalaría esta superficialidad, pero como no conozco algunos de los temas, me produce una cierta desconfianza. No mucha, conozco gente del grupo de embebidos que me consta que saben un montón pero no escribir.<br /></p><p>No sé cual es la tasa de entradas bibliográficas normal para un paper, pero con respecto a algunos libros conocidos, es mayor y en algunos capítulos muy mayor:<br /></p><p></p><p><br /></p><table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: medium; font-family: Arial; font-size: 10pt; table-layout: fixed; width: 0px;"><colgroup><col width="22"></col><col width="403"></col><col width="54"></col><col width="72"></col><col width="72"></col></colgroup><tbody><tr style="height: 21px;"><td style="border-bottom: 1px solid #000000; border-color: rgb(0, 0, 0); border-left: 1px solid #000000; border-right: 1px solid #000000; border-style: solid; border-top: 1px solid #000000; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;"><br /></td><td style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;"><br /></td><td data-sheets-value="{"1":2,"2":"páginas"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">páginas</td><td data-sheets-value="{"1":2,"2":"bibliografía"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">notas</td><td data-sheets-value="{"1":2,"2":"bibliografía\n/ página"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">n / p<br /></td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":1}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1</td><td data-sheets-value="{"1":2,"2":"Blockchain-Enabled Electronics Supply Chain Assurance"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Blockchain-Enabled Electronics Supply Chain Assurance</td><td data-sheets-value="{"1":3,"3":25}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">25</td><td data-sheets-value="{"1":3,"3":48}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">48</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":1.92}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1.9</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":2}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2</td><td data-sheets-value="{"1":2,"2":"Digital Twin with a Perspective from Manufacturing Industry"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Digital Twin with a Perspective from Manufacturing Industry</td><td data-sheets-value="{"1":3,"3":35}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">35</td><td data-sheets-value="{"1":3,"3":145}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">145</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":4.142857142857143}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">4.1</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":3}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">3</td><td data-sheets-value="{"1":2,"2":"Trillion Sensors Security"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Trillion Sensors Security</td><td data-sheets-value="{"1":3,"3":34}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">34</td><td data-sheets-value="{"1":3,"3":151}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">151</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":4.4411764705882355}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">4.4</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":4}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">4</td><td data-sheets-value="{"1":2,"2":"Security of AI Hardware Systems"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Security of AI Hardware Systems</td><td data-sheets-value="{"1":3,"3":16}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">16</td><td data-sheets-value="{"1":3,"3":37}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">37</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.3125}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.3</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":5}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">5</td><td data-sheets-value="{"1":2,"2":"Machine Learning in Hardware Security"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Machine Learning in Hardware Security</td><td data-sheets-value="{"1":3,"3":36}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">36</td><td data-sheets-value="{"1":3,"3":85}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">85</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.361111111111111}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.4</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":6}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">6</td><td data-sheets-value="{"1":2,"2":"Security Assessment of High-Level Synthesis"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Security Assessment of High-Level Synthesis</td><td data-sheets-value="{"1":3,"3":24}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">24</td><td data-sheets-value="{"1":3,"3":40}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">40</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":1.6666666666666667}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1.7</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":7}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">7</td><td data-sheets-value="{"1":2,"2":"CAD for Side-Channel Leakage Assessment"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">CAD for Side-Channel Leakage Assessment</td><td data-sheets-value="{"1":3,"3":28}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">28</td><td data-sheets-value="{"1":3,"3":45}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">45</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":1.6071428571428572}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1.6</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":8}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">8</td><td data-sheets-value="{"1":2,"2":"Post-Quantum Hardware Security"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Post-Quantum Hardware Security</td><td data-sheets-value="{"1":3,"3":30}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">30</td><td data-sheets-value="{"1":3,"3":101}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">101</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":3.3666666666666667}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">3.4</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":9}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">9</td><td data-sheets-value="{"1":2,"2":"Post-Quantum Cryptographic Hardware and Embedded Systems"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Post-Quantum Cryptographic Hardware and Embedded Systems</td><td data-sheets-value="{"1":3,"3":28}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">28</td><td data-sheets-value="{"1":3,"3":53}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">53</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":1.8928571428571428}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1.9</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":10}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">10</td><td data-sheets-value="{"1":2,"2":"Neuromorphic Security"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Neuromorphic Security</td><td data-sheets-value="{"1":3,"3":24}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">24</td><td data-sheets-value="{"1":3,"3":61}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">61</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.5416666666666665}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.5</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":11}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">11</td><td data-sheets-value="{"1":2,"2":"Homomorphic Encryption"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Homomorphic Encryption</td><td data-sheets-value="{"1":3,"3":28}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">28</td><td data-sheets-value="{"1":3,"3":64}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">64</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.2857142857142856}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.3</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":12}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">12</td><td data-sheets-value="{"1":2,"2":"Software Security with Hardware in Mind"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Software Security with Hardware in Mind</td><td data-sheets-value="{"1":3,"3":26}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">26</td><td data-sheets-value="{"1":3,"3":61}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">61</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.3461538461538463}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.3</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":13}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">13</td><td data-sheets-value="{"1":2,"2":"Firmware Protection"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Firmware Protection</td><td data-sheets-value="{"1":3,"3":22}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">22</td><td data-sheets-value="{"1":3,"3":21}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">21</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":0.9545454545454546}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1.0</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":14}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">14</td><td data-sheets-value="{"1":2,"2":"Security of Emerging Memory Chips"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Security of Emerging Memory Chips</td><td data-sheets-value="{"1":3,"3":34}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">34</td><td data-sheets-value="{"1":3,"3":76}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">76</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.235294117647059}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.2</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":15}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">15</td><td data-sheets-value="{"1":2,"2":"Security of Analog, Mixed-Signal, and RF Devices"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Security of Analog, Mixed-Signal, and RF Devices</td><td data-sheets-value="{"1":3,"3":28}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">28</td><td data-sheets-value="{"1":3,"3":63}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">63</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.25}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.3</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":16}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">16</td><td data-sheets-value="{"1":2,"2":"Analog IP Protection and Evaluation"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Analog IP Protection and Evaluation</td><td data-sheets-value="{"1":3,"3":52}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">52</td><td data-sheets-value="{"1":3,"3":67}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">67</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":1.2884615384615385}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1.3</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":17}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">17</td><td data-sheets-value="{"1":2,"2":"Application of Optical Techniques to Hardware Assurance"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Application of Optical Techniques to Hardware Assurance</td><td data-sheets-value="{"1":3,"3":22}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">22</td><td data-sheets-value="{"1":3,"3":60}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">60</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.727272727272727}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.7</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":18}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">18</td><td data-sheets-value="{"1":2,"2":"Computer Vision for Hardware Security"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Computer Vision for Hardware Security</td><td data-sheets-value="{"1":3,"3":34}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">34</td><td data-sheets-value="{"1":3,"3":75}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">75</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.2058823529411766}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.2</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":19}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">19</td><td data-sheets-value="{"1":2,"2":"Asynchronous Circuits and Their Applications in Hardware Security"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Asynchronous Circuits and Their Applications in Hardware Security</td><td data-sheets-value="{"1":3,"3":28}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">28</td><td data-sheets-value="{"1":3,"3":68}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">68</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.4285714285714284}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.4</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":20}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">20</td><td data-sheets-value="{"1":2,"2":"Microfluidic Device Security"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Microfluidic Device Security</td><td data-sheets-value="{"1":3,"3":24}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">24</td><td data-sheets-value="{"1":3,"3":68}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">68</td><td data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.8333333333333335}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.8</td></tr><tr style="height: 21px;"><td style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;"><br /></td><td data-sheets-value="{"1":2,"2":"Total"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Total</td><td data-sheets-formula="=SUM(R[-20]C[0]:R[-1]C[0])" data-sheets-value="{"1":3,"3":578}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">578</td><td data-sheets-formula="=SUM(R[-20]C[0]:R[-1]C[0])" data-sheets-value="{"1":3,"3":1389}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1389</td><td data-sheets-formula="=R[0]C[-1]/R[0]C[-2]" data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":2.403114186851211}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2.4</td></tr></tbody></table><p><style type="text/css">td {border: 1px solid #cccccc;}br {mso-data-placement:same-cell;}</style></p><p> </p><p></p><table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: medium; font-family: Arial; font-size: 10pt; table-layout: fixed; width: 0px;"><colgroup><col width="339"></col><col width="54"></col><col width="72"></col><col width="72"></col></colgroup><tbody><tr style="height: 21px;"><td style="border-bottom: 1px solid #000000; border-color: rgb(0, 0, 0); border-left: 1px solid #000000; border-right: 1px solid #000000; border-style: solid; border-top: 1px solid #000000; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;"><br /></td><td data-sheets-value="{"1":2,"2":"páginas"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">páginas</td><td data-sheets-value="{"1":2,"2":"bibliografía"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">notas</td><td data-sheets-value="{"1":2,"2":"bibliografía\n/ página"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">n / p<br /></td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Artificial Intelligence - Russel Norvig"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Artificial Intelligence - Russel/Norvig</td><td data-sheets-value="{"1":3,"3":1000}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1000</td><td data-sheets-value="{"1":3,"3":900}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">900</td><td data-sheets-formula="=R[0]C[-1]/R[0]C[-2]" data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":0.9}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">0.9</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Object Oriented Software Construction - Meyer"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Object Oriented Software Construction - Meyer</td><td data-sheets-value="{"1":3,"3":1200}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1200</td><td data-sheets-value="{"1":3,"3":360}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">360</td><td data-sheets-formula="=R[0]C[-1]/R[0]C[-2]" data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":0.3}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">0.3</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Security Engineering - Anderson"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Security Engineering - Anderson</td><td data-sheets-value="{"1":3,"3":890}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">890</td><td data-sheets-value="{"1":3,"3":1380}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1380</td><td data-sheets-formula="=R[0]C[-1]/R[0]C[-2]" data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":1.550561797752809}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1.6</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Computer Architecture - Hennessy Patterson"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Computer Architecture - Hennessy/Patterson</td><td data-sheets-formula="=490+54+86" data-sheets-value="{"1":3,"3":630}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">630</td><td data-sheets-formula="=32*20" data-sheets-value="{"1":3,"3":640}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">640</td><td data-sheets-formula="=R[0]C[-1]/R[0]C[-2]" data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":1.0158730158730158}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1.0</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Hardware Security - Tehranipoor Bhunia"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Hardware Security - Tehranipoor/Bhunia</td><td data-sheets-value="{"1":3,"3":450}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">450</td><td data-sheets-formula="=sum(R[1]C[0]:R[16]C[0])" data-sheets-value="{"1":3,"3":748}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">748</td><td data-sheets-formula="=R[0]C[-1]/R[0]C[-2]" data-sheets-numberformat="{"1":2,"2":"0.0","3":1}" data-sheets-value="{"1":3,"3":1.6622222222222223}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1.7</td></tr></tbody></table><p></p><p></p><p></p><p><style type="text/css">td {border: 1px solid #cccccc;}br {mso-data-placement:same-cell;}</style> </p><p>El último es especialmente interesante pues Tehranipoor es el editor del libro en cuestión.<br /></p><p>Las cuentas no están del todo bien hechas pues no estoy considerando al cantidad de palabras por página, OOSC en particular tiene la letra grande. No estoy seguro que estos números sean indicadores de calidad o de su falta.</p><p>¿Por qué me molesta esto de la bibliografía? Se debe a que estoy más acostumbrado a leer textos donde la mayor parte es explicación, no "tal xxx hizo tal prueba" sin dar ningún otro detalle.<br /></p><p></p><p>Dejando de lado este aspecto superficial, pasemos a lo importante.<br /></p><p><br /></p><p>El contexto general de la seguridad de hardware, que es el hilo conductor de algunos artículos de modo explícito y afecta de modo implícto a todos es la protección durante la cadena de suministro del hardware (esto sale del capítulo 1):</p><ul style="text-align: left;"><li>IP Owner y la fábrica</li><li>Ensamblado del PCB</li><li>Integración del sistema</li><li>Usuario final</li><li>Disposición final o reciclado<br /></li></ul><p></p><p>Existiendo estos ataques más comunes:<br /></p><p></p><ul style="text-align: left;"><li>Sobreproducción, para venta no declarada<br /></li><li>Ingeniería reversa, para falsificación, copia o ahorrarse parte del diseño<br /></li><li>Reutilización en lugar de disposición final</li><li>Falsificación, es hacer algo copiado y ponerle una marca ajena<br /></li><li>Reclasificación, tipo remarcar un componente común como industrial<br /></li></ul><p></p><p><br /></p><p></p><p>Mi opinión</p><p><br /></p><p>Dejando de lado lo superficial y la calidad despareja, es un libro muy rellenador de detalles de los temas que ya conocía de antes y más aún disparador de los que ni estaba al tanto de la existencia, como:<br /></p><p><br /></p><p></p><ul style="text-align: left;"><li>Neuromorphic y sus memristores</li><li>Microfluidic devices</li><li>El nicho de los circuitos asincrónicos.<br /></li></ul><p><br /></p><p></p>Si prestaste atención al título, "General", da a entender que puede haber otra nota. No te prometo, me llevó cuatro meses leerlo, como estoy un poco traumatizado y con más ganas de pasar al siguiente libro que de revisar este para dejar registradas mis notas.<p><br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-53706638736301390612023-10-08T18:27:00.001-03:002023-10-08T18:27:07.929-03:00Un poco de history<p>En esta ocasión, algunas ideas y tips relativas al comando history.</p><p></p><p>Provee la funcionalidad de registrar los comandos ingresados para consulta o reejecución.</p><p>Repecto a la concurrencia, tiene la particularidad de que a medida que se van cerrando las sesiones se van guardando, cada una con su estado y sobreescribiendo las otras. En otras palabras, gana la última que escriba y eso vale para las abiertas que no tenés a la vista como accesos vía ssh o terminales en otras workspaces.<br /></p><p>El registro está en ~/.bash_history, se puede editar.</p><p></p><p>Con el comando </p><p></p><p><b><span style="font-family: courier;">history -d N</span></b></p><p>eliminar la línea N.</p><p>Si no querés que se salve <br /></p><p><span style="font-family: courier;"><b>unset HISTFILE && exit</b></span></p><p>y este que es más lindo, pero no cierra la ventana si estás en un entorno gráfico <br /></p><p></p><p><b><span style="font-family: courier;">kill -9 $$</span></b> <br /></p><p>y la verdad que no sé que hace en un entorno no gráfico. <br /></p><p>Un truquito que se me ocurrió hace muchos años, incluso me lo pagaron en la revista Linux Journal, lo llamé "disposable alias", me había matado con el texto y lo redujeron a casi nada:</p><p> </p><p></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg47-DNJBLvNszgSzw5Qnw67QZdejods1hTNSGp_9iX1INWYfHPpfTx0XrlDur1bGxInPnHL2wXJLGMTlWCYA-mkwq1B4ZljajRf9Grdx6Aa874ldhfsVSmnKy-8NocgF_mVBZDFYvr51cO2s0jUzjXlHz3zHuDRCbxMdzJA5A56CNWvDKcfb329iLtVMWa/s1280/techtip2008.jpeg" style="margin-left: auto; margin-right: auto;"><img alt="tech tip" border="0" data-original-height="720" data-original-width="1280" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg47-DNJBLvNszgSzw5Qnw67QZdejods1hTNSGp_9iX1INWYfHPpfTx0XrlDur1bGxInPnHL2wXJLGMTlWCYA-mkwq1B4ZljajRf9Grdx6Aa874ldhfsVSmnKy-8NocgF_mVBZDFYvr51cO2s0jUzjXlHz3zHuDRCbxMdzJA5A56CNWvDKcfb329iLtVMWa/w640-h360/techtip2008.jpeg" title="tech tip" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">tech tip<br /></td></tr></tbody></table><br /> <p></p><p></p><p>Consiste en agregar un comentario al final de los comandos que querés ejecutar varias veces pero no vale la pena hacer un script o un alias y querés recuperar con control-R:<br /></p><p><b style="font-family: courier;">comando ; # tag</b></p><p>Por ejemplo:</p><p><span style="font-family: courier;"><b>find . -iname "*borrar* -exec ls -l {} \;" ; # listar_a_borrar</b></span> <br /></p><p></p><p>Si pensás que con <b>control-R borrar</b> podés lograr el mismo efecto, considerá que cerca va a estar lleno de cosas como:<br /></p><p><b><span style="font-family: courier;">view borrar.txt</span></b></p><p><b><span style="font-family: courier;">rm borrar2.txt</span></b></p><p><b><span style="font-family: courier;">mkdir TRASH</span></b></p><p><b><span style="font-family: courier;">mv borrar3.txt TRASH</span></b></p><p>y así... <br /></p><p></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">La joya</h2><h2 style="text-align: left;"><br /></h2><p>Todo esto que escribí es solo para entrar en tema, ¿qué pasa si ejecutaste algo como esto?</p><p><span></span></p><div><span><b style="font-family: courier;">export HTTP_PROXY=http://user:password@server:port</b></span></div><div><span> </span></div><div><span><span>Te ha quedado en history la clave del proxy, para que la vea cualquiera que pueda acceder a tu history.</span></span></div><div><span><span> </span><br /></span></div><div><span>Tenés que hacer <b>history | less</b> para encontrar el número y luego <b>history -d N</b>.</span></div><div><span> </span></div><div><span>Según ví en <b>man history</b>, hay toda una serie interminable de opciones para hacer... ni entendí bien qué, tomar un comando, reemplazarle una parte y ejecutarlo, me parece un poco bloatware.<br /></span></div><div><span></span></div><p></p><h3 style="text-align: left;"><span><div> </div><div>Hay una manera mucho más sencilla </div><div> </div></span></h3><h3 style="text-align: left;"></h3><p><span></span></p><div><span>Escondida en la documentación,
hay una joyita que <a href="https://github.com/TenoTrash" target="_blank">Mar Fer</a> comentó en una conversación cyberciruja. Si
tocás una cierta variable de la configuración, podés evitar que queden
registrados los comandos de las líneas que inicies con espacios.<br /></span></div><div><span><br /></span></div><div><span>Dice <a dir="auto" href="https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html">https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html</a>:</span></div><div><span> </span></div><div><p></p><span> </span></div><div><dt><span><span><code>HISTCONTROL</code><a href="https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html#index-HISTCONTROL"></a></span></span></dt><dd><p><span>A colon-separated list of values controlling how commands are saved on
the history list.
If the list of values includes ‘<samp>ignorespace</samp>’, lines which begin
with a space character are not saved in the history list.</span></p><p><span> <br /></span></p></dd></div><p></p><p></p><div style="text-align: left;"><span>Cuando Mar Fer contó, me fijé en <b>man history</b> y nada dice, casi que parecía un bug, pero no, <i>it is a feature</i>.</span></div><h2 style="text-align: left;"><br /></h2><h2 style="text-align: left;">Perspectiva de seguridad</h2><h2 style="text-align: left;"> </h2><p>Debido a la destrucción producto de la concurrencia, la facilidad de eliminar, editar o incluso suprimir todo, <b>history</b> sirve de modo muy incompleto para análisis forense. Si realmente necesitás trazabilidad,
andá por el lado de <b>auditd</b>.</p><p></p><p>Respecto a comentar que existe lo de <b>HISTCONTROL</b>, un atacante que lo conozca podría en el medio de una serie de comandos normales que no llamarían la atención, ejecutar sin que quede registrado alguno malicioso en particular.</p><p>Mantener oculto lo de <b>HISTCONTROL</b> sólo contribuiría a una falsa sensación de seguridad mientras que el hacerlo conocido ayuda a que hayan menos datos sensibles en <b>history</b>, gana comentarlo.<br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-60794133689312004642023-09-29T22:30:00.000-03:002023-09-29T22:35:39.304-03:00Cómo pegar texto sin portapapeles<p>Supongamos estos escenarios:</p><p><br /></p><p>Tenés una VM recién instalada sin entorno gráfico y hay que ejecutar algunas instrucciones muy largas. Como no tenés portapapeles, a tipear.</p><p></p><p>Estás haciendo login en una terminal o aplicación que no soporta copiar y pegar y terminás bloqueándote porque tenés una clave tipo "1lI0OG68B". <br /></p><p>Estás llenando un campo en una página web que por algún perverso motivo tiene <br /></p><p> <span style="font-family: courier;"><b><input type="text" onpaste="return false" /> </b></span></p><p></p><p>Seguro te ha ocurrido cuando te piden un mail y en la verificación no te deja pegar.<br /></p><p>La generalización del problema es:</p><p> </p><p style="text-align: center;"><i>Quiero pegar texto y el portapapeles no funciona.</i></p><p><br /></p><p>Entonces pensás. Si hiciste ataque del "falso pendrive" en el cual pusiste un microcontrolador que se registra como un teclado y envía texto, ¿se podría hacer algo parecido con software? ¿Un programa que envíe el texto a la ventana como si fuera el teclado?</p><p>Pues existe y si usás X11, no Wayland, se llaman xdotool.</p><p>Para saber si usás X11, ejecutás:<br /></p><p><span style="font-family: courier;"><b>$ echo "$XDG_SESSION_TYPE"</b></span><br /></p><p>o</p><p><span style="font-family: courier;"><b>$ env | grep -E -i 'x11|xorg|wayland'</b></span></p><p></p><p>Para instalar xdotool en Debian y derivados</p><p></p><p><span style="font-family: courier;"><b>$ sudo apt install xdotools</b></span></p><p></p><p>Luego, tenés que ejecutar esta secuencia:</p><p></p><ul style="text-align: left;"><li>Encontrar la ventana </li><li>Seleccionar la ventana</li><li>Enviar el texto</li></ul><p>Por ejemplo:<br /></p><p><span style="font-family: courier;"><b>xdotool search "Virtual" windowactivate --sync type "ls"</b></span></p><p>¿Fácil? Nada lo es. Si mirás </p><p><span style="font-family: courier;"><b>$ man xdotool</b></span></p><p>verás que es una herramienta superpower, pero quedémonos con lo más básico y veamos los detalles<br /></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Encontrar la ventana</h2><h2 style="text-align: left;"><br /></h2><p></p><p></p><p>El search viene a ser un <b>/.*PATTERN.*/i</b></p><p></p><p>Otra, hay ventanas embebidas, por ejemplo para firefox, te trae todas las solapas:</p><p></p><p><span style="font-family: courier;"><b>$ xdotool search "Firefox" | wc -l<br />Defaulting to search window name, class, and classname<br />94</b></span><br /></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Seleccionar la ventana</h2><h2 style="text-align: left;"><br /></h2><p>Es hacerla activa y el<b> --sync</b> es para que espere a que ocurra</p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Enviar el texto</h2><h2 style="text-align: left;"><br /></h2><p></p><p>Esto no debería tener sorpresas hasta que lo probás y el teclado de un host no corresponde con el de destino.</p><p>Se debe a que en realidad no se están enviando letras sino keycodes, que es exactamente lo mismo que pasa con el microcontrolador.</p><p></p><p>O cambiás la disposición del teclado en el destino o tenés que hacer alguna conversión del texto que vas a enviar. Un <b>tr</b> nunca viene mal, hasta que intentás hacerlo y te recomiendo cambiar la disposición.</p><p><br /></p><p>Si no podés hacerlo y no hay mucho que enviar, te recomiendo que lo mandes como está y luego edites y corrijas, perdí un montón de tiempo con <b>tr</b>. </p><p> </p><p>Retrospectivamente, lo mejor sería escribir un programita que haga el proceso inverso, obtener el keycode de las teclas que habría que mapear y que genere el texto apropiado pero ya es todo un proyectito.</p><p><br /></p><p>Ponele que no podés cambiar la disposición del teclado, aún queda el Plan Base64.</p><p></p><p></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwGVZmbLy3WnI06fLNR4R5DW7SpdCAECirYX9lliRtG5ouy-Jhk6STKo4ZR_s2eCxH3B9supeaVcOufOUccFM6llFSm2FMW7wvyAo-BEVpnf-hlQ4AkIXyLGEk2BV6ZN5hZ3d61GwPutn6poIls3NeYakVXZtCwzZosfPXXyPmMgfpdyJ5bb1GRl8AgXMc/s1039/xdotool.png" style="margin-left: auto; margin-right: auto;"><img alt="Primero la falla y luego con base64" border="0" data-original-height="278" data-original-width="1039" height="172" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwGVZmbLy3WnI06fLNR4R5DW7SpdCAECirYX9lliRtG5ouy-Jhk6STKo4ZR_s2eCxH3B9supeaVcOufOUccFM6llFSm2FMW7wvyAo-BEVpnf-hlQ4AkIXyLGEk2BV6ZN5hZ3d61GwPutn6poIls3NeYakVXZtCwzZosfPXXyPmMgfpdyJ5bb1GRl8AgXMc/w640-h172/xdotool.png" title="Primero la falla y luego con base64" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Primero la falla y luego con base64</td></tr></tbody></table><br /><p></p><p>Después de haber fallado:<br /></p><ol style="text-align: left;"><li>Pasás el texto a base64</li><li>Preparás el comando y ponés el cursos entre las comillas ""</li><li>Enviás el texto </li><li>Ejecutás falla porque el "=" no se transmite...</li><li>Lo arreglás a mano y volvés a ejecutar</li><li>Mostrás el contenido correcto </li></ol><p></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Ideas adicionales</h2><h2 style="text-align: left;"><br /></h2><p></p>En una terminal no X de una VM, instalando <b>gpm</b> se puede copiar y pegar localmente, pero aún con VboxAdditions y el portapapeles activado no pude pegar entre entornos. Igual no me maté mucho probando.<p>Lo de los campos a los que no se les puede pegar, que el ejemplo más básico sería una página que abrís directamente del sistema de archivos con este contenido:</p><p></p><p><span style="font-family: courier;"><b><form><br /> <input type="text" /><br/><br /> <input type="text" /><br/><br /> <input type="text" <span style="background-color: #fcff01;">onpaste="return false"</span> /><br /></form></b></span><br /></p><p>lo podés burlar muy fácilmente quitando lo marcado en amarillo desde el navegador con Developer Tools, ahí fué la seguridad de Client Side Validation...<br /></p><p>Estos métodos pueden parecer rehacking pero si mirás atentamente sólo
estás introduciendo texto, no hay fuga de información, cosa que sí
habría en caso de funcionar el portapapeles.</p>Una idea para facilitar la transcripción de credenciales cuando todo lo demás falla, es que tengan la forma <b>???_???_???_???</b>, no disminuye la fortaleza y facilita la copia humana.<p>Finalmente, si usás estos métodos con claves, no te olvides de borrar en el historial de comandos...</p><p><b>Bonus</b>: <a href="https://gzalo.com/" target="_blank">gzalo</a> me avisó que la mayoría de los password managers tiene esta función, en el caso particular de KeePassXC es botón derecho sobre la cuenta, "Perform Auto-Type", que le envía la clave a la última ventana a la que le hayas hecho foco. Probalo con una cuenta inútil y un editor de texto hasta que lo entiendas bien.<br /></p><p><b>Bonus</b>: lo de usar un microcontrolador para almacenar claves es la idea que todos tuvimos pero solo <a href="https://github.com/TenoTrash/Raspi_Pico_botonera_hack" target="_blank">mar fer</a> realizó.</p><p><br /></p><p>Dejo pegados acá los comandos:</p><p><span style="font-family: courier;"><b> </b></span></p><p><span style="font-family: courier;"><b>xdotool search "ventana" windowactivate --sync type "txt"<br /></b></span></p><p><b style="font-family: courier;"> </b></p><p><b style="font-family: courier;">xdotool search "ventana" windowactivate --sync type $( echo "txt" | base64 ) </b></p><p><span style="font-family: courier;"><b>cmd=$( echo "" | base64 -d )</b></span><b style="font-family: courier;"> <br /></b></p><p><b style="font-family: courier;"> </b></p><p><b style="font-family: courier;">xdotool search "ventana" windowactivate --sync type $( base64 script.sh) </b></p><span style="font-family: courier;"></span><p><span style="font-family: courier;"></span></p><p><span style="font-family: courier;"><b>echo "" | base64 -d > script.sh<br /></b></span></p><p><span style="font-family: courier;"><b><br /></b></span></p><p><br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-57393470102630961072023-08-03T19:24:00.001-03:002023-08-03T19:24:39.897-03:00Emulador chip-8<p> </p><p>En el marco cyberciruja, <a href="https://emuladores.gzalo.com/" target="_blank">gzalo</a> dictó un excelente taller de emulación de CHIP-8 el sábado 2023-07-22. Comparto mi experiencia y resultado.<br /></p><p><br /></p><p></p><p>Me apoyé en el ejemplo provisto, tanto el base como los fragmentos de código de la presentación, le refactoricé las globales a un struct, quité el boolean y renombré .cpp a .c, es que había una trampita de estar usando g++ para compilar código C.</p><p> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2xrXxd7U2TKMgKFL48yv_-gj9q8mEvnbYexogjOqOScJpiTd13z9Ae0obIdOq3iO-UOCZ0BvpmAbHyyrfK2s32na7nd5kih5XIBgI_gyCFj5AcFEcTNEeI5hDuI8d-chRdJt1ig54qg3tx6Ufsiz2aggYQNFJzQBM0wQDOWKtJSNbEJqRUMYFQCD2CsFc/s1116/chip8-screen.png" style="margin-left: auto; margin-right: auto;"><img alt="Screen dump al finalizar la ejecución" border="0" data-original-height="783" data-original-width="1116" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2xrXxd7U2TKMgKFL48yv_-gj9q8mEvnbYexogjOqOScJpiTd13z9Ae0obIdOq3iO-UOCZ0BvpmAbHyyrfK2s32na7nd5kih5XIBgI_gyCFj5AcFEcTNEeI5hDuI8d-chRdJt1ig54qg3tx6Ufsiz2aggYQNFJzQBM0wQDOWKtJSNbEJqRUMYFQCD2CsFc/w606-h426/chip8-screen.png" title="Screen dump al finalizar la ejecución" width="606" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Screen dump al finalizar la ejecución<br /></td></tr></tbody></table><br /><p> </p><p></p><p>Mi objetivo, además de la diversión, es repasar un poco C para no olvidar demasiado, probar algunos recursos que no he usado mucho y otros que sí pero no en C. Entonces ejercité:<br /></p><ul><li>Makefile <br /></li><li>procesar argumentos con getopt</li><li>FSM</li><li>testing unitario sin framework<br /></li><li>valgrind</li><li>gdb</li></ul><p>Mi enfoque fue incrementar de modo testeable la menor funcionalidad posible en cada paso. En un comienzo, testeable era que ejecutara el programa hasta la próxima instrucción no implementada, luego agregué test unitario.<br /></p><p>Antes de seguir, para no spoilearte, te dejo mi recomendación de cómo encararlo:</p><ul style="text-align: left;"><li>Elegí e inicializá las estructuras u objetos de tu arquitectura. </li><li>Hacé el loop de ejecución.</li><li>Implementá los dumps de los registros y estructuras</li><li>Cargá la ROM<br /></li><li>Armá el switch para los opcodes y los switches internos para los subcodes, poné en cada rama una llamada a una función unimplemented(), unknown() en el default del switch principal, invalid() en cada default de los switches internos:</li></ul><p><br /></p><p><span style="font-family: courier;"><b> void unimplemented(){<br /> printf("UNIMPLEMENTED INSTRUCTION\n");<br /> exit(1);<br /> }<br /></b></span><br /></p><ul style="text-align: left;"><li>Ejecutá el programa, tiene que tirar un unimplemented, implementá esa instrucción. Y así....</li></ul><p>Ya sea a mano o con un framework de testing, respetá TDD.</p><ul style="text-align: left;"><li>Ejecutá hasta el unimplemented: eso te genera el requerimiento</li><li>Escribí el test ateniendote a la especificación, ojo que hay sutiles diferencias<br /></li><ul><li>https://chip8.gulrak.net/ (marcá solo CHIP-8) </li><li>https://github.com/Timendus/chip8-test-suite </li><li>https://en.wikipedia.org/wiki/CHIP-8</li><li>https://tobiasvl.github.io/blog/write-a-chip-8-emulator/</li></ul><li>Dejá que falle para comprobar que es efectivo en la falla<br /></li><li>Hardcodeá para comprobar que es efectivo en el éxito<br /></li><li>Implementá hasta que pase</li><li>Refactorizá <br /></li><li>Again...</li></ul><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Spoiler Alert </h2><h2 style="text-align: left;"><br /></h2><p>Ahora te cuento lo que hice yo, que más o menos se parece, está en <a href="https://github.com/cpantel/CHIP-8/tree/master" target="_blank">cpantel/CHIP-8</a></p><p></p><p>Implementé la carga del programa en memoria y comprobé visualmente que soc_dump_memory() y hexdump -C ROM/1-chip8-logo.ch8 correspondieran. Recordá que en el dump debe estar la fuente, luego todos ceros y la imagen del ROM recién en 0x200, 512 decimal)<br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjODGuv0pU3YuPZ7K-xJuVNVZRbvNNiAyd0w57f9UXi90VSB8x4p6zEjYlfSIW5JRL-eDKCsO198_J2wsJcfdz846wJkrD7fJU19nApJaiUq4fspkGh69EXV0CI88-0hco1kv8E2bGUxitEfpES-wiQEwjSY7kTkGF08SgUuzWH057RMWu87IWYtjHblDPC/s1150/chip8-memory.png" style="margin-left: auto; margin-right: auto;"><img alt="Comparación de memory dump y hexdump de 3-corax+.ch8" border="0" data-original-height="242" data-original-width="1150" height="134" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjODGuv0pU3YuPZ7K-xJuVNVZRbvNNiAyd0w57f9UXi90VSB8x4p6zEjYlfSIW5JRL-eDKCsO198_J2wsJcfdz846wJkrD7fJU19nApJaiUq4fspkGh69EXV0CI88-0hco1kv8E2bGUxitEfpES-wiQEwjSY7kTkGF08SgUuzWH057RMWu87IWYtjHblDPC/w640-h134/chip8-memory.png" title="Comparación de memory dump y hexdump de 3-corax+.ch8" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Comparación de memory dump y hexdump de 3-corax+.ch8<br /></td></tr></tbody></table><br /><p></p><p>Implementé avanzar un paso, que haga el fetch y la descomposición en opcode, nibbles, X, Y, keys, NN, NNN, el nombre que sea útil en cada contexto<br /></p><p></p><p>Tomé el ROM 1-chip8-logo.ch8 que es el que menos instrucciones precisa. De cada instrucción que invoca, implementé el decode y execute. Obviamente para SPRITE me copié de lo que Gustavo proveyó.</p><p>Para la primera instrucción que es CLS, mi clear_screen toma un valor, así en init() pongo la pantalla en blanco y ante la primera llamada de CLS se pone en negro.<br /></p><p></p><p>Implemente que varias medidas intrusivas se activen con left shift, tales como:</p><ul><li>avance paso a paso</li><li>volcado de memoria, video, registros, teclas</li><li>des/activación de debug</li></ul><p> Esto es por que el teclado esta mapeado en:</p><p><span style="font-family: courier;"> 1 2 3 4</span></p><p><span style="font-family: courier;"> <b>q</b> w <b>r</b> <b>t</b></span></p><p><span style="font-family: courier;"> a <b>s</b> <b>d</b> f</span></p><p><span style="font-family: courier;"> z x c <b>v<br /></b></span></p><p></p><p>Y algunas de esas letras son buenas como atajos:<br /></p><p></p><p><span style="font-family: courier;"><b>while (!quit) {<br /> while (SDL_PollEvent(&event)) {<br /> if (event.type == SDL_QUIT) {<br /> quit = 1;<br /> } else if(event.type == SDL_KEYDOWN){<br /> if (event.key.keysym.mod & KMOD_LSHIFT ) {<br /> </b></span><span style="font-family: courier;"><b> // para que se vea bien acá</b></span><br /><span style="font-family: courier;"><b> // sym = event.key.keysym.sym;<br /> if(sym == SDLK_r) run = ! run;<br /> if(sym == SDLK_n) soc_step(&soc,1);<br /> if(sym == SDLK_d) {debug = ! debug; run=0;}<br /> if(sym == SDLK_t) {show_time = ! show_time; run=0;}<br /> if(sym == SDLK_v) {soc_dump_registers(&soc);run=0;}<br /> if(sym == SDLK_m) {soc_dump_memory(&soc); run=0;}<br /> if(sym == SDLK_s) {soc_dump_screen(&soc); run=0;}<br /> if(sym == SDLK_k) {soc_dump_key(&soc); run=0;}<br /> if(sym == SDLK_h) {show_help(); run=0;}<br /> if(sym == SDLK_q) quit = 1;<br /> } else {<br /></b></span><span style="font-family: courier;"><b> if(sym == SDLK_1) soc_press_key(&soc, 1);<br /> ....<br /></b></span></p><p><span style="font-family: courier;"><b> }<br /> } else if(event.type == SDL_KEYUP){<br /> if (event.key.keysym.mod == KMOD_NONE ) {<br /> if(sym == SDLK_1) soc_release_key(&soc, 1);<br /> ...<br /></b></span></p><p><span style="font-family: courier;"><b> if (run) soc_step(&soc, debug);<br /> }<br /> ... </b></span><br /></p><p><br /></p><p>Ahí entrás en un loop de ir implementando la siguiente instrucción que falle....<br /></p><p><br /></p><p></p><p><b><span style="font-family: courier;"><span style="font-size: x-small;">pc: 200 fetch: 00E0 opcode: 0 X: 0 Y: E opcode2: 0 NN: E0 NNN: 0E0<br />pc: 202 fetch: A22A </span></span><span style="font-family: courier;"><span style="font-size: x-small;">opcode</span></span><span style="font-family: courier;"><span style="font-size: x-small;">: A X: 2 Y: 2 </span></span><span style="font-family: courier;"><span style="font-size: x-small;">opcode2</span></span><span style="font-family: courier;"><span style="font-size: x-small;">: A NN: 2A NNN: 22A<br />pc: 204 fetch: 600C </span></span><span style="font-family: courier;"><span style="font-size: x-small;">opcode</span></span><span style="font-family: courier;"><span style="font-size: x-small;">: 6 X: 0 Y: 0 </span></span><span style="font-family: courier;"><span style="font-size: x-small;">opcode2</span></span><span style="font-family: courier;"><span style="font-size: x-small;">: C NN: 0C NNN: 00C<br />pc: 206 fetch: 6108 </span></span><span style="font-family: courier;"><span style="font-size: x-small;">opcode</span></span><span style="font-family: courier;"><span style="font-size: x-small;">: 6 X: 1 Y: 0 </span></span><span style="font-family: courier;"><span style="font-size: x-small;">opcode2</span></span><span style="font-family: courier;"><span style="font-size: x-small;">: 8 NN: 08 NNN: 108<br />pc: 208 fetch: D01F </span></span><span style="font-family: courier;"><span style="font-size: x-small;">opcode</span></span><span style="font-family: courier;"><span style="font-size: x-small;">: D X: 0 Y: 1 </span></span><span style="font-family: courier;"><span style="font-size: x-small;">opcode2</span></span><span style="font-family: courier;"><span style="font-size: x-small;">: F NN: 1F NNN: 01F<br />UNIMPLEMENTED INSTRUCTION</span></span></b></p><p></p><p><br /></p><p>Implementé una opciones de línea de comando para determinar: </p><ul style="text-align: left;"><li>Estado inicial variable<br /></li><ul><li><b>Corriendo</b> o pausado</li><li>Imprimiendo debug o <b>no</b></li><li>Hacer o <b>no</b> dump de pantalla al finalizar <br /></li></ul><li>Cantidad de instrucciones a ejecutar hasta detenerse <br /></li><li>Cantidad de instrucciones por frame, 8 parece ok<br /></li><li>Delay para completar el frame, medio en vano, todo ocurre en mucho menos de un milisegundo, el default de 16 parece ok<br /></li><li>ROM a cargar <br /></li></ul><p>Fui tomando cada ROM de https://github.com/Timendus/chip8-test-suite y no hubo problemas hasta la quinta, quirks. De paso ahí noté que muchas de las operaciones tenían una equis en lugar del check ok en los anteriores, entonces tuve que...<br /></p><p></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Test</h3><h3 style="text-align: left;"> </h3><p></p><p>Llegó el momento de agregar test unitario. Hasta este momento tenía algo parecido a:</p><p><b><span style="font-family: courier;">void step(struct typeSOC* soc) {<br /> struct typeInstruction ins;<br /> fetch(soc,&ins);<br /> soc->pc+=2;<br /> switch (ins.opcode) {<br /> case 0x3:<br /> if (soc->v[ins->X] == ins->NN) soc->pc+=2;<br /> break;<br /> ...<br /> ...</span></b><br /></p><p></p><p></p><p>Lo cual es imposible de probar, la implementación de la instrucción debe estar en una función aislada para no estar probando a la vez el fetch y fundamentalmente ese <b>soc->pc+=2;</b></p><p>Me llevé la implementación de cada operación a otro archivo <br /></p><p></p><p><span style="font-family: courier;"><b> switch (ins.opcode) {<br /> case 0x0: // CLS<br /> switch(ins.NNN) {<br /> case 0x0E0:<br /> api(soc, &ins, OPCODE_CLS);<br /> if (debug) printf(" CLS\n");<br /> break;<br /><br /> case 0x0EE: // RET<br /> api(soc,&ins, OPCODE_RET);<br /> break;<br /></b></span> </p><p> Este es el test de XOR<br /></p><p><b><span style="font-family: courier;">void test_XOR(struct typeSOC* soc, struct typeInstruction* ins) {<br /> soc->v[8] = 0xff;<br /> soc->v[2] = 0x2a;<br /> ins->fetch = 0x8823;<br /> predecode(ins);<br /> api(soc, ins, OPCODE_XOR);<br /> assert_equal(0xd5, soc->v[8], "XOR: bad result");<br />}</span></b></p><p> </p><p>siendo assert_equal: <br /></p><p></p><p><b><span style="font-family: courier;">void assert_equal(uint32_t expected, uint32_t got, char * msg) {<br /> if (expected != got) {<br /> printf("\n%s, expected: %x got: %x\n", msg, expected, got);<br /> } else {<br /> printf(".");<br /> }<br />}</span></b><br /></p><p>En lo versionado actual quedaron unos if's en lugar de assert_equal, algún dia...<br /> </p><p>Pude haber implementado una función para cada instrucción, tipo <b>api_CLS()</b>, <b>api_RET()</b> o como lo hice, que es pasarle a una sola función el código y ahí dentro otro switch(), lo cual puede ser mal visto por que parece haber repetición de código, pero, no estoy tan seguro. El primer switch tiene switches anidados y el segundo no, es plano. </p><p></p><p>Usar funciones distintas es mejor manera de autodocumentar y un mejor lugar para poner los unimplemented(). Los invalid() y unknown() quedarían en el switch de soc.c.<br /></p><p></p><p></p><p></p><p>Tal como hice los test, sin framework, tiene una muy evidente desventaja, que es no poder imprimir un puntito tras cada test realizado de modo elegante. Ni poder llevar la cuenta de los tests y asserts ejecutados. Digo de manera elegante, siempre se puede llenar todo de printfs y globales...<br /></p><p>Otra limitación, no es que no se pueda hacer con C, es que de haber usado un lenguaje orientado a objetos, quedaría muy prolijo encapsular todo con setters y getters en lugar de acceder directamente a los registros y memorias y así poder recopilar algunas estadísticas como:</p><ul><li>uso de registros <br /></li><li>uso de instrucciones</li><li>uso del stack</li><li>uso de botones <br /></li><li>área de memoria leída y escrita</li></ul><p>Esto serviría para hacer una versión reducida, como para portar a FPGA chica o lo que me interesaría, el core RISC-V icicle en la EDU-FPGA.<br /></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Traza</h3><h3 style="text-align: left;"> </h3><p>Un recurso es analizar una traza prexistente, se puede obtener de los emuladores octo. Por ejemplo en (<a class="text-entity-link long-word-break-all" data-entity-type="MessageEntityUrl" dir="auto" href="https://timendus.github.io/chip8-test-suite/3-corax+.html" rel="noopener noreferrer" target="_blank" title="https://timendus.github.io/chip8-test-suite/3-corax+.html">https://timendus.github.io/chip8-test-suite/3-corax+.html</a>), poniendo algo como<br /><br /><span style="font-family: courier;"><b><span style="font-size: small;">console.log("op: " + op.toString(16) + " o: " <br />+ o.toString(16) + " pc: " + this.pc.toString(16)); </span></b></span><br /><br />cerca de la línea 470 cuando descompone el fetch, genera una traza. Si en tu emulador hacés algo compatible, con ./tools/compare comparás.<br /></p><p>Esto sirve para las partes donde no hay uso de timer ni lectura de teclado.</p><p></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Headless</h3><h3 style="text-align: left;"><br /></h3><p>Implementé una versión headless, más que todo porque en mi máquina no quería instalar SDL2, entonces hice todo en otra con ssh y una ventana de VNC, solo en esa ventana se puede ejecutar código con SDL. Medio en vano pues con ssh -X funciona casi ok.</p><p></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Dump ascii</h3><h3 style="text-align: left;"> <br /></h3><p>Motivado por la posibilidad de testear la imagen rederizada, implementé que se haga un dump por terminal. Para ser franco no es ascii, es unicode, pero bueno. Es la primera imagen de este post, se puede ejecutar en cualquier momento o al finalizar.</p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Autostop</h3><h3 style="text-align: left;"> </h3><p>Aunque ningún programa baremetal como son estos termina, quizás queremos que terminen al terminar de ejecutar. Esto tiene sentido en los tests y la manera de implementarlo es hacer un salto incondicional a esta misma instrucción, o sea al PC actual. Esto se detecta y finaliza la emulación.</p><p><span style="font-family: courier;"><b> if (ins.opcode == 1 && soc->pc == ins.NNN) {<br /> return 1;<br /> }</b><br /></span></p><p></p><h2 style="text-align: left;"><br /></h2><h2 style="text-align: left;">Mi implementación en C<br /></h2><h2 style="text-align: left;"> </h2><div style="text-align: left;">Está en <a href="https://github.com/cpantel/CHIP-8/tree/master" target="_blank">cpantel/CHIP-8</a> y te cuento que no me maté mucho en que los componentes respetaran la jerarquía, fijate que debió haber sido así:<br /></div><div style="text-align: left;"> </div><div style="text-align: left;"></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><b><span style="font-family: courier;">struct typeSOC</span></b></div><div style="text-align: left;"><span style="font-family: courier;"><b> pc -> soc.cpu.pc<br /> i -> soc.cpu.i<br /> v[] -> soc.cpu.v[]</b></span></div><div style="text-align: left;"><b style="font-family: courier;"> stack_pointer -> soc.cpu.stack_pointer</b></div><div style="text-align: left;"><span style="font-family: courier;"><b> key[] -> soc.keyboard.keys[]</b></span></div><div style="text-align: left;"><b style="font-family: courier;"> kb_state -> soc.keyboard.state</b></div><div style="text-align: left;"><b style="font-family: courier;"> last_key -> soc.keyborad.last </b></div><div style="text-align: left;"><span style="font-family: courier;"><b> stack[] -> soc.stack[]<br /> memory[] -> soc.memory[]<br /> screen[] -> soc.screen.memory[]</b></span></div><div style="text-align: left;"><b style="font-family: courier;"> redraw -> soc.screen.redraw </b></div><div style="text-align: left;"><span style="font-family: courier;"><b> delay_timer -> soc.timer.delay<br /> sound_timer -> soc.timer.sound</b></span><br /></div><div style="text-align: left;"> </div><div style="text-align: left;">y la parte de la instruction, quizás así:</div><div style="text-align: left;"> </div><div style="text-align: left;"><span style="font-family: courier;"><b> count -> soc.cpu.instruction.count<br /> fetch -> soc.cpu.instruction.fetch <br /> opcode -> soc.cpu.instruction.opcode<br /> X/key -> soc.cpu.instruction.X/key<br /> Y/N/opcode2 -> soc.cpu.instruction.Y/N/opcode2<br /> NN -> soc.cpu.instruction.NN<br /> address/NNN -> soc.cpu.instruction.address/NNN<br /></b></span></div><div style="text-align: left;"><b style="font-family: courier;"> </b></div> <div style="text-align: left;">pero implica agregar archivos y un montón de refactorización, no vale la pena.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">Valgrind lo usé para ./tools/compare, no para chip8, así que no sé si <br /></div><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Posibilidades de mejora</h2><h2 style="text-align: left;"> </h2><p>RND: proveerle una seed por línea de comando.</p><p>Comparar la memoria de pantalla con una imagen de referencia.</p><p>Poder cambiar mediante parámetros de línea los colores de background y foreground.</p><p></p><p>Que en debug imprima el código disassembly. </p><p>Que pase el test quirks. </p><p>Implementar las validaciones de uso del stack y algunas otras.</p><p>Que imprima algún help para las command line options.</p><p>Que valide que exista el archivo de ROM y su longitud.</p>Usar funciones para cada instrucción en lugar del segundo switch.<h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Conclusión</h2><h2 style="text-align: left;"> </h2><p>Muy buena la explicación de <a href="https://emuladores.gzalo.com/">gzalo</a> y su asistencia posterior, me destrabó al menos en un ínfimo pero mortífero error muy difícil de notar en la lectura del teclado.<br /></p><p>La experiencia fue muy buena, sin presión, hacer algo que no sirve para nada por fuera de haberlo hecho. Es que los juegos son horribles, inusables, no probé ninguno más allá de cargarlo para ver que funcionara algo.</p><p>La mayor parte de las posibilidades de mejora serían aplicables en caso de querer desarrollar programas para esta plataforma, nada más lejos de mis intenciones, se lo dejo a la gente más retro.<br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-89826363907905820312023-07-09T12:56:00.004-03:002023-07-13T12:36:00.857-03:00MD5 como IOC apesta<h1 style="text-align: left;">Qué es un IOC</h1><p>Cuando hay ataque, en sus distintas etapas, se van generando acciones y artefactos, que deberían quedar registradas en algún lado y que son detectables.<br /></p><p></p><p>Por ejemplo, te envían un link malicioso, para que te descargues un archivo, que al ejecutarse accede a una url para bajar componentes adicionales, exfiltrar información o recibir órdenes. Además, se escribe en el disco como persistencia y agrega una clave en el registro para reiniciarse cuando el sistema lo haga, ¿qué tenemos?</p><ul style="text-align: left;"><li>Una url maliciosa</li><li>Un archivo malicioso</li><li>Más archivos maliciosos</li><li>Más urls</li><li>Claves en el registro</li></ul><p>Si vos ves este ataque, podés tomar nota de identificadores de cada una de estas piezas y luego, ante cada intento de acceder a urls comparar con las maliciosas, al bajar, escribir o leer un archivo hacerlo con los maliciosos y revisar el registro buscando claves.... maliciosas.<br /></p><p><br /></p><p></p><p>El caso particular del archivo no es muy práctico tomarlo como referencia pues puede ser grande, lo mejor es calcularle un hash y guardar ese Indicator Of Compromise.<br /></p><p></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Pequeña pieza de recomendación</h2><h2 style="text-align: left;"> </h2><p></p><p>Lamentablemente, incluso entre la gente técnica, la falta de conocimiento detallado hace que se cometan errores de concepto, por ejemplo el que paso a reportar, pues lo he visto varias veces con varias personas.</p><p>Ponele que tenés dos herramientas que entienden IOCs, el DNS y el proxy saliente.</p><p>Te llega este IOC, ¿dónde lo ponés?</p><p>https://3984274.aws.com</p><p>Muy bien, en cualquiera o ambos.<br /></p><p>¿Y este? <br /></p><p>https://3984274.aws.com/api/service/34 <br /></p><p></p><p>Si tuvieras la tentación de decir lo mismo, antes mirá este:<br /></p><p>https://www.afip.gob.ar/api/service/34</p><p>Hay personas que han dicho:</p><p>"Pongamos en ambos"</p><p>Hay dos problemas, el de seguridad y el conceptual técnico. </p><p>El de seguridad es que si para bloquear </p><p>https://www.afip.gob.ar/api/service/34</p><p>ponés "www.afip.gob.ar" en el DNS, generás una denegación de servicio a todo afip sólo por una ruta comprometida. Podría ser válido, razonando "si tiene esa ruta comprometida, puede estar todo el resto, no interactuemos en absoluto con afip hasta que corrijan", ok, es una decisión.</p><p>En la conversación de esa decisión es cuando detecté el problema conceptual técnico:<br /></p><p></p><p></p><p>El DNS no entiende ni "https://" ni "/api/service/34"</p><p></p><p>La única manera de bloquear sin "daños colaterales" es en el proxy.</p><p>Sigamos....</p><h1 style="text-align: left;"> </h1><h1 style="text-align: left;">Qué es MD5</h1><h1 style="text-align: left;"><br /></h1><p>Hashing es una operación que se hace sobre un dato y devuelve un hash, que es un número largo y en teoría cambia ante cualquier modificación sobre el dato. Si calculás un hash de un dato, modificás un bit, recalculás, te da otro hash.<br /></p><p>Por alguna falta de visión, pues esto de los IOCs es relativamente reciente, se utilizan como IOCs de archivos hashes MD5, que se diseñó en 1991 y ya desde 1993 se le han hallado problemas criptográficos que en el mejor de los casos, parecería que ya desde 2010 se considera deprecado.</p><p></p><p>Digo falta de visión pues si buscamos en wikipedia IOC, el artículo nace en 2013, como que ya existían varios SHA para ese entonces, pero seguro que lo de los IOC con MD5 entraron de la mano de gente de seguridad no técnica y programadores sin conocimientos de seguridad que buscaban ahorrar espacio y tiempo de ejecución.<br /></p><p>Ojo, siempre es fácil señalar los errores del pasado desde el futuro, pero bueno.</p><p></p><h1 style="text-align: left;"> </h1><h1 style="text-align: left;">La colisión "accidental"</h1><h1 style="text-align: left;"> <br /></h1><p>Una colisión de hash es cuando dos datos distintos dan el mismo hash. Las colisiones son esperables pues la variedad de datos es infinita y los hashes son números, en el caso de MD5 entre 0 y 2 a la 128, que aunque es un número grande, claramente es muy muy muy inferior a infinito.</p><p> <br /></p><p>Se podría argumentar que dada la baja probabilidad de colisión y la ventaja del ahorro de espacio y tiempo de ejecución no importa, aunque ya tenemos al menos un caso conocido.</p><p> </p><p></p><p>Dice este reporte que no sé de dónde saqué, pero se parece a la situación habitual de malware, en este caso Trojan.Win64.CoinMiner, un minero:<br /></p><p>https://itsafety.net/report/20200515-65ade21dc82c01972891285581d85866-servermanager-exe_process-partofthreat</p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg2WFPYmfjGIZaVCFHmo4t0A4Dc3iz0df3aYtFmthmFfQ1_48dZJ1yIitBQ94szWM_0IPpZn0yFZzmmkyVIegzuvb5RmVxQLRIjGLsRx2Z1NFPzfWdoD8tVHlNDSuAN7z3Sr-8FdoQtvgxaDy-N0kP14b0raLfMZX-8Nk6ROYEtIbIlJRqs0uOwtQJIobh/s1045/Screenshot%202023-07-09%20at%2012-05-38%20ITSafety%20report%20%E2%80%94%20(SOLVED)%20How%20to%20REMOVE.png" style="margin-left: auto; margin-right: auto;"><img alt="Trojan.Win64.CoinMiner" border="0" data-original-height="746" data-original-width="1045" height="456" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg2WFPYmfjGIZaVCFHmo4t0A4Dc3iz0df3aYtFmthmFfQ1_48dZJ1yIitBQ94szWM_0IPpZn0yFZzmmkyVIegzuvb5RmVxQLRIjGLsRx2Z1NFPzfWdoD8tVHlNDSuAN7z3Sr-8FdoQtvgxaDy-N0kP14b0raLfMZX-8Nk6ROYEtIbIlJRqs0uOwtQJIobh/w640-h456/Screenshot%202023-07-09%20at%2012-05-38%20ITSafety%20report%20%E2%80%94%20(SOLVED)%20How%20to%20REMOVE.png" title="Trojan.Win64.CoinMiner" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Trojan.Win64.CoinMiner</td></tr></tbody></table><br /><p></p><p><br /></p><p>Fijate que dice que la mayor parte de los antivirus no lo detecta, ¿por qué será?</p><p>Dice Microsoft, que respecto a windows debe tener una cierta autoridad<br /></p><p>https://learn.microsoft.com/en-us/windows-server/administration/server-manager/server-manager</p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxofq36tBTHDtpiFOYDJz0RdDoSLoSu4dtqyrlD8L6Gxvw94AKosPy449SOXPmD9D5Sz7GQbxc-oq_zxzpb4rEdKZsx_GPatlfwRchaY8NrAL95mI-T1rkfCjaeF5QuabTLbPydKdVSSA_j-liIroFzXLlr1eeNxA9Wmyl274LEFBi2tXt0sCtXdwk1ZhZ/s827/Screenshot%202023-07-09%20at%2012-04-42%20Server%20Manager.png" style="margin-left: auto; margin-right: auto;"><img alt="Microsoft" border="0" data-original-height="609" data-original-width="827" height="472" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxofq36tBTHDtpiFOYDJz0RdDoSLoSu4dtqyrlD8L6Gxvw94AKosPy449SOXPmD9D5Sz7GQbxc-oq_zxzpb4rEdKZsx_GPatlfwRchaY8NrAL95mI-T1rkfCjaeF5QuabTLbPydKdVSSA_j-liIroFzXLlr1eeNxA9Wmyl274LEFBi2tXt0sCtXdwk1ZhZ/w640-h472/Screenshot%202023-07-09%20at%2012-04-42%20Server%20Manager.png" title="Microsoft" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Microsoft</td></tr></tbody></table><br /><p></p><p><br /></p><p>Puede ser que estemos hablando de distintas piezas, pero si buscás en virustotal ese hash (65ade21dc82c01972891285581d85866), te trae</p><p> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI-lbQTRb81p7Fnd_Cy40IglTKYqX9ssAJgmApKl7BeWgeOGjg4GBbiCN-fs8xeZzLi6JfX9W6TFqog2zOvXNapt2MiPJS-2VI8pO1EFE9fpMZEgzEsajgdL8piudeCvfSp53jB9mU6z3S7pHea4n2GxyabiyN-AlpgQHDFINXPgaoeW12ot7FsxkfysH_/s1057/Screenshot%202023-07-09%20at%2012-13-54%20VirusTotal%20-%20File%20-%2057fb008faeb05dd34fc1c224ce456b38ced950243fbac7f7cb348df68f990ebe.png" style="margin-left: auto; margin-right: auto;"><img alt="VirusTotal" border="0" data-original-height="279" data-original-width="1057" height="168" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI-lbQTRb81p7Fnd_Cy40IglTKYqX9ssAJgmApKl7BeWgeOGjg4GBbiCN-fs8xeZzLi6JfX9W6TFqog2zOvXNapt2MiPJS-2VI8pO1EFE9fpMZEgzEsajgdL8piudeCvfSp53jB9mU6z3S7pHea4n2GxyabiyN-AlpgQHDFINXPgaoeW12ot7FsxkfysH_/w640-h168/Screenshot%202023-07-09%20at%2012-13-54%20VirusTotal%20-%20File%20-%2057fb008faeb05dd34fc1c224ce456b38ced950243fbac7f7cb348df68f990ebe.png" title="VirusTotal" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">VirusTotal</td></tr></tbody></table><br /><p>De paso observá que el hash que te muestra es un SHA256, correcto.<br /></p><p>No tengo las ganas de buscar cada versión legítima del archivo hasta encontrar el que coincide con esa firma, para demostrar fehacientemente el punto pues su demostración pasa por otro lado.</p><p></p><h1 style="text-align: left;"> </h1><h1 style="text-align: left;">La colisión a propósito</h1><h1 style="text-align: left;"><br /></h1><p>Desde hace años en mis charlas muestro este ejemplo:</p><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbPekJJsXOcCll-ucnn20I25rXaEpbJYmdbhkHJDh9bKunPdwBBaEfAGSt2eGz-3Soc1hpQNrqiAyj9MAj3oC7RqazcqV3Qg47I-8w9F7ZpPT_4Gv-REXdvx2Iw_uASsPx0CloD8_qlu9k_voL47idzMlH9zNnfSCznRWyxcjlMnG5OZqkbGcp3Q3knCZq/s850/Screenshot%20at%202023-07-09%2012-27-28.png" style="margin-left: auto; margin-right: auto;"><img alt="angel devil" border="0" data-original-height="850" data-original-width="802" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbPekJJsXOcCll-ucnn20I25rXaEpbJYmdbhkHJDh9bKunPdwBBaEfAGSt2eGz-3Soc1hpQNrqiAyj9MAj3oC7RqazcqV3Qg47I-8w9F7ZpPT_4Gv-REXdvx2Iw_uASsPx0CloD8_qlu9k_voL47idzMlH9zNnfSCznRWyxcjlMnG5OZqkbGcp3Q3knCZq/w605-h640/Screenshot%20at%202023-07-09%2012-27-28.png" title="angel devil" width="605" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">angel devil<br /></td></tr></tbody></table><br /><p>Vemos que dos programas generan distinto output, miden lo mismo, tienen la misma longitud pero son distintos, con sha256 eso no pasa.</p><p> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9HWNNdUySGiSrgpPIBupDCT4iqTsp-YWPm_3npQRMqX3ixhRyKSHkhwWPlOAkc-mxo_jzuurmexclC-GhcJrfnjDdD8cWrDJd8R5LP7vzUMYaGTtp-2ECD7sz-wcJCNX7VCZYqNot_Ch_CekLzFxjclSEbV74wFsGrUipq8oGxgK7AwNGxHHJIB7w0zvA/s819/Screenshot%20at%202023-07-09%2012-33-46.png" style="margin-left: auto; margin-right: auto;"><img alt="sha256" border="0" data-original-height="60" data-original-width="819" height="46" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9HWNNdUySGiSrgpPIBupDCT4iqTsp-YWPm_3npQRMqX3ixhRyKSHkhwWPlOAkc-mxo_jzuurmexclC-GhcJrfnjDdD8cWrDJd8R5LP7vzUMYaGTtp-2ECD7sz-wcJCNX7VCZYqNot_Ch_CekLzFxjclSEbV74wFsGrUipq8oGxgK7AwNGxHHJIB7w0zvA/w640-h46/Screenshot%20at%202023-07-09%2012-33-46.png" title="sha256" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">sha256</td></tr></tbody></table><br /><p><br /></p><p></p><p>La verdad verdad, no sé bien de dónde lo saqué, tampoco importa muchísimo pues se trata de criptoarqueología y no hay nadie que discuta que MD5 no sirve.</p><p>Es un programa en C con un buffer. En ese buffer hay un valor, se compila y al ejecutar se comprueba que sea ese valor. En este caso se ejecuta angel().</p><p><br /></p><p>Luego, con fastcoll y longEgg se manipula ese buffer en la copia de angel llamada devil hasta que da el mismo hash MD5. Al ejecutar y fallar la comprobación, se ejecuta devil().</p><p> </p><p><span style="font-family: courier;"><b>int main() {<br /> if (strcmp(dummya, dummyb) != 0) {<br /> return angel();<br /> } else {<br /> return devil();<br /> }<br />}</b></span><br /><br /><br /></p><p>Lo que importa, es que probablemente se puedan tomar dos programas de la misma longitud, manipular una parte y hacerles concidir los hashes, con lo cual para cada ejecutable legítimo del sistema</p><p></p><p></p><p>Digo <i><b>probablemente</b></i> pues como script kiddie todo esto parece fácil, pero no lo he comprobado.</p><p>Me pregunto por qué no se hace y apuesto a que no vale la pena, es demasiado fácil contrarestar, leyendo el archivo de atrás para adelante para el MD5 o tomando otro SHA cualquiera basta para detectar correctamente, salvo en las herramientas más precarias, para decirles de alguna manera....<br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQXQR4SFM2_pO_qEz6_rUAXH5f3tCRfLDZ8tUQuU_96nRDS2-CTaAWOmwmrObPGEESX4viBXGgywmBqlrvm9ALdncXFh7mIxOkf0splou2tKyl_Yz7oO8KHY4qUH0KNbzVii9gtAHrEtV-Fv_H8diM1qklhg_RfAoGbPRl2OMhyzctMMhRYGzSU8ynSrSL/s817/Screenshot%20at%202023-07-09%2012-53-19.png" style="margin-left: auto; margin-right: auto;"><img alt="lectura invertida" border="0" data-original-height="85" data-original-width="817" height="66" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQXQR4SFM2_pO_qEz6_rUAXH5f3tCRfLDZ8tUQuU_96nRDS2-CTaAWOmwmrObPGEESX4viBXGgywmBqlrvm9ALdncXFh7mIxOkf0splou2tKyl_Yz7oO8KHY4qUH0KNbzVii9gtAHrEtV-Fv_H8diM1qklhg_RfAoGbPRl2OMhyzctMMhRYGzSU8ynSrSL/w640-h66/Screenshot%20at%202023-07-09%2012-53-19.png" title="lectura invertida" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">lectura invertida</td></tr></tbody></table><br /><p></p><p><br /></p><h1 style="text-align: left;">Para qué puede servir MD5</h1><h1 style="text-align: left;"> </h1><p></p><p>MD5 es útil en situaciones sin adversarios. Por ejemplo, tenés dos archivos del mismo tamaño y no sabés si son iguales. Si están en la misma máquina corrés cmp y listo, te lo dice. Pero si están en distintas máquinas, tendrías que copiar uno a la otra o montar en una una carpeta de otra.... mucho trabajo. El MD5 de cada archivo te puede confirmar si son distintos, no tanto que sean iguales, pero ya dije, sin adversarios.<br /></p><p>Me ha servido para hacer unas pruebas con FPGA, tal cual relato en <a href="https://seguridad-agile.blogspot.com/search?q=forzando+brutalmente+md5" target="_blank">un montón de entradas</a>....<br /></p><p></p><p>Y por supuesto sirve para demostrar lo inseguro que es.<br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-77336852604832103822023-07-09T10:30:00.000-03:002023-07-09T10:30:04.317-03:00Aprovechando pantallas obsoletas: la implementación<p> </p><p>Esto viene de <a href="https://seguridad-agile.blogspot.com/2023/06/aprovechando-pantallas-obsoletas-la-idea.html " target="_blank">una idea</a>.<br /></p><p>Obviamente la experiencia que transité no corresponde a lo que he dejado registrado, al ser una investigación ha habido una ida y vuelta y varias de las pruebas infructuosas no quedaron registradas</p><p></p><h1 style="text-align: left;"> </h1><h1 style="text-align: left;">Implementación</h1><h1 style="text-align: left;"></h1><p>Lo
que terminé haciendo es VNC al Remoto, para el momento de
iniciar la aplicación y hacer ssh -X al principal. Luego se puede minimizar y volver a maximizar cuando hace falta interactuar. En el caso de xwindows pelado como es con una tablet, la interacción es desde la tablet.<br /></p><p></p><p><br /></p><h2 style="text-align: left;">Los pasos del setup</h2><h2 style="text-align: left;"><br /></h2><h3 style="text-align: left;">Principal</h3><p><b style="font-family: courier;">sudo apt install remmina-plugin-vnc</b><br /></p><h3 style="text-align: left;"></h3><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Remoto linux<br /></h3><p>Como es i32, tengo un Linux Mint 19 con XFCE.</p><h4 style="text-align: left;"> </h4><h4 style="text-align: left;">Autologin</h4><p><span style="font-family: courier;"><b>sudo vi /etc/lightdm/lightdm.conf<br /><br /> [Seat:*]<br /> autologin-session=xfce<br /> autologin-user=YourDesiredAutoLoginUserName<br /> autologin-user-timeout=0</b></span><br /><br /></p><h4 style="text-align: left;">VNC server</h4><p><span style="font-family: courier;"><b>sudo apt install x11vnc<br />x11vnc -storepasswd somefile</b></span><br /><br /></p><p>Cuando te conectás te aparece un botón efímero en Secundario. Para evitarlo, le ponemos autenticación más que por seguridad. <br /><br /></p><h4 style="text-align: left;">Autostart de VNC<br /></h4><p> Settings -><br /> Session and startup -><br /> Application autostart -><br /> add x11vnc<br /> x11vnc -rfbauth somefile<br /></p><p><br /></p><h4 style="text-align: left;">Ver IP</h4><p><b><span style="font-family: courier;">sudo apt install xfce4-genmon-plugin</span></b></p><p><b><span style="font-family: courier;"> </span></b><br />panel -> add new items -> generic monitor <br />armar script con este contenido y ponerlo en "command" </p><p><br /><b><span style="font-family: courier;">ip a | grep inet.*global | cut -d" " -f 6</span></b></p><p></p><p> </p><p><br /></p><h3 style="text-align: left;">Remoto android</h3><br /><h4 style="text-align: left;">samsung tab 3 lite sm-t110 android 4.2.2</h4><p>Hay que instalar XServer-XSDL en su versión v1.20.41_apkpure de <br />https://sourceforge.net/projects/libsdl-android/files/apk/XServer-XSDL/<br /></p><p>Cuando falla con "Error: X server failed to launch", hay que reiniciar y configurar seleccionar</p><p>resolución nativa<br />x1<br />device configuration -><br /> mouse emulation -><br /> mouse emulation mode -><br /> desktop, no emulation<br /></p><p>Cuando aparece la cuenta regresiva, tocar hasta tener display number = 3</p><p></p><p></p><p>Sacado de https://www.youtube.com/watch?v=TcgTrkA8Oj0</p><p>Me
falta autostart, por ahora puedo prescindir. Estaría bueno un vnc
server pero no hay, quizás lo mejor sería ver de meter un linux, no vale
la pena.<br /></p><p><br /></p><p><br /></p><h2 style="text-align: left;">Los pasos de la conexión<br /></h2><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">A linux</h3><p>Via VNC, conectar a Secundario, la IP debe estar en el Panel<br /></p><p>Abrir una terminal</p><p><b style="font-family: courier;">ssh -X a Principal</b></p><p>Ejecutar el comando deseado, por ejemplo, "top"<br /></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">A android<br /></h3><p>En la pantalla de la tablet debe haber instrucciones tipo:</p><p><b><span style="font-family: courier;">export DISPLAY=192.168.1.105:3</span></b></p><p><b><span style="font-family: courier;">export PULSE_SERVER=tcp:192.168.1.105:4713</span></b></p><p><br /></p><p>Se invoca así:<br /></p><p><b><span style="font-family: courier;">xwindows-manager & mate-terminal -e top</span></b></p><p><br /></p><p>o así:<br /></p><p><b style="font-family: courier;">mate-terminal --display=$DISPLAY -e top</b><br /></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Detalles de uso</h2><h2 style="text-align: left;"><br /></h2><h3 style="text-align: left;">xed </h3><p></p><p>en linux Secundario hace el render en el principal, debe ser por su
integración con Mate, así que hay que usar otro, yo puse
/opt/sublime_text/sublime_text</p><br /><h3 style="text-align: left;">screensaving y powersaving <br /></h3><p>En todos los Secundarios hay que apagar los salvapantallas y poner al máximo o infinito los tiempos de activación de bajo cosumo.</p><h3 style="text-align: left;">Firefox <br /></h3><p>En linux:<br /></p><p><b style="font-family: courier;">firefox -P remoto https://www.google.com </b></p><p>En android, muy difícil de interactuar:<br /></p><p><b style="font-family: courier;">firefox -P remoto --display=$DISPLAY https://www.google.com </b><br /></p><p> </p><h3 style="text-align: left;"></h3><h3 style="text-align: left;">En tablet </h3><h3 style="text-align: left;"> </h3><h3 style="text-align: left;"></h3><h4 style="text-align: left;">teclado<br /></h4><p>Para hacer aparecer el teclado en
la tablet que tengo, hay que apretar el botón del medio para elegir la
xserver y ahí aparece con el teclado que luego se quita con el botón de
volver.</p><p><br /></p><h4 style="text-align: left;">move y resize</h4><p>se puede mover, pero no conseguí cambiar el tamaño, voy a ver uno de estos días si al menos se puede setear al invocar el comando.<br /></p><p><br /></p><h2 style="text-align: left;">Evidencias</h2><p><br /></p><p>En esta imagen podemos ver en la conexión de VNC a una netbook, una terminal con ssh -X de retorno al sistema principal y una tablet con x-windows aguardando conexiones.<br /></p><p><br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgjWRxnNcETgijjEAKuled61jWE1Nh04SjnHdL6S3zcLHj9kH8uBmu9GBpfiTBisH5o6mQ2QUkdeJSZPz-d4106pcU8QfKXMeQnPSjwuf_0zfl6k_fpVvh2XHCAXRX4xn2Tt_0vtMjfpe04w2mnm-NAqO19DbZesqPhwnIcoYmPPP8DMg9rvrFtcaH8oRT/s1306/setup.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Conexiones abiertas" border="0" data-original-height="861" data-original-width="1306" height="422" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgjWRxnNcETgijjEAKuled61jWE1Nh04SjnHdL6S3zcLHj9kH8uBmu9GBpfiTBisH5o6mQ2QUkdeJSZPz-d4106pcU8QfKXMeQnPSjwuf_0zfl6k_fpVvh2XHCAXRX4xn2Tt_0vtMjfpe04w2mnm-NAqO19DbZesqPhwnIcoYmPPP8DMg9rvrFtcaH8oRT/w640-h422/setup.png" title="Conexiones abiertas" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Conexiones abiertas<br /></td></tr></tbody></table><br /><p>En esta, hemos abierto un xcalc en el principal con su render en la netbook y el top de la principal con su render en la tablet.<br /></p><p><br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJLUWu_ELZ1c6Ewkt4zeQrxSYhRRmGXXunnh-szaYCmibzbvFqQexb64nEcWOCj9Ygn3tW1motKiHrCv6fcvqmuiADs2S63AgIINKRMReahvnt535UZFvZy_vVFsmR2_AS7WRJTi3drcnf0ATuZXfsbI9x8VLZR8KzBB_QwO9fELPF9GkHdUq0hUwrDuUi/s1634/running.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Programas en ejecución" border="0" data-original-height="871" data-original-width="1634" height="342" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJLUWu_ELZ1c6Ewkt4zeQrxSYhRRmGXXunnh-szaYCmibzbvFqQexb64nEcWOCj9Ygn3tW1motKiHrCv6fcvqmuiADs2S63AgIINKRMReahvnt535UZFvZy_vVFsmR2_AS7WRJTi3drcnf0ATuZXfsbI9x8VLZR8KzBB_QwO9fELPF9GkHdUq0hUwrDuUi/w640-h342/running.png" title="Programas en ejecución" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Programas en ejecución<br /></td></tr></tbody></table><br /><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-12177288853051919362023-07-04T20:22:00.012-03:002023-07-05T09:52:34.152-03:00Reflexiones sobre rbash<p>Supongamos que tenemos un linux al cual se accede por ssh. La situación normal es que a nivel de permisos tenemos root y el resto.</p><p>El usuario root puede hacer todo, listo.<br /></p><p>Dentro de ese resto, manejando grupos y permisos podríamos más o menos manejar algún tipo de restricción. Una medida común es utilizar sudo, que habilita una lista de acciones que podrá ejecutar quien tenga los permisos.</p><p>Pero, ponele que en lugar de estar viendo como le permitimos a los usuarios hacer algunas tareas administrativas, estamos buscando restringir lo que ya pueden hacer. Si el usuario en realidad es una cuenta para que un script pueda ejecutar algunas consultas sobre el sistema, no hay motivo para que pueda ejecutar ningún otro comando que no corresponda a lo que va a hacer.<br /></p><p>Para este requerimiento, se puede usar rbash.<br /></p><p>Si, si, ahí los del fondo, escuché que existe selinux y apparmor, pero esas son palabras mayores, quedémonos con lo sencillo.</p><p><br /></p><p>Lo que hace rbash es empezar por desabilitar un montón de comportamiento provisto por bash, <a href="https://www.gnu.org/software/bash/manual/html_node/The-Restricted-Shell.html" target="_blank">acá</a> está la lista completa, lo más importante es que no permite cd ni cambiar la ruta de invocación de comandos.<br /></p><p></p><p>Además:</p><p></p><p></p><p><i>The restricted shell mode is only one component of a useful restricted
environment. It should be accompanied by setting <code>PATH</code> to a value
that allows execution of only a few verified commands (commands that
allow shell escapes are particularly vulnerable), changing the current
directory to a non-writable directory other than <code>$HOME</code> after login,
not allowing the restricted shell to execute shell scripts, and cleaning
the environment of variables that cause some commands to modify their
behavior (e.g., <code>VISUAL</code> or <code>PAGER</code>). </i></p><p><br /></p><p>Sumado a eso, en .bashrc o similar hay que setear el PATH a una carpeta con symlinks a los ejecutables permitidos, según he visto que se hace.</p><p><br /></p><p></p><p>Luego, se debe considerar que:</p><p><i>When a command that is found to be a shell script is executed
(see <a href="https://www.gnu.org/software/bash/manual/html_node/Shell-Scripts.html">Shell Scripts</a>), <code>rbash</code> turns off any restrictions in
the shell spawned to execute the script.</i></p><p>Estoy citando pues como tengo casi nula experiencia con rbash, me siento irresponsable. Pero mi ínfima experiencia algo me ha hecho pensar.<br /></p><p> </p><p>Vamos ahora al escenario concreto, quiero: </p><ul style="text-align: left;"><li>que exista una cuenta</li><li>que tenga shell restringido <br /></li><li>a la que sólo se pueda acceder vía ssh</li><ul><li>esto implica no login por consola ni "desplazamiento lateral" tipo su o login <br /></li></ul></ul><p>Este comando lo hace:<br /></p><p></p><p></p><p><span style="font-family: courier;"><b>$ sudo adduser --shell /usr/bin/rbash --disabled-login prueba</b></span></p><p><span style="font-family: courier;"></span></p><p></p><p>Si estás modificando un usuario existente, editás /etc/password para que tenga el shell correcto y /etc/password para deshabilitar el login.</p><p>También se hace con </p><p><b style="font-family: courier;">$ sudo passwd -l prueba</b><br /></p><p>Que le agrega a "!" al password existente.<br /></p><p>De un modo u otro lo controlás con:<br /></p><p><span style="font-family: courier;"><b>$ sudo grep prueba /etc/passwd /etc/shadow <br />/etc/passwd:prueba:x:1001:1001:,,,:/home/prueba:<span style="background-color: #fcff01;">/usr/bin/rbash</span><br />/etc/shadow:prueba:<span style="background-color: #fcff01;">!</span>:19542:0:99999:7:::</b></span><br /></p><p>Solo vía ssh, hay que habilitar la key ya que se trata de clientes script, no de personas ingresando claves, aunque con la key un usuario puede entrar.</p><p></p><p><b style="font-family: courier;">$ ssh-keygen -f prueba.key -t ecdsa</b></p><p></p><p>En la carpeta del usuario prueba, hay que crear <b><span style="font-family: courier;">.ssh</span></b> con rwx------ y el archivo <b><span style="font-family: courier;">authorized_keys</span></b><b><span style="font-family: courier;"> </span></b>con permisos rw------- y el contenido de prueba.key.pub.</p><p> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtksS7ypq-T-i4B7kTsN32RDNP5ZH6RpF_g1W9RCmRC4quSAtcD2OEqcrBYISpk66lXNsM-6N06zyt-Cl-qhkPWLG14MiIfL548YzZ7LInUjiUKJ7xnALXX9P6EBN8ahQ8eYX5iVEkOu7-RQmX0u_wMvfjd4BxybIdysB_9VlwT6XffiAmlQuvEfuRMiaG/s435/01_rbash_ok.png" style="margin-left: auto; margin-right: auto;"><img alt="rbash en acción" border="0" data-original-height="106" data-original-width="435" height="98" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtksS7ypq-T-i4B7kTsN32RDNP5ZH6RpF_g1W9RCmRC4quSAtcD2OEqcrBYISpk66lXNsM-6N06zyt-Cl-qhkPWLG14MiIfL548YzZ7LInUjiUKJ7xnALXX9P6EBN8ahQ8eYX5iVEkOu7-RQmX0u_wMvfjd4BxybIdysB_9VlwT6XffiAmlQuvEfuRMiaG/w400-h98/01_rbash_ok.png" title="rbash en acción" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">rbash en acción<br /></td></tr></tbody></table><br /><p></p><p>El problema que hay acá es que si ejecutás:</p><p></p><p><b style="font-family: courier;">$ ssh prueba@localhost -t bash</b></p><p>sshd ignora el shell de /etc/passwd y te da un shell irrestricto.</p><p> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWu1qFnVsPBt3vvnVykjM62Gc5XREsESN5K5Fa14m7k7NQtPgHaCQYsGgHWlo2oV_viv8-gVSugKoBk1NVIiiluML_50UcWE9ryfRkWOymlSc4PHk22s6PH5U8eEc-i466ocxUT53FDuhO1JM93u9PluLWQXJuO9SbeVrAXajCb7omGygZG1vgtJt9kArS/s484/02_rbash_fail.png" style="margin-left: auto; margin-right: auto;"><img alt="rbash bypass" border="0" data-original-height="87" data-original-width="484" height="73" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWu1qFnVsPBt3vvnVykjM62Gc5XREsESN5K5Fa14m7k7NQtPgHaCQYsGgHWlo2oV_viv8-gVSugKoBk1NVIiiluML_50UcWE9ryfRkWOymlSc4PHk22s6PH5U8eEc-i466ocxUT53FDuhO1JM93u9PluLWQXJuO9SbeVrAXajCb7omGygZG1vgtJt9kArS/w400-h73/02_rbash_fail.png" title="rbash bypass" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">rbash bypass<br /></td></tr></tbody></table><br /><p></p><p>Se arregla de dos maneras, una global y otra específica para cada usuario.</p><p><br /></p><p>La global es poner en <b><span style="font-family: courier;">sshd_config</span></b> esta línea, que no la probé:<br /></p><div><b><span style="font-family: courier;">ForceCommand <span class="il">rbash</span></span></b> <br /></div><div><br /></div><div>Tiene la ventaja de restringir a todos por si alguno se te escapa, pero si querías tener uno que haga de administrador, vas a tener que ponerle específicamente que pueda ejecutar sudo.<br /></div><div> <br /></div><div>La específica para cada usuario es poner <span class="il"><span style="font-family: courier;"><b>no-pty</b></span> </span>en <b><span style="font-family: courier;">.ssh/authorized_keys</span></b></div><div>a la key con la que se autentica.Queda algo asi:<br /></div><p></p><p><br /><b><span style="font-family: courier;">no-pty ssh-ed25519 AAAAC3NzaC1....</span></b><br /></p><p></p><p></p><p>El problema es que perdés el prompt y bash completion, algo completamente irrelevante para un script.</p> <table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-_aX2kOs7ubI7l63R0_SHA5qRwo4Hn8JrHoLY09nHS5KCSYItoH1oSXK9qyBcxML1OTU8C9kwWeMKtdQHEpHeaxZzX4uJV_MpEzFeYCdD_F5iVcatp96pBZOaSNsPxIJ94Ca3NMK8IlIc_Rnq-gDd1VfI4qf8q6M7GqmSdxg1JlEZvWru9dARtCwpzOvD/s690/03_rbash_ok.png" style="margin-left: auto; margin-right: auto;"><img alt="rbash con no-tty en authorized_keys" border="0" data-original-height="58" data-original-width="690" height="54" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-_aX2kOs7ubI7l63R0_SHA5qRwo4Hn8JrHoLY09nHS5KCSYItoH1oSXK9qyBcxML1OTU8C9kwWeMKtdQHEpHeaxZzX4uJV_MpEzFeYCdD_F5iVcatp96pBZOaSNsPxIJ94Ca3NMK8IlIc_Rnq-gDd1VfI4qf8q6M7GqmSdxg1JlEZvWru9dARtCwpzOvD/w640-h54/03_rbash_ok.png" title="rbash con no-tty en authorized_keys" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">rbash con no-tty en authorized_keys<br /></td></tr></tbody></table><br /><p></p><p> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKKtHGwsPX6EdIsfnQgGcY2BN81cH-bM_7_F37btGPt3XZQhqCugr3QcPAdCVlDYsqz34Ydom3onQ3QQMP-XMMdMxPmBtlVh82cpH87EgX7diNtthcoIhIXSXQqzYjmTFF4RpfUz5C9eDysUFtyicWhEJTTIqoRKMV19MtIzSOCbQ_gowxrg0rV8wB8acX/s556/04_rbash_deny.png" style="margin-left: auto; margin-right: auto;"><img alt="no login" border="0" data-original-height="74" data-original-width="556" height="86" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKKtHGwsPX6EdIsfnQgGcY2BN81cH-bM_7_F37btGPt3XZQhqCugr3QcPAdCVlDYsqz34Ydom3onQ3QQMP-XMMdMxPmBtlVh82cpH87EgX7diNtthcoIhIXSXQqzYjmTFF4RpfUz5C9eDysUFtyicWhEJTTIqoRKMV19MtIzSOCbQ_gowxrg0rV8wB8acX/w640-h86/04_rbash_deny.png" title="no login" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">no login<br /></td></tr></tbody></table><br /><p></p><h2 style="text-align: left;">Mis reflexiones</h2><p> </p><h3 style="text-align: left;">Porque no password al azar <br /></h3><p>Se podría poner un password al
azar, pero al ser un password existente hay una increíblemente remota
posibilidad de que alguien le acierte. También que al azar sea un password en un diccionario. O que en el momento de la creación haya leak.<br /></p><p>Es mejor poner "!" antes que usar azar pues es un indicador visual y fácil de controlar de modo automático que luego no cambie la situación.<br /></p><p>Es mejor dejar solo "!" pues agrega que no haya ninguna posibilidad de login.</p><p><br /></p><h3 style="text-align: left;">Porque <strike>no</strike> <span style="font-family: courier;">ForceCommand <span class="il">rbash</span></span></h3><p><span class="il">Si la idea es que en ese equipo no haya ningún usuario remoto sin rbash, de acuerdo con </span><span class="il"><span style="font-family: courier;"><b>ForceCommand rbash</b></span></span><span class="il">. Pero eso implica que al menos a algún usuario hay que habilitarle que pueda ejecutar sudo, además de las reglas de sudoers.</span></p><p><span class="il"></span></p><p><span class="il">Me parece más sencillo configurar <span style="font-family: courier;"><b>no-pty</b></span> en </span><b><span style="font-family: courier;">.ssh/</span></b><b><span style="font-family: courier;">authorized_keys</span></b> para cada usuario a restringir.<br /></p><p><span class="il"></span></p><p><span class="il">Igual en este aspecto mi opinión no es tan fuerte como con el punto anterior. De hecho, mientras escribo esto, no puedo dejar de notar que <span style="font-family: courier;"><b>ForceCommand rbash</b></span></span> + <b><span style="font-family: courier;">sudo</span></b> responde más a la política de denegar todo y luego permitir de a uno, como que cambiaría de idea muy fácil... listo, ya cambié de idea.</p><p>Igual mi instinto algo me dice a favor de <span class="il"><span style="font-family: courier;"><b>no-pty</b></span></span>, por el lado de evitar una denegación de servicio. Si vuelvo a cambiar de idea, lo registraré.</p><p>Mi posición actual es, depende del perfil de uso del equipo, si es de uso general y hay que restringir a un usuario de servicio, <span class="il"><span style="font-family: courier;"><b>no-pty</b></span></span>, si nadie debería acceder salvo ciertas tareas de mantenimiento, <span class="il"> <span style="font-family: courier;"><b>ForceCommand rbash</b></span></span> + <b><span style="font-family: courier;">sudo.</span></b></p><h2 style="text-align: left;"> <br /></h2><h2 style="text-align: left;">Disclaimer</h2><p>No tomes este post como ninguna autoridad de cómo implementar correctamente rbash, no he investigado la parte de las variables de entorno ni sometido a pruebas exhaustivas.<br /></p><p> </p><p> </p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-60353432483242897982023-06-18T10:46:00.003-03:002023-07-09T11:25:10.746-03:00Aprovechando pantallas obsoletas: la idea<p>Desde hace rato que la acumulación de netbooks de 2GB y tablets con android 4.x me viene haciendo mal y el demonio interno me dice que aproveche al menos las pantallas, asi que me puse.</p><p>Mi contexto histórico relacionado: había incursionados hace muuuuucho tiempo en utilizar dual head mediante el uso de dos placas de video cuando tenían una sola salida. También había investigado, sin éxito, el usar una misma computadora con dos placas de video, dos mouses y dos teclados como si fueran dos. </p><p>Luego, intenté <a href="https://seguridad-agile.blogspot.com/2022/07/recuperacion-fallida-pantalla-bangho.html" target="_blank">nuevamente usar las pantallas peladas</a>, pero como hablan LVDS, quedó fuera de mi alcance.<br /></p><p>Luego, con éxito, <a href="https://seguridad-agile.blogspot.com/2020/12/para-trabajar-mas-comodo-y-aprovechar.html" target="_blank">usar varias máquinas a la vez</a>.<br /></p><p></p><p>Como siempre, empecé preparando un mensaje con preguntas, en este caso dirigido al chat de cybercirujas, que decía algo así como:</p><p><i>"Tengo un problema, aparte de la cara. El contexto es que querría usar esas notebooks pedorritas de 1 o 2gb RAM por sus pantallas, pero sin ejecutar nada más que linux base + xwindows. Por ejemplo para tener abierto en mi máquina principal un firefox con una cuenta de mail alternativa y visualizarlo en la notebook. Si además funciona el portapales, es un plus."</i></p><p></p><p>Como siempre, continué con la técnica de <a href="https://seguridad-agile.blogspot.com/2019/08/preguntar-bien-para-aprender.html" target="_blank">preguntar bien para aprender</a>, escribí un montón de mensajes alternativos y seguí pistas en Internet hasta que comprendí bien el problema y algunas posibles soluciones y esto es a lo que llegué, no voy a contar toda la historia porque la verdad es que no la recuerdo.</p><p>Comencemos por la topología y mis requerimientos, habiendo un nodo principal y uno o más secundarios.</p><p></p><h1 style="text-align: left;"> </h1><h1 style="text-align: left;">Topología</h1><h1 style="text-align: left;"><br /></h1><p style="text-align: center;"><span style="font-family: inherit;"><b>Principal ---> Secundarios</b></span><span style="font-family: inherit;"> </span><br /></p><p>La idea es ejecutar en Principal una aplicación y que se visualice en Secundario, esto es porque los secundarios pueden no tener la potencia o carecer del contexto. Es un plus mantener la interacción desde Principal, pues Secundario puede estar lejos del alcance o sin dispositivos de entrada.<br /></p><p></p><p>Con contexto me refiero a que puedo tener una VM que está conectada a una VPN, puedo mostrar el escritorio de esa VM en Secundario pero no puedo ejecutarlo ahí y menos tener la conexión a la VPN.</p><p> </p><p>Una manera de expresar esto es:</p><p> </p><p style="text-align: center;"><b>Interacción <span class="matching-text-highlight">-></span> Ejecución -> Visualización</b></p><p> </p><p>Lo que deseo es: <br /></p><p> </p><p style="text-align: center;"><b>Principal -> Principal -> Secundario </b></p><p></p><h1 style="text-align: left;"> </h1><h1 style="text-align: left;">Requerimientos</h1><h1 style="text-align: left;"> </h1><div style="text-align: left;"><ul style="text-align: left;"><li>Van con nombres para luego verlos en una tabla comparativa.</li></ul></div><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Incondicionales</h2><h2 style="text-align: left;"> </h2><ul style="text-align: left;"><li>Render Remoto: Usar la pantalla remota.<br /></li></ul><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Negociables</h2><h2 style="text-align: left;"> </h2><ul style="text-align: left;"><li>Input en Principal: que tome el teclado y el mouse de la principal.</li><li>Ejecución en Principal: el contexto de ejecución debe ser en Principal </li><li>Visibilidad Permanente: que independientemente de lo que haya en Principal, por ejemplo al cambiar de escritorio, se siga viendo. </li></ul><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Adicionales</h2><h2 style="text-align: left;"> </h2><ul style="text-align: left;"><li>Modo Render Aplicación: que se visualice una ventana en particular.<br /></li><li>No SSH a Principal: que no se ingresen credenciales del principal en el secundario.</li><li>Modo Render Total: que se muestre todo el desktop. Podría servir como un facilitador de navegación, pero si es el único modo es poco útil.</li><li>Integración: que haya integración con el display principal como si fuera un monitor más.</li></ul><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Transversal</h2><h2 style="text-align: left;"> </h2><p>Y existe un requerimiento adicional que es un plus:<br /></p><ul style="text-align: left;"><li>Autónomo: Sin interacción física con el equipo remoto, tal que el dispositivo puede estar en un lugar de incómodo acceso o sin periféricos de entrada.</li></ul><p></p><p></p><p></p><h1 style="text-align: left;"><br /></h1><h1 style="text-align: left;">Recursos disponibles</h1><h1 style="text-align: left;"><br /></h1><p></p><ul style="text-align: left;"><li>navegador con http: vendría a ser el más portable, pero siempre ocupa una ventana en Principal, se parece conceptualmente a lo que hice con <a href="https://seguridad-agile.blogspot.com/2020/05/xzoom-mejorado.html" target="_blank">xzoom</a> en el sentido que se toma algo que se está visualizando y se transmite, en el caso de xzoom a una ventana local.<br /></li><li>xwindows: es el más natural, pero implica que haya xwindows en los Secundarios, cosa que a veces puede ser dificultoso.</li><li>vnc: permite desde una máquina ver y potencialmente interactuar con otra. <br /></li><li>ssh: permite acceder de modo remoto y seguro y meter xwindows en un tunel.</li><li>x2x: permite con teclado y mouse saltar de un escritorio a otro remoto que tenga xwindows. <br /></li></ul><p></p><h1 style="text-align: left;"> </h1><h1 style="text-align: left;">Un poco de análisis</h1><h1 style="text-align: left;"><br /></h1><p>Para cumplir con Principal -> Principal -> Secundario, mi sueño sería que en Principal yo lance algo, aparezca en Secundario y pueda seguir interactuando desde Principal.</p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">x2x (Principal -> Secundario -> Secundario)</h2><h2 style="text-align: left;"> </h2><p>Usar x2x queda descartado pues la aplicación se ejecuta en Secundario y en mi caso en particular, como tengo tres monitores en L, el
escritorio remoto sólo se puede recorrer con esa misma forma en L.
Recuerdo hace un tiempo haber visto el código fuente de x2x a ver si
podía darme cuenta por donde tendría que investigarlo y me superó. Pero anotemos que podría servir para la interacción.<br /></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">VNC (Principal -> Secundario -> Secundario)</h2><h2 style="text-align: left;"> </h2><p>VNC queda descartado por la misma ejecución en Secundario. También anotemos que podría servir para la interacción.</p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Deskscreen y WEYLUS (Principal -> Principal -> Secundario)</h2><h2 style="text-align: left;"><br /></h2><p>En <a href="https://www.youtube.com/watch?v=EOzqhLPXLCY" target="_blank">un video</a> ví estas opciones. Usan el navegador del lado de Secundario.<br /></p><h3 style="text-align: left;"></h3><p>WEYLUS es la única opción que ofrece Integración, pero sólo con chipset Intel, el cual no tengo.<br /></p><p></p><p></p><p>Tienen como problema sólo mostrar lo que se está viendo, si te pasás a otro desktop, deja de visualizar. Se soluciona con "always on visible workspace", lo que no es ninguna solución pues el objetivo era que no ocupe pantalla en Principal. Si lo que te interesa es mostrar en Secundario, como por ejemplo para compartir con otras personas en una red local, te servirían.<br /></p><p></p><p>https://deskreen.com/lang-en <br /></p><p>https://github.com/H-M-H/Weylus</p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">ssh -X (Principal -> Secundario -> Principal)</h2><h2 style="text-align: left;"> </h2>Para
esto con conviene usarlo al revés, Secundario -> Principal ->
Secundario, con lo cual tenemos la ejecución en Principal y
visualización en Secundario, solo nos falta ver el asunto de la
interacción. No me gusta porque hace falta que el Secundario se
autentique frente al Principal y no es autónomo.<p></p><p></p><p></p><h1 style="text-align: left;"> </h1><h1 style="text-align: left;">La solución</h1><h1 style="text-align: left;"> </h1><div style="text-align: left;">Esos "descartado" de antes no eran definitivos y si hacemos unas combinaciones, tenemos algo que aunque un poco complicado de poner en marcha y utilizar, cumple bastante bien.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">La combinación es instalar o aprovechar el xwindows del Secundario. Desde Secundario con ssh -X abrir la aplicación y luego con x2x o VNC desde Principal interactuar. Por el bug de x2x, nos quedamos con VNC.</div><div style="text-align: left;"><span style="font-family: courier;"><br /></span></div><div style="text-align: left;"><b><span style="font-family: courier;">+----------------+ +--------------+<br /></span></b></div><div style="text-align: left;"><b><span style="font-family: courier;">| Principal +---VNC--> Secundario |</span></b></div><div style="text-align: left;"><b><span style="font-family: courier;">| +------------+ | | +----------+ |<br /></span></b></div><div style="text-align: left;"><b><span style="font-family: courier;">| | Aplicación <-- ssh -X --+ Terminal | |</span><span style="font-family: courier;"></span></b></div><div style="text-align: left;"><b><span style="font-family: courier;"></span><span style="font-family: courier;">| | | | | +----------+ |</span></b></div><div style="text-align: left;"><b><span style="font-family: courier;"></span><span style="font-family: courier;"></span><span style="font-family: courier;">| | | | | +--------+ |</span></b></div><div style="text-align: left;"><b><span style="font-family: courier;">| | +--xwindows---> render | |</span></b></div><div style="text-align: left;"><b><span style="font-family: courier;"></span></b><div style="text-align: left;"><b><span style="font-family: courier;"></span><span style="font-family: courier;"></span><span style="font-family: courier;">| | | | | +--------+ |</span></b></div></div><div style="text-align: left;"><div style="text-align: left;"><b><span style="font-family: courier;">| +------------+ | | |</span></b></div><b><span style="font-family: courier;">+----------------+ +--------------+</span></b> <br /></div><div style="text-align: left;"></div><div style="text-align: left;"></div><div style="text-align: left;"></div><h1 style="text-align: left;"> </h1><h1 style="text-align: left;">Comparativa</h1><h1 style="text-align: left;"><br /></h1><table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: medium none; font-family: Arial; font-size: 10pt; table-layout: fixed; width: 0px;"><colgroup><col width="140"></col><col width="100"></col><col width="100"></col><col width="100"></col><col width="100"></col></colgroup><tbody><tr style="height: 21px;"><td style="border-bottom: 1px solid #000000; border-color: rgb(0, 0, 0); border-left: 1px solid #000000; border-right: 1px solid #000000; border-style: solid; border-top: 1px solid #000000; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;"><br /></td><td data-sheets-value="{"1":2,"2":"Deskscreen"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Deskscreen</td><td data-sheets-value="{"1":2,"2":"WEYLUS"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">WEYLUS</td><td data-sheets-value="{"1":2,"2":"x2x"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">x2x</td><td data-sheets-value="{"1":2,"2":"vnc + ssh -X"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">vnc + ssh -X</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"render remoto"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">render remoto</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"input en principal"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">input en principal</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"ejecución principal"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">ejecución principal</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"no"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">no</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"visibilidad permanente"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">visibilidad permanente</td><td data-sheets-value="{"1":2,"2":"no"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">no</td><td data-sheets-value="{"1":2,"2":"no"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">no</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"render aplicación"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">render aplicación</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"no"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">no</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"no ssh a principal"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">no ssh a principal</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"no"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">no</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"render total"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">render total</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"si"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">si</td><td data-sheets-value="{"1":2,"2":"no"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">no</td><td data-sheets-value="{"1":2,"2":"no"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">no</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"integración"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">integración</td><td data-sheets-value="{"1":2,"2":"no"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">no</td><td data-sheets-value="{"1":2,"2":"potencial"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">potencial</td><td data-sheets-value="{"1":2,"2":"falla por \"L\""}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">falla por "L"</td><td data-sheets-value="{"1":2,"2":"no"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">no</td></tr></tbody></table><p><style type="text/css">td {border: 1px solid #cccccc;}br {mso-data-placement:same-cell;}</style></p><p><br /></p>Esto sigue en <a href="https://seguridad-agile.blogspot.com/2023/07/aprovechando-pantallas-obsoletas-la.html" target="_blank">la implementación</a><br /><p><br /></p><p><br /></p><p><br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-81244671141571951902023-04-14T17:02:00.000-03:002023-04-14T17:02:55.348-03:00Preguntar bien para trabajar<p>Este artículo es el resultado de la aplicación del concepto, técnica, modalidad o como lo quieras llamar que había registrado antes, en ese momento fue ponerle una descripción a lo que hacía de modo intuitivo y medio inconsciente.<br /></p><p>Tras todos estos años, ya de modo conciente de aplicarlo, también lo he extendido desde el aprendizaje al trabajo y hace unos pocos días tuve un evento muy ilustrativo que me disparó escribir esto como actualización.<br /></p><p> </p><p>Lo que había dicho <a href="https://seguridad-agile.blogspot.com/2019/08/preguntar-bien-para-aprender.html " target="_blank">en la otra oportunidad</a> se podría resumir así:</p><p></p><p><b><i>Estoy con un problema, hago una pregunta y antes de enviarla, me pongo en el lugar de quien podría contestarla y me imagino que me va a pedir que complete. Lo hago, vuelvo a mirar y cuando ya no puedo hacer nada más, lo envío.</i></b></p><p></p><p>Lo interesante es que cerca de tres de cada cuatro veces, no necesito enviar pues el problema queda resuelto.</p><p> </p><p>Lo último que ha ocurrido, está relacionado algo que no es de estudio
o hobby pero tampoco es de trabajo, llamemoslo de "responsabilidad
profesional", mi colaboración el el proyecto CIAA.</p><p>En pocas
palabras por si no conocés, es un proyecto de Open Source Hardware y
Software (<a href="https://seguridad-agile.blogspot.com/2023/04/open-de-todo.html" target="_blank">Open de Todo</a>) en el cual vengo
colaborando, últimamente en arreglar el sitio cuando algo falla.</p><p>La
última falla fue por una migración automática que produjo una catarata
de dependencias. Estando yo con poco tiempo y sabiendo muy poco de la
aplicación solicité ayuda en <a href="https://groups.google.com/g/embebidos32/c/U9HImmT7lCY" target="_blank">embebidos</a>.</p><p></p><p>Fuí
muy escueto a propósito, estaba filtrando, buscando más alguien que
supiera de antemano que alguna persona solidaria que me ayudara a
investigar, no quería pasarle el muerto a algiuen en mi misma situación.<br /></p><p>Tres minutos más tarde una persona me contestó en privado, Daniel C.B.<br /></p><p>En
mi borrador de mail primero expliqué qué había ocurrido y cómo había
roto, en este caso la esencia del problema era que php había sido
actualizado, entonces tiraba unos deprecated.<br /></p><p>Cómo había ido
solucionando algunos aspectos, armé un listado tipo problema/solución
para ir relatándole lo ya hecho y el bloqueo actual.</p><p></p><p>Luego
noté que había estado aplicando de modo desordenado los pasos de
migración [*]. Por completitud entonces comprobé los había hecho y
completé los faltantes, que igual, como sospechaba y por eso no los
había respetado mucho, no hacían mucha diferencia.</p><p></p><p><br /></p><p>Me
puse entonces en el lugar de la persona y pensé, si le paso esto como
está, aún con este lindo mail, lo mato. Evalué que para poder hacer un
mail mejor, me iba a llevar el mismo o más tiempo que quizás arreglarlo.
No estamos hablando de veinte minutos, de hecho me llevó varias horas y
un esfuerzo mental considerable.</p><p>Pero, magia, otra vez, al estar
conforme con las dependencias del mail, el problema ya estaba
solucionado... en su mayor parte, ahora quedan algunos detalles de
terminación.</p><p>Pasamos de la perspectiva de "tomá este sitio que no
se puede exponer a Internet" a "¿te podrías fijar que parece que quedó
un plugin sin instalar o mal configurado? </p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Lo nuevo</h2><h2 style="text-align: left;"><br /></h2><p></p><p>Durante todos estos años extendí la técnica debido a las cadenas de mail de trabajo. Estas suelen ir ampliando su audiencia ("sumo a tal que se encarga de ese aspecto") y a veces se extienden durante varios días sino semanas.</p><p><br /></p><p>Esto provoca dos cosas: que hay gente nueva en la conversación a la que se le obliga a leer toda la cadena con sus idas y vueltas. Las otras personas, si ha pasado algún tiempo y como todo el mundo lleva siempre varios temas adelante, o no recuerdan o les cuesta.</p><p> </p><p></p><p>Entonces, una práctica que me autoimpongo y recomiendo es cada tanto hacer un resumen e incluso, borrar las partes superfluas de la conversación del cuerpo principal, sí dejarla por si tengo un error de interpretación que pueda ser detectado.</p><p>Quedan entonces uno o dos párrafos diciendo el problema es tal, tal persona sugirió esta causa, la otra otra, tal esta solución y estamos más o menos así.<br /></p><p><br /></p><p>Como ejemplo tengo reciente que gestionando una vulnerabilidad ocurrió esto:</p><p></p><p>Se estaba reportando que estaba TLS 1.1 activo y había LUCKY13. El problema es que al revisar el sistema, TLS 1.1 ya no estaba activo y LUCKY13 era potencial debido a unas ciphersuites débiles, que de todos modos eran un defecto por si mismo.</p><p>Habían personas que retomaban la cadena con el reporte original, lo cual me producía increibles confusiones.<br /></p><p></p><p>Entonces, el reporte actualizado, es: hay ciphersuites débiles, su eliminación producirán como efecto colateral la desaparición del potencial LUCKY13<br /></p>Lo que agrego en esta oportunidad es:<p></p><p><b><i>No asumir que todos estamos prestando la misma atención a la conversación ni sabemos lo mismo, hacer frecuentes resúmenes y actualizaciones para no retroceder ni confundir.</i></b><br /></p><p><br /></p><p>Nota:</p><p><br /></p><p>[*] No es el tema, pero esto me recuerda algo que ocurrió en uno de los cursos que doy. Usamos una VM con unos pasos a seguir en la instalación. Uno de los alumnos en lugar de seguir los pasos next->next->next para configurarla e instalarla se buscó algún video en internet y por supuesto luego no le anduvo, argumentó que "Admito que <span class="il">me</span> salí del manual porque no lo sentí tan practico", lo cual, considerando que cerca de 60 personas lo habían transitado previamente y que cada vez está más refinado, es un tanto subjetivo.<br /></p><p>Eh, pero es justo lo que vos hiciste, me vas a decir, ¿por qué no respetaste a rajatabla el procedimiento de migración?</p><p>Bueno, la verdad es que en uno de los intentos sí lo había respetado, pero el problema es que procedimiento contempla pasar de una versión a la
siguiente, no como era este el caso de... no voy a decir cuántas, muchas... demasiadas...<br /></p><p>Quizás el paso más crítico que no respeté, ni lo voy a hacer, es leer el historial de cambios, no me alcanza la vida. Usé mi instinto y sumándole la metodología expuesta, funcionó. <br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-79404077726481682842023-04-12T11:44:00.001-03:002023-04-12T11:44:25.027-03:00Open de todo<p>Estas son unas reflexiones a raiz de alguna conversación parcial en el grupo de <a href="https://seguridad-agile.blogspot.com/search/label/cybercirujeo" target="_blank">cybercirujas</a>, cosas que converso acaloradamente conmigo mismo. Por un lado comparto, por el otro registro para mí mismo dentro de unos años. No pretenden ser muy completas ni balanceadas, estoy apuntando más bien a open cores y open hardware y asumo que quien lea mayormente conoce el tema.<br /></p><p></p><p><br /></p><p>Empiezo con varias modalidades y áreas que irán creciendo:<br /></p><p></p><ul><li>Gratis <br /></li><li>Free</li><li>Open/Libre</li><li>Pago</li></ul><p></p><p></p><ul style="text-align: left;"><li>Software</li><li>Hardware</li></ul><p></p><p></p><p>Hay mucho "open", que a veces se confunde con "free", el cuál por su significado en inglés se confunde "libre" con "gratis".</p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Gratis/Licenciado</h2><h2 style="text-align: left;"> </h2><p></p><p>Empecemos con "gratis", sabiendo que no hay (casi) nada gratis. Software gratis es el que uno no paga. ¿Son las herramientas como Vivado, Keil, MCUxpresso gratis? Si, aunque nadie las llama "freeware". Yo las llamaría "licenciadas", o sea, no te cobran pero es igual a haberlas comprado, o sea, te las venden por $0.</p><p><br /></p><p>No voy a ahondar en los aspectos en los cuales para los proveedores de estas herramientas les sacan provecho pese a ser $0, pero así rapidito podríamos mencionar que sirven para que la gente las use y sí pague por versiones más completas, librerías, servicios, cores y hardware real.</p><p>También existe el hardware gratuito, lo que pasa es que es muy muy escaso por su naturaleza no copiable sin costo.</p><p>Están las muestras gratis y los kits que se sortean o se reparten a ciertos proyectos, conozco algunos casos que comento para mostrar a quienes no conocen nada que si uno está
atento, puede conseguir algo cada tanto. Hay poco link a artículos pues los
tengo todos a medio hacer:<br /></p><p><br /></p><ul style="text-align: left;"><li>A los asistentes de un workshop reciente de diseño de sistema embebido les regalaron una <b>Raspberry Pi RP2040</b>.</li><li>A los asistentes de <a href="https://seguridad-agile.blogspot.com/2019/04/python-productivity-for-zynq.html" target="_blank">un tutorial de uso de ZYNQ con Python</a> nos intentaron regalar unas <b>PYNQ-Z2</b> pero los organizadores no sabían cómo funciona la aduana por acá y no hubo manera razonable de obtenerlos.</li><li>A los que llenamos una encuesta de ya ni recuerdo qué, nos regalaron una <b>MiMXRT-1020 EVK</b> (te lo debo).</li><li>A los que asistimos a un webinar de SRAM PUF de nos regalaron una <b>STM32L4A6</b> (te lo debo).</li><li>A los que asistimos a una charla de microvisores, estoy por recibir una placa apropiada para probarlos (te lo debo).</li><li>Si tenés un proyecto Arduino que bastante gente use, pudiste haber recibido una placa <a href="https://sites.arduino.cc/unor4" target="_blank">Arduino UNO R4</a> </li><li>Me han contado que muchos fabricantes te mandan unas muestritas pequeñas de componentes y que hace algunos años Argentina había sido banneada por que empresas locales pedían mediante muchas personas modo proxy para sus productos finales.<br /></li></ul><p><br /></p><p>El nicho de las muestras gratuitas se extiende bastante, pero contar con ello para algo por fuera de pruebas e investigaciones, me parece que es como llevarse el shampú del hotel... no escala.</p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Libre/Open</h2><h2 style="text-align: left;"><br /></h2><p></p><p>Los pongo juntos pues son extremandamente parecidos, es algo con lo que podés hacer lo que quieras, podés ver el código fuente, ya sea un programa, un diseño de hardware o un core, modificarlo y luego según el detalle de la licencia específica (gpl, apache, lo que sea), redistribuirlo, venderlo.<br /></p><p>Puede ser open:<br /></p><p></p><ul style="text-align: left;"><li>Software</li><ul><li>Sistema operativo</li><li>Programa</li><li>Herramienta</li><li>Librería <br /></li></ul><li>BIOS/Firmware</li><ul><li>boot loader <br /></li></ul><li>Core</li><ul><li>CPU</li><li>Controlador de memoria</li><li>Acelerador criptográfico <br /></li></ul><li>Hardware</li><ul><li>Motherboard <br /></li><li>Placa</li><ul><li>de red<br /></li></ul><li>Módulo</li><ul><li>Adaptador USB-Ethernet<br /></li></ul></ul></ul><p>La diferencia fundamental respeco a Gratis/Licenciado es que podés ver el código fuente, modificarlo, lo que sea dependiendo de la licencia específica.<br /></p><p>Lo más correcto es llamarlos "Open Source XXX", que distingue claramente entre verle las tripas y tenerlo funcionando. Esto es tanto en hardware como en software, puede ser muy gratuito y open tener, pero ejecutar requiere hardware y electricidad (y otro montón de cosas que uno no presta atención como espacio, ventilación, seguridad, conectividad, limpieza) que no son gratis para nada.</p><p>Los modelos de Machine Learning pueden ser muy Open Source, pero entrenar uno te puede salir un ojo de la cara en hardware/tiempo/electricidad.<br /></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Todos contra todos</h2><h2 style="text-align: left;"> </h2><p>¿Algo pago puede ser open?</p><p>El primer ejemplo que me viene a la cabeza es todo lo del proyecto CIAA que es Open Source Hardware y Firmware, pero tenés que pagar las placas. La sutileza es que no tenés que pagar para usar, modificar o fabricar los diseños, sólo pagás el producto terminado o los componentes y el uso de herramientas y trabajo si vas a fabricarlo vos. </p><p style="text-align: center;"><br /></p><p>El hardware tiene al menos dos niveles, siendo "cores" lo que hay dentro de un chip y "hardware" lo que une los chips: </p><p></p><p>El diseño del chip, lo que va ahí dentro, no voy a decir que cualquiera
puede hacerlo, pero si voy a decir que fabricar ese diseño es
infernalmente caro.</p><p style="text-align: center;">Open Source Core o Silicon es el diseño del chip, no su fabricación. <br /></p><p>El de armar una placa que dependiendo de la tecnología es algo que uno mismo puede hacer o mandar a hacer por un precio relativamente accesible.<br /></p><p></p><p style="text-align: center;"></p><p style="text-align: center;"> Open Source Hardware es el diseño del hardware, no el hardware físico.</p><p style="text-align: center;"></p><p></p><p>FPGA te permite instanciar en Hardware que puede ser Open Source o no (ciaa-fpga o iceStick respectivamente), Cores que pueden ser Open, como una CPU RISC-V en un SOC icicle en las anteriores () o no como un Microblaze (que es Gratis/Licenciado) en una placa de Xilinx (que no es ni Open ni nada).<br /></p><p>Con una FPGA más poderosa, con una CPU RISC-V apropiada y otros cores adicionales como MMU, timers, controlador de interrupciones, podés ejecutar un Linux, que es Open Source Software.</p><p>Una placa del proyecto CIAA que utilice un SoC RISC-V o POWER para correr un Linux, sería el ejemplo más Open que puedo imaginar.</p><p><br /></p><p>¿Es posible una computadora completamente Open Source? No sé, no creo, ¿qué pasa con la memoria? ¿con los componentes analógicos?</p><p> </p><p>Una especie de resumen: <br /></p><p></p><table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: medium none; font-family: Arial; font-size: 10pt; table-layout: fixed; width: 0px;"><colgroup><col width="100"></col><col width="133"></col><col width="100"></col><col width="171"></col><col width="118"></col></colgroup><tbody><tr style="height: 21px;"><td style="border-bottom: 1px solid #000000; border-color: rgb(0, 0, 0); border-left: 1px solid #000000; border-right: 1px solid #000000; border-style: solid; border-top: 1px solid #000000; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;"><br /></td><td data-sheets-value="{"1":2,"2":"software"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">software</td><td data-sheets-value="{"1":2,"2":"bios"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">bios</td><td data-sheets-value="{"1":2,"2":"cores"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">cores</td><td data-sheets-value="{"1":2,"2":"hardware"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">hardware</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"gratis"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">gratis</td><td data-sheets-value="{"1":2,"2":"linux"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">linux</td><td data-sheets-value="{"1":2,"2":"libreboot"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">libreboot</td><td style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">open cores<br /></td><td data-sheets-value="{"1":2,"2":"muestras"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">muestras</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"open/libre"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">open/libre</td><td data-sheets-value="{"1":2,"2":"linux"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">linux</td><td data-sheets-value="{"1":2,"2":"libreboot"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">libreboot</td><td data-sheets-value="{"1":2,"2":"risk-v"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">risk-v</td><td data-sheets-value="{"1":2,"2":"el proyecto ciaa"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">el proyecto ciaa</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"licenciado"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">licenciado</td><td data-sheets-value="{"1":2,"2":"vivado"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">vivado</td><td data-sheets-value="{"1":2,"2":"???"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">???</td><td data-sheets-value="{"1":2,"2":"los que vienen con vivado"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">los que vienen con vivado</td><td data-sheets-value="{"1":2,"2":"???"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">???</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"cerrado"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">cerrado</td><td data-sheets-value="{"1":2,"2":"windows"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">windows</td><td data-sheets-value="{"1":2,"2":"ami bios"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">ami bios</td><td data-sheets-value="{"1":2,"2":"arm"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">arm</td><td data-sheets-value="{"1":2,"2":"nxp"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">nxp</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"pago"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">pago</td><td data-sheets-value="{"1":2,"2":"windows y vivado"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">windows y vivado</td><td data-sheets-value="{"1":2,"2":"am bios"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">ami bios</td><td data-sheets-value="{"1":2,"2":"arm"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">arm</td><td data-sheets-value="{"1":2,"2":"nxp"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; vertical-align: bottom;">nxp</td></tr></tbody></table><p><style type="text/css">td {border: 1px solid #cccccc;}br {mso-data-placement:same-cell;}</style></p><p></p><p><br /></p><p><br /></p><p>Algunos links interesantes<br /></p><p> </p><p><a href="https://libreboot.org/ " target="_blank">https://libreboot.org/ </a><br /></p><p><a href="https://lowrisc.org/open-silicon/" target="_blank">https://lowrisc.org/open-silicon/</a></p><p></p><p><a href="https://www.proyecto-ciaa.com.ar/" target="_blank">https://www.proyecto-ciaa.com.ar/</a></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-26251822889567401042023-03-08T09:05:00.005-03:002024-01-29T12:49:16.930-03:00Cyberciruja 2023<p></p><p>Acompañando y de algún modo continuando unos artículos previos de una
mezcla de forense con cyberciruja, elaboro estas reflexiones
actualizadas.</p><p></p><p>La actividad cyberciruja es aparentemente sencilla, consiste en estar atento a hallar en la basura equipamiento recuperable. Esta basura puede ser la mera calle, alguien que avisa "en mi trabajo/familia" van a tirar tal cosa.<br /></p><p></p><p>Yo he sido siempre parcialmente cyberciruja y recientemente me uní a un grupo cuya interacción me ha llevado a conclusiones parecidas y extendidas a lo que había llegado en <a href="https://seguridad-agile.blogspot.com/2015/03/wipe.html" target="_blank">Wipe</a> relativo a regalar cosas.<br /></p><p></p><p style="text-align: center;">No es fácil y puede ser antieconómico regalar cosas.<br /></p><p></p><p></p><p>Tras unos meses en el grupo hallé un cierto comportamiento recurrente. Se han ofrecido cosas
que si alguien hubiese encontrado en la calle hubiese dicho "guau! qué
bueno! no entiendo por qué tiran esto, ...." y probablemente levantado, sin generar ningún interés.<br /></p><p>Luego, tengo un TV no smart de 40 pulgadas víctima de un <a href="https://seguridad-agile.blogspot.com/2019/03/jugando-con-los-rayos-0-intro.html" target="_blank">rayo</a>,
es muy probable que la pantalla esté intacta. Si lo dejo en la vereda y
aviso, según mensajes previos de piezas equivalentes, "uh, qué pena que
no estoy por ahí", debería ser muy codiciado, pero lo ofrecí y nadie lo
quiso.</p><p>Hay varias otras cosas registradas en <a href="https://seguridad-agile.blogspot.com/p/material-cyberciruja.html">Material Cyberciruja</a> con el estado actualizado.<br /></p><p></p><p>¿Será que la esencia de la experiencia cyberciruja no es el objeto en sí
sino el encontrarlo en la basura? ¿Será que encontrarlo en la basura lo
anonimiza sin generar relación u obligación con quién lo ha tirado?
¿Será que al recibirlo se genera algún tipo de deuda y al encontrarlo
tras haber sido irresponsablemente abandonado la deuda es de quien lo
tiró y de algún modo al recuperarlo se logra una satisfacción de índole social/ecológica?</p><p>¿Qué pesa más, estos aspectos o lo económico?</p><p>Analizando mi propia experiencia, he hallado tirado en el centro algo raqueable de comunicaciones que no sé que es y me lo he traido a casa pese
a que alguien se le paró encima y lo deformó y usa una fuente de 48v y
la verdad no me sirve para nada más que haberlo abierto y estudiado 15
minutos, quizás le pueda sacar unos chips fpga algún dia... Pero si me
lo hubieran ofrecido, habría pensado: "¿voy a tener tiempo para
dedicarle?", muy difícilmente lo hubiera aceptado.</p><p> </p><p> </p><p>Actualización 2024/01/29: ver https://seguridad-agile.blogspot.com/2024/01/analisis-de-entrega-de-material.html <br /></p><p></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Aspectos de seguridad</h2><h2 style="text-align: left;"> </h2><p></p><p>Eh amigo, entiendo que este blog es más bien técnico y por el nombre probablemente algo de seguridad y aunque lo del cybercirujéo es técnico, hasta ahora todo lo que escribiste no es ni muy técnico ni muy de seguridad!</p><p></p><p>Ok, veamos los aspectos de seguridad...</p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Aspecto forense y la confidencialidad. </h3><h3 style="text-align: left;"> <br /></h3><p>En el grupo alguien necesitaba discos IDE
chicos, yo tenía al menos cuatro, pero no sabía que tenían adentro, ni
siquiera si eran míos los datos. No se puede dar equipamiento con
memoria persistente sin antes sanitizarla.</p><p>Es por ello que en el
trabajo no consigo que me cedan nada obsoleto de comunicaciones, estos
equipos son destruidos por empresas certificadas por normativa.</p><p>Volviendo a los discos, al no tener mother con IDE tuve que usar un adaptador USB-IDE, pero no funcionó con ningúno. Probé con otro que tiene el conector combinado IDE/Power y sólo era compatible con dos. Les hice </p><p><br /></p><p><span style="font-family: courier;">sudo dd if=/dev/zero of=/dev/hdc</span><br /></p><p> </p><p>¿Porqué /dev/zero y no "borrado forense multipass" o /dev/urandom? Pues para los ataques posibles para los mortales comunes con una pasada alcanza, hace falta equipamiento muy caro, casi diría que es medio mito el recuperar algo.<br /></p><p>Los otros dos no los puedo dar hasta poder escribirles...</p><p></p><p></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Ingeniería Social</h3><h3 style="text-align: left;"> </h3><p></p><p></p><p></p><p>¿Será que el objeto "regalado" vale menos que el "ganado"?</p><p>Alguien dijo algo tipo "el regalo de algún modo te tiene que costar",
de acuerdo. ¿qué sería entonces cuando en lugar de tirar algo a la
basura, lo ofrecés'. Evidentemente no prima "me cuesta", sino el alivio
de no tirarlo, en realidad sería "me hacés el favor de aceptarme esto
pues me conflictúa tirarlo?".</p><p>De hecho, las empresas hacen donaciones diversas pero movidas por el retorno, que puede ser reducción de impuestos o publicidad.<br /></p><p></p><p>Tambien está la protección ante la ingeniería social, uno sospecha un engaño. Un pariente de un amigo que era docente de la Facultad de Psicología
de la UBA hizo un experimento con sus alumnos. Se pusieron en la puerta y
ofrecieron billetes de 10 pesos a cambio de 7 pesos y nadie aceptó. <br /></p><p>Yo no tengo para nada estos mecanismos, ofrecieron un equipo que tiene una FPGA adentro (otro día otra entrada), un thinclient (otro día otra entrada) y un lector de tarjetas (otro día otra entrada) y los acepté sin dudar.</p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Hardware Security Live Cycle</h3><p> </p><p>Esto no tiene que ver con la idea principal de la nota, pero recordá que habías reclamado por el aspecto de seguridad del hardware. Dicen los que saben que la cadena de suministro del hardware es:</p><ul style="text-align: left;"><li>IP Owner/fábrica</li><li>Ensamblado del PCB</li><li>Integración del sistema</li><li>Usuario final</li><li>Reciclador/basura<br /></li></ul><p>Y que las principales amenazas de seguridad al hardware son:</p><p></p><ul style="text-align: left;"><li>Remarcación, cambiarle la especificación de hogareño a industrial.</li><li>Clonado, una empresa copia el producto de otra.</li><li>Con defectos, una pieza no pasa el control de calidad y se vende igual.<br /></li><li>Sobreproducción, la fábrica hace más componentes que los acordados y los vende por su lado.<br /></li><li>Reciclado, que consiste en usar como nuevos componentes resultantes del fin del ciclo de vida anterior. <br /></li></ul><p>El cyberciruja de algún modo participa de ambas últimas, no de mala fé, no intenta usar o vender componentes recuperados como si fueran nuevos, pero en términos de safety (la seguridad no de la información, "security", sino la del mundo físico) el usar componentes rescatados, ya sea por el uso previo o por la técnica de recuperación, atenta contra las probabilidades de que el sistema no falle. <br /></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Ideas finales</h2><h2 style="text-align: left;"> </h2><p>¿Puede ser que lo que descarta un cyberciruja, al menos instintivamente, sea visto por los demás cybercirujas como algo que ya no puede ser recuperado?<br /></p><p></p><p></p><p>Actualizando mi estado cyberciruja actual, pienso que:<br /><br />Me
parece que es ineficiente dedicarle tantas horas de esfuerzo a
recuperar un equipo, esas horas de trabajo generarían más valor en un
trabajo renumerado.</p><p><br />En términos de conciencia social, seguramente sería más productivo ir a ayudar en una villa a implementar o corregir en los tendidos cloacales o de suministro de agua o electricidad. O ayudar a personas en condición de calle. </p><p></p><p></p><p><br /></p><p> </p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-64865391995187395012023-03-06T14:24:00.001-03:002023-03-06T14:24:20.975-03:00VirtualBox con Secure Boot<p>Hago esta nota más para no tener que buscar y recordar. Tomé todo de [1] y [2] y le pongo un poco de mi sabor, pues tengo mezcla con otro tema. De paso queda en spanish.<br /></p><p><br /></p><p>Tengo una máquina en modo dual boot con Windows 10 y bitlocker por un lado y Ubuntu 22 por el otro. En Windows 10, aparentemente por bitlocker, las virtuales con VirtualBox cada tanto le hacen tirar un BSOD. Mitiga un poco bajar en Execution Cap (de la virtual a usar, Settings -> System -> Processor -> Execution Cap) hasta el piso de lo verde, evitar hacer operaciones intensivas de disco y darle mucha memoria para que evite swappear, pero no alcanza, no puedo tener un BSOD en medio de una charla o taller.<br /></p><p></p><p></p><p>Cuando instalé VirtualBox en Ubuntu, me encontré con un diálogo que nunca había visto, debido a que tiene activado Secure Boot.</p><p>No tomé nota bien de qué ofrecía o pedía, algo de una clave para UEFI o similar. Le dije que no, probablemente cancelé cerrando la terminal pues no me dejaba de otra manera. Luego, aun desinstalando y volviendo a instalar no volvió a ofrecerlo, así que no pude documentar.<br /></p><p> </p><p>Como efecto colateral me hizo reingresar la key de bitlocker al reiniciar, eso es, tras arruinarme el grub, de ahí en más, arranca directo con Windows.</p><p>Esto no es gran problema, cuando quiero arrancar con linux invoco el menú de boot del firmware que reconoce la partición UEFI Ubuntu, con eso se carga el grub y de ahí Ubuntu o si quisiera Windows.</p><p><br /></p><p>Yendo a lo importante, al intentar ejecutar VirtualBox falla con un mensaje parecido a</p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;">modprobe vboxdrv failed. Please use 'dmesg' to find out why.</span><br /> </p><p>dmesg dice:</p><p> </p><p></p><p><span style="font-family: courier;">kernel: Lockdown: modprobe: unsigned module loading is restricted; see man kernel_lockdown.7</span><br /></p><p> </p><p>Buscando en internet llegué, tras varios artículos y respuestas diciendo "desactivá Secure Boot", que estupidéz, a uno que aunque bastante viejito es correcto.</p><p>Lo que dice es que si tenés Secure Boot, el kernel no te va a dejar insertar módulos que no estén firmados y brinda una manera de firmarlos. No voy a intentar explicar el detalle por que tengo una intuición pero no claridad.</p><p>Mi intuición es, para que un módulo esté firmado, hay que hacerlo con un secreto. Ese secreto hay que cargarlo en alguna zona protegida.<br /></p><p> </p><p>Esto genera el secreto:<br /></p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;">$ openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj "/CN=VBox Cert/" <br /></span></p><p></p><p></p><p></p><p></p><p> </p><p>Esto firma el módulo con el secreto:</p><p></p><p></p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;">$ sudo /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 ./MOK.priv ./MOK.der $(modinfo -n vboxdrv)</span> <br /></p><p> </p><p>En mi caso la expansión es:</p><p></p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;">$ sudo /usr/src/linux-headers-5.15.0-48-generic/scripts/sign-file sha256 ./MOK.priv ./MOK.der /lib/modules/5.15.0-48-generic/updates/dkms/vboxdrv.ko</span><br /></p><p> </p><p>Lo mismo para hay que hacer para <b><span style="font-family: courier;">vboxnetflt</span></b>.<br /></p><p>Esto inicia el proceso de guardar el secreto en la zona protegida, es registrar la key con Secure Boot, te pide un secreto que establece la cadena de confianza rumbo al siguiente paso:<br /></p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;">$ sudo mokutil --import MOK.der</span><br /></p><p> </p><p>Reiniciás: <br /></p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;">$ shutdown -r now</span></p><p> </p><p>Todo lo que sigue es la finalización del proceso de guardar el secreto. <br /></p><p>Te aparecen unas pantallas ascii azul con un menú sencillo, en este elegís qué vas a hacer </p><p> </p><p style="text-align: center;"><span style="font-family: courier;"><span style="color: white;"><span style="background-color: #2b00fe;">Perform MOK management</span></span></span> <br /></p><p style="text-align: center;"><span style="color: white;"><span style="background-color: #2b00fe;"><span style="font-family: courier;">+-----------------------+<br />| Continue Boot |<br />|<span style="background-color: black;"> Enroll MOK </span>|<br />| Enroll key from disk |<br />| Enroll hash from disk |<br />+-----------------------+</span></span></span> <br /></p><p> </p><p>Te permite ver el secreto a registrar o continuar, continuar<br /></p><p><br /></p><p style="text-align: center;"><span style="font-family: courier;"><span style="color: white;"><span style="background-color: #2b00fe;">[Enroll MOK]</span></span></span></p><p style="text-align: center;"><span style="color: white;"><span style="background-color: #2b00fe;"><span style="font-family: courier;">+------------+<br />| View key 0 |<br />|<span style="background-color: black;"> Continue </span>|<br />+------------+</span></span></span></p><p> </p><p>¿Está usted seguro?</p><p> </p><p></p><p style="text-align: center;"><span style="font-family: courier;"><span style="color: white;"><span style="background-color: #2b00fe;">Enroll the key(s)?</span></span></span> <br /></p><p style="text-align: center;"><span style="color: white;"><span style="background-color: #2b00fe;"><span style="font-family: courier;">+---+<br />|No |<br />|<span style="background-color: black;">Yes</span>|<br />+---+</span></span></span></p><p> </p><p>Te pide el password que ingresaste previamente:</p><p><br /></p><p style="text-align: center;"><span style="font-family: courier;"><span style="color: white;"><span style="background-color: #2b00fe;">Enroll the key(s)?</span></span></span><br /></p><p style="text-align: center;"><span style="color: white;"><span style="background-color: #2b00fe;"><span style="font-family: courier;">+-------------------+<br />| Password: |<br />+-------------------+</span></span></span> <br /></p><p style="text-align: left;"> </p><p style="text-align: left;">Listo</p><p style="text-align: left;"> </p><p style="text-align: left;"></p><p style="text-align: center;"><span style="font-family: courier;"><span style="color: white;"><span style="background-color: #2b00fe;">The system must now be rebooted</span></span></span><br /></p><p style="text-align: center;"><span style="color: white;"><span style="background-color: #2b00fe;"><span style="font-family: courier;">+--+<br />|<span style="background-color: black;">OK</span>|<br />+--+</span></span></span> <br /></p><p> <br /></p><p>Con esto se puede comprobar si está enrolado: <br /></p><p><span style="font-family: courier;"> </span></p><p><span style="font-family: courier;">$ mokutil --test-key MOK.der<br />MOK.der is already enrolled<br /></span> </p><p>Con esto listás las keys:</p><p> </p><p><span style="font-family: courier;">$ mokutil --list-enrolled | grep -e "\[key" -e Issuer</span></p><p><span style="font-family: courier;"><br />[key 1]<br /> Issuer: C=GB, ST=Isle of Man, L=Douglas, <br /> O=Canonical Ltd.,<br /> CN=Canonical Ltd. Master Certificate Authority<br />[key 2]<br /> Issuer: CN=mint Secure Boot Module Signature key<br />[key 3]<br /> Issuer: CN=VBox Cert</span><br /><br /></p><p></p><br /><p><br /></p><p></p><p>Ese MOK.priv lo podés borrar del sistema tras resguardarlo, por ejemplo dentro del mismo keepass donde guardás las otras claves, en el campo de comentario. Al DER lo pasás antes a ascii con base64.<br /></p><p></p><br /><p></p><p><br /></p><p><br /></p><p>[1] https://askubuntu.com/questions/760671/could-not-load-vboxdrv-after-upgrade-to-ubuntu-16-04-and-i-want-to-keep-secur<br /></p><p>[2] https://sourceware.org/systemtap/wiki/SecureBoot</p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-14838384962368823362023-02-01T11:35:00.001-03:002023-02-01T11:35:40.650-03:00Procesamiento de CSV mayor a 2GB con node<p> Problemas, problemas, siempre tengo problemas.</p><p><br /></p><p>¿Cuál es mi problema esta vez?</p><p></p><p>Un archivo CSV de 2M5 líneas, que al tener saltos de línea válidos dentro de algunos campos llega a 18M líneas de texto, ocupando 3.1 GB.</p><p></p><p>Es un listado de algo que no puedo decir, pero sí que me conviene procesarlo con javascript para hacerle una transformación a algunos campos selectos y agregar otros desde unas tablas, tipo una desnormalización. Esto es para luego meterlo en otra herramienta y ahí extraerle unas estadísticas.</p><p>De paso, al archivo resultante, según el valor de un registro, partirlo en varios en formato CSV.<br /></p><p><br /></p><p>¿Por qué una librería especial en lugar de parsearlo así nomás? Ocurre que si tenemos un CSV simple, donde no hay valores en los campos que coincidan con los delimitadores ni saltos de línea, es muy sencillo, tipo:<br /></p><b><span style="font-family: courier;">console.log("hola,como,estas,vos".split(/,/));</span></b><p><b><span style="font-family: courier;">[ 'hola', 'como', 'estas', 'vos' ]</span></b><br /></p><p>Pero si el CSV fuera<br /></p><p><b><span style="font-family: courier;">"mensaje,'hola, como estás vos', '2023-01-08 14:14'"</span></b><br /></p><p>quedaría:<br /></p><p><b><span style="font-family: courier;">[ 'mensaje', "'hola", " como estás vos'", " '2023-01-08 14:14'" ]</span></b><br /></p><p>distinto al esperado, no le prestes mucha atención a las comillas, que es un problema adicional:</p><p><b><span style="font-family: courier;">[ 'mensaje', "hola, como estás vos", "2023-01-08 14:14" ]</span></b></p><p><br /></p><p>Y sumale los saltos de línea para los campos multilínea... para que esto funcione bien hay que usar caracteres de escape, un bolonqui, mejor usar alguna librería existente, como la muy recomendada csvtojson.</p><p> </p><p>Se instala con: <br /></p><p><b><span style="font-family: courier;">npm install --save csvtojson</span></b><br /></p><p>Luego, anticipando que va a haber problemas con el tamaño, mirando los ejemplos me decidí por <a href="https://www.npmjs.com/package/csvtojson#asynchronously-process-each-line-from-csv-url" target="_blank">procesar línea a línea</a>. <br /></p><p><span></span></p><p> </p><p><b><span style="font-family: courier;">const request=require('request')<br />const csv=require('csvtojson')<br /> <br />csv().fromStream(request.get('http://mywebsite.com/mycsvfile.csv'))<br />.subscribe((json)=>{<br /> return new Promise((resolve,reject)=>{<br /> // transform and output operation<br /> })<br />},onError,onComplete); </span></b><br /></p><p> </p><p>Como quiero levantar el archivo localmente, reemplacé request con un stream reader o como se llame.<br /></p><p><b><span style="font-family: courier;">const request=require('fs')<br />const csv=require('csvtojson')<br /> </span></b><br /><b><span style="font-family: courier;">csv().fromStream(fs.createReadStream(fileName))<br />.subscribe((json)=>{<br /> return new Promise((resolve,reject)=>{<br /></span></b><b><span style="font-family: courier;"> // transform and output operation</span></b><br /><b><span style="font-family: courier;"> })<br />},onError,onComplete);</span></b> <br /></p><p>Para lidiar con la asincronía, probablemente de modo incorrecto, hice esto, si alguien me señala cualquier error, me avisa por favor:</p><p> </p><p><b><span style="font-family: courier;">const csvtojsonV2=require('csvtojson/v2');<br />const fs=require('fs');<br /><br />class Processor {<br /> async process(fileName) {<br /> let setTitle = true;<br /> await csvtojsonV2().fromStream(fs.createReadStream(fileName))<br /> .subscribe( (json)=> {<br /> return new Promise((resolve,reject)=> {<br /> if (setTitle) {<br /> console.log(<br /> Object.keys(json).map(e=>`'${e}'`).join(',')<br /> );<br /> setTitle = false;<br /> }<br /> // transform<br /> console.log(<br /> Object.values(json).map(e=>`'${e}'`).join(',')<br /> );<br /> resolve()<br /> })<br /> },this.onError,this.onComplete)<br /> }<br />}<br /><br />module.exports = { Processor }; </span></b></p><p>Y con </p><p><b><span style="font-family: courier;">const {Processor} = require('./Processor.js');<br />const processor = new Processor();<br /><br />allRecordsFileName=process.argv[2];<br /><br />async function run() {<br /> let result = await processor.processExport(allRecordsFileName);<br />}<br /><br />run()</span></b> <br /></p><p> </p><p>funciona bien hasta que no funciona: <br /></p><p><b><span style="font-family: courier;">FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory</span></b><br /><br /></p><p>Buscando rapidito, hallé que con:<br /></p><p><b><span style="font-family: courier;">export NODE_OPTIONS="--max-old-space-size=7168"</span></b></p><p>llega un poco más lejos y falla, pero con más swapping. Como que necesitaría más memoria según todas las entradas que encontré en Internet.<br /></p><p>Para mi que necesitar más memoria es una completa estupidez, hace falta saber más, por que la idea misma de usar el stream es que vaya leyendo y descartando para que tenga un impacto reducido, no que lea todo el archivo en memoria.<br /></p><br /><p>Dicho sea de paso, leí todo el archivo en memoria y falló igual:</p><p><span style="font-family: courier;"><b>const csv=require('csvtojson')<br />csv().fromFile(csvFilePath)<br />.then((jsonObj)=>{<br /> jsonObj.forEach(line=> {<br /> console.log(line);<br /> }<br /> );<br />})</b></span><br /></p><p>Voy apostando a una de estas, en este orden: </p><ul style="text-align: left;"><li>implementé mal lo del manejo de las Promises, muy probable pues no sé usarlas, vale tirarme alguna pista...<br /></li><li>hice mal uso del stream reader, lo mismo...<br /></li><li>csv2json tiene un error relacionado al stream reader<br /></li></ul><p> </p><p> Pero csv2json sabe manejar archvios grandes de algún modo, pues con:<br /></p><p><span style="font-family: courier;"><b>./node_modules/csvtojson/bin/csvtojson \<br /> < input.3GB.csv \<br /> > output.json</b></span><br /></p><p>aunque tardó horrores, lo hizo, sabe lidiar con más de 2GB, problema que ya veremos....</p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Plan B</h2><h2 style="text-align: left;"> </h2><p>Siempre recordemos que no podemos leer línea a línea un CSV y pretender que sea correcto, pero si el output.json anterior está listo, es de una sóla línea por registro. Ahora necesitamos leer:</p><p></p><p><span style="font-family: courier;"><b>require('output.json');</b></span></p><p>nop, falla:<br /></p><p></p><p><b><span style="font-family: courier;">RangeError [ERR_FS_FILE_TOO_LARGE]: File size (5734037250) is greater than 2 GB</span></b></p><p>La solución con <a href="https://itnext.io/using-node-js-to-read-really-really-large-files-pt-1-d2057fe76b33" target="_blank">stream</a>, falla igual en el createStreamRead():</p><p><b><span style="font-family: courier;">const fs = require('fs');<br />const readline = require('readline');<br />const stream = require('stream');<br /><br />var inputFileName=process.argv[2];<br /><br />var input = fs.createReadStream(inputFileName);<br />var output = new stream();<br />var rl = readline.createInterface(input,output);<br /><br />rl.on('line',function(line) {<br /> var record = JSON.parse(line);<br /> console.log(line);<br />});</span></b><br /></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Plan C</h2><h2 style="text-align: left;"><br /></h2><p>Se puede leer con <b>request</b> tal como está el ejemplo original, por algo lo habrán puesto, ¿no?, pero, maldición, está deprecated!... no importa, funciona ok, pero no soporta file:///, así que hay que armar un servidor efímero:</p><p><span style="font-family: courier;"><b>sudo php -S 127.0.0.1:80</b></span><br /></p><p>Cada vez menos elegante....<br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-89876759459844369892023-01-18T12:51:00.002-03:002023-01-23T11:29:24.485-03:00La asimetría entre una campaña de EH y un control de seguridad.<p>En Nerdearla 2022 tuve el privilegio de dar dos charlas, una mía personal que más que un taller era una charla larga, una versión extendida de lo presentado en Flisol 2022 relativa a open hardware, cores y software y otra, en representación de mi trabajo, ésta si una charla de verdad, nacida de una combinación de necesidades y oportunidades, de la aplicación de ML a un problema de seguridad.</p><p><br /></p><p>El proyecto expuesto trata de cómo hallar información sensible en diversos almacenamientos, en particular credenciales en texto plano en archivos de texto plano en sistemas de archivos utilizando técnicas de ML. Claramente todas estas ideas pueden extenderse otra información sensible en más tipo de archivos (pdf, documentos con formato, planillas) en diversos sistemas (repositorios, páginas web, comprimidos), pero no de modo sencillo ni automático.</p><p> </p><p>Sin embargo, el aspecto que quiero destacar en esta entrada no es tanto el diseño técnico y la arquitectura del sistema, que vendrían a incluir aspectos como lidiar con diversos encodings, realizar la exploración en determinados horarios para no impactar en la disponibilidad de los sistemas a examinar, actualizar el modelo y las reglas de inclusión y exclusión de búsqueda tanto de archivos como de patrones de palabras clave de modo relativamente dinámico para poder aplicarlos durante la ejecución y no tener que esperar a que finalice, considerá que quizás estás recorriendo millones de archivos a lo largo de semanas. De este tema tengo muchísimo elaborado pero poco testeado y además no he revisado soluciones existentes para comparar.</p><p><br /></p><p>Lo que me interesa y tema de esta entrada nace de esta frase:</p><p> </p><p><i>"(A) Vinieron unos pentesters y revisaron en cierto lugar y (B) encontraron un archivo con una clave que aunque no era la actual mostraba el patrón de generación </i><i>(C) </i><i> lo cual permitió acceder a un sistema donde se encontraron otras credenciales.</i><i>(D) </i><i>Tenemos que hacer un control para prevenir esta situación".</i></p><p></p><p><br /></p><p>Ok, nos gustaría mucho que no ocurra que hayan credenciales en texto plano en primer lugar, para ello existen técnicas de autenticación para evitar que hayan claves en los scripts y concientización para que no hayan claves fuera de los almacenes seguros tipo keepass, pero esto se trata justamente de detectar cuando alguien no las respeta.</p><p><br /></p><p>Aunque a primera vista no lo parezca, el salto que hay desde (A) <i>unos pentesters</i>... a (D) <i>hacer un control.</i>.. es abismal y más si pasamos por (B) y (C), veamos el detalle y el contraste:</p><p><br /></p><ul style="text-align: left;"><li>El éxito de una campaña de pentesting se puede alcancar ante el primer hallazgo importante o cuando se alcanza al tiempo límite de ejecución asignado.<br /></li><li>Ésta campaña, aunque pueda tener mucha asistencia de automatización, es esencialmente manual e interactiva, no hay foco en optimizar aspectos como que un humano no tenga que revisar más de 5.000 líneas, por decir un número para mí razonable. Esto significa que:</li><ul><li>si el humano se tiene que pasar una tarde mirando una lista de 100.000 líneas candidatas, lo va a hacer. <br /></li></ul><li>La búsqueda no es exhaustiva, se pueden buscar archivos con nombres clave tipo "claves.txt", con hallar uno alcanza.</li><li>La frecuencia puede ser tal que sea una o dos veces por año, quizás cada dos años.<br /></li></ul><p><br /></p><p> </p><p></p><p>Contrastemos con un control:</p><ul style="text-align: left;"><li>La ejecución del control se completa cuando recorre todo el conjunto de activos a revisar y emite su reporte, el cual puede ser contínuo, no hace falta que sea al final.</li><li>El éxito se alcanza cuando recorre todo y halla todo lo que podría hallar.<br /></li><li>Debe ser esencialmente automático, el humano sólo debería intervenir para una decisión final acerca de los positivos y realimentar la lógica.</li><ul><li>En mi experiencia, completamente personal, no debería examinar más de 10.000 líneas. Y pensá que esto hay que repetirlo periódicamente, es esencial que sean pocas líneas.<br /></li></ul><li>Debe ser permanente, no bien termina de ejecutarse debe comenzar otra vez.<br /></li><li>Considerando (B) <i>clave pista</i> y (C) <i>que conduce a otro lado</i>, esto es imposible en un control, se hace indispensable la intervención humana.<br /></li></ul><p>Esta intervención puede pasar a formar parte del control, pero hay que tener en cuenta que pueden haber mucho "candidatos", una cosa es mirar rápido y ver que <span style="font-family: courier;">"let password = "3234234"</span> amerita contactar al dueño del sistema y otra es que cuando el dueño te contesta "esa clave no se usa más" confiar y seguir escarbando.</p><p>Otra es, si el hit fué "let password = $texto", tendrías que ir a ver dónde y cómo se definió $texto, pudo haber sido</p><p><span style="font-family: courier;">let texto = "3234234"</span></p><p>que es un nivel de indirección que nuestro análisis difícilmente pueda interpretar, o peor aún:</p><p></p><p><span style="font-family: courier;">let password = exec("proceso.exe", "id_sistema")</span><br /></p><p>donde <span style="font-family: courier;">proceso.exe</span> puede ni siquiera estar presente en el sistema que estamos examinando. No pongo las manos en el fuego pero consideraría esta una técnica válida, esa línea la encontraste en un repositorio y proceso.exe sólo existe en el sistema productivo donde se ejecutará el código.</p><p>Existen herramientas de análisis estático de código que son
capaces de seguirle el rastro a una cadena de asignación de valores
dentro del flujo de un programa, sólo sería cuestión de activarla cuando se detecta que es código fuente, pero bueno, es una complejidad adicional.<br /></p><div><p>En síntesis, la idea está en concordancia con el concepto de la asimetría que hay entre atacante y el defensor, el EH respeta la visión del atacante y el Control la del defensor:<br /></p><ul style="text-align: left;"><li>El atacante tiene toda la ventaja del tiempo, es lo único que hace.<br /></li><li>El atacante tiene toda la ventaja de concentrarse en un único conocimiento, el de tal ataque en particular, mientras el defensor debe abarcar de modo obviamente superficial todo el conocimiento de todo lo que defiende.</li><li>Al atacante le alcanza con un éxito y en última instancia no importa mucho cómo lo consigue.<br /></li></ul><p>Entonces la idea es, no sencillo en general <b><i>modelar</i></b> un control a partir del resultado de un reporte de EH y en particular en el caso de la frase, probablemente imposible.<br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p></div>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com1tag:blogger.com,1999:blog-6148370834456516013.post-28634601995203609842022-10-25T18:44:00.001-03:002022-10-25T18:44:48.378-03:00Secure Boot con ESP32c3<p>Primero hay que leer atentamente la <a href="https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/security/secure-boot-v2.html">documentación</a> y cuantos más clicks hagas en los links que tiene más vas a comprender todo, elegí para la v4.4. Puse ESP32c3 en el título pero probablemente aplica a Secure Boot V2, que incluye al menos ESP32s2.<br /></p><p><br /></p><p>El primer programa que se ejecuta es el que está en la ROM, también llamado FSB (First Stage Bootloader), que entre otras cosas se fija si el eFuse de secure boot está activado, ponele que sí. Luego busca el SSB (Second Stage Bootloader) y si tiene hasta 3 firmas agregadas. Utiliza las hasta 3 public keys que pueden haber en los eFuses y si alguna firma está ok, ejecuta el SSB.</p><p></p><p> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDvHseRkxuRSN-HW6IPc837R4nTopdPBYBemFI0kpb45Hu31QQ4RmpW-OQwqVy8laLmqfTIgTaWssDx13Cqcv_OQ3dpF2gfVqfUjDHFkxE9jd0Y81SbuK5wtWCrXaYWSc4omjALvhrT4Wvuv3_XvDqKjp5e6wJ1kWRJH8bAGxsiCeN-Ry2NRW3umEhpA/s976/normal_boot.png" style="margin-left: auto; margin-right: auto;"><img alt="Arranque normal" border="0" data-original-height="352" data-original-width="976" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDvHseRkxuRSN-HW6IPc837R4nTopdPBYBemFI0kpb45Hu31QQ4RmpW-OQwqVy8laLmqfTIgTaWssDx13Cqcv_OQ3dpF2gfVqfUjDHFkxE9jd0Y81SbuK5wtWCrXaYWSc4omjALvhrT4Wvuv3_XvDqKjp5e6wJ1kWRJH8bAGxsiCeN-Ry2NRW3umEhpA/w476-h171/normal_boot.png" title="Arranque normal" width="476" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Arranque normal</td><td class="tr-caption" style="text-align: center;"><br /></td></tr></tbody></table><p></p><p><br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3h4t8GPL6R9WIdeZMZgvm9EKGLM4AdfgsE4efRpBcucT8SzSMqCgTKSZT7kEX4h3JjeGBPhkoZ-fWmX4-smPuJPa6qHhsfCgmYoaaIhpRuGN2yNSP-guZVzVnBiwVi6mQvFlrNEc_OZIT3fDRXLm8_4ScnmEVVK0Wp4-3o0OKTHI9lbx6b0nX9dm6Kw/s987/secure_boot.png" style="margin-left: auto; margin-right: auto;"><img alt="Arranque seguro" border="0" data-original-height="359" data-original-width="987" height="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3h4t8GPL6R9WIdeZMZgvm9EKGLM4AdfgsE4efRpBcucT8SzSMqCgTKSZT7kEX4h3JjeGBPhkoZ-fWmX4-smPuJPa6qHhsfCgmYoaaIhpRuGN2yNSP-guZVzVnBiwVi6mQvFlrNEc_OZIT3fDRXLm8_4ScnmEVVK0Wp4-3o0OKTHI9lbx6b0nX9dm6Kw/w481-h174/secure_boot.png" title="Arranque seguro" width="481" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Arranque seguro<br /></td></tr></tbody></table><br /><p></p><p> <br /></p><p>Este hace lo mismo para cada imagen que haya en el resto de la memoria hasta encontrar una válida. Luego, de la aplicación, copia a memoria los datos y programa correspondientes y mapea a la memoria los datos y programas que vayan a quedar en la EEPROM. Por último ejecuta la aplicación.</p><p>Para poder llegar a esta situación, tenemos que hacer algunas cositas:</p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Generar las claves</h2><h2 style="text-align: left;"> </h2><p>En la carpeta de tu elección, pero luego el pem va en cada proyecto. <br /></p><p><span style="font-family: courier;">$ openssl genrsa -out secure_boot_signing_key.pem 3072</span><br /></p><p>No te olvides de agregar un *.pem a tu .gitignore, si llegás a versionar esto, pensá que podrías revocar el certificado en el chip pero sólo tenés lugar para tres.<br /></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Toolchain</h2><h2 style="text-align: left;"><br /></h2><p>Bajar todo el entorno de esp-idf según <a href="https://github.com/cpantel/ceiot_base/" target="_blank">las instrucciones del paso 4</a>. Si ya lo tenías de antes, es conveniente que lo actualices. <br /></p><p><span style="font-family: courier;">$ cd ~/esp/esp-idf <br /></span></p><p><span style="font-family: courier;">$ git pull --recurse-modules</span></p><p><span style="font-family: courier;">$ ./install.sh esp32,esp32c3,esp32s2</span><br /></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Tu proyecto</h2><h2 style="text-align: left;"><br /></h2><p></p><p>Para este ejemplo usé CIBS/esp32c3-secure-boot, que es lo mismo que esp32c3-pinout. De un modo u otro, activar el entorno</p><p><span style="font-family: courier;">$ . export.sh</span><br /></p><p>Ir a tu proyecto, si lo tenías ya construido, hacelo papilla con</p><p><span style="font-family: courier;">$ rm -rf build</span><br /></p><p>Para empezar de cero:<br /></p><p><span style="font-family: courier;">$ idf.py set-target esp32c3<br />$ idf.py menuconfig</span></p><p><span style="font-family: courier; font-size: x-small;"># Security features<br />[*] Enable hardware Secure Boot in bootloader (READ DOCS FIRST)<br /> Select secure boot version (Enable Secure Boot version 2) ---><br /> (X) Enable Secure Boot version 2<br />[*] Sign binaries during build (NEW)<br /> (secure_boot_signing_key.pem) Secure boot private signing key (NEW)<br /></span></p><p><span style="font-family: courier; font-size: x-small;"># Partition Table ---><br />(0xa000) Offset of partition table<br /></span></p><p><span style="font-family: inherit;"> </span></p><p><span style="font-family: inherit;">Ese 0xa000 en lugar del 0x8000 original podría ser opcional pero en mis pruebas dijo:</span></p><p><br /></p><p><span style="font-family: courier;">Bootloader binary size 0x8c30 bytes is too large for partition table
offset 0x8000. Bootloader binary can be maximum 0x8000 (32768) bytes
unless the partition table offset is increased in the Partition Table
section of the project configuration menu.</span></p>La tentación es poner 0x8d00, pero tras varias iteraciones, mejor 0xa000, más que por ahí dice que debe ser múltipo de 0x1000.<br /><p><br /></p><p><span style="font-family: courier;">$ idf.py build</span><br /></p><p>En algún punto va a tirar dos mensajes, uno que gentilmente explica como agregarle firmas al bootloader:<br /></p><p><span style="font-family: courier;">To sign the bootloader with additional private keys.<br />
/home/iot/.espressif/python_env/idf4.4_py3.10_env/bin/python
/home/iot/esp/esp-idf/components/esptool_py/esptool/espsecure.py
sign_data -k secure_boot_signing_key2.pem -v 2 --append_signatures -o
signed_bootloader.bin build/bootloader/bootloader.bin </span> <br /></p><p>Y otro de cómo grabarlo, hay que hacerlo a mano, sólo cuando hay nuevas keys. <br /></p><p><br /></p><p><span style="font-family: courier;">/home/iot/.espressif/python_env/idf4.4_py3.10_env/bin/python /home/iot/esp/esp-idf/components/esptool_py/esptool/esptool.py --chip esp32c3 --port=(PORT) --baud=(BAUD) --before=default_reset --after=no_reset --no-stub write_flash --flash_mode dio --flash_freq 80m --flash_size 2MB 0x0 /home/iot/ceiot_base/CIBS/esp32c3-secure-boot/build/bootloader/bootloader.bin</span></p><p><br /></p><p>¿Qué ponemos en PORT y BAUD?</p><p>PORT = /dev/ttyUSB0<br /></p><p>BAUD = 115200</p><p><br /></p><p>Ambos salen de haber visto alguna vez la salida de idf.py monitor:</p><p><span style="font-family: courier;">--- idf_monitor on /dev/ttyUSB0 115200 ---</span><br /></p><p><br /></p><p>Luego</p><p><span style="font-family: courier;">$ idf.py flash</span></p><p><span style="font-family: courier;">$ idf.py monitor</span></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Resultados</h2><h2 style="text-align: left;"><br /></h2><p>La primera vez, tal como dice la documentación, sirve para activar, hace falta un reset</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHJj1gOArG31gdAvTJ5z-eVE1tINUi56GsOvk3dIn6zovU8pFYRtMQoWBvyjV5vUJYUBcGlpjJpAtiAUlcdHEm7IvV7KSz6m3an61Kp4q8C9Zb6-Sy5OJXLhaNq2wrY8W43-o6yJ1bKiaTlUHi8bBoea7-Kz7qHYba6QuOHWlcs3hAuG_o4COH5YT_QA/s859/last_insecure_boot_01.png" style="margin-left: 1em; margin-right: 1em;"><img alt="Último arranque inseguro" border="0" data-original-height="859" data-original-width="842" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHJj1gOArG31gdAvTJ5z-eVE1tINUi56GsOvk3dIn6zovU8pFYRtMQoWBvyjV5vUJYUBcGlpjJpAtiAUlcdHEm7IvV7KSz6m3an61Kp4q8C9Zb6-Sy5OJXLhaNq2wrY8W43-o6yJ1bKiaTlUHi8bBoea7-Kz7qHYba6QuOHWlcs3hAuG_o4COH5YT_QA/w628-h640/last_insecure_boot_01.png" title="Último arranque inseguro" width="628" /></a></div><p></p><p></p>Desde la próxima vez que arranque:<p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim5IkjKYsszPsf3g4LhNvvh9QyxgHlHzO6vspfYiIouIVKRk2ZaZK1jrBmAXkxmfors6So7sNf3Zv2fZ5oaffOzxOpz73oGL1AV4Mz2GrSo6WyCMMzfx6qLefxrmqmM2cSAnztcWmdQgNpbrYhGzHoljFvYdC0WD6INKwHjasTtC4kBPgrKr3AndTgSA/s785/first_secure_boot.png" style="margin-left: 1em; margin-right: 1em;"><img alt="Primer arranque seguro" border="0" data-original-height="673" data-original-width="785" height="548" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim5IkjKYsszPsf3g4LhNvvh9QyxgHlHzO6vspfYiIouIVKRk2ZaZK1jrBmAXkxmfors6So7sNf3Zv2fZ5oaffOzxOpz73oGL1AV4Mz2GrSo6WyCMMzfx6qLefxrmqmM2cSAnztcWmdQgNpbrYhGzHoljFvYdC0WD6INKwHjasTtC4kBPgrKr3AndTgSA/w640-h548/first_secure_boot.png" title="Primer arranque seguro" width="640" /></a></div><br /><p>Notá tanto la diferencia del FSB (en negro) como la del SSB (en verde).</p><p>Este proceso en dibujitos:</p><p><br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEmKsfJBJsFLhNCcmVspRB_7keYz3RNAM7hpLC3uqFoP2VyOofZmA4spUSmUFTgI4sEQJDV1TNllIM18bjDHAPGbbjEJLBadlSpNoWegGXhBost3RaOVfjz5kVhH1-qZF_s6QCVq-ZaS5CGkNrr4znnqYPzAvjoGMVLWGSS27N7HAxducStDimkDtC7A/s1054/setup_app.png" style="margin-left: auto; margin-right: auto;"><img alt="Setup bootloader" border="0" data-original-height="371" data-original-width="1054" height="169" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEmKsfJBJsFLhNCcmVspRB_7keYz3RNAM7hpLC3uqFoP2VyOofZmA4spUSmUFTgI4sEQJDV1TNllIM18bjDHAPGbbjEJLBadlSpNoWegGXhBost3RaOVfjz5kVhH1-qZF_s6QCVq-ZaS5CGkNrr4znnqYPzAvjoGMVLWGSS27N7HAxducStDimkDtC7A/w479-h169/setup_app.png" title="Setup bootloader" width="479" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Setup bootloader</td></tr></tbody></table><br /><br /><p><br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrFvEm_dl8Qq-WaJwusJvvQIwJSDEekgg0SoPiXZYGBHMvNlWhGc1hKHjBSaGp6c6bgtpEqHeDXKFVlDw4o36G7R-pCcCyq0nwU2jVLs0pOQfuYwhaSEkeCZd74UDCm_9rfSMXyNPcHhdPxKevFlTHA_aG6Wrz0eOQusJEpT8BRGbOzxoSTRb8_YPCTQ/s1002/setup_bootloader.png" style="margin-left: auto; margin-right: auto;"><img alt="Setup App" border="0" data-original-height="376" data-original-width="1002" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrFvEm_dl8Qq-WaJwusJvvQIwJSDEekgg0SoPiXZYGBHMvNlWhGc1hKHjBSaGp6c6bgtpEqHeDXKFVlDw4o36G7R-pCcCyq0nwU2jVLs0pOQfuYwhaSEkeCZd74UDCm_9rfSMXyNPcHhdPxKevFlTHA_aG6Wrz0eOQusJEpT8BRGbOzxoSTRb8_YPCTQ/w471-h177/setup_bootloader.png" title="Setup App" width="471" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Setup App</td></tr></tbody></table><p></p><p><br /></p><p><br /></p><p></p><p>A mi no me salió de una tán fácil, no encontraba la tabla de particiones, no había nada en ésta, horas...<br /></p><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheNlwXFdqe8Yg4vQpwvnJbnK9hNrJU6XuGq2GEwlCzq_RyKv9vEsAU7zm2iCxLc6-0NQDABVs4QQ1jT6VBBmg32r2wVafkC-IAr95B1SwVoUI7fPOXf27txKG836jb0pHgr0jy14xguo3MRVWhAIL8NZQGf-z4p5rvsfdpwJA-cMNHqI-C0cgzpHOcLA/s646/just_the_bootloader.png" style="margin-left: auto; margin-right: auto;"><img alt="Una de las tantas fallas..." border="0" data-original-height="514" data-original-width="646" height="319" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheNlwXFdqe8Yg4vQpwvnJbnK9hNrJU6XuGq2GEwlCzq_RyKv9vEsAU7zm2iCxLc6-0NQDABVs4QQ1jT6VBBmg32r2wVafkC-IAr95B1SwVoUI7fPOXf27txKG836jb0pHgr0jy14xguo3MRVWhAIL8NZQGf-z4p5rvsfdpwJA-cMNHqI-C0cgzpHOcLA/w400-h319/just_the_bootloader.png" title="Una de las tantas fallas..." width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Una de las tantas fallas...</td></tr></tbody></table><br />Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com2tag:blogger.com,1999:blog-6148370834456516013.post-48949161701503829742022-09-28T14:30:00.003-03:002022-09-28T14:30:55.790-03:00Nerdearla 2022 Open de todo, la previa<p>El taller en realidad no es tan taller, ¿cuántas personas del ámbito de nerdearla tienen una edu-ciaa-fpga, el entorno armado e interés en hacer un taller de esto? Mmmh, poquita. En realidad es una charla larga, es que hay mucho tema pero aprovecho para que quien tenga la edu-ciaa-fpga y ganas, pueda ir probando en el momento, tipo taller.</p><p>Tal como he contado mi experiencia en https://seguridad-agile.blogspot.com/2021/09/h4ck3d-2021-configuracion-basica.html, el proceso para poder generar el bitstream es larguísimo. Para facilitar la vida de quien lo haga, he tomado la virtual que uso habitualmente y le apliqué un proceso de limpieza, sanitización y compresión para ahorrar ancho de banda por un lado y para ahorrar espacio en el disco de quien la instale por el otro.</p><p></p><br /><p>En mis últimos proyectos similares he utilizado para las virtuales Ubuntu Server con xorg y openbox, pero puede ser demasiado minimalista para otras personas, así que en lugar de rehacerlo con Ubuntu Server, reduciendo aún más el tamaño de la imagen, me concentré en quitar. El proceso de limpieza fue eliminar toda aplicación superflua, caches, logs, los repositorios utilizados para la construcción de las toolchains, lo que sea, esto quizás lo detalle en otro post uno de estos días.</p><p></p><p>Las precauciones que he tomado al exportar es cambiar la contraseñas y fundamentalmente eliminar de .ssh la key que uso para github. Tras el proceso de zerofill y compactación, no debería quedar ningún rastro forense, pero como no tengo garantías, de todos modos también eliminé la key en github.</p><p></p><p>Reformulando, eliminé la key en github para no tener ningún problema de robo de credenciales y de modo secundario la purgué en la imagen para que nadie que no ha leído esto la encuentre y piense que fuí descuidado. Y fundamentalmente para predicar con el ejemplo.</p>El repo consideré borrarlo también y que hicieras git clone, pero de un modo u otro tenías que bajarlo, así que lo dejé.<p></p><p></p><p><br /></p><p>Durante la charla/taller lo que iré mostrando es el proceso asumiendo que ya tenés todo instalado y funcionando, comprenderás que no voy a poder en ese momento resolver ningún problema. Para poder participar del taller probando los ejemplos, es necesario que ejecutes la siguiente secuencia de operaciones, que terminaría en la grabación del bitstream a la placa y como control deberías tener algunos leds cambiantes en la placa y en la terminal serial un menú.</p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Pasos</h2><h2 style="text-align: left;"> </h2><p>Asumo que si estás jugando con FPGA y más edu-ciaa-fpga, ya tenés bastante experiencia con linux y virtualización. Aún así, cualquier problema que tengas agregalo a los comentarios abajo e iré completando el instructivo.</p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">El anfitrión</h3><h3 style="text-align: left;"> </h3><p>Tenés que agregar tu usuarios a estos grupos: <br /></p><p><span style="font-family: courier;">$ sudo addgroup "$USER" vboxusers</span></p><span style="font-family: courier;">$ sudo addgroup "$USER" dialout</span><p> </p><p>Instalá el Extension Pack si no lo tenés.</p><p><br /></p><h3 style="text-align: left;">La imagen</h3><h3 style="text-align: left;"> </h3><p></p><p>La imagen exportada a OVA ocupa unos 3GB y <a href="https://drive.google.com/file/d/1TV8vEKsH7ZEkF4hVi2nJS7iNmfpLHw-y/view?usp=sharing">está en un drive</a>.</p><p>La
virtual importada ocupa al menos 9.3 GB, con el uso no debería crecer
mucho, pero considerá que la partición es de 30 GB. Es un Linux Mint 19 o
20, lo cual provée un entorno gráfico agradable.</p><p></p><p>Desde VirtualBox elegí "File", "Import Appliance"</p><p>Yo la uso con 8GB de RAM, pero
seguro que anda con menos, mucho menos, tipo 3GB. <br /></p><p></p><p></p><p>Configurá networking en modo bridge </p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Arranque</h3><h3 style="text-align: left;"><br /></h3><p>Luego la arrancás, el usuario es "Charly", la clave "educiaa", abrís una terminal y averiguás la IP:</p><p><span style="font-family: courier;">$ ip a</span> <br /></p><p>El repo está en: </p><p></p><span style="font-family: courier;">$ cd ~/Desktop/repo/github/cpantel/evilcodesequence</span><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">El bitstream</h3><h3 style="text-align: left;"> </h3><p><span style="font-family: courier;">$ make PROGRAM=fulldemo system </span></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">El flasheo</h3><h3 style="text-align: left;"> <br /></h3><p>Para evitar tener que conectar la placa a la virtual, que es bastante sencillo pero puede ser fuente de inconvenientes, el flasheo se hará desde el anfitrión si es linux, si es windows, vas a tener que hacerle funcionar el USB y flashear desde la VM, vemos luego.</p><p>En el anfitrion, ejecutar una sola vez:</p><p><br /></p><p></p><p><span style="font-family: courier;">$ scp charly@192.168.1.xx:/usr/local/bin/iceprog .</span></p><br /><p>Luego, para cada nueva regeneración del bistream<span style="font-family: courier;">:</span></p><p><span style="font-family: courier;"><br /></span></p><p><span style="font-family: courier;">$ scp charly@192.168.1.xx:/home/charly/Desktop/REPO/github/cpantel/evilCodeSequence/BUILD/top.bin .</span></p><p><span style="font-family: courier;">$ ./iceprog top.bin</span></p><p> </p><p>si dice </p><p> </p><p><span style="font-family: courier;">./iceprog: error while loading shared libraries: libftdi.so.1: cannot open shared object file: No such file or directory</span><br /></p><p> </p><p>Es por que te falta</p><p> </p><span style="font-family: courier;">$ sudo apt install libftdi1</span><p><br /></p><p>Si optaras por conectar directamente la placa a la VM</p><p><br /></p><p></p><span style="font-family: courier;">$ make PROGRAM=fulldemo flash</span><p><br /></p><p>Considerá que flashear desde el anfitrión que es MUCHO MUCHO más rápido.<br /></p><p></p>Luego, usando tu programa favorito a /dev/ttyUSB1 con velocidad 9600, tendrías que ver algo como esto:<p></p><p> <table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinyQg2_8j7T8AG6RlTUsTuRgNAqpLNHqxW75WtQzEmhj87DKtcp8MRLxb7KZy-lmFy0OTvhmzvxpGO937qvT9QEuSY_yC_JG9AKDSizjm-hq9NxgElgI2p0SOOLQ9p2IFE_i0CrcUvTX64rgTsYXMNliAIXT-Q5ZgVWYp9X2-ojRfi3xb1l5niVObbFQ/s506/educiaafpga_menu.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Menu" border="0" data-original-height="366" data-original-width="506" height="289" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinyQg2_8j7T8AG6RlTUsTuRgNAqpLNHqxW75WtQzEmhj87DKtcp8MRLxb7KZy-lmFy0OTvhmzvxpGO937qvT9QEuSY_yC_JG9AKDSizjm-hq9NxgElgI2p0SOOLQ9p2IFE_i0CrcUvTX64rgTsYXMNliAIXT-Q5ZgVWYp9X2-ojRfi3xb1l5niVObbFQ/w400-h289/educiaafpga_menu.png" title="Menu" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Menu</td></tr></tbody></table></p><p>Jugá con las opciones, mejor la (1) LEDS pues el resto está a medio implementar en la imagen.<br /></p><p>Contactame ANTES del taller si algo no te funciona, durante el taller no va a haber tiempo.</p><p>Hay otras maneras de obtener un entorno equivalente, ya sea que lo hagas vos de cero o que uses docker, es irrelevante siempre y cuando puedas compilar el programa, construir el bitstream y flashearlo, proveo la virtual como una facilidad.</p><p><br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-83667731095919542502022-07-19T22:45:00.002-03:002022-10-23T16:17:57.540-03:00Recuperación fallida pantalla bangho, premio consuelo webcam<p>Me habían regalado una bangho b-n0x1, que tenía de interesante dos slots MiniPCIE, (creo), uno ocupado por WiFi, el otro libre. La prendí, tenía un windows roto, la olvidé. Meses despues la quise prender y nada, murió algo y pasé a modo carroñero.</p><p>Disco ok, memoria veremos, teclado se me soltó la tecla de enter, lo más interesante la pantalla, a su lado una webcam...<br /></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Recuperación fallida</h2><h2 style="text-align: left;"><br /></h2><p>Gracias a un cierto esfuerzo y la generosa colaboración de Pablo Llanos en <a href="https://groups.google.com/g/embebidos32/c/2GWZL2_qXVo" target="_blank">este hilo de embebidos</a>, pasé de no saber absolutamente nada a saber porqué no puedo usar la pantalla, resumo:</p><p>La pantalla es una HannStar HSD100IFW1-A00, que se comunica con LVDS. Por medio de tres pares de cables se transmite:</p><p><br /></p><div><span style="font-family: courier;"><b>g[0], r[5], r[4], r[3], r[2], r[1], r[0]<br />b[1], b[0], g[5], g[4], g[3], g[2], g[1]<br />de, vs , hs , b[5], b[4], b[3], b[2</b>]</span><br /></div><div><br /></div><div> </div><div>siendo supongo <span style="font-family: courier;"><b>de</b></span> Display Enable, <span style="font-family: courier;"><b>vs</b></span> Vertical Sync y <span style="font-family: courier;"><b>hs</b></span> Horizontal Sync. No importa mucho el detalle pero cuento mi idea, que era, a la usanza de los primeros video juegos, tener algo así como un Video Sync Generator y mediante lógica combinacional generar algo. Pero la frecuencia es de 45MHz, multiplicada por esos 7 bits de más arriba, 315 MHz, completamente fuera de mi alcance generar, tratar adecuadamente, medir o diagnosticar.</div><div> </div><div>Luego pensé que si la disposición hubiese sido: <br /></div><div> </div><div></div><div><span style="font-family: courier;"><br /></span></div><b><span style="font-family: courier;">de, g[0], r[5], r[4], r[3], r[2], r[1]<br />vs, b[1], b[0], g[5], g[4], g[3], g[2]<br />hs, b[5], b[4], b[3], b[2], r[0], g[1]</span></b><p><br /></p><p>con las señales de control separadas, podrían haber posibilidades de trabajar a 90MHz, pero eso es en un universo alternativo.<br /></p><p>En realidad no es que no sabía nada, estuve <a href="https://seguridad-agile.blogspot.com/2020/03/para-estudiar-designing-video-game.html" target="_blank">adaptando unos ejemplos de verilog que generan VGA</a>, <a href="https://seguridad-agile.blogspot.com/2020/09/mi-segundo-pmod-dual-pmod-vga.html" target="_blank">me he hecho un PMOD VGA</a> e implementé <a href="https://seguridad-agile.blogspot.com/2019/12/vga-rendering-de-simulacion-fpga.html" target="_blank">un render de VGA en TCL para la salida de una simulación de FPGA</a>, pero de esto nuevo no tenía ni la menor idea.<br /></p><p></p><p></p><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Premio consuelo</h2><h2 style="text-align: left;"><br /></h2><p>Me quedó la cámara web, con un chip que dice ser Aveo AV301W, una datasheet aparentemente compatible que dice "Delock industry USB 2.0 CMOS Kameramodul 1.3", no recuerdo el camino de navegación que me llevó hasta ahí, pero creo recordar que fue por la imagen.</p><p> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihMlbi2CBVKBuPL5x-Sm7HQy9evxJjWM96VrS-wYg2F9Xd94BuaPPVDDyrUYDaH-hUEnHds0hZ2k4qcsISJWXj7t1XKAjiwqWzRGq-bIPzQAJz-PQx4xKPiZ57TOupKflLJPHp1VM9r7rKvn96F-mdCaYpraTopF9d5StvImaa7UA_yAfTKlCkeyJV5A/s1600/placa.jpeg" style="margin-left: auto; margin-right: auto;"><img alt="Aveo AV301W" border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihMlbi2CBVKBuPL5x-Sm7HQy9evxJjWM96VrS-wYg2F9Xd94BuaPPVDDyrUYDaH-hUEnHds0hZ2k4qcsISJWXj7t1XKAjiwqWzRGq-bIPzQAJz-PQx4xKPiZ57TOupKflLJPHp1VM9r7rKvn96F-mdCaYpraTopF9d5StvImaa7UA_yAfTKlCkeyJV5A/w400-h300/placa.jpeg" title="Aveo AV301W" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Aveo AV301W</td></tr></tbody></table><br /><p></p><p> </p><p>Este módulo implementa comunicación USB, asi que tomé un cable USB roto, aposté a que la falla estaba cerca del conector del lado del dispositivo, corté, agregue un PCB para poder disociar la soldadura de la correcta conexión, miré los pinouts fijo, soldé y listo.</p><p> </p><p>Del lado del cable, elegí "imágenes" en https://www.google.com/search?q=usb+pinout. Dejo como referencia con ASCII Art, viéndolo desde arriba:</p><p><span style="font-family: courier;"> - D+ D- +</span></p><span style="font-family: courier;">[] [] [] []</span><span style="font-family: courier;"><span style="font-size: large;"><span style="font-family: courier;"></span></span></span><p><span style="font-family: courier;"> 4 3 2 1</span></p><p><br /></p><p style="text-align: left;">En el módulo:<br /></p><p style="margin-left: 120px; text-align: left;"></p><p style="margin-left: 120px; text-align: left;"><br /></p><p style="margin-left: 120px; text-align: left;"><style type="text/css">td {border: 1px solid #ccc;}br {mso-data-placement:same-cell;}</style></p><table border="1" cellpadding="0" cellspacing="0" style="border-collapse: collapse; border: medium none; font-family: Arial; font-size: 10pt; margin-left: 120px; table-layout: fixed; text-align: left; width: 0px;"><colgroup><col width="69"></col><col width="100"></col></colgroup><tbody><tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Pin#"}" style="background-color: #d9d9d9; border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">Pin#</td><td data-sheets-value="{"1":2,"2":"Signal Name "}" style="background-color: #d9d9d9; border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); border-top: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">Signal Name </td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":1}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">1</td><td data-sheets-value="{"1":2,"2":"+5v","6":1}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">+5v</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":2}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">2</td><td data-sheets-value="{"1":2,"2":"USB_D-"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">USB_D-</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":3}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">3</td><td data-sheets-value="{"1":2,"2":"USB_D+"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">USB_D+</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":4}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">4</td><td data-sheets-value="{"1":2,"2":"BTN"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">BTN</td></tr><tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":5}" style="border-bottom: 1px solid rgb(0, 0, 0); border-left: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">5</td><td data-sheets-value="{"1":2,"2":"GND"}" style="border-bottom: 1px solid rgb(0, 0, 0); border-right: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: left; vertical-align: bottom;">GND</td></tr></tbody></table><p style="margin-left: 120px; text-align: left;"><br /></p><p>BTN es un botón opcional para disparar capturas, no me molesté en conectarlo</p><p></p><p></p><p>Lo enchufé en una vieja Sarmiento y nada.</p><p></p><p>Superado por tanta derrota, abandoné el proyecto. <br /></p><p>Semanas despues, reviví el proyecto.<br /></p><p>El motivo de este resucitamiento fue una confluencia de astros: por un lado <a href="https://groups.google.com/g/embebidos32/c/ZHwwsX7D9Is" target="_blank">alguien ofreció hardware en embebidos32</a>, lo que me llevó a <a href="https://cybercirujas.rebelion.digital/foro/index.php" target="_blank">cybercirujas</a>, que me puso nuevamente en sintonía con el modo recuperador. Por el otro, con motivo a un proyecto candidato a H4CK3D 2022, estaba viendo una excelente clase de USB a cargo de Pablo Gómez y ví en un diagrama que D+ va con D+ y D- con D-, no como en UART que Rx va con Tx y Tx con Rx y me pregunté si lo había conectado bien. Al revisar, estaba bien conectado, pero no había soldado correctamente el pin de alimentación. </p><p>Corregí, volví a conectar la cámara a la vieja Sarmiento y listo, anda.</p><p>Para llevar la sinergía al máximo, hallé tirado en la calle hace meses, sino años, un gabinete de webcam, en perfecto estado.</p><p> </p><div style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiidqfjtOdXhPaEJaZASRQTtmFBZJu7j13_BQ_qXHmVs-Q_O5kvhij68ipeOGAfVgd2VAUkat9YUx1KSNQTwYXdrpljmfDVwk6dIjSNISpbHX3kWtauZ_baUAlHtQ-bk6Fg-cp23HMQ0Ym2Nxrgoh0oGVHFB8o8vmlZHVQeX_NT8q6ONt7XxyltB4AVbw/s840/desarmada.jpeg"><img alt="A medio armar" border="0" data-original-height="630" data-original-width="840" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiidqfjtOdXhPaEJaZASRQTtmFBZJu7j13_BQ_qXHmVs-Q_O5kvhij68ipeOGAfVgd2VAUkat9YUx1KSNQTwYXdrpljmfDVwk6dIjSNISpbHX3kWtauZ_baUAlHtQ-bk6Fg-cp23HMQ0Ym2Nxrgoh0oGVHFB8o8vmlZHVQeX_NT8q6ONt7XxyltB4AVbw/w400-h300/desarmada.jpeg" title="A medio armar" width="400" /></a></div><br /><p><br /></p><p>Que de premio extra traía un micrófono:</p><p> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidodEW40733AdjmDb4fWiFR1LChMWg4pkczR5hiKf2eRWjM_V8YbKCzdvGk-5JADnGhwltE6G4R97ERy-gqQkRO3YOfEGQ574HZzhuWbKb-QYvVPI7BTWQbgJDCABH4T4YJpI5Ul_pzkELEzDpbWcyjCPc-lIKmeq-k3fnK_2dUO_2OSedx-pvDsMn-Q/s605/microfono.jpeg" style="margin-left: auto; margin-right: auto;"><img alt="Micrófono" border="0" data-original-height="362" data-original-width="605" height="239" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidodEW40733AdjmDb4fWiFR1LChMWg4pkczR5hiKf2eRWjM_V8YbKCzdvGk-5JADnGhwltE6G4R97ERy-gqQkRO3YOfEGQ574HZzhuWbKb-QYvVPI7BTWQbgJDCABH4T4YJpI5Ul_pzkELEzDpbWcyjCPc-lIKmeq-k3fnK_2dUO_2OSedx-pvDsMn-Q/w400-h239/microfono.jpeg" title="Micrófono" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Micrófono</td></tr></tbody></table><br /><p><br /></p><p>Le hice unas ranuritas, pístola de plástico caliente y listo.<br /></p><p>El único problema es que el cable es un poco corto y en la máquina donde más serviría conectarla, con un alargador no anda, en otra si.</p><p><br /></p><p>2022-10-23, por si algún día retomo https://hackaday.io/project/179868-all-about-laptop-display-reuse/log/193081-common-lvds-laptop-panel-pinouts<br /></p><p><br /></p><p><br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-63470013458975580892022-05-04T18:40:00.000-03:002022-05-04T18:40:02.095-03:00Parte de Flisol 2022 <p>En esta oportunidad expuse un mezcladito de varios open:</p><p><b><i>Open HW/Core/SW: SoC ICICLE con CPU RISC-V en EDU-CIAA-FPGA</i></b><br /></p><p>A mi propuesta original que incluía el ataque mostrado en H4CK3D 2021, el Profesor Matías me recomendó podarla para que sea menos técnica. Esa poda fué insuficiente, ya el título es bastante largo y complicado, a la mayor parte de la asistencia no era un tema que le interesara, no importa, para FLISoL 2023 tengo pensado algo más apropiado.</p><p> </p><p>Mi idea fue ir evolucionando distintas implementaciones de la luz ondulante de K.I.T.T. hasta llegar a un softcore en FPGA, aprovechando el trabajo de un montón de gente:</p><p> </p><p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyEcEM7T3jvHvaIM116VeZB4d6lTbM5RqgXV_vA6EQNgsQdInbiQKPpM1CTiE9EIE6gYH6n1nq3Iw0I4q25NruV2niHZ-webCE_D7GLfKFRbfoLPEvTxJPabLRWP8HXtDyVd5yi1A-TWT0j_0A4WRRMC-tnKtsSqTAD37bsg-20ZopfQtgVUmRYdm-Rg/s1034/historia.png" style="margin-left: auto; margin-right: auto;"><img alt="Historia" border="0" data-original-height="569" data-original-width="1034" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyEcEM7T3jvHvaIM116VeZB4d6lTbM5RqgXV_vA6EQNgsQdInbiQKPpM1CTiE9EIE6gYH6n1nq3Iw0I4q25NruV2niHZ-webCE_D7GLfKFRbfoLPEvTxJPabLRWP8HXtDyVd5yi1A-TWT0j_0A4WRRMC-tnKtsSqTAD37bsg-20ZopfQtgVUmRYdm-Rg/w555-h305/historia.png" title="Historia" width="555" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Historia<br /></td></tr></tbody></table></p><p> Lo rojito a la derecha era mi objetivo, lo expuesto en <a href="https://seguridad-agile.blogspot.com/search/label/h4ck3d" target="_blank">H4CK3D 2021</a><br /></p><p> </p><p>La primera versión es con componentes digitales, la hice hace casi 35 años, un registro de desplazamiento con unas puertas OR animadas a continuación, con un 555 para el clock, unos OR, un flip flop y algún capacitor para inyectar el primer bit.</p><p>Ese bit entra en la primera posición del registro de desplazamiento y en cada tick del clock se va moviendo, con la salida conectada a la entrada con un OR al flip flop que salvo en el arranque siempre está en cero, lo tenemos para siempre. Yendo hacia los leds, con los OR de la derecha transformamos el movimiento en un aparente ida y vuelta.<br /></p><p></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjxp5Szdtlex5JwJWjle4FIKNMHdmDAiJmzutwnHtDAdETronpgJiSrf5-TPKjrikk-ctmH3lQKm-nTOh9SqkiOlSYDnXk5VH0dYPrmkfWq9-m10XGvD8saj98diVOatTo9VE25hEx3DAZPodGYwk7RBg8RBqvr7hF4CEoPQvlXiJIfsaCb0hlhhBPBw/s500/kitt.gif" style="margin-left: auto; margin-right: auto;"><img alt="K.I.T.T. con compuertas digitales" border="0" data-original-height="384" data-original-width="500" height="289" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjxp5Szdtlex5JwJWjle4FIKNMHdmDAiJmzutwnHtDAdETronpgJiSrf5-TPKjrikk-ctmH3lQKm-nTOh9SqkiOlSYDnXk5VH0dYPrmkfWq9-m10XGvD8saj98diVOatTo9VE25hEx3DAZPodGYwk7RBg8RBqvr7hF4CEoPQvlXiJIfsaCb0hlhhBPBw/w375-h289/kitt.gif" title="K.I.T.T. con compuertas digitales" width="375" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">K.I.T.T. con compuertas digitales<br /></td></tr></tbody></table><br /> <p></p><p>Comparando precios, el costo es similar a implementarlo con un microcontrolador. Ponemos un bit en uno y lo vamos desplazando para un lado hasta detectar que llegó al punto deseado, ahí invertimos el sentido del movimiento, para siempre.<br /></p><p></p><p><br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6jkQ2wCaxQ9fMlzkm2tsL7cI63kLCrcTpRQv4ti3by0Q4I-0_jsjBGPdoh04j3m17HI8N1fvHn-4Llb-w4PD_Z9k5yX6XD3-CMTHocpU_DC6o8YFQaVatXc-2B-vUnV2wIP4RYajSe19DXWELRmwz-juLij50-6BmPkDCkaORUE9DLOfhj6wVcwS2Kg/s873/kitt_cpu2.gif" style="margin-left: auto; margin-right: auto;"><img alt="K.I.T.T. con microcontrolador y lógica específica" border="0" data-original-height="382" data-original-width="873" height="205" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6jkQ2wCaxQ9fMlzkm2tsL7cI63kLCrcTpRQv4ti3by0Q4I-0_jsjBGPdoh04j3m17HI8N1fvHn-4Llb-w4PD_Z9k5yX6XD3-CMTHocpU_DC6o8YFQaVatXc-2B-vUnV2wIP4RYajSe19DXWELRmwz-juLij50-6BmPkDCkaORUE9DLOfhj6wVcwS2Kg/w469-h205/kitt_cpu2.gif" title="K.I.T.T. con microcontrolador y lógica específica" width="469" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">K.I.T.T. con microcontrolador y lógica específica<br /></td></tr></tbody></table><p></p><p>El programa es corto pero complicado e inadaptable a otros patrones. Una versión mejor aunque te indigne desde el punto de vista de la programación es:</p><p><span style="font-family: courier;">while (true) {<br /> gpio_A.out(1);<br /> delay(DELAY);<br /> gpio_A.out(2);<br /> delay(DELAY);<br /> gpio_A.out(4);<br /> delay(DELAY);<br /> gpio_A.out(8);<br /> delay(DELAY);<br /> gpio_A.out(16);<br /> delay(DELAY);<br /> gpio_A.out(8);<br /> delay(DELAY);<br /> gpio_A.out(4);<br /> delay(DELAY);<br /> gpio_A.out(2);<br /> delay(DELAY);<br /> gpio_A.out(1);<br /> delay(DELAY);<br />}</span> <br /></p><p>¿Por qué me atrevo a incluir esta manera? Pues por que es el precursor para esta version más linda, en lugar de código hardcodeado, la información está en un array:<br /></p><p><span style="font-family: courier;">unsigned int out[]={1,2,4,8,16,8,4,2,1};<br />int pos = 0;<br />int limit = sizeof(out)/sizeof(out[0]);<br /><br />while ( true) {<br /> gpio_A.out(1);<br /> delay(DELAY);<br /> ++pos;<br /> if (pos == limit) {<br /> pos = 0;<br /> }<br />}<br /></span><br /></p><p>y esto se parece mucho a la implementación nuevamente con componentes digitales.<br /></p><p></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid7WS2hbxOj_fkTFLiDSqiS8kW4QnYTt3icPCYUP8KGT9xwXjAvnLelyeteJfeEFYDsxCDaK3YG5asXT2c3AahFwzWFT3K9L51Cm1191_N-RB02Wy9k7aW7msoQTfrHpHcNExIMrytZMhxyy-yzOGQUg_X5Ioev4H3dkEg-z208cqrKel1f8R7SkcdFw/s724/kitt_counter.gif" style="margin-left: auto; margin-right: auto;"><img alt="K.I.T.T. con contador y memoria" border="0" data-original-height="317" data-original-width="724" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid7WS2hbxOj_fkTFLiDSqiS8kW4QnYTt3icPCYUP8KGT9xwXjAvnLelyeteJfeEFYDsxCDaK3YG5asXT2c3AahFwzWFT3K9L51Cm1191_N-RB02Wy9k7aW7msoQTfrHpHcNExIMrytZMhxyy-yzOGQUg_X5Ioev4H3dkEg-z208cqrKel1f8R7SkcdFw/w423-h185/kitt_counter.gif" title="K.I.T.T. con contador y memoria" width="423" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">K.I.T.T. con contador y memoria<br /></td></tr></tbody></table> <br /><p></p><p>Ahora, tanto en hardware como en software, podemos con gran facilidad mostrar otros patrones manipulando la memoria o el array según corresponda:</p><p> <br /></p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPvvCAmQtwWNFBnnvqb6bushhDQitF2X2gFGgr8q4ZCTichXrd21s9eQ_hjGjhzWhQQFDTH_O9VuFlESezlp84-dxmlpsgdi6hdTPSHa9NU1cnq5BVD6_5Qa7j2dCndOlXtv6wz-B1_so8coI01zSYB5nIzyHMK1_fFUwvtLV1U6zmRI-vMY32V0GcSQ/s724/kitt_counter_dual.gif" style="margin-left: auto; margin-right: auto;"><img alt="K.I.T.T. con contador y memoria y patrones arbitrarios" border="0" data-original-height="317" data-original-width="724" height="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPvvCAmQtwWNFBnnvqb6bushhDQitF2X2gFGgr8q4ZCTichXrd21s9eQ_hjGjhzWhQQFDTH_O9VuFlESezlp84-dxmlpsgdi6hdTPSHa9NU1cnq5BVD6_5Qa7j2dCndOlXtv6wz-B1_so8coI01zSYB5nIzyHMK1_fFUwvtLV1U6zmRI-vMY32V0GcSQ/w400-h175/kitt_counter_dual.gif" title="K.I.T.T. con contador y memoria y patrones arbitrarios" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">K.I.T.T. con contador y memoria y patrones arbitrarios<br /></td></tr></tbody></table><p></p><p></p><p> </p><p>En la charla acompañando a esta evolución también fui contando como funciona una computadora a un nivel más bajo, que me cuesta mucho convertir a este formato, quizás haga un video en algún momento, lamentablemente no pude grabar la sesión.</p><p><br /></p><p>Eso llevó a la explicación de FPGA y RISC-V, desembocando en el tema que me interesaba, la implementación primero en Verilog de la versión con lógica, como dispositivo incluido en el SoC icicle:</p><p>https://github.com/cpantel/evilCodeSequence/blob/master/kitt.sv<br /></p><pre>module kitt #( parameter BASETIME) (
input clk,
input reset,
output [4:0]display_out,
/* memory bus */
input [31:0] address_in,
input sel_in,
//input read_in,
//output logic [31:0] read_value_out,
input [3:0] write_mask_in,
input [31:0] write_value_in,
output logic ready_out
);
logic [25:0]q;
logic direction;
logic [4:0]display;
assign ready_out = sel_in;
assign display_out = display;
always_ff @(posedge clk) begin
if (reset) begin
display <= 1;
direction <= 1;
end else if ( q > ( BASETIME / 1000 * 300 ) ) begin
q <= 0;
if (direction ) begin
if ( display[4] ) begin
direction = ~ direction;
display <= display >> 1;
end else
display <= display << 1;
end else begin
if ( display[0] ) begin
direction = ~ direction;
display <= display << 1;
end else
display <= display >> 1;
end
end else begin
q <= q + 1;
display <= display;
end
end
endmodule</pre><p> </p><p>Y por software, de modo concurrente y absolutamente independiente, ejecutándose en la CPU:<br /></p><p> </p><pre>/*
This program implements a SW kitt
*/
#include <stdint.h>
#include "../memmap.h"
#include "../uart.h"
#include "../delay.h"
int main() {
uart_init();
uart_puts("KITT starting\r\n");
for (;;) {
LEDS = 1;
delay();
LEDS = 2;
delay();
LEDS = 4;
delay();
LEDS = 8;
delay();
LEDS = 4;
delay();
LEDS = 2;
delay();
uart_puts("KITT .\r\n");
}
}</pre><p> </p><p> </p><p>Si algo entendés de Verilog, te darás cuenta que ese dispositivo como que está en vano conectado a los buses, ya que no hay nada con lo que el programa en la CPU pueda interactuar. Es que me quedé sin tiempo, querría al menos haberle permitido cambiar la velocidad.</p><p>En una próxima entrega espero no muy lejana, mostraré la implementación de un nuevo dispositivo que he de llamar "sequencer", que consistirá en una lógica que lea un trozo de memoria y lo exponga en los leds (vía PMOD como es ahora kitt) y que desde el programa se pueda arrancar, detener, pausar, cambiar la velocidad y modificar esa memoria. <br /></p><p><br /></p><p> <br /></p><p> <br /></p><p><br /></p><br />Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-7072341308527305352022-04-29T19:44:00.010-03:002022-04-29T20:21:48.107-03:00Buscando capacitación introductoria de SQL<p>En el marco de las cosas que estoy haciendo de <a href="https://seguridad-agile.blogspot.com/search/label/iot" target="_blank">IOT</a>, andaba necesitando hallar capacitación gratuita de SQL para recomendar y lo primero que se me ocurrió fue buscar en Oracle, ya que tiene OracleDB y también MySQL. De paso busqué en Udemy filtrando con free, esta es mi experiencia. Aclaro que mi visión de todos estos cursos es un tanto limitada pues yo ya sé SQL, como que sólo puedo decir más o menos que tan completos o comprensibles son, destacando cuando hay algo interesante.<br /></p><p> </p><h2 style="text-align: left;">Oracle <br /></h2><p>El curso que hallé es <a data-saferedirecturl="https://www.google.com/url?q=https://devgym.oracle.com/pls/apex/dg/class/databases-for-developers-foundations.html&source=gmail&ust=1646853397263000&usg=AOvVaw3IGzX9oaLXAl0WZ1L9YP3R" href="https://devgym.oracle.com/pls/apex/dg/class/databases-for-developers-foundations.html" target="_blank">https://devgym.oracle.com/pls/<wbr></wbr>apex/dg/class/databases-for-<wbr></wbr>developers-foundations.html</a> dice que se puede hacer en unas 6 horas. Al comienzo me agarró una sensación de que aunque simpático era medio inusable, recién en el tercer bloque entré en sintonía. y empecé a considerarlo útil.<br /></p><p></p><p>Tenés que darte de alta en:</p><ul><li>https://www.oracle.com/index.html</li><li>view accounts</li><li>Oracle account</li><li>Create account<br /></li></ul><p>no hace falta cloud account, se puede usar gmail.<br /></p><p></p><p> </p><p>Tuve algunas dificultades con el SSO pero creo que fué más de capa ocho. Utilicé el <a href="https://seguridad-agile.blogspot.com/2019/08/preguntar-bien-para-aprender.html" target="_blank">método de preparar el mejor mensaje de consulta posible</a>, esto es revisar a conciencia cada paso imaginándo qué me iban a preguntar y llegué a que tenía mal puesta la dirección en el keepass, lo cual me daba un comportamiento errático porque a veces copiaba esta dirección y a veces la llenaba a mano, muy confuso y difícil de diagnosticar.<br /></p><p>Seguramente el comportamiento errático fue 100% por lo mío, pero como quedé medio traumatizado, hago el login en oracle.com y luego voy a cada subsistema.</p><div></div><div>Cada módulo tiene varias secciones:</div><div> </div><div><h4 style="text-align: left;">El video</h4></div><div> </div><div>Es muy simpático y aparentemente superficial, pero si prestás antención son muy didácticos.<br /></div><div> </div><div><h4 style="text-align: left;">Take live sql tutorial</h4></div><div> </div><div>Para los ejercicios tenés tres opciones, copio y pego:<br /></div><div> </div><div><ul><li><a href="https://cloud.oracle.com/free">Always free cloud services</a>. These allows you to create two free-forever <a href="https://www.oracle.com/database/autonomous-database.html">Oracle Autonomous Databases</a>.</li><li><a href="https://www.oracle.com/xe">Oracle Database XE</a>. A fully-featured free version you can download and install on your computer.</li><li><a href="https://livesql.oracle.com/">Live SQL</a>. This is a free, browser-based tool you can use to write SQL.</li></ul> </div><div> </div><div>Sólo probé la última. Cuando entrás en la sección arriba a la derecha te ofrece login al laboraratorio</div><div> </div><div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCZm4mtDhtoI0LwKN7rYhe-mZdy2FmbaoFe3sUdZN68zFvXJ9lH5i_poTLHbjbUEdj41LTdjeO8E7HVaR6A94OozRWCGyODMNXoMh7b0ZS73LsJf3b5P0nh0VYbBiUzhq7BdtySGZ18yMRDx2P3PsAlyM8DqXjY5-R8SFAc2iJjTJ9vqCxtkW3wk3iXQ/s385/Screenshot_2022-03-07%20Oracle%20Live%20SQL%20-%20Tutorial%20Table%20Design%20Databases%20for%20Developers.png" style="margin-left: auto; margin-right: auto;"><img alt="login" border="0" data-original-height="159" data-original-width="385" height="165" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCZm4mtDhtoI0LwKN7rYhe-mZdy2FmbaoFe3sUdZN68zFvXJ9lH5i_poTLHbjbUEdj41LTdjeO8E7HVaR6A94OozRWCGyODMNXoMh7b0ZS73LsJf3b5P0nh0VYbBiUzhq7BdtySGZ18yMRDx2P3PsAlyM8DqXjY5-R8SFAc2iJjTJ9vqCxtkW3wk3iXQ/w400-h165/Screenshot_2022-03-07%20Oracle%20Live%20SQL%20-%20Tutorial%20Table%20Design%20Databases%20for%20Developers.png" title="login" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">login</td></tr></tbody></table><br /> <br /></div><div> </div><div>Luego a la derecha te replica los enunciados que tenías, asi no tenés que estar yendo y viniendo de tab.<br /></div><div> </div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-TDmqGB8M8xIF6o-gh8SPlW-S1eYuGePo0Y5wm7QE7MUO8jbLVDomozSvdhMXP8Vg3OU2Eg1J0JiDr-RrOJUqGx-K7Gt0IGY6j_KvVDepgSQyKXjEMRxvy1h8baRGHSCnp13iPHjjSCCslCBnfR24OLAlho_zjRjfcw4r89WYJJIcucXvlSqfXWJLAg/s621/Screenshot_2022-03-07%20Oracle%20Live%20SQL%20-%20SQL%20Worksheet.png" style="margin-left: auto; margin-right: auto;"><img alt="enunciados" border="0" data-original-height="621" data-original-width="462" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-TDmqGB8M8xIF6o-gh8SPlW-S1eYuGePo0Y5wm7QE7MUO8jbLVDomozSvdhMXP8Vg3OU2Eg1J0JiDr-RrOJUqGx-K7Gt0IGY6j_KvVDepgSQyKXjEMRxvy1h8baRGHSCnp13iPHjjSCCslCBnfR24OLAlho_zjRjfcw4r89WYJJIcucXvlSqfXWJLAg/w298-h400/Screenshot_2022-03-07%20Oracle%20Live%20SQL%20-%20SQL%20Worksheet.png" title="enunciados" width="298" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">enunciados</td></tr></tbody></table><br /><div><br /></div><div> </div><div>Algunos tiene un botón de prerequistos. Todas las instrucciones las podés copiar y pegar o enviar directamente al editor, yo te recomiendo que las transcribas, es una manera de ir memorizando. <br /></div><div></div><div></div><div> </div><div><h4 style="text-align: left;">Further study</h4></div><div> </div><div></div><div>Respecto a esta sección, si estuviera corto de tiempo y tuviera que priorizar, les prestaría atencion a estos:<br /></div><div><div> <br /></div></div><div><br /></div><div>https://blog.jooq.org/say-no-to-venn-diagrams-when-explaining-joins/<br /></div><div>https://blog.jooq.org/a-beginners-guide-to-the-true-order-of-sql-operations</div><br /><div> </div><div>En general, cuando te referencia a <b><i>From Oracle Database 11g Release 2 Documentation Library</i></b> y <b><i>From Oracle-BASE</i></b> son algo heavy, es el manual.<br /></div><div> </div><div><h3 style="text-align: left;">No relacionales</h3></div><div> <br /></div><div>Menciona modelos no relacionales como Document Storage pero medio para apalearlos, obviamente son los amigos relaciones.<br /></div><div> </div><div><br /></div><div>Si tu objetivo es el mismo que yo exploré, que es tener una idea de cómo operar sin meterte en detalles finos como los distintos tipos de bases de datos, o sea, si con </div><ul style="text-align: left;"><li>create table</li><li>insert</li><li>select</li><li>update</li><li>delete</li><li>una idea básica de cómo modelar y normalizar</li></ul><div>te contenta y no partís completamente de cero, te puede servir. No le prestaría mucha atención al módulo de multi insert. Si lo tomás por favor dejame un comentario.</div><div><br /></div><div><h2 style="text-align: left;">Cursos de Udemy</h2></div><div><br /></div><div>Udemy no es gratis, pero hay algunos cursos en algunos momentos que lo son, paso a detallar mi experiencia.</div><div><br /></div><div><h3 style="text-align: left;">A beginner's guide to MySQL</h3></div><div></div><div><br /></div><div>https://www.udemy.com/course/mysql-basics</div><div><br /></div><div>Media hora, inglés no nativo, mediocre.<br /></div><div><br /></div><div>Me hizo notar un detalle, que si no estás en embebidos ni se te pasa por la cabeza:</div><div><br /></div><div>Para ejecutar MySQL necesitás un sistema operativo, al igual que con Erlang. Resultaría interesante saber que opciones hay para un sistema embebido baremetal o con FreeRTOS. Es difícil de buscar pues "database server bare metal" te lleva a la definión en el contexto de bases de datos que es tener el sistema operativo y nada más que el servidor de base de datos.</div><div> </div><div>Otra dificultad es que al buscar "embedded database" ser refiere a un servidor que se puede incluir en la aplicación, por ejemplo para un servidor web en java existe Jetty, https://github.com/cpantel/boxControl.<br /></div><div><br /></div><div>Busquemos entonces con "sqlite freertos" y tras varios saltos llegamos a https://sqlite.org/custombuild.html, mmh, podría... hacerlo otra persona, olvidemos el asunto pero sin olvidar que existe una opción comercial https://www.ittia.com/products/ittia-db-iot que parece interesante.</div><div><br /></div><div>Volviendo al curso, empieza horrible, leyendo las presentación, luego mejora, va mostrando ejemplos de operaciones sin entrar en mucho detalle conceptual.</div><div><br /></div><div><br /></div><div>Lo que más me sirvió de toda esta experiencia es que repasé que para comparar con NULL es no es valor = NULL sino isnull valor, que de algún modo asocié en clase de Testing de Sistemas IoT que alguien había puesto en javascript:</div><div><br /></div><div><span style="font-family: courier;"><b>if (value != NaN)</b></span></div><div><br /></div><div>y cuando falló le pude sugerir que era</div><div><br /></div><div><span style="font-family: courier;"><b>if ( isNaN(value) )</b></span><br /></div><div><br /></div><div><br /></div><div><br /></div><div>Me quedaron pendientes para otra vida:<br /></div><div><br /></div><div><div><a data-saferedirecturl="https://www.google.com/url?q=https://www.udemy.com/course/curso-basico-de-introduccion-a-mysql-y-postgresql-en-linux/&source=gmail&ust=1646853397263000&usg=AOvVaw2p89EbKZKt4smvWpe0aZEX" href="https://www.udemy.com/course/curso-basico-de-introduccion-a-mysql-y-postgresql-en-linux/" target="_blank">https://www.udemy.com/course/<wbr></wbr>curso-basico-de-introduccion-<wbr></wbr>a-mysql-y-postgresql-en-linux/</a> 1 1/4 horas español</div><div> </div><div><a data-saferedirecturl="https://www.google.com/url?q=https://www.udemy.com/course/mysql-para-principiantes/&source=gmail&ust=1646853397263000&usg=AOvVaw2BjVeYnY091zWZFkV6XfqO" href="https://www.udemy.com/course/mysql-para-principiantes/" target="_blank">https://www.udemy.com/course/<wbr></wbr>mysql-para-principiantes/</a> 2 horas español</div><div><br /></div><a data-saferedirecturl="https://www.google.com/url?q=https://www.udemy.com/course/curso-de-mysql/&source=gmail&ust=1646853397263000&usg=AOvVaw19vSIRjn5s46d_XpFf_tfX" href="https://www.udemy.com/course/curso-de-mysql/" target="_blank">https://www.udemy.com/course/<wbr></wbr>curso-de-mysql/</a> 2 horas portugués</div><br />Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-70487355710587666022022-03-21T19:47:00.000-03:002022-03-21T19:47:19.635-03:00ESP32 con BMP280<p>En el marco del mínimo sistema IoT que he preparado para la futura materia Implementación de IoT, mientras se confeccionaba la lista de materiales para la carrera completa, hubo discusión acerca de si usar DHT11 o BMP280, ambos sensores de temperatura.</p><p><br /></p><ul style="text-align: left;"><li>El DHT11 es más barato, usa un solo pin, pero es menos preciso.</li><li>El BMP280 usa I2C, dos pines y se deduce de la frase anterior que es más caro y preciso.</li></ul><p></p><p> </p><p>Lo que no se deduce es que el primero mide temperatura y humedad y el segundo además presión, salvo el modelo que he conseguido que no mide humedad.</p><p>Al DHT11, dependiendo de la presentación hace falta agregarle un resistencia de entre 5 a 10 K, le he puesto unas SMD rescatadas de unas viejas placas de una central telefónica hallada en un volquete en el centro cerca del trabajo.</p><p> </p><p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEi1hIW8ZcQCcfva19QiXvmrMmqg8hEvDzZAdHL8KOMC7U-Cktlwpo9VMIhKSZ-vv8ZTleKvUT1MpXfPRxWVxvLijXSklj4s2T5tM_e_r-nEP7Q7i5MEOr8lpbfMi6wtoCHhIAbl3A9AEWiqKuskT9fssaSgrjaoHlbC7f5rcABVaPNjl0NUgYSq-zVlgA=s1280" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="DHT11 con resistencia SMD en los pines" border="0" data-original-height="1280" data-original-width="960" height="487" src="https://blogger.googleusercontent.com/img/a/AVvXsEi1hIW8ZcQCcfva19QiXvmrMmqg8hEvDzZAdHL8KOMC7U-Cktlwpo9VMIhKSZ-vv8ZTleKvUT1MpXfPRxWVxvLijXSklj4s2T5tM_e_r-nEP7Q7i5MEOr8lpbfMi6wtoCHhIAbl3A9AEWiqKuskT9fssaSgrjaoHlbC7f5rcABVaPNjl0NUgYSq-zVlgA=w365-h487" title="DHT11 con resistencia SMD en los pines" width="365" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">DHT11 con resistencia SMD en los pines<br /></td></tr></tbody></table><br /> </p><p>Había implementado todo para DHT11 pero entre que las otras materias no lo iban a usar y que para ESP32c3 no funcionó, incorporé el BMP280 al ESP32c3 y luego al ESP32, llegando al punto de poder retirar al DHT11 de la lista de materiales, discusión resuelta. De todos modos quedó en el repo disponible.</p><p><br /></p><p>Para la adaptación no hay ningún sufrimiento, hay que tomar la implementación con DHT11, borrar lo específico y reemplazarlo con el código de <a href="https://github.com/UncleRus/esp-idf-lib/tree/master/examples/bmp280" target="_blank">ejemplo de UncleRus</a>, que es básicamente un include, elegir los pines, armar una estructura, inicializar y leer.</p><p> </p><p>Respecto a los pines, a diferencia de DHT11 que usa un protocolo serial OneWire por software y se puede implementar en cualquier pin GPIO, BMP280 usa I2C por hardware, supuse que debía ser un subconjunto bastante menor.<br /></p><p></p><p></p><p><br /></p><p>Busqué en <a href="https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf" target="_blank">esp32-wroom-32_datasheet_en.pdf</a> y nada. Por suerte luego hallé un tutorial https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/ que decía que:</p><p> </p><p style="text-align: center;"><b><i>the SDA line may also be labeled as SDI and the SCL line as SCK. </i></b><br /></p><p> </p><p>y luego que se podían mapear a casi cualquier pin, supuse mal.<br /></p><p> <br /></p><p>Alguna líneas interesantes del código, en estas se determina que chip es: </p><p><br /></p><p><b><span style="font-family: courier;">bool bme280p = dev.id == BME280_CHIP_ID;<br />ESP_LOGI(TAG, \<br /> "BMP280: found %s\n", bme280p ? "BME280" : "BMP280"); <br /></span></b></p><p> </p><p>Luego se manifiesta en los valores que se pueden completar:</p><p><br /></p><p><b><span style="font-family: courier;">if (bmp280_read_float( \<br /> &dev, \<br /> &temperature, \<br /> &pressure, \<br /> &humidity) != ESP_OK) {<br /> ESP_LOGI(TAG, "Temp./press. reading failed\n");<br />} else {<br /> ESP_LOGI(TAG, \<br /> "Press: %.2f Pa, Temp: %.2f C", pressure, temperature);<br /> </span></b></p><p><b><span style="font-family: courier;">//if (bme280p) {<br /> sprintf(send_buf, REQUEST_POST, temperature , humidity );<br />//} else {<br />// sprintf(send_buf, REQUEST_POST, temperature , 0);<br />//}<br />} </span></b></p><p> </p><p>Lo dejé comantado pues la verdad es que me dá lo mismo mandar un cero hardcodeado que uno proveniente de la lectura, pero es incorrecto, debería no enviar el valor y/o agregar un campo con el tipo de sensor, para diferenciar el cero de cero humedad del cero de cero lectura.</p><p></p><p>Este sistema está todo hecho así, una reducción muy básica con múltiples oportunidades de completar y mejorar. Si te viene interesando, podés implementarlo <a href="https://github.com/cpantel/TSIOT/blob/main/README.md" target="_blank">siguiendo las instrucciones</a> y luego:</p><ul style="text-align: left;"><li>Agregar campos para reportar errores.</li><li>Agregar timestamp, pensá donde...<br /></li><li>Enviar JSON en lugar de x-www-form-urlencoded.<br /></li><li>Implementar algún DNS para usar nombres en lugar de IPs. </li><li>Usar https en lugar de http. <br /></li><li>Envíar vía MQTT en lugar de HTTP-POST.</li></ul><p>Truquito, en el router fijá la MAC address del servidor a una IP y te va a facilitar la vida.<br /></p><p>Se supone que quizás viste todo esto antes de llegar hasta acá:</p><p><br /></p><p><a href="https://seguridad-agile.blogspot.com/2022/03/ejemplo-de-esp8266-con-lectura-de-dht11planB.html">https://seguridad-agile.blogspot.com/2022/03/ejemplo-de-esp8266-con-lectura-de-dht11planB.html</a></p><p><br /></p><p><a href="https://seguridad-agile.blogspot.com/2022/02/ejemplo-de-esp32-con-lectura-de-dht11.html">https://seguridad-agile.blogspot.com/2022/02/ejemplo-de-esp32-con-lectura-de-dht11.html</a></p><p><br /></p><p><a href="https://seguridad-agile.blogspot.com/2022/02/primer-contacto-con-esp32.html">https://seguridad-agile.blogspot.com/2022/02/primer-contacto-con-esp32.html</a><br /></p><p><br /></p><p><br /></p><p><br /></p><p> <br /></p><p><br /></p><p><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-34144810578169881332022-03-19T21:02:00.009-03:002022-03-21T10:19:38.773-03:00Ejemplo de ESP8266 con lectura de DHT11: Plan BVenimos de un <a href="https://seguridad-agile.blogspot.com/2022/03/ejemplo-de-esp8266-con-lectura-de-dht11.html" target="_blank">momentáneo fracaso</a>.<br /><div><h2 style="text-align: left;"> </h2><h2 style="text-align: left;">Plan B</h2><h2 style="text-align: left;"> </h2></div><div>La
gente que viene de sistemas embebidos siente un cierto desprecio por
ArduinoIDE debido al alto nivel de abstracción, te pasaste años
estudiando como funciona una CPU, un microcontrolador, viendo como se
configura bit a bit cada dispositivo y ArduinoIDE te lo reduce a un
.setup() y obviamente en situaciones anormales no tenés recursos y
probablemente hayas perdido el RealTime.</div><div><br /></div><div>Se
parece al desprecio que sentimos los que venimos del otro lado al ver
como con cualquier gestor de Cloud cualquier iletrado puede armar cosas
bastante complejas, completamente inconcientes de cómo instalar y configurar un sistema operativo, base de datos, servidor de lo que sea, optimización y hardening. No importa, no quiero ninguna flame war.<br /></div><div><br /></div><div><br /></div><div>Te bajás ArduinoIDE de </div><div><br /></div><div><span style="font-family: courier;"><b>https://www.arduino.cc/en/software</b></span></div><div> </div><div>Descomprimís: <br /></div><div> </div><div><span style="font-family: courier;"><b>tar -xf ../Downloads/arduino-1.8.19-linux64.tar.xz </b></span></div><div><br /></div><div>Primero no hice el <b>install.sh</b> pues mirándolo por encima no parecía aportar nada, luego al ver que no aparecía el programmer en tools, ejecuté <b>arduino-linux-setup.sh</b>, pero no era por eso, el flash se hace directamente.</div><div><br /></div><div>Para ejecutar:<br /></div><div><br /></div><div><span style="font-family: courier;"><b>./arduino</b></span></div><div></div><div><br /></div><p>Hay que agregar el board con </p><ul style="text-align: left;"><li>File</li><ul><li>Preferences</li><ul><li>Additional Boars Manager URLs: </li></ul></ul></ul><p>ahí ponés</p><p></p><p><span style="font-family: courier;"><b>http://arduino.esp8266.com/stable/package_esp8266com_index.json </b></span><br /></p><p> </p><p>Luego vás a </p><p></p><ul style="text-align: left;"><li>Tools </li><ul><li>Board</li><ul><li>Board Manager</li><ul><li>search: esp8266</li><ul><li>esp8266 by ESP8266 Community <br /></li><ul><li>Install <br /></li></ul></ul></ul></ul><li>Board</li><ul><li>ESP8266 Boards</li><ul><li>ESP Generic Module</li></ul></ul><li>Port </li><ul><li>/dev/ttyUSB0</li></ul><li>Manage Libraries</li><ul><li>filtrar por dht</li><ul><li>DHT Sensor Library for ESPx </li><ul><li>install<br /></li></ul></ul></ul></ul></ul><p></p><div><br /></div><div>Para
el DHT quise apoyarme en lo <a href="https://seguridad-agile.blogspot.com/2020/05/regulando-ventilacion-de-un-switch.html" target="_blank">aprendido antes</a>,
pero no me sirvió, lo que hice fue incorporar <b>DHT Sensor Library for ESPx</b></div><div> </div><div> </div><div> </div><div>Y funcionó ok con el siguiente programa, que es una mezcla entre los ejemplos:<br /></div><ul style="text-align: left;"><li>File</li><ul><li>Examples</li><ul><li>Examples for Generic ESP8266 Module</li><ul><li>ESP8266HTTPClient</li><ul><li>PostHTTPClient</li></ul></ul><li>Examples for Custom Libraries</li><ul><li>DHT_sensor_library_for_ESPxDHT_ESP8266</li></ul></ul></ul></ul><div><br /></div><div><br /></div><div><b><span style="font-family: courier;">#include <ESP8266WiFi.h><br />#include <ESP8266HTTPClient.h><br /><br />#include "DHTesp.h" <br /> </span></b></div><div><b><span style="font-family: courier;"><b><span style="font-family: courier;">#define DEVICE_ID "61"<br />#define SERVER_IP "192.168.0.100:8080"<br /><br />#define STASSID "" <- recordá no versionar<br />#define STAPSK "" <- recordá no versionar<br /></span></b></span></b></div><div><b><span style="font-family: courier;"> <br />DHTesp dht;<br /><br />float humidity = 0.0;<br />float temperature = 0.0;<br /><br />void setup() {<br /> delay(10000);<br /><br /> Serial.begin(115200);<br /><br /> Serial.println("ESP8266 DHT HTTP POST");<br /> <br /> dht.setup(2, DHTesp::DHT11);<br /> delay(dht.getMinimumSamplingPeriod());<br /><br /> Serial.println(dht.getStatusString());<br /> humidity = dht.getHumidity();<br /> temperature = dht.getTemperature();<br /> Serial.print("Temperature : ");<br /> Serial.println(temperature);<br /> Serial.print("Humidity : ");<br /> Serial.println(humidity);<br /><br /> WiFi.begin(STASSID, STAPSK);<br /><br /> while (WiFi.status() != WL_CONNECTED) {<br /> delay(500);<br /> Serial.print(".");<br /> }<br /> Serial.println("");<br /> Serial.print("Connected! IP address: ");<br /> Serial.println(WiFi.localIP());<br />}<br /><br />void loop() {<br /> // wait for WiFi connection<br /> if ((WiFi.status() == WL_CONNECTED)) {<br /> WiFiClient client;<br /> HTTPClient http;<br /><br /> Serial.print("[HTTP] begin...\n");<br /> // configure traged server and url<br /> http.begin(client,</span></b></div><div><span style="font-size: xx-small;"><b><span style="font-family: courier;">"http://" SERVER_IP "/measurement"); //HTTP http.addHeader("Content-Type", "application/x-www-form-urlencoded"</span></b></span></div><div><b><span style="font-family: courier;"> );<br /><br /> Serial.print("[HTTP] POST...\n");<br /> // start connection and send HTTP header and body<br /> String post("id=");<br /> post += DEVICE_ID;<br /> post += "&t=";<br /> post += temperature;<br /> post += "&h=";<br /> post += humidity;<br /> int httpCode = http.POST(post);<br /><br /> // httpCode will be negative on error<br /> if (httpCode > 0) {<br /> Serial.printf("[HTTP] POST... code: %d\n", \</span></b></div><div><b><span style="font-family: courier;"> httpCode);<br /><br /> // file found at server<br /> if (httpCode == HTTP_CODE_OK) {<br /> const String& payload = http.getString();<br /> Serial.println("received payload:\n<<");<br /> Serial.println(payload);<br /> Serial.println(">>");<br /> }<br /> } else {<br /> Serial.printf( \</span></b></div><div><b><span style="font-family: courier;"> "[HTTP] POST... failed, error: %s\n", \</span></b></div><div><b><span style="font-family: courier;"> http.errorToString(httpCode).c_str());<br /> }<br /><br /> http.end();<br /> }<br /><br /> delay(10000);<br />}<br /></span></b></div><div></div><div><br /></div><div> </div><div>El código bastante parecido está en <a href="https://github.com/cpantel/ceiot_base" target="_blank">github</a> en la carpeta esp8266-arduino. En esp8266 dejé la fallada con esp-idf.<br /></div><div> </div><div>Nos quedó asi:</div><div> </div><div><span style="font-family: courier;"><b>~/esp/<br /> /esp-idf<br /> /esp-idf-lib<br /> /<span style="background-color: #fcff01;">ESP8266_RTOS_SDK</span><br /> /<span style="background-color: #04ff00;">arduino-1.8.19</span> <br /></b></span></div><div><span style="font-family: courier;"><b> /ceiot/<br /> /esp32<br /> /esp32c3<br /> /esp32s2<br /> /<span style="background-color: #fcff01;">esp8266</span></b></span></div><div><span style="font-family: courier;"><b><span style="background-color: #fcff01;"><span style="background-color: white;"><span> /<span style="background-color: #04ff00;">esp8266-arduino</span> </span></span></span></b></span> <br /></div><p><br /></p><p><br /><br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-67885067669801544142022-03-19T21:01:00.005-03:002022-03-19T21:18:48.882-03:00Ejemplo de ESP8266 con lectura de DHT11<p>Hace ya un tiempo exploré como lidiar con el entorno de desarrollo de ESP8266. Mientras incorporaba esa arquitectura a un proyecto educativo que consiste en leer un sensor de temperatura DHT11 y transmitirlo por HTTP-POST, me encontré con que las instrucciones <a href="https://seguridad-agile.blogspot.com/2020/06/primer-contacto-con-esp8266.html" target="_blank">que tenía</a> quizás ya no son vigentes.</p><p>El proceso es similar a
<a href="https://seguridad-agile.blogspot.com/2022/02/primer-contacto-con-esp32.html">cómo se hace con ESP32</a> y acá lo mostraré adaptado. </p><p> </p><h2 style="text-align: center;">No tomes este camino</h2><p>Si no tenés curiosidad por mis desgracias, andá directo al Plan B más abajo.</p><p>Si lo tomás, tené en cuenta que te rompe la instalación de <b>esp-idf</b>.<br /></p><p> </p><h2 style="text-align: left;">Plan A <br /></h2><p>La estructura de archivos que es esta:</p><p><span style="font-family: courier;"><b>~/esp/<br /> /esp-idf<br /> /esp-idf-lib<br /> /<span style="background-color: #fcff01;">ESP8266_RTOS_SDK</span><br /> /ceiot/<br /> /esp32<br /> /esp32c3<br /> /esp32s2<br /> /<span style="background-color: #fcff01;">esp8266</span></b> </span></p><p>Resaltado lo que vamos a agregar.</p><p><b>esp-idf</b> es la SDK para ESP32, <b>esp-idf-lib</b> son componentes de un tal RusLand.<br /></p><p>Vamos a suponer que al haber instalado previamente todo lo necesario para esp-idf, si siguieras los siguientes pasos en una máquina limpia quizás no alcanzaría.<br /></p><p></p><h3></h3><div><br /></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;">$ git clone https://github.com/espressif/ESP8266_RTOS_SDK.git</span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;">$ cd ESP8266_RTOS_SDK.git</span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;">$ git checkout origin/release/v3.4<br />$ sudo apt install python3-pip python-setuptools libncurses5-dev<br />$ /usr/bin/python3 -m pip install --user -r requirements.txt <br /></span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;">$ ./install.sh <br />$ . export.sh</span></b></span><br /></div><div><br /></div><div><br /></div><div>Mirando por encima <b>requirements.txt</b>, que es lo que consume <b>install.sh</b> apreciarás que hay poca superposición.<br /></div><div><br /></div><div> </div><div><b>export.sh </b>te genera un entorno para que funcionen los <b>make</b> posteriores y se debe ejecutar en cada terminal que abrás. Si te falla por que no encuentra <b>python</b>, la primera tentación es ponerse a modificar las referencias a <b>python</b> por <b>python2</b> o <b>python3</b> en mi caso, primero en <b>export.sh</b> y luego en otras partes. Mala idea, lo mejor, recordando que tengo armada una virtual sólo para esto, es:</div><div> </div><p><span style="font-family: courier;"><b>sudo ln -s /usr/bin/python3 /usr/bin/python</b></span></p><p></p><div>El problema de hacer esto es que te rompe luego lo que tengas para ESP32.</div><div><br /></div><div>Así que tenés que estar alternando con:</div><div><br /></div><div><span style="font-family: courier;"><b>sudo rm /usr/bin/python</b></span><br /></div><div><br /></div><div></div><div></div><div></div><div>Como no pienso hacer mucho es ESP8266, alternaré. Si luego se me ocurre algo mejor o alguien lo tiene, me lo pasa y lo pongo.<br /></div><div> </div><div>Si prestaste atención a cómo se hace en ESP32, habrás notado que acá no existe el paso para determinar que chip usas:<br /></div><div> </div><div><span style="font-family: courier;"><b>idf.py set-target esp8266</b></span></div><div><br /></div><div>Esto es porque hay múltiples ESP32, como ESP32, ESP32c3, ESPs2 para mencionar algunos y sólo hay un ESP8266.<br /></div><div><br /></div><div>Listo para el build. Pero antes, incorporemos el proyecto, lo que hay uno tiene la tentación de hacer es (no hacer):<br /></div><div> </div><div> </div><div><div><span style="font-family: courier;"><b>mkdir esp8266</b></span></div><div><span style="font-family: courier;"><b>cd esp32</b></span></div><div><span style="font-family: courier;"><b>cp CMakeLists.txt -r main/ Makefile ../esp8266</b></span></div><div><span style="font-family: courier;"><b>cd ../esp8266</b></span></div> </div><div> </div><div>Pero no, equivocado, lo que hay que hacer es:</div><div> </div><div><span style="font-size: x-small;"><b><span style="font-family: courier;">cp -r ../ESP8266_RTOS_SDK/examples/wifi/getting_started/station .</span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;">mv station esp8266<br /></span></b></span></div><div><span style="font-family: courier;"><span style="font-size: x-small;"><b># modificar el programa tal como con ESP32</b></span><br /></span></div><div> </div><div> <br /></div><div>Para la configuración de los componente, en este caso credenciales de WiFi:<br /></div><div> </div><div><b>make menuconfig</b></div><div><br /></div><div></div><div> </div><div>No te olvides de borrarlas al versionar .</div><div><br /></div><div>Finalmente, para que funcione la parte del DHT11, hay que tocar el Makefile:</div><div><br /></div><div><span style="font-family: courier; font-size: x-small;"><b>EXTRA_COMPONENT_DIRS += $(IDF_PATH)/../esp-idf-lib/components</b></span><br /><br /></div><div></div><div><br /></div><div>Y ahora si<br /></div><div><br /></div><div></div><div><b><span style="font-family: courier;">make </span></b></div><div><b><span style="font-family: courier;">make flash</span></b></div><div><b><span style="font-family: courier;">make monitor</span></b></div><div></div><div><br /></div><div><br /></div><div>No tan fácil...</div><div><br /></div><div>Habían varios errores simultáneos que me confundieron. Algunos relacionados con la inclusión de archivos, otros quizás relativos a los branches de cada repositorio, en <a href="https://groups.google.com/g/embebidos32/c/0-J7p5j5MGQ" target="_blank">una conversación en embebido</a>s quedó registrado parte de esto, no aporta que lo repita acá.</div><div> </div><div>Lo más significativo de esa conversación es que si hubiera leido el manual quizás hubiera detectado que hay componentes no soportados de esp-idf-lib en ESP8266 y que hay que excluirlos del proceso de compilación.<br /></div><div><br /></div><div>La receta resultante es, por ahora:</div><div> </div><div><div>Usar los tags v3.4 y v0.8.2 (esp-idf y esp-idf-lib respectivamente)</div><div> </div><div>En el Makefile, para que incluya esp-idf-lib:</div><div> </div><div><span style="font-size: x-small;"><b><span style="font-family: courier;">EXTRA_COMPONENT_DIRS += $(IDF_PATH)/../esp-idf-lib/components</span></b></span></div><div> </div><div>para que excluya los componentes no soportados: <br /></div><div></div><div></div><div></div><div></div><div><br /><span style="font-size: x-small;"><span style="font-family: courier;"><b>EXCLUDE_COMPONENTS := max7219 mcp23x17 led_strip max31865 ls7366r hts221 </b></span></span><br /></div> </div><div> </div><div>Aún así, aunque compila no funciona:</div><div> </div><div> </div><div></div><div></div><div>...a ver... <br /></div><div><br /></div><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgjBsKKJ_Ied3Xe--cF-N1M0aTDRoNyXNRfZFEwXzfVgbqZxo4NgXt8O_2YO2f7jWlmA8nEsCIFaLc1ctz-38uObXY0MUB2IFlEn7qhLaDEc-VVgbLJGSOKi89RuVlW5Ril-xrQjjcntii3S-E8fHZLUIWiwUBghaBYhvFx0GdnTMZRPbFxfyYG3w1dBw=s563" style="margin-left: auto; margin-right: auto;"><img alt="Reconectando..." border="0" data-original-height="200" data-original-width="563" height="177" src="https://blogger.googleusercontent.com/img/a/AVvXsEgjBsKKJ_Ied3Xe--cF-N1M0aTDRoNyXNRfZFEwXzfVgbqZxo4NgXt8O_2YO2f7jWlmA8nEsCIFaLc1ctz-38uObXY0MUB2IFlEn7qhLaDEc-VVgbLJGSOKi89RuVlW5Ril-xrQjjcntii3S-E8fHZLUIWiwUBghaBYhvFx0GdnTMZRPbFxfyYG3w1dBw=w496-h177" title="Reconectando..." width="496" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Reconectando...</td></tr></tbody></table><br /><div></div><br /><div> </div><div>Mmmh, fijate que intenta conectar a como dé lugar, habría que agregar un mensajito de log tal como he resaltado:<br /></div><div><br /></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;">static void on_wifi_disconnect(void *arg, </span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> esp_event_base_t event_base,<br /> int32_t event_id,</span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> void *event_data){<br /> system_event_sta_disconnected_t *event =</span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> (system_event_sta_disconnected_t *)event_data;</span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> </span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> <span style="background-color: #fcff01;">ESP_LOGI(TAG,</span> </span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> <span style="background-color: #fcff01;">"Wi-Fi disconnected reason %d\n\r",</span></span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> <span style="background-color: #fcff01;">event->reason);</span> <br /><br /> ESP_LOGI(TAG,"Wi-Fi disconnected, trying to reconnect...");<br /> if (event->reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT){<br /> /*Switch to 802.11 bgn mode */</span></b></span></div><div><span style="font-size: x-small;"><br /></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"><b><span style="font-family: courier;"> </span></b> esp_wifi_set_protocol(</span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> ESP_IF_WIFI_STA,</span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> WIFI_PROTOCOL_11B | </span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> WIFI_PROTOCOL_11G |</span></b></span></div><div><span style="font-size: x-small;"><b><span style="font-family: courier;"> WIFI_PROTOCOL_11N);<br /> }<br /> ESP_ERROR_CHECK(esp_wifi_connect());<br />}</span></b></span><br /></div><div><br /></div><div>Si querés ver que hace <b><span style="font-family: courier;">esp_wifi_connect</span></b>, no existe, me parece que está implementado en ROM o similar en el chip.<br /></div><div><br /></div><div>Ahora dice:</div><div><br /></div><div><span style="font-family: courier;"><b>phy_version: 1163.0, 665d56c, Jun 24 2020, 10:00:08, RTOS new<br />I (415) phy_init: phy ver: 1163_0<br />I (426) example_connect: Connecting to thebox...<br />I (3217) wifi:state: 0 -> 2 (b0)<br />I (4217) wifi:state: 2 -> 0 (200)<br />I (4218) example_connect: Wi-Fi disconnected reason 2<br /><br />I (4220) example_connect: Wi-Fi disconnected, trying to reconnect...<br />I (6286) example_connect: Wi-Fi disconnected reason 205</b></span><br /></div><div><br /></div><div></div><div><br /></div><div><br /></div><div>Las <b>event-reason</b>s están en <b>components/esp8266/include/esp_wifi_types.h</b>, son un montón y se llaman <b>wifi_err_reason_t</b>.<br /></div><div><br /></div><div><b><span style="font-family: courier;">WIFI_REASON_AUTH_EXPIRE = 2</span></b></div><div><b><span style="font-family: courier;">WIFI_REASON_CONNECTION_FAIL = 205</span> </b></div><div><br /></div><div> </div><div>¿Qué si probé con reiniciar el router? ¡Claro! antes de usar linux usaba windows...</div><div><br /></div><div>Probé con</div><div> </div><div>make menuconfig -> </div><div> Component config ---><br /></div><div> Wi-Fi ---> <br /></div><div>[*] Enable WiFi debug log (ESP8266_WIFI_DEBUG_LOG_ENABLE)</div><div> <br /></div><div> </div><div>Pero no hallé como acceder o interactuar con ese log.</div><div> </div><div><br /></div><div> </div><div>Me pasé al ejemplo más básico, <b>station</b>, para reducir variables, probé todo lo que sigue: <br /></div><div> </div><ul style="text-align: left;"><li>ESP8266_PHY_MAX_WIFI_TX_POWER, ya está en 20, pasé a 21Cambié de canal en el AP, del 11 al 1 y al 6 </li><li>Puse modo B only</li><li>Puse modo G only</li><li>Puse modo N only </li><li>AES en lugar de TKIP + AES</li><li>a 30 centímetros del AP</li><li>Branches v3.3 y v3.3-rc1</li><li>Cambié de router</li><li>Probé con 20 y 40 MHz de ancho </li></ul><div><br /></div> <div>No encuentro más recursos, sólo esta pista:<br /></div><div><br /></div><div> <b><code>WiFi.hostname("ESP-host");</code> before <code>WiFi.begin(ssid, password);</code></b></div><div><br /></div><div>Pero eso es con ArduinoIDE.</div><div><br /></div><div>Me quedaría armar un Access Point para diagnosticar desde ese lado o buscar como hacer sniffing, quedará para otra vez.</div><div><br /></div><div><a href="https://seguridad-agile.blogspot.com/2022/03/ejemplo-de-esp8266-con-lectura-de-dht11planB.html" target="_blank">Vamos al Plan B</a>...</div><div><br /></div><div><br /></div>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0tag:blogger.com,1999:blog-6148370834456516013.post-41029252758838219972022-03-03T08:12:00.000-03:002022-03-03T08:12:28.755-03:00Por qué IoT y sistemas embebidos si trabajás en un banco<p>...o cualquier trabajo que aparentemente no tenga sistemas embebidos ni nada que ver con IoT. <br /></p><p> </p><p>Buena pregunta, un banco es el terreno del mainframe rodeado de bases de datos y servidores diversos que atienden vía web en el home banking, en las aplicaciones mobile, por terminales diversas a empleados, en ATM, en encoladores, dispensadores de tarjetas y ahí ya te estoy contestando un poco, pues todos estos últimos vienen a ser el terreno de los SSEE.</p>Que un sistema esté implementado con "commodity hardware", off-the-shelf cómo le dicen, es una cuestión completamente táctica, no afecta su esencia.<p>Tenemos a grandes rasgos que si una computadora lo que más hace es operaciones específicas atendiendo quizás multitud de orígenes, le decimos servidor. Puede tener pantalla y teclado, es irrelevante. Puede ser una raspberry-pi, su función es servidor. Si tenemos un montón dependiendo de como estén organizadas, son cloud, farms, supercomputadoras.<br /></p><p>Tenemos que si tiene KVM (Keyboard Video Mouse - Teclado Video Mouse) y es de uso general, ya sea en formato laptop o desktop, le decimos "Estación de Trabajo", la compu, una PC.</p><p>Si en lugar de KVM tiene una pantalla táctil y un par de botones, funciona con batería, entra en el bolsillo y tiene wifi y pegada una línea de teléfono somos lo suficientemente smart para denominarlo "mobile".</p><p>Una y otra vez, no dejan de ser computadoras.</p><p>Cuando tenemos una computadora que tiene un teclado loco o ni tiene, que anda en batería encima de un poste o bajo tierra, que maneja a una máquina, que es tan chica que apenas le entra un hello world, que la mayor parte del tiempo se la pasa durmiendo, se despierta unos milisegundos, mide un sensor, lo transmite y vuelve a dormir, que desde que se prende ejecuta el mismo conjunto de programas en lugar de ir ejecutar programas arbitrarios, que en realidad son varias distintas haciendo lo mismo y comparando que estén haciendo realmente lo mismo, que es tán... lo que sea, estamos en el terreno de los SSEE.</p><p>Si no tiene nada salvo un montón de conexiones de red, como un
switch, un router, un firewall, balanceador de carga, es equipamiento de
comunicaciones, SE.<br /></p><p></p><p></p><p>Entonces, una PC común dentro de un ATM, un sistema de dispensador de turnos o de reconocimiento facial, no es una PC, es un SE. Para contrastar, una raspberry-pi a la cual le conectás KVM y no usas los GPIO (los cablecitos para leer botones y prender leds) para mi deja de ser un SE y pasa a ser una PC.</p><p>No es lo mismo sin embargo un SE que nace como tal y se usa como SE que usar una PC con el mismo propósito. Esto es en parte por el hardware, que en la PC es de uso general, debe funcionar lo mejor posible en situaciones muy distintas. Contrastando, los SSEE acostumbran usar hardware especializado para lo que van a hacer, pueden estar optimizados para bajo consumo, tiempo real, mínima latencia, infernal paralelismo, ínfimo precio, obviamente no todos a la vez, es como la regla del PM: rápido, barato, bueno, elegí sólo dos.<br /></p><p>En el motor de un auto debe ir inevitablemente un SE, pues una PC no soporta las vibraciones, temperaturas y ruido eléctrico ni los requerimientos de tiempo real de que la chispa ocurra en ese preciso instante.</p><p>En un equipo médico de soporte vital debe ir un SE, pues no puede colgarse ni ponerse a hacer otra cosa que la que está haciendo.<br /></p><p></p><p>En un ATM, será más lenta la PC o consumirá más que el SE, pero no hay actividades críticas a nivel de hardware. En realidad si hay pero a nivel de cada dispositivo, el lector de la autenticación, el lector de cheques, el expendedor, que tienen su propio SE, orquestados por la PC. Es por eso que en un ATM se puede usar una PC, por que las actividades especiales no las lleva adelante la PC, si no estos SSEE específicos.</p><p>No es nada novedoso, incluso dentro de la PC hay SSEE, como la controladora de disco rígido, ya he lidiado con eso al intentar <a href="https://seguridad-agile.blogspot.com/2020/04/rescatando-un-8051.html" target="_blank">rescatar un microcontrolador 8051 de un disco</a>. El teclado tiene un microcontrolador, es un SE.<br /></p><p>Siguiendo por el resto del banco, de modo directo tenemos esos SSEE y de modo indirecto, de soporte tenemos cámaras IP, sistemas de alarmas, control de acceso, la controladora de los ascensores si los hay, aire acondicionado.</p><p>Si por algún motivo se pudiera saltar de la red de las cámaras IP o cualquier otro sistema de soporte a las otras redes, entonces la seguridad de esas redes nos interesa tanto como la propia del "negocio".</p><p>Este salto puede ser por compartir la red aunque esté segregada de modo lógico (buscá VLAN), puede haber un componente con una patita en cada red, pueden tener un almacenamiento o servidor común en Cloud.</p><p></p><h3 style="text-align: left;"> </h3><h3 style="text-align: left;">Falta IoT</h3><h3 style="text-align: left;"> </h3><p></p><p>IoT parece ser un montón de dispositivos (evidentemente SSEE) comunicándose entre ellos o con servidores, recolectando información y actuando. Por ejemplo ese coso que se llama Alexa que le decís "quiero escuchar música de ascensor" y te pasa esa música por el SmartTV, o que controles algún automatismo de tu casa desde el SmartPhone o que si bajó el nivel de humedad de las macetas y no hay pronóstico de lluvia cercano, se abra una válvula y haya riego.</p><p>La clave que diferencia o mejor dicho lo que extiende SSEE a IoT es la comunicación. Un lavarropas por mucho microcontrolador que tenga, si no tiene conexión a algo, no es IoT. Y claramente la comunicación no es un mero capricho de la gente de marketing, es para poder controlar el lavaropas remotamente y/o poder obtener telemetría. <br /></p><p>Un componente con un protagonismo no del todo evidente en todos esos ejemplos es que buena parte de la inteligencia no está en los dispositivos, está en algún servidor o conjunto, ya sea en Cloud o en un servidor local. Y lo interesante es que la complejidad y extensión de estos servidores es probablemente siempre superior a la de los dispositivos. Y quizás fundamentalmente, los datos y el control están en esos servidores.<br /></p><p>En el caso de Alexa, el dispositivo probablemente sea un microcontrolador con un parlante, un micrófono, una conexión wifi y otra bluetooth. El código seguramente sea un loop que va comprimiendo y transfiriendo el audio a Cloud, donde es reconocido y se generan los comandos que luego se envían al SmartTV, sistema un poco más complicado pero no por el aspecto IoT, la parte IoT es sólo que ejecute una acción que normalmente se hace manualmente. De hecho, si se usara siempre con Alexa, se podría simplificar, ser menos Smart.</p><p> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEguG-9mTIMMDMYSticCYXqU5Wd6TzoXJpv2mi91twK8mF8k2AXfYCdCM9w3XiTfblV44IxK7q8Y7NrpAbNx9gk0-TEYL3DBz9pITaNsKn-aid1jI0N9qrbQAwJplZTeTL-zVIUenitn9XbA82disf-mHfTLPwvJKh6St-gYmjt7INhWaV5edoeXFR8kDw=s469" style="margin-left: auto; margin-right: auto;"><img alt="Visión IoT vs SSEE" border="0" data-original-height="373" data-original-width="469" height="318" src="https://blogger.googleusercontent.com/img/a/AVvXsEguG-9mTIMMDMYSticCYXqU5Wd6TzoXJpv2mi91twK8mF8k2AXfYCdCM9w3XiTfblV44IxK7q8Y7NrpAbNx9gk0-TEYL3DBz9pITaNsKn-aid1jI0N9qrbQAwJplZTeTL-zVIUenitn9XbA82disf-mHfTLPwvJKh6St-gYmjt7INhWaV5edoeXFR8kDw=w400-h318" title="Visión IoT vs SSEE" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Visión IoT vs SSEE<br /></td></tr></tbody></table><p></p><p> </p><p>Este gráfico es una simplificación extrema, las formas tan pronunciadas son para no entrar en discusiones de detalles de cuál sería la verdadera forma, si más redonditas. Pensá que SSEE en principio no tiene nada que ver con los servidores de la izquierda, pero para comprender bien el funcionamiento de estos tenés que saber de arquitectura de computadoras y eso claramente no es terreno de IoT, si de SSEE, pues una vez que comprendiste un ARM o un RISC-V estás a centímetros de comprender un x86, si es que los servidores no son ARM.<br /></p><p></p><p>Entonces, el eje del conocimiento de IoT termina siendo en realidad el conocimiento de la infraestructura de soporte, condimentado con los casos de Edge Processing, donde la inteligencia vuelve al dispostivo, esto es por ejemplo cuando se transmite un video sólo cuando se detecta un evento complejo como el reconocimiento de que hay una cara. Se envía al servidor la foto y este reconoce la identidad de la cara. Reconocer que hay una cara no es tarea menor y ahorra un montón de ancho de banda.<br /></p><p>O un vehículo autónomo, a dónde va a ir se lo dice el sistema central, quizás más o menos por dónde, pero el cómo, el evitar chocar lo va a resolver por si mismo. <br /></p><p>Otra característica que mueve el eje es cuando hay condiciones "especiales", para llamarlas de alguna manera, esto es, por ejemplo cuando hay distancias apreciables y la fuente de alimentación es restringida, lo cual te obliga a usar protocolos de bajo consumo, ya no es entonces uso WiFi cero cerebro, hay que estudiar un poquito mejor el asunto.</p><p>Y a lo que se está yendo, pero me parece que aún no es tan importante, es la coordinación autónoma entre los dispositivos. Por ahora es más sencillo que el sensor de humedad le diga al servidor que la maceta está seca y éste le diga a la válvula de riego que se abra. Es que ni el sensor ni la válvula saben cual es el pronóstico para las próximas horas. Y un auto claramente puede negociar mucho mejor el cruce en una calle sin semáforo comunicándose con los autos cercanos, pero no puede anticipar una congestión un kilómetro más adelante así.</p><p></p><p></p><p>Volviendo a un banco, tenemos que aunque un poco distintos, con respecto a las estaciones de trabajo, notebooks y SmartPhones al menos, se tiene un problema similar al de IoT respecto al inventario, tracking, actualización de imagen en el caso de IoT más básico, del sistema operativo y aplicaciones en no IoT, autenticación de los dispositivos.</p><p>Respecto a los ATM el aspecto de desatendido y que se protejan de ataques físicos, no sólo físicos físicos, para eso está el blindaje, sino para que no se les haga escupir billetes conectándole un cable en el expendedor.<br /></p><p></p><p></p><p></p><p>Asi que aunque en mi caso lo que prima es mi interés natural por SSEE e IoT, a cualquier persona técnica lo que aprenda de arquitecturas y seguridad le servirá de modo directo pues no dejemos de ver que los ATM son los que entregan la plata y aunque parezcan PCs adornadas, son SSEE. El resto forma parte de la superficie de ataque y en todo caso servirá de modo indirecto pues se aprende mucho al cruzar campos de conocimiento.<br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com2tag:blogger.com,1999:blog-6148370834456516013.post-37691870351996633632022-03-02T09:18:00.004-03:002022-03-02T09:18:45.956-03:00Vulnerabilidades masivas, continuación<p></p><p>Para quienes no les ha convencido mucho <a href="https://seguridad-agile.blogspot.com/2022/02/talento-vs-kpi-una-muerte-es-una.html" target="_blank">talento vs kpi</a> y se resisten a la aplicación de parches de aplicaciones de terceros a escala, llamemosla, industrial, va un poco más de contexto relativo a cómo se descubren las vulnerabilidades y se puede reaccionar para mitigarlas.<br /></p><p><br /></p><p>A la hora de localizar vulnerabilidades, veo que hay como tres "zonas":</p><p><br /></p><ul style="text-align: left;"><li>Aplicaciones y componentes de terceros, esto incluye sistemas operativos y aplicaciones de usuario tipo browsers, ofimática, entornos locales de desarrollo e IDEs.<br /></li><li>Su uso y configuración.</li><li>Nuestras aplicaciones y componentes propios.<br /></li></ul><p> </p><p>El tercero es el terreno del Pentesting, nuestro, lo primero es el Pentesting de sus respectivo creadores u otros interesados, que difícilmente tengan acceso a lo tercero, fin del asunto por hoy.<br /></p><p> </p><p>Hay varias maneras de "descubrir" las vulnerabilidades de modo (semi)automatizado, con las inevitables superposiciones, cada manera puede utilizar recursos de las otras.<br /></p><p><br /></p><p>Por inventario, implica un grado de madurez infernal, es saber que aplicación con qué componentes está desplegada en cada equipo.</p><p><br /></p><p>Por revisión de repositorios y filesystems, mediante la inspección de maven o node. Te fijás en los entornos previos el código fuente y las dependencias. Por includes/requires, por greps. Por <b>apt list --instaled</b>, por <b>yum list installed</b>, <b>rpm -qa</b>, <b>/var/log/packages</b>, hashes de librerías vulnerables, lo que sea.<br /></p><p>Esta revisión se hace de dos maneras, mediante inspección de cada servidor por acceso remoto, tipo ansible con ssh. Se revisa qué componentes están presentes y las configuraciones. Puede ser una tarea manual, tanto rutinaria como exploradora que alimente a las automatizadas.<br /></p><p>La otra manera es inspección de cada servidor por agente, esto es, hay un programa en cada equipo que recibe reglas y busca. Estas reglas se consiguen <br /></p><p>La diferencia entre las maneras autenticada/agente radica en el impacto en la topología de la red, los agentes sólo requieren una conexión saliente, los accesos remotos entrante, quizas jump servers, pueden afectar la aislación que tan cuidadosamente habíamos armado.<br /></p><p>Por revisión perimetral, banners y otros indicadores cuando no hay acceso autenticado como los dos anteriores.<br /></p><p><br /></p><p>Todas estas medidas aumentan la superficie de ataque: nuevos accesos de red, nuevos programas instalados, scripts que se ejecutan con privilegios que quizás no son tan bajos como desearíamos. Esos sistemas centralizadores pueden abrir la puerta a nuevos ataques y seamos francos, las aplicaciones de seguridad no necesariamente son seguras, son tan solo otras aplicaciones, pasan a engrosar nuestro inventario de activos sensibles.<br /></p><p><br /></p><p>La mayor parte de la investigación de seguridad sobre la primera zona es llevado adelante por terceros. Nuestro trabajo, que puede estar resuelto automáticamente, es tener el inventario para saber si y dónde aplicar aplicar los parches cuando aparecen. Ese "cuando aparecen" es crítico, pues si tomamos este ciclo de vida de una vulnerabilidad:</p><p> </p><p><span style="font-family: courier;"><b>existencia | descubrimiento | parche |<span style="background-color: #04ff00;"> aplicado</span><br /> |<span style="background-color: red;"><-- difusión --></span>|</b><br /><br /></span></p><p> <br /></p><p>tenemos una ventana de oportunidad entre que se hace pública y apliquemos el parche en el mejor de los casos, si es que no se hace pública antes que el parche esté disponible.</p><p> </p><p><b><span style="font-family: courier;">existencia | descubrimiento | parche |<span style="background-color: #04ff00;"> aplicado</span><br /> |<-- difusión -->|<br /> |<span style="background-color: red;"> </span>|<span style="background-color: #fcff01;"> workaround</span>|</span></b></p><p> </p><p>Mientras el parche no esté disponible podemos tomar medidas mitigatorias:</p><p> </p><ul style="text-align: left;"><li>Desactivar componente</li><li>Cambiar configuración <br /></li><li>Proteger en WAF/FW/IPS</li></ul><p> </p><p>Desde el mantenimiento del inventario centralizado hasta el salir en el momento a ver donde está tal componente, requiere un cantidad de esfuerzo, que puede no estar priorizado, recordemos que lo importante es que "el negocio funcione", los aspectos tecnológicos estan subordinados a ello y los de seguridad quedan como puro gasto.</p><p>Si tenés una política de mantenimiento actualizado, disminuye la necesidad del inventario preciso y pasa a tomar un mayor protagonismo la aplicación de protección perimetral (WAF, IPS, FW), que es la más sencilla pero sólo se debe aplicar si hay
componentes, pues introducen latencia y potenciales falsos negativos,
cuanto más larga sea la lista de reglas, más va a demorar el mensaje en
circular.</p><p>Quizás la mejor táctica sea aplicar toda nueva regla sin
evaluar si la necesitás y luego ir viendo si conservarla. Esa purga
podría traer el problema de que si a futuro se agrega un nuevo tipo de
servicio, no estén las reglas y quede expuesto. Igual en teoría uno no
agregaría servicios viejos, pero podría ser resultado de una migración
de algo.</p><p><br /></p><p>Lo que nos resta es el uso y configuración de los componentes de terceros, ahí es donde entra el Talento mencionado en la entrada anterior, donde aplica el "esta vulnerabilidad sólo está activa si está presente la configuración tal", que por un lado es un mitigante pues nos puede ahorrar tener que lidiar en lo inmediato con la vulnerabilidad, pero por el otro nos genera el trabajo de tener que evaluar si está presente la configuración tal y en caso de que estuviera y no se pudiera cambiar, de todos modos hay que aplicar la actualización, haciendo que esa evaluación haya sido trabajo perdido. Además, quizás ahora no está la configuración así, pero quién sabe como estará mañana. Por eso soy partidario de analizar menos y actualizar más.<br /></p>Carlos Pantelideshttp://www.blogger.com/profile/17961973028243389444noreply@blogger.com0