jueves, 6 de octubre de 2016

Arduino - Comunicacion con PLC industriles.

Me encontre este blog del señor Cartiman Iman de Indonesia y realizo un excelente trabajo en comunicacion entre Arduino y PLC su web es http://program-plc.blogspot.com.ar su google+ https://plus.google.com/+CartimanIman#+CartimanIman/posts.

Voy a traducir sus publicaciones y realizar las practicas con PLC ya que tengo acceso a PLC5 micrologic 1000 y micrologix 1100 de Allen Bradley para unas interfaces HMI tactiles :)...


Comunicacion en PLC Allen-Bradley y Arduino mediante el protocolo DF1

Comunicacion entre PLC de Allen Bradley y Arduino mediante el protocolo DF1.
los datos son enviados desde Arduino al PLC AB y viceversa
los datos se envian desde el arduino en le rango de (0-5v / 0-32767) a el registro de datos del PLC AB N7:1(registro de flotantes) y viceversa.


Se utilizo el PLC Micrologix 1000 AB seteado a 9600 baudios.

Requerimientos de Hardware:

1)PLC AB con soporte de protocolo DF1 ej Micrologix 1000/1100/PLC5 /Controllogix etc.
2)Cables RS232 para el PLC.
3)Arduino uno.
4)Conversor RS232 a TTL (ampliar info).
5)Sensores varios pulsadores, potenciometros.


Requerimientos de Software:
1)Arduino IDE
2)La libreria con el protocolo implementado de DF1 que me sorprendio como q lo hizo el je
3)El codigo a subir para el arduino
4)el codigo a subir al PLC Micro1000

jueves, 25 de agosto de 2016

Hack - shellcode en arm raspberry pi 3


Arranque probando un cross-compiler para arm y termine haciendo un shellcode para la rpi3 para no olvidarme, lo dejo anotado si alguien puede aportar lo nombro y agrego sus ideas.

Dejo el git de un sript para geany para poder compilar y subir el elf-arm a una rpi
git@github.com:pablinn/arm-pi.git

git clone git@github.com:pablinn/arm-pi.git


*Para conectarme a la RPI3 en forma remota
ssh ->shell remoto a mi rpi3
ssh pi@192.168.43.222
~ $

*Para ver puertos en la rpi3 para tranquilidad
nmap -v 192.168.43.222
22/tcp ssh (el servicio ssh activo)

 *Para pasar archivos de mi PC a la RPI3
 scp hello pi@192.168.43.222:/home/pi

 *Para ver la informacion de la cpu de la RPI3
cat /proc/cpuinfo

me muestra que es micro ARMV7 rev4 32bits de cuatro nucleos :)



*Para ver mi PC es lo mismo pero es un I7 de 8 nucleos 64bits
Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz


*Para compilar en ubuntu tenemos gcc pero para x486_64

gcc -dumpmachine
x86_64-linux-gnu

gcc -o  archivo archivo.c 


*Para compilar en rpi3 tenemos gcc pero para arm

gcc -dumpmachine
arm-linux-gnueabihf(cross-compiler-armlinux-con soporte coma flotante)


*Cross-compiler para linux x486

Instalarlo en ubuntu
sudo apt-get install gcc-arm-linux-gnueabi 
sudo apt-get install gcc-arm-linux-gnueabihf (version usada en rpi3 soporte de flotantes)


Modo de compilar 1

 Compila un archivo assembler en un objeto
arm-linux-gnueabi-as -o archivo.o archivo.s
 Compila el objeto en un ELF_ARM
arm-linux-gnueabi-gcc -o elf_arm archivo.o
 rm -vf *.o

Modo de compilar 2
Compila el *.C en un ELF_AR
arm-linux-gnueabi-gcc -o elf_arm archivo.c  -static
rm -vf *.o

Los programas compilados desde un x486 con el cross-compiler van a funcionar en un arm la rpi3 o en una maquina virtual como qemu.
por razones de proof (pruebas de concepto) voy a probar los archivo en la RPI3 para ver compatibilidades del CC.
Para automatizar la compilacion se puede usar los makefile el cual son un dolor de cabeza mas jodido q hacer el shellcode por lo q dejo un ejemplo pero voy a usar geany.


 Makefile para un cross-compiler en C solo hay que cambir el nombre de los archivos y listo tener en cuenta que MAKE usa TAB en el comienzo de los comandos no espacio. (make hdp @~$)


sudo nano makefile

********makefile*******************************
all: prueba1

en = as
CC = gcc
$OBJ = prueba1.o
$files = prueba1.s
$sal = prueba1

$(OBJ): $(files)
    $(en) -o $(OBJ) $(files)

$(sal): $(OBJ)
    $(CC) -o $(sal) $(OBJ)
    rm -vf *.o


************************************************
make

pero es un quilombo resumiendo

en un x486 pueden generar
1-elf_x486-64 o su version elf_x486-32 con GCC
2-elf_arm  ARM-GCC

el elf_arm lo emulan con qemu o lo copian a la RPI3 y lo prueban
scp elf_arm pi@192.168.43.222:/home/pi

Bueno hasta aca todo nuevo para mi y divertido, algunas herramientas a usar



geany - gdb -strace objdump ver syscall
asrl - dep nx

Un poco de teoria de procesadores ARM

16 rgistros enteros de 32bits

r0 .. r15
r0 .. r10 de uso general
r11 --->FP(frame pointer) puntero del stack
r12 --->IP(intra-procedure register) guarda datos temp de funciones
r13 --->SP(stack pointer) puntero a la parte mas alta de la pila  -4 crece +4 decrece

r14 --->LR(link register) puntero de retorno de una funcion
r15 --->PC(program counter) direccion de la siguiente instruccion a ejecutar

el CPSR o (current program status register) es un registro de 32bits

Se utiliza en operaciones de comparaciones bucles y saltos.

instrucciones aritmeticas :add - sub - rsb - sbc - adc - rsc
ej suma
add r1,r2,r3   /*  r1=r3+r2 */
add r1,r2,#120 /* r1=r2+120*/


Instrucciones logicas: and - or eor - bic
Instrucciones de comparacion: cmp - cmn  utiliza los registros  N C Z  V
Instrucciones simd o de 16 y 8 bits UADD8
Instrucciones de memoria :LDR -STR
instrucciones de comparacion:

Instrucciones Branch : B - BL - BX - BLX


Bueno otra herramienta es GDB un excelente debuger



primer codigo de prueba1.c con el cross-compiler lo pasamos a la  rpi3
y funciona perfecto o compilamos desde la rpi3.

hello.c
****************************************************************
#include <stdio.h>

int main(int argc, char** argv) {
   printf("Usando el cross compiler para ARM\n");
   return 0;
}
****************************************************************
x486_64
GDB ./hello 
disass main















ARMV7
GDB ./hello
disass main






Con este comando vemos en las definiciones de las librerias en que direccion estan las funciones write() y exit()



ARM - RPI3 - raspbian
cat /usr/include/arm-linux-gnueabihf/asm/unistd.h | grep write
#define __NR_write            (__NR_SYSCALL_BASE+  4)

cat /usr/include/arm-linux-gnueabihf/asm/unistd.h | grep exit
#define __NR_exit            (__NR_SYSCALL_BASE+  1)

segun la code wiki
http://codewiki.wikidot.com/c:system-calls:write


Desde ubuntu linux con x486
arm-linux-gnueabihf-as -o bash.o bash.s
arm-linux-gnueabihf-gcc -o bash bash.o -STATIC

Este programa solo escribe lsusb y retorna nada mas tiene mucho comentario es cortito.


/*bash.s
compilado con geany 
arm-linux-gnueabihf-as -o %e.o %f
arm-linux-gnueabihf-gcc -o %e %e.o 

Este es solo un ejemplo solo escribe un texto, usa write y exit
size_t write(int fildes, const void *buf, size_t nbytes);
Por lo que deberiamos de usar 4 registros.
r2 (len cadena) =  6
r1 (cadena)        "lsusb\n" 
r0 (output)        1
r7 (syscall write) 0x04 
*/ 
 
 
**********************bash.s********************************************** 
 /*inicio*/
.section .text

.global main
main:
    /*write()*/
    mov  r2,#6      
    mov  r1,pc
    add  r1,#24
    mov  r0,$0x1 
    mov  r7,$0x4  
    svc  0            /*software interrupt o swi */
    
    /*exit()*/
    sub r0,r0,r0      /*0=1-1*/ 
    mov r7,$0x1
    svc 0
     
.ascii "lsusb\n"
/*fin*/ 
 ******************************************************************************** 
 
 
 Ahora traceamos el programa para ver lo que hace coloque una imagen porque es mucho
 
strace ./bash 
 
 
execve("./bash", ["./bash"], [/* 18 vars */]) = 0     -->ejecuta
write(1, "lsusb\n", 6lsusb                                      -->escribe
)                  = 6                                                     --->sale
exit(0)                                 = ?


Bueno usamos objdump para ver los opcodes y todo el codigo que se ejecuta nos importa solo lo que hay en main el resto no lo puse es lo que se va a jecutar si lo ponemos como shellcode en un puntero y lo llammos.
Pero este codigo tiene problemas no puede tener nulos 0x0 espacios 0x20 por lo que generalmente cambian instruciones por algunas parecidas para que en la salida no hayan nulos o opcodes no deseados.

objdump -d ./bash

0000840c <main>:
    840c:    e3a02006     mov    r2, #6
    8410:    e1a0100f     mov    r1, pc
    8414:    e2811018     add    r1, r1, #24
    8418:    e3a00001     mov    r0, #1
    841c:    e3a07004     mov    r7, #4
    8420:    ef000000      svc    0x00000000
    8424:    e0400000     sub    r0, r0, r0
    8428:    e3a07001     mov    r7, #1
    842c:    ef000000      svc    0x00000000
    8430:    7375736c     .word    0x7375736c
    8434:    0a62             .short    0x0a62

Encontre algo interesante en el paper de shellcode y en los datos de arm que tiene opciones de funcionar en modo de direccionamiento en memoria de 16 u 8 bit es el modo "thumb mode"  el codigo queda algo asi :

arm-linux-gnueabihf-as -mthumb -o bash.o bash.s
arm-linux-gnueabihf-gcc -o bash bash.o -STATIC
***************************prueba.s*********************************
.section .text

.global main
main:

.code 32                      /*modo thumb*/
    add r6,pc,#1
    bx  r6
   
.code 16                   /*mode 16*/
    /*write()*/
    mov  r2,#6            /*longiud de la cadena*/
    mov  r1,pc             /*program counter*/
    add  r1,#12          /*program counter + 12*/
    mov  r0,$0x1        /*parametro 1*/
    mov  r7,$0x4        /*syscall write*/
    svc  0                    /*int*/
   
     /*exit()*/
     sub r0,r0,r0      /*0=1-1*/
     mov r7,$0x1     /*syscall exit*/
     svc 0                  /*int*/
    
.ascii "lsusb\n"
**************************************************************************
Vemos como queda la parte de 32bits y la de 16bits o sea funciona igual y esta reducido, pero tiene un par de nulos.

objdump -d ./bash

000083bc <main>:
    83bc:    e28f6001     add    r6, pc, #1
    83c0:    e12fff16     bx    r6
    83c4:    2206          movs    r2, #6
    83c6:    4679          mov    r1, pc
    83c8:    310c          adds    r1, #12
    83ca:    2001          movs    r0, #1
    83cc:    2704          movs    r7, #4
    83ce:    df00          svc    0
    83d0:    1a00          subs    r0, r0, r0
    83d2:    2701          movs    r7, #1
    83d4:    df00          svc    0
    83d6:    736c          .short    0x736c
    83d8:    0a627375     .word    0x0a627375

Otra modificacion para sacar nulos

********************lsusb.s*******************************
.section .text

.global main
main:

.code 32
    add r6,pc,#1
    bx  r6
   
.code 16    
    /*write()*/
    mov  r2,#6
    mov  r1,pc
    add  r1,#14
    mov  r0,$0x1
    mov  r7,$0x4
    svc  1
   
     /*exit()*/
     sub r4,r4,r4
     mov r0,r4     
     mov r7,$0x1
     svc 1
    
.ascii "lsusb\n"
*********************************************************
y el resultado quedaria bastante bien sin nulos ahora a armar el shellcode esto se puede automtizar

objdump -d ./prueba


000083bc <main>:
    83bc:    e28f6001     add    r6, pc, #1
    83c0:    e12fff16     bx    r6
    83c4:    2206          movs    r2, #6
    83c6:    4679          mov    r1, pc
    83c8:    310e          adds    r1, #14
    83ca:    2001          movs    r0, #1
    83cc:    2704          movs    r7, #4
    83ce:    df01          svc    1
    83d0:    1b24          subs    r4, r4, r4
    83d2:    1c20          adds    r0, r4, #0
    83d4:    2701          movs    r7, #1
    83d6:    df01          svc    1
    83d8:    7375736c     .word    0x7375736c
    83dc:    46c00a62     .word    0x46c00a62

Ahora la parte en rojo es lo que nos interesa con eso se arma el shellcode pero hay que rotar los opcodes


e28f6001  -> \x01\x60\x8f\xe2

asi sucesivamente hasta llegar al shellcode y agregarlo a un puntero y llamarlo

*************************lsusb2*****************************************************
#include <stdio.h>
char *SC =  "\x01\x60\x8f\xe2"
            "\x16\xff\x2f\xe1"
            "\x06\x22"
            "\x79\x46"
            "\x0e\x31"
            "\x01\x20"
            "\x04\x27"
            "\x01\xdf"
            "\x24\x1b"
            "\x20\x1c"
            "\x01\x27"
            "\x01\xdf"
            "\x6c\x73\x75\x73"
            "\x62\x0a\xc0\x46";

int main(void)
        {
                fprintf(stdout,"Longiud: %d\n",strlen(SC));
                (*(void(*)()) SC)();
        return 0;
        }

*********************************************************************************

 Lo compilamos
arm-linux-gnueabihf-gcc -o lsusb2 lsusb2.c

funciona y si lo traceamos
objdump -d ./lsusb2

execve("./lsusb2", ["./lsusb2"], [/* 18 vars */]) = 0
write(1, "Longiud: 36\n", 12Longiud: 36
)           = 12
write(1, "lsusb\n", 6lsusb
)                  = 6
exit(0)                                 = ?
+++ exited with 0 +++

Bueno hasta llegamos tratando de ejecutar el bendito

execve("/bin/sh", ["bin/sh"],0)
consigo violacion de segmento
o llamadas inesperadas jaja






protecciones
aslr - dep - nx
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
echo 1 | sudo tee /proc/sys/kernel/randomize_va_space
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space



Referencias
http://shell-storm.org/blog/Shellcode-On-ARM-Architecture/
http://shell-storm.org/shellcode/


martes, 29 de marzo de 2016

Framework Platformio + Geany + Raspberry PI

Hace un tiempo me quede sin PC sin notebook y buscanba la forma de programar diferentes microcontroladores usando el IDE de arduino bajo RPI (Raspberry PI) pero no hay version del cross-compiler para arm para poder programar los ESP.
Buscando encontre de casualidad Platformio un cross-compiler desde linea de comandos para diferentes entornos de trabajo Atmel, esspresif entre otros y la verdad es que me sorprendio logre programar arduinos y esp8266 sin problemas desde un RPI.
Tiene un excelente control de librerias e instalacion de lo que nesecites es mas que recomendable.
Tiene un par de inconvenientes el IDE grafico para RPI estoy usando GEANY debe haber otro pero realmente estoy comodo programando de esta forma.

Estube realizando pruebas con arduino uno, mega y un esp-01 y andubo perfecto, podemos cargar el firmware de OTA o webupdate y actualizar los esp de forma remota configurando la IP.


Instalacion siguiendo la info de la pagina web http://platformio.org/#/ y otros blogers
***********************************************
si no esta instalado easy_install
sudo apt-get install python-setuptools
luego
sudo easy_install pip (gestor de paquetes en python)
sudo pip install platformio
***********************************************

Tiene algunas complicaciones porque hay q usar la terminal pero es mas de mi agrado:
Crear la carpeta

***********************************************
sudo mkdir arduino/proy_01 (CARPETA DE PROYECTOS)
***********************************************

inicializar la placa tiene muchas opciones pero las podes listar y ver cual necesitas

***********************************************
platformio init --board esp01-1M (ESP8266 CON 1M ojo las esp-01 de color azul claro son de 512K)
***********************************************

otro ejemplo:
***********************************************
platformio init --board uno  (arduino uno)
***********************************************


poner el codigo en la carpeta genera un .ini y dos carpetas src y lib

***********************************************
-platformio.ini (archivo de configuracion)
-src(adentro va el .ino o .cpp)
-lib(librerias externas o propias)
***********************************************

Compilar generar el firmware en modo local.
***********************************************
platformio run
***********************************************

Subir o descargar el firmware al uC
***********************************************
platformio run --target upload
***********************************************

Limpiar archivos compiladodos y temporales.
***********************************************
platformio clean
***********************************************

Todo esto se puede hacer desde geany y compilar desde ahi... :) solo hay que configurar en opciones de compilacion.

compile=platformio run
build=platformio run --target upload
make object=platformio clean

y seleccionar la sintaxis de color de C++ y compilar seleccionando el archivo .ini









Voy a ir actualizando porque me siento bastante comodo con platformio y raspberry PI.
Sldos...

Siguiendo con las pruebas me consegui un esp-12, me costo programarlo pero funciono bien, unos de los problemas es la memoria no sabes si tienen 512K-1M o 4M y vienen con el protector para EMF el cual no te deja ver la flash a menos que lo desarmes.

Voy a tratar de analizar y probar un poco la arquitectura asi me queda en el blog...

Tamaños de memoria SPI

***********esto es del foro del esp822 *******************************
# SPI_SIZE_MAP
# 0 : 512 KB (256 KB + 256 KB)
# 1 : 256 KB
# 2 : 1024 KB (512 KB + 512 KB)
# 3 : 2048 KB (512 KB + 512 KB)
# 4 : 4096 KB (512 KB + 512 KB)
# 5 : 2048 KB (1024 KB + 1024 KB)
# 6 : 4096 KB (1024 KB + 1024 KB)
*******************************************************

esp8266-01 azul claro 512k (no funcionan para OTA)



esp8266-01 negro o verde obscuro  1M (si funcionan pero tienen poco espacio)


esp8266-12 azul claro (1M - no estoy seguro si alguien lo sabe he visto q les cambian la memoria de 512k a 1M  no hay mucha info muchas dudas, yo le descargue con la opcion esp01_1m pero no estoy seguro ya que hice una prueba con un DHT11 y me muestra un float y no hay conversion a entero esto lo tengo que revisar creo q son de 512k)


esp8266-12E verde oscuro AI (4M de memoria eeprom)
esp12E - Pinout

Diagrama de ingenieria inversa de la version de AI-Thinker


esta bueno agregarla un capacitor en la alimentacion por pequeñas variaciones en los consumos de corriente para evitar se active el WDT y se resetee.

Programando el esp12



Programando el esp12E(no lo probe aun)



Bueno programe un esp12 como indica el datasheet

1-reset no lo use aun pero es necesario una ves descargas el firmware, sacar jumper y debes resetearlo
2-ADC (convertidor analogico a digital soporta 1v)
3-CH_PD (enable chip va a 1 yo use una resist. 101R - 100ohm)
4-GPIO16 usado para el modo deep_sleep (no probado aun)
5-GPIO14
6-GPIO12
7-GPIO13
8-VCC (3.3 Vcc) va a 1
9-GND
10-102R smd a GND va a 0
11-GPIO2
12-GPIO0 este se usa para ponerlo en modo programacion va a 0 con un jumper
13-GPIO5
14-GPIO4
15-TX aca va cruzado a RX (en los datasheet sale diferente chequear)
16-RX aca va cruzado a TX (en los datasheet sale diferente chequear)

Entonces:
*******************************************************
Flash Mode
vcc CH_PD  GPIO0 GPIO15
 1        1           0            0

Boot Mode
vcc CH_PD GPIO0  GPIO15
1        1             X        0

X- a nada libre o a VCC
*******************************************************

Funciono asi es mas al GPIO2 lo use para leer un DHT11 otra cosa que lei y lo voy a poner en practica es el modo bajo consumo o "deep sleep mode" algo que es muy util bajar el consumo tambien tiene un WDT (watdog timer) muy util cuando se cuelga el uP.

La idea es ponerlo a dormir y despertarlo (deep sleep mode) por decirlo asi con:

un timer interno (que lea cada 1hs un DHT22 ej. )
una interrupcion externa(arduino - rpi)
via UART (Arduino - RPI - uP - uC - PC con ftdi )
WDT (bueno este es interesante teoricamente se genera un pulso el cual si no existe resetea el uC lo he usado en PLC se genera el pulso sobre un rele/timer si falla el PLC chau pulso y activa una proteccion, aca es algo diferente porque es interno pero se podria crear un WDT con un GPIO generas el pulso y con algun arduino si deja de leerlo activar el respaldo)

Administracion de energia(sacado del datasheet de espressif)



OFF
si se pone a 0 CH_PD el RTC se desabilita y se borran los registros.

DEEP_SLEEP
Solo el RTC se alimenta el resta esta desconectado y mantiene datos basicos dela coneccion WIFI

SLEEP
El RTC queda operando algun evento para despertarlo (MAC - host - RTC timer - ext int) lo pone en modo de funcionamiento

WAKEUP
en este modo funciona el crystal oscilador y los PLL todo habilitado

ON
EN este modo el clock opera a toda velocidad se puede usar la instruccion WAITI para operar a velocidad minima.

:) mas que interesante no ?




Detalles a tener en cuenta para programar(no hacer lo que yo jaja)

Algunos errores al descargar el firmware con PlatformIO, fueron ocasionados por el cableado arme
todo en una plaqueta y funciona bien, tambien fallo la descarga por que tenia una terminal serie abierta leyendo por el puerto usb /dev/USB0, o sea usaba el archivo, (terminal minicom no aconsejada pero funciona ya encontrare alguna mejor).

*usar plaquetas para prototipos
*usar el menor cableado posible y que este bien firme
*no dejar abierta las consolas serie (arduino ide - minicom - putty etc.)

Saludos....