Loader un binaire Arduino dans IDA

Bon, maintenant que l’on sait comment prendre un dump d’un Arduino, Il ne faut pas croire qu’on peut juste ouvrir le binaire dans IDA.

Ca n’est pas aisé de faire manger ce binaire à IDA. Pour ma part déjà, j’ai un IDA qui ne connait pas le cpu atmel AVR ATmega328 que l’on retrouve sur le Arduino Uno.

Heureusement il suffit d’indiquer les spécifications de ce contrôleur dans le fichier /cfg/avr.cfg et IDA retrouve miraculeusement ses petits. On trouve tous ces paramètres dans la documentation de référence ATmega48A/PA/88A/PA/168A/PA/328/P chez Atmel.

J’ai donc recopié et modifié la configuration du 168p et ca semble aller. Voici ma conf, j’espère que je n’ai pas fait d’erreurs. Si qqun en trouve merci de me le dire.

.ATmega328
; Ida avr.cfg (c) THANATOS

SUBARCH=5

RAM=2048
ROM=32768
EEPROM=1024

; MEMORY MAP
; Memory configuration A

area DATA GPWR_        0x0000:0x0020   General Purpose Working Registers
area DATA FSR_         0x0020:0x0060   I/O registers
area DATA EXTIO_       0x0060:0x0100   I/O registers
area DATA I_SRAM       0x0100:0x08ff   Internal SRAM

; Interrupt and reset vector assignments
entry __RESET        0x0000   External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset
entry INT0_          0x0004   External Interrupt Request 0
entry INT1_          0x0008   External Interrupt Request 1
entry PCINT0_        0x000C   Pin Change Interrupt Request 0
entry PCINT1_        0x0010   Pin Change Interrupt Request 1
entry PCINT2_        0x0014   Pin Change Interrupt Request 2
entry WDT            0x0018   Watchdog Time-out Interrupt
entry TIMER2_COMPA   0x001C   Timer/Counter2 Compare Match A
entry TIMER2_COMPB   0x0020   Timer/Counter2 Compare Match B
entry TIMER2_OVF     0x0024   Timer/Counter2 Overflow
entry TIMER1_CAPT    0x0028   Timer/Counter1 Compare Match
entry TIMER1_COMPA   0x002C   Timer/Counter1 Compare Match A
entry TIMER1_COMPB   0x0030   Timer/Counter1 Compare Match A
entry TIMER2_OVF     0x0034   Timer/Counter1 Overflow
entry TIMER0_COMPA   0x0038   Timer/Counter0 Compare Match A
entry TIMER0_COMPB   0x003c   Timer/Counter0 Compare Match B
entry TIMER0_OVF     0x0040   Timer/Counter0 Overflow
entry SPI_STC        0x0044   Serial Transfer Complete
entry USART0_RXC     0x0048   USART Rx Complete
entry USART0_UDRE    0x004c   USART Data Register Empty
entry USART0_TXC     0x0050   USART Tx Complete
entry ADC            0x0054   ADC Conversion Complete
entry EE_READY       0x0058   EEPROM Ready
entry ANALOG_COMP    0x005c   Analog Comparator
entry TWI            0x0060   2-wire Serial Interface
;entry SPM_READY      0x0064   Store Program Memory Ready

; INPUT/OUTPUT PORTS
UBRR1L           0x0000   USART1 Baud Rate Register Low Byte
UCSR1B           0x0001   USART Control and Status Register B
UCSR1B.RXCIE      7   RX Complete Interrupt Enable
UCSR1B.TXCIE      6   TX Complete Interrupt Enable
UCSR1B.UDRIE      5   USART Data Register Empty Interrupt Enable
UCSR1B.RXEN       4   Receiver Enable
UCSR1B.TXEN       3   Transmitter Enable
UCSR1B.UCSZ2      2   Character Size
UCSR1B.RXB8       1   Receive Data Bit 8
UCSR1B.TXB8       0   Transmit Data Bit8
UCSR1A           0x0002   USART Control and Status Register A
UCSR1A.RXC        7   USART Receive Complete
UCSR1A.TXC        6   USART Transmit Complete
UCSR1A.UDRE       5   USART Data Register Empty
UCSR1A.FE         4   Frame Error
UCSR1A.DOR        3   Data OverRun
UCSR1A.PE         2   Parity Error
UCSR1A.U2X        1   Double the USART Transmission Speed
UCSR1A.MPCM       0   Multi-processor Communication Mode
UDR1             0x0003   USART I/O Data Register
OCDR             0x0004   On-chip Debug Register
PINE             0x0005   Port E Input Pins Address
PINE.PINE2        2
PINE.PINE1        1
PINE.PINE0        0
DDRE             0x0006   Port E Data Direction Register
DDRE.DDE2         2   Port E Data Direction Register bit 2
DDRE.DDE1         1   Port E Data Direction Register bit 1
DDRE.DDE0         0   Port E Data Direction Register bit 0
PORTE            0x0007   Port E Data Register
PORTE.PORTE2      2   Port E Data Register bit 2
PORTE.PORTE1      1   Port E Data Register bit 1
PORTE.PORTE0      0   Port E Data Register bit 0
ACSR             0x0008   Analog Comparator Control and Status Register
ACSR.ACD          7   Analog Comparator Disable
ACSR.ACBG         6   Analog Comparator Bandgap Select
ACSR.ACO          5   Analog Comparator Output
ACSR.ACI          4   Analog Comparator Interrupt Flag
ACSR.ACIE         3   Analog Comparator Interrupt Enable
ACSR.ACIC         2   Analog Comparator Input Capture Enable
ACSR.ACIS1        1   Analog Comparator Interrupt Mode Select 1
ACSR.ACIS0        0   Analog Comparator Interrupt Mode Select 0
UBRR0L           0x0009   USART0 Baud Rate Register Low Byte
UCSR0B           0x000A   USART Control and Status Register B
UCSR0B.RXCIE      7   RX Complete Interrupt Enable
UCSR0B.TXCIE      6   TX Complete Interrupt Enable
UCSR0B.UDRIE      5   USART Data Register Empty Interrupt Enable
UCSR0B.RXEN       4   Receiver Enable
UCSR0B.TXEN       3   Transmitter Enable
UCSR0B.UCSZ2      2   Character Size
UCSR0B.RXB8       1   Receive Data Bit 8
UCSR0B.TXB8       0   Transmit Data Bit8
UCSR0A           0x000B   USART Control and Status Register A
UCSR0A.RXC        7   USART Receive Complete
UCSR0A.TXC        6   USART Transmit Complete
UCSR0A.UDRE       5   USART Data Register Empty
UCSR0A.FE         4   Frame Error
UCSR0A.DOR        3   Data OverRun
UCSR0A.PE         2   Parity Error
UCSR0A.U2X        1   Double the USART Transmission Speed
UCSR0A.MPCM       0   Multi-processor Communication Mode
UDR0             0x000C   USART I/O Data Register
SPCR             0x000D   SPI Control Register-
SPCR.SPIE         7   SPI Interrupt Enable
SPCR.SPE          6   SPI Enable
SPCR.DORD         5   Data Order
SPCR.MSTR         4   Master/Slave Select
SPCR.CPOL         3   Clock Polarity
SPCR.CPHA         2   Clock Phase
SPCR.SPR1         1   SPI Clock Rate Select 1
SPCR.SPR0         0   SPI Clock Rate Select 0
SPSR             0x000E   SPI Status Register
SPSR.SPIF         7   SPI Interrupt Flag
SPSR.WCOL         6   Write COLlision Flag
SPSR.SPI2X        0   Double SPI Speed Bit
SPDR             0x000F   SPI Data Register
PIND             0x0010   Port D Input Pins Address
PIND.PIND7        7
PIND.PIND6        6
PIND.PIND5        5
PIND.PIND4        4
PIND.PIND3        3
PIND.PIND2        2
PIND.PIND1        1
PIND.PIND0        0
DDRD             0x0011   Port D Data Direction Register
DDRD.DDD7         7   Port D Data Direction Register bit 7
DDRD.DDD6         6   Port D Data Direction Register bit 6
DDRD.DDD5         5   Port D Data Direction Register bit 5
DDRD.DDD4         4   Port D Data Direction Register bit 4
DDRD.DDD3         3   Port D Data Direction Register bit 3
DDRD.DDD2         2   Port D Data Direction Register bit 2
DDRD.DDD1         1   Port D Data Direction Register bit 1
DDRD.DDD0         0   Port D Data Direction Register bit 0
PORTD            0x0012   Port D Data Register
PORTD.PORTD7      7   Port D Data Register bit 7
PORTD.PORTD6      6   Port D Data Register bit 6
PORTD.PORTD5      5   Port D Data Register bit 5
PORTD.PORTD4      4   Port D Data Register bit 4
PORTD.PORTD3      3   Port D Data Register bit 3
PORTD.PORTD2      2   Port D Data Register bit 2
PORTD.PORTD1      1   Port D Data Register bit 1
PORTD.PORTD0      0   Port D Data Register bit 0
PINC             0x0013   Port C Input Pins Address
PINC.PINC7        7
PINC.PINC6        6
PINC.PINC5        5
PINC.PINC4        4
PINC.PINC3        3
PINC.PINC2        2
PINC.PINC1        1
PINC.PINC0        0
DDRC             0x0014   Port C Data Direction Register
DDRC.DDC7         7   Port C Data Direction Register bit 7
DDRC.DDC6         6   Port C Data Direction Register bit 6
DDRC.DDC5         5   Port C Data Direction Register bit 5
DDRC.DDC4         4   Port C Data Direction Register bit 4
DDRC.DDC3         3   Port C Data Direction Register bit 3
DDRC.DDC2         2   Port C Data Direction Register bit 2
DDRC.DDC1         1   Port C Data Direction Register bit 1
DDRC.DDC0         0   Port C Data Direction Register bit 0
PORTC            0x0015   Port C Data Register
PORTC.PORTC7      7   Port C Data Register bit 7
PORTC.PORTC6      6   Port C Data Register bit 6
PORTC.PORTC5      5   Port C Data Register bit 5
PORTC.PORTC4      4   Port C Data Register bit 4
PORTC.PORTC3      3   Port C Data Register bit 3
PORTC.PORTC2      2   Port C Data Register bit 2
PORTC.PORTC1      1   Port C Data Register bit 1
PORTC.PORTC0      0   Port C Data Register bit 0
PINB             0x0016   Port B Input Pins Address
PINB.PINB7        7
PINB.PINB6        6
PINB.PINB5        5
PINB.PINB4        4
PINB.PINB3        3
PINB.PINB2        2
PINB.PINB1        1
PINB.PINB0        0
DDRB             0x0017   Port B Data Direction Register
DDRB.DDB7         7   Port B Data Direction Register bit 7
DDRB.DDB6         6   Port B Data Direction Register bit 6
DDRB.DDB5         5   Port B Data Direction Register bit 5
DDRB.DDB4         4   Port B Data Direction Register bit 4
DDRB.DDB3         3   Port B Data Direction Register bit 3
DDRB.DDB2         2   Port B Data Direction Register bit 2
DDRB.DDB1         1   Port B Data Direction Register bit 1
DDRB.DDB0         0   Port B Data Direction Register bit 0
PORTB            0x0018   Port B Data Register
PORTB.PORTB7      7   Port B Data Register bit 7
PORTB.PORTB6      6   Port B Data Register bit 6
PORTB.PORTB5      5   Port B Data Register bit 5
PORTB.PORTB4      4   Port B Data Register bit 4
PORTB.PORTB3      3   Port B Data Register bit 3
PORTB.PORTB2      2   Port B Data Register bit 2
PORTB.PORTB1      1   Port B Data Register bit 1
PORTB.PORTB0      0   Port B Data Register bit 0
PINA             0x0019   Port A Input Pins Address
PINA.PINA7        7
PINA.PINA6        6
PINA.PINA5        5
PINA.PINA4        4
PINA.PINA3        3
PINA.PINA2        2
PINA.PINA1        1
PINA.PINA0        0
DDRA             0x001A   Port A Data Direction Register
DDRA.DDA7         7   Port A Data Direction Register bit 7
DDRA.DDA6         6   Port A Data Direction Register bit 6
DDRA.DDA5         5   Port A Data Direction Register bit 5
DDRA.DDA4         4   Port A Data Direction Register bit 4
DDRA.DDA3         3   Port A Data Direction Register bit 3
DDRA.DDA2         2   Port A Data Direction Register bit 2
DDRA.DDA1         1   Port A Data Direction Register bit 1
DDRA.DDA0         0   Port A Data Direction Register bit 0
PORTA            0x001B   Port A Data Register
PORTA.PORTA7      7   Port A Data Register bit 7
PORTA.PORTA6      6   Port A Data Register bit 6
PORTA.PORTA5      5   Port A Data Register bit 5
PORTA.PORTA4      4   Port A Data Register bit 4
PORTA.PORTA3      3   Port A Data Register bit 3
PORTA.PORTA2      2   Port A Data Register bit 2
PORTA.PORTA1      1   Port A Data Register bit 1
PORTA.PORTA0      0   Port A Data Register bit 0
EECR             0x001C   The EEPROM Control Register
EECR.EERIE        3   EEPROM Ready Interrupt Enable
EECR.EEMWE        2   EEPROM Master Write Enable
EECR.EEWE         1   EEPROM Write Enable
EECR.EERE         0   EEPROM Read Enable
EEDR             0x001D   EEPROM Data Register
EEARL            0x001E   EEPROM Address Register Low Byte
EEARH            0x001F   The EEPROM Address Register High
EEARH.EEAR8       8   EEPROM Address 8
UCSR0C           0x0020   USART Control and Status Register C (page 180)
UCSR0C.URSEL      7   Register Select
UCSR0C.UMSEL      6   USART Mode Select
UCSR0C.UPM1       5   Parity Mode 1
UCSR0C.UPM0       4   Parity Mode 0
UCSR0C.USBS       3   Stop Bit Select
UCSR0C.UCSZ1      2   Character Size 1
UCSR0C.UCSZ0      1   Character Size 0
UCSR0C.UCPOL      0   Clock Polarity
WDTCR            0x0021   Watchdog Timer Control Register
WDTCR.WDCE        4   Watchdog Change Enable
WDTCR.WDE         3   Watchdog Enable
WDTCR.WDP2        2   Watchdog Timer Prescaler 2
WDTCR.WDP1        1   Watchdog Timer Prescaler 1
WDTCR.WDP0        0   Watchdog Timer Prescaler 0
OCR2             0x0022   Output Compare Register
TCNT2            0x0023   Timer/Counter2
ICR1L            0x0024   Input Capture Register Low Byte
ICR1H            0x0025   Input Capture Register High Byte
ASSR             0x0026   Asynchronous Status Register
ASSR.AS2          3   Asynchronous Timer/Counter2
ASSR.TCN2UB       2   Timer/Counter2 Update Busy
ASSR.OCR2UB       1   Output Compare Register2 Update Busy
ASSR.TCR2UB       0   Timer/Counter Control Register2 Update Busy
TCCR2            0x0027   Timer/Counter Control Register
TCCR2.FOC2        7   Force Output Compare
TCCR2.WGM20       6   Waveform Generation Mode 0
TCCR2.COM21       5   Compare Match Output Mode 1
TCCR2.COM20       4   Compare Match Output Mode 0
TCCR2.WGM21       3   Waveform Generation Mode 1
TCCR2.CS22        2   Clock Select 2
TCCR2.CS21        1   Clock Select 1
TCCR2.CS20        0   Clock Select 0
OCR1BL           0x0028   Output Compare Register B Low Byte
OCR1BH           0x0029   Output Compare Register B High Byte
OCR1AL           0x002A   Output Compare Register A Low Byte
OCR1AH           0x002B   Output Compare Register A High Byte
TCNT1L           0x002C   Counter Register Low Byte
TCNT1H           0x002D   Counter Register High Byte
TCCR1B           0x002E   Timer/Counter1 Control Register B
TCCR1B.ICNC1      7   Input Capture Noise Canceler
TCCR1B.ICES1      6   Input CaptureEdgeSelect
TCCR1B.WGM13      4   Waveform Generation Mode 3
TCCR1B.WGM12      3   Waveform Generation Mode 2
TCCR1B.CS12       2   Clock Select 2
TCCR1B.CS11       1   Clock Select 1
TCCR1B.CS10       0   Clock Select 0
TCCR1A           0x002F   Timer/Counter1 Control Register A
TCCR1A.COM1A1     7   Compare Output Mode for channel A 1
TCCR1A.COM1A0     6   Compare Output Mode for channel A 0
TCCR1A.COM1B1     5   Compare Output Mode for channel B 1
TCCR1A.COM1B0     4   Compare Output Mode for channel B 0
TCCR1A.FOC1A      3   Force Output Compare for channel A
TCCR1A.FOC1B      2   Force Output Compare for channel B
TCCR1A.WGM11      1   Waveform Generation Mode 1
TCCR1A.WGM10      0   Waveform Generation Mode 0
SFIOR            0x0030   Special Function IO Register
SFIOR.TSM         7   Timer/Counter Synchronization Mode
SFIOR.XMBK        6   External Memory Bus Keeper Enable
SFIOR.XMM2        5   External Memory High Mask 2
SFIOR.XMM1        4   External Memory High Mask 1
SFIOR.XMM0        3   External Memory High Mask 0
SFIOR.PUD         2   Pull-up Disable
SFIOR.PSR2        1   Prescaler Reset Timer/Counter2
SFIOR.PSR310      0   Prescaler Reset Timer/Counter3, Timer/Counter1, and Timer/Counter0
OCR0             0x0031   Timer/Counter0 Output Compare Register
TCNT0            0x0032   Timer/Counter0
TCCR0            0x0033   Timer/Counter Control Register
TCCR0.FOC0        7   Force Output Compare
TCCR0.WGM00       6   Waveform Generation Mode 0
TCCR0.COM01       5   Compare Match Output Mode 1
TCCR0.COM00       4   Compare Match Output Mode 0
TCCR0.WGM01       3   Waveform Generation Mode 1
TCCR0.CS02        2   Clock Select 2
TCCR0.CS01        1   Clock Select 1
TCCR0.CS00        0   Clock Select 0
MCUCSR           0x0034   MCU Control and Status Register
MCUCSR.JTD        7   JTAG Interface Disable
MCUCSR.SM2        5   Sleep Mode Select Bit 2
MCUCSR.JTRF       4   JTAG Reset Flag
MCUCSR.WDRF       3   Watchdog Reset Flag
MCUCSR.BORF       2   Brown-out Reset Flag
MCUCSR.EXTRF      1   External Reset Flag
MCUCSR.PORF       0   Power-on Reset Flag
MCUCR            0x0035   MCU Control Register
MCUCR.SRE         7   External SRAM/XMEM Enable
MCUCR.SRW10       6   Wait State Select Bit
MCUCR.SE          5   Sleep Enable
MCUCR.SM1         4   Sleep Mode Select Bit 1
MCUCR.ISC11       3   Interrupt Sense Control 1 Bit 1
MCUCR.ISC10       2   Interrupt Sense Control 1 Bit 0
MCUCR.ISC01       1   Interrupt Sense Control 0 Bit 1
MCUCR.ISC00       0   Interrupt Sense Control 0 Bit 0
EMCUCR           0x0036   Extended MCU Control Register
EMCUCR.SM0        7   Sleep Mode Select Bit 0
EMCUCR.SRL2       6   Wait State Sector Limit 2
EMCUCR.SRL1       5   Wait State Sector Limit 1
EMCUCR.SRL0       4   Wait State Sector Limit 0
EMCUCR.SRW01      3   Wait-state Select Bits for Lower Sector 1
EMCUCR.SRW00      2   Wait-state Select Bits for Lower Sector 0
EMCUCR.SRW11      1   Wait-state Select Bits for Upper Sector
EMCUCR.ISC2       0   Interrupt Sense Control 2
SPMCR            0x0037   Store Program Memory Control Register
SPMCR.SPMIE       7   SPM Interrupt Enable
SPMCR.RWWSB       6   Read-While-Write Section Busy
SPMCR.RWWSRE      4   Read-While-Write Section Read Enable
SPMCR.BLBSET      3   Boot Lock Bit Set
SPMCR.PGWRT       2   Page Write
SPMCR.PGERS       1   Page Erase
SPMCR.SPMEN       0   Store Program Memory Enable
TIFR             0x0038   Timer/Counter Interrupt Flag Register
TIFR.TOV1         7   Timer/Counter1, Overflow Flag
TIFR.OCF1A        6   Timer/Counter1, Output Compare A Match Flag
TIFR.OCF1B        5   Timer/Counter1, Output Compare B Match Flag
TIFR.OCF2         4   Output Compare Flag 2
TIFR.ICF1         3   Timer/Counter1, Input Capture Flag
TIFR.TOV2         2   Timer/Counter2 Overflow Flag
TIFR.TOV0         1   Timer/Counter0 Overflow Flag
TIFR.OCF0         0   Output Compare Flag 0
TIMSK            0x0039   Timer/Counter Interrupt Mask Register
TIMSK.TOIE1       7   Timer/Counter1, Overflow Interrupt Enable
TIMSK.OCIE1A      6   Timer/Counter1, Output Compare A Match Interrupt Enable
TIMSK.OCIE1B      5   Timer/Counter1, Output Compare B Match Interrupt Enable
TIMSK.OCIE2       4   Timer/Counter2 Output Compare Match Interrupt Enable
TIMSK.TICIE1      3   Timer/Counter1, Input Capture Interrupt Enable
TIMSK.TOIE2       2   Timer/Counter2 Overflow Interrupt Enable
TIMSK.TOIE0       1   Timer/Counter0 Overflow Interrupt Enable
TIMSK.OCIE0       0   Timer/Counter0 Overflow Flag
GIFR             0x003A   General Interrupt Flag Register
GIFR.INTF1        7   External Interrupt Flag 1
GIFR.INTF0        6   External Interrupt Flag 0
GIFR.INTF2        5   External Interrupt Flag 2
GIFR.PCIF1        4   Pin Change Interrupt Flag 1
GIFR.PCIF0        3   Pin Change Interrupt Flag 0
GICR             0x003B   General Interrupt Control Register
GICR.INT1         7   External Interrupt Request 1 Enable
GICR.INT0         6   External Interrupt Request 0 Enable
GICR.INT2         5   External Interrupt Request 2 Enable
GICR.PCIE1        4   Pin Change Interrupt Enable 1
GICR.PCIE0        3   Pin Change Interrupt Enable 0
GICR.IVSEL        1   Interrupt Vector Select
GICR.IVCE         0   Interrupt Vector Change Enable
UCSR1C           0x003C   USART Control and Status Register C (page 180)
UCSR1C.URSEL      7   Register Select
UCSR1C.UMSEL      6   USART Mode Select
UCSR1C.UPM1       5   Parity Mode 1
UCSR1C.UPM0       4   Parity Mode 0
UCSR1C.USBS       3   Stop Bit Select
UCSR1C.UCSZ1      2   Character Size 1
UCSR1C.UCSZ0      1   Character Size 0
UCSR1C.UCPOL      0   Clock Polarity

SPL              0x003D   Stack Pointer Low
SPL.SP7           7
SPL.SP6           6
SPL.SP5           5
SPL.SP4           4
SPL.SP3           3
SPL.SP2           2
SPL.SP1           1
SPL.SP0           0
SPH              0x003E   Stack Pointer High
SPH.SP15          15
SPH.SP14          14
SPH.SP13          13
SPH.SP12          12
SPH.SP11          11
SPH.SP10          10
SPH.SP9           9
SPH.SP8           8
SREG             0x003F   Status Register
SREG.I            7   Global Interrupt Enable
SREG.T            6   Bit Copy Storage
SREG.H            5   Half Carry Flag
SREG.S            4   Sign Bit
SREG.V            3   Two's Complement Overflow Flag
SREG.N            2   Negative Flag
SREG.Z            1   Zero Flag
SREG.C            0   CarryFlag

Mais c’est pas tout. Ca serait trop simple. Si on charge un binaire on se retrouve avec des access à des variable qui sont non initialisées. C’est donc fortement pénalisant pour comprendre le code. D’autant que pour une simple led, il est de bon ton sur arduino de faire comme l’exemple et d’utiliser des variables :)

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.

  This example code is in the public domain.
 */

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Même si on a identifié la procédure setup et la procédure pinmode, la valeur de LED mise dans r24 restera un mystère.
avrnoref

Pour comprendre ce qui nous arrive, il faut un peut s’intéresser à comment marchent les cpu AVR. Ces CPUs sont basés sur une architecture Harvard, ca veut dire qu’il y a une mémoire pour le programme (la ROM) qui est complètement séparée de la RAM où sont les variables. La rom subsiste en cas de coupure d’électricité, mais évidemment pas la ram. Dans cette architecture, les programmes peuvent utiliser des variables en RAM, la ROM étant Read Only (ou presque, car cela se flash tout de même.)

Donc, la lecture/écriture c’est dans la ram. A coté de cela en plus il y a un espace mémoire nommé EEPROM qui permet d’écrire et de lire des data qui survivrons en cas de coupure électrique, un genre de disque dur quoi. Ici je ne m’en sert pas.

Grosso modo, pour ne pas perdre les quelques uns d’entre nous qui comprennent le x86 et qui ont connus le code en 16 Bits. c’est comme ca : Il y a 3 Segments. Un “CS” la Rom, Un “DS” la RAM, et un Extra “ES” l’eeprom. Ces segments ne se chevauchent pas, et celui de la RAM est remplis de 0 à chaque power on.

Dans le cas du AtMega328 on a 2k de Ram, 32k de Rom et 1K d’eeprom.

AVR_memory_01_lrg

Mais pour désassembler le code AVR c’est «chiant». Tous les programmes utilisent des références à des variables en RAM, mais la ram n’est pas initialisée chez nous, on n’a que un dump de la ROM. Alors dans la vrai vie, comment ca fonctionne;

Si on utilise l’environnement de développement Arduino ou simplement GCC pour avr, il y à une procédure nommée “__do_copy_data” qui au démarrage du programme s’occupe de recopier les variables initialisée de la ROM vers la RAM.

La ram est organisée de cette façons sur le AtMega328 :

0x0000:0x0020   General Purpose Working Registers
0x0020:0x0060   I/O registers
0x0060:0x0100   I/O registers extended
0x0100:0x08ff   Internal SRAM

Ouais je sais c’est chelou, Les 32 registres du CPU (R0 à R31) Sont en fait de la ram, après cela de 0x20 à 0x100 il y a les registres d’entrée sortie. C’est tous des registres un peu spéciaux par exemple en 0x5F c’est SREG que l’on connait nous sur x86 sous le nom de FLAGS.

C’est Seulement à partir de 0x100 on à de la vrai ram ou l’on peut faire ce que l’on veut. Mais voila, comment faire pour initialiser cette ram dans IDA et pouvoir reverser tranquille. GCC à la compilation pose les variables initialisées au cul du code, et donc pour chaque programme l’emplacement en ROM des variables change de place.

Et bien il faut “simplement” reverser “__do_copy_data” pour trouver l’emplacement des variables et leur taille. Si j’ai le courage, je pondrais un jour un python automatique.

Tout commence dans la fonction __RESET qu’IDA connait grace à notre cfg custom. (Sinon, elle est pointée par un saut au tout début de la rom). La première étape est de reseter les flags, et d’initialiser l’offset de la stack. La stack est sur 16 bits, et son pointeur est découpé en 2 registres 8 bits. SPH pour la partie haute du stack pointeur partie haute et SPL pour la partie basse. On retrouve ces deux pointeurs en RAM dans la partie I/0 Register 0x3D pour SPH et 0x3E pour SPH, mais ici aussi notre cfg fait un miracle.

ROM:0062                 ; public __RESET
ROM:0062 __RESET:                                ; CODE XREF: TIMER1_COMPB_0j
ROM:0062
ROM:0062 ; FUNCTION CHUNK AT ROM:04D2 SIZE 00000002 BYTES
ROM:0062
ROM:0062                 clr     r1
ROM:0063                 out     SREG, r1        ; Flags = 0
ROM:0064                 ser     r28             ; mov r28,0xff Set all bit
ROM:0065                 ldi     r29, 8          ; ldi= load immediate, mov quoi
ROM:0066                 out     SPH, r29        ; Stack point High
ROM:0067                 out     SPL, r28        ; Stack Pointer Low
ROM:0067                                         ; Now SP = 0x8ff

Alors c’est un truc auquel il va falloir s’habituer les enfants, les CPUs AVR aiment les couples de registres 8 Bits. Il y a même 3 couples célèbres qui font des registres 16 Bits. Le couple r26,r27 qui est nommé le registre X. r28,29 qui est Y et r30,r31 qui est Z. Ils appellent ca les registres indirects.

Nous voila enfin dans la partie juteuse. le couple r26,r27 est l’adresse de destination en RAM, le couple R30,31 est l’adresse sources de nos variables. Dans cet exemple c’est en 0x9a8.

ROM:0068                 ldi     r17, 1
ROM:0069                 ldi     r26, 0
ROM:006A                 ldi     r27, 1          ; X = 0x100
ROM:006B                 ldi     r30, 0xA8
ROM:006C                 ldi     r31, 9          ; Z = 0x9a8
ROM:006D                 rjmp    loop_end??      ; Relatif Jump

A partir de là c’est partis pour recopier byte à byte jusqu’a ce que X pointe 0x122.

ROM:006E loop_copy:                              ; CODE XREF: __RESET+10j
ROM:006E                 lpm     r0, Z+          ; en clair : Mov r0,[Z] ; Inc Z
ROM:006F                 st      X+, r0          ; mov [X],r0 ; Inc X
ROM:0070
ROM:0070 loop_end??:                             ; CODE XREF: __RESET+Bj
ROM:0070                 cpi     r26, 0x22
ROM:0071                 cpc     r27, r17        ; X = 0x122 ? double test part haute et basse.
ROM:0072                 brne    loop_copy       ; Si X != 0x122 on saute.
ROM:0073                 ldi     r17, 1
ROM:0074                 ldi     r26, 0x22       ; On remet X = 0x122
ROM:0075                 ldi     r27, 1
ROM:0076                 rjmp    loc_78

On a donc bien compris, l’initialisation copie 0x22 Bytes depuis ROM:0x9a8 vers RAM:0x100. Et bien on va se créer un fichier “RAM” identique au programme qui se serait déjà fait “initialiser” et on l’utilisera darns IDA.

Etape 1 on crée un pad de bytes à 0 qui à une taille de 0x100 (256 en décimal).

$ dd if=/dev/zero of=/tmp/RAM.bin count=256 bs=1
154+0 records in
154+0 records out
154 bytes (154 B) copied, 0.000453577 s, 340 kB/s

Ensuite on extrait de la rom nos 0x22 bytes tant convoités et on les colle au cul de la ram.

$ dd if=/tmp/RepulsCAT.cpp.bin skip=2472 bs=1 count=34 >> /tmp/RAM.bin
34+0 records in
34+0 records out
34 bytes (34 B) copied, 0.000128219 s, 265 kB/s

Et enfin on pad le reste de cette ram avec du 0. ( 2Ko – (256 + 34)) = 1758

$ dd if=/dev/zero bs=1 count=1758 >> /tmp/RAM.bin
1758+0 records in
1758+0 records out
1758 bytes (1.8 kB) copied, 0.0037651 s, 467 kB/s

Et on se retrouve alors avec un joli fichier représentant une ram initialisée.

$ ls -l /tmp/RAM.bin
-rw-r--r-- 1 thanat0s thanat0s 2048 Jan 23 10:42 /tmp/RAM.bin
$ hexdump -C /tmp/RAM.bin
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000100  41 41 41 41 41 41 41 41  41 41 00 03 00 02 00 04  |AAAAAAAAAA......|
00000110  00 00 00 00 00 ae 03 53  04 44 03 75 03 55 03 9e  |.......S.D.u.U..|
00000120  03 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000800

Ne reste plus qu’a la mettre en place dans IDA en lieu et place de cette ram non initialisée. Pour cela dans IDA on fait : View/Open Subview/Segment. On delete le segment nommé RAM.

delram

On fait FILE/Load File/Load additionnal File et on sélectionne notre RAM.bin. On charge le segment en 0x10000 tout le reste à 0 et on décoche “Code Segment”

Il ne reste plus qu’a éditer les attributs du segment pour faire joli et changer le segment name en RAM et le segment class en DATA et désormais, les variables sont initialisée !! Tous est vachement plus clair.

after

Voila, il n’y a plus qu’a désosser maintenant. le grand fichier des opcodes est là.

Have Fun !

Posted in Reverse | Tagged , , , | 3 Comments

Le hacking c’est aussi CA !

Le très officiel et très prout prout Forum Internationnal sur la Cybersécurité, le FIC. S’est fait décontenancer par le petit journal et une télécommande Tv Gone.

Ca commence à 14mn10.. Ce genre de truc m’éclate. Si j’avais facebook je dirais “LIKE”.

http://www.canalplus.fr/c-divertissement/c-le-petit-journal/pid6515-l-emission.html?vid=1008956

Posted in BlaBla | Tagged | Leave a comment

Dumper un Arduino.

Bon, je pense que pas grand monde connais le Arduino, c’est un contrôleur autonome qui à la particularités d’être super simple d’utilisation. On branche le cable USB, on code un genre de programme en C dans son l’IDE et on pousse. A partir de là, le bitonio est autonome. Il peut alors commander 14 Entrées/Sorties et 5 Entrées analogique, bref le pied pour tout petit montage électronique funky qui détecte et réagit. Et le fer à souder n’est même pas sollicité.

Bon, ok… mais comment on reverse le code. C’est un processeur ATmel qui est le coeur du bitonio, pour le Arduino modèle Uno c’est même précisément un Atmega 328,  rien à voir avec un Mips ni un X86, c’est encore autre chose. Pour ceux que ca intéresse voir Ici : http://www.atmel.com/Images/doc0856.pdf

On peut donc le désassembler avec un IDA évidemment mais aussi avec du libre comme vavrdisasm.

Mais avant de désassembler, faut le dumper ce programme de la chip vers un fichier. Pour cela on peut utiliser avrdude qui est fournis par l’ide de m. Arduino. Petit example sur mon MachinTosh.

$ /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avrdude \
-C /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/etc/avrdude.conf \
-v -patmega328p -carduino -P/dev/tty.usbmodem1421 -b115200 -D -Uflash:r:/tmp/mydump.hex:i

avrdude: Version 5.11, compiled on Sep  2 2011 at 18:52:52
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch

         System wide configuration file is "/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/etc/avrdude.conf"
         User configuration file is "/Users/Thanat0s/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/tty.usbmodem1421
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         AVR Part                      : ATMEGA328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 3
         Firmware Version: 4.4
         Vtarget         : 0.3 V
         Varef           : 0.3 V
         Oscillator      : 28.800 kHz
         SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f
avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: reading flash memory:

Reading | ################################################## | 100% 4.21s

avrdude: writing output file "/tmp/mydump.hex"

avrdude: safemode: lfuse reads as 0
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: safemode: Fuses OK

avrdude done.  Thank you.

Et hop, on se retrouve avec un fichier au format i-hex. Mais voila c’est le format ascii de M. Intel utilisé généralement pour flasher toutes puces de tous poils, IDA l’aime pas !

$ head /tmp/mydump.hex 
:200000000C9461000C947E000C947E000C947E000C947E000C947E000C947E000C947E000D
:200020000C947E000C947E000C947E000C947E000C947E000C947E000C947E000C947E00D0
:200040000C94E6000C947E000C947E000C947E000C947E000C947E000C947E000C947E0048
:200060000C947E000C947E0000000000240027002A0000000000250028002B000000000057
:20008000230026002900040404040404040402020202020203030303030301020408102071
:2000A0004080010204081020010204081020000000070002010000030406000000000000EB
:2000C000000011241FBECFEFD8E0DEBFCDBF11E0A0E0B1E0E2E7F5E002C005900D92A63003
:2000E000B107D9F711E0A6E0B1E001C01D92A531B107E1F70E94A8020C94B7020C94000055
:20010000CF93DF93809102010E945502EC0190930B0180930A018130910581F480910001F6
:2001200061E00E9401028091060190910701892BC1F4D0930701C093060113C08091000185

Pour ceux que ca intéresse, ce format est fortement documenté sur wikipedia. Nous, pour le passer à la moulinette on veut une image de la puce bit à bit. Pour convertir celui ci, on va utiliser avr-objcopy qu’on trouve dans tout bonne distrib généralement comme compagnon de avr-libc.

$ avr-objcopy -I ihex /tmp/mydump.hex -O binary /tmp/mydump.bin
$ ls -lh /tmp/mydump.bin 
-rw-r--r-- 1 thanat0s thanat0s 32K Jan 22 11:42 /tmp/mydump.bin
$ hexdump -C /tmp/mydump.bin | head
00000000  0c 94 61 00 0c 94 7e 00  0c 94 7e 00 0c 94 7e 00  |..a...~...~...~.|
00000010  0c 94 7e 00 0c 94 7e 00  0c 94 7e 00 0c 94 7e 00  |..~...~...~...~.|
*
00000040  0c 94 e6 00 0c 94 7e 00  0c 94 7e 00 0c 94 7e 00  |......~...~...~.|
00000050  0c 94 7e 00 0c 94 7e 00  0c 94 7e 00 0c 94 7e 00  |..~...~...~...~.|
00000060  0c 94 7e 00 0c 94 7e 00  00 00 00 00 24 00 27 00  |..~...~.....$.'.|
00000070  2a 00 00 00 00 00 25 00  28 00 2b 00 00 00 00 00  |*.....%.(.+.....|
00000080  23 00 26 00 29 00 04 04  04 04 04 04 04 04 02 02  |#.&.)...........|
00000090  02 02 02 02 03 03 03 03  03 03 01 02 04 08 10 20  |............... |
000000a0  40 80 01 02 04 08 10 20  01 02 04 08 10 20 00 00  |@...... ..... ..|

Et voila, tout est prêt désormais pour passer à la phase torture du cerveau sur un désassembleur.

 

Posted in Hacking, Reverse | Tagged , , | Leave a comment

PHP… La débacle est toujours en marche.

C’est pas tout jeune jeune, mais ça à le don de toujours m’énerver :
http://php.net/manual/en/features.safe-mode.php

The PHP safe mode is an attempt to solve the shared-server security problem. It is architecturally incorrect to try to solve this problem at the PHP level, but since the alternatives at the web server and OS levels aren’t very realistic, many people, especially ISP’s, use safe mode for now.

On résume, safe mode permet de désactiver l’exécution directe d’exécutables, de coincer les scripts dans leur répertoire, restreindre ce qu’ils peuvent lire et couper éventuellement l’envois de mail en PHP. Ca sert pas seulement à empêcher que M. DUS lise le “config.php” de Mme DUS dans le répertoire d’à coté. C’est pas parfait, il ne faut pas tout baser sur cela, mais je pense que c’est un plus.

Il n’y a pas d’alternative viables pour le multiple hosting d’après eux. DONC, Bande de cons ! :)  On le coupe pas si il n’y a pas d’alternative viable. D’autant que les gars qui on mis ca en place c’est parce qu’ils sont pas du tout sur le reste généralement :)

Le coté multi-user c’est de base désormais il faudra s’y mettre,  https://wiki.apache.org/httpd/PHP-FPM. Sinon Il y a toujours http://www.suphp.org/Home.html.

Je suis persuadé que PHP 5.4 ne rendra par magiquement le codeur de page plus conscient des failles de sécurité. Moi ce qui m’embête c’est que désormais la donne c’est ”une injection en php réussie = un shell et un spammer/ddos bot”. C’est inextricable.  Well Done !

Et pourtant en PHP il y a maintenant de quoi cleaner ses inputs ;
http://websec.io/2013/12/31/Input-Filtering-Validation-Aura-Filter.html
http://www.php.net/manual/en/filter.filters.sanitize.php

Php 5.4 est déjà disponible sur Debian 7 et sera dans le prochain LTS Ubuntu. Auditez votre code ou passez vite sur SUSE :)

Posted in WebSecurity | Tagged , | Leave a comment

Ha ouais on en est là…

British Telecom et le VPN expliqué aux enfants; Un anglais dans la salle pour tester ?

http://cryptome.org/2013/12/Full-Disclosure.pdf

Et pendant ce temps là, le site d’open SSL se fait défacer… ayez confiance …

30-Dec-2013:   UPDATE: site defacement provisional details.

Posted in BlaBla, Crypto, Network | Tagged , | Leave a comment

The French touch :)

La grosse grosse classe :) Deux options,  A.. poncé… B… FrenchPrism… (Je sais pas pourquoi je dit A )

http://googleonlinesecurity.blogspot.fr/2013/12/further-improving-digital-certificate.html

“Late on December 3rd, we became aware of unauthorized digital certificates for several Google domains. We investigated immediately and found the certificate was issued by an intermediate certificate authority (CA) linking back to ANSSI”

Pour rappel, c’est qui déja l’anssi ?? :

http://www.ssi.gouv.fr/en/

Posted in BlaBla, Crypto, Hacking | Tagged , , | 1 Comment

Packer sans ta mère, Level II, Prérequis I : ViewOfFile

Voila un titre bien pompeux. Je vais consacrer une série d’articles à l’art du dépacking (Oui c’est un ART !), et sachant que c’est en forgeant qu’on devient forgeron dessoudeur (Proverbe Ukrainien), je me rend compte qu’il est nécessaire de maitriser quelques concept de base. (PE, PEB, TIB, CPU Context, ViewOfFile etc..) avant de pouvoir pleinement comprendre ce que l’on va faire.

Je ne vais pas revenir non plus sur qu’est – ce qu’un exécutable packé et comment réussir à le dépacker de façon générique (Et pour l’instant magiques). Cela à déjà été couvert par de précédents articles :

Donc allons y. On reprend depuis le début. Nous allons déjà voir comment Windows représente les exécutables en mémoire. Première étape, on reprend depuis le début, je pense que tous le mode était au courant mais soit;

Chaque exécutable pense qu’il est seul au monde. Si on est en 32 bits par exemple, chaque exécutable dispose devant lui de potentiellement de 4Go de ram de 0x00000000 à 0xFFFFFFFF. Et peut importe si la station ne dispose de 256 Mo de mémoire tout est remappé et virtuel. On remercie au passage l’operating system pour cela. Dans cette plage mémoire, il n’a quand même pas tout pour lui. le Kernel de windows se réserve un pan de mémoire, cette mémoire n’est pas atteignable par le process. C’est de 0x8000000 à 0xFFFFFFF en 32 bits (bref 2Go pour le Process et 2 Go pour le Kernel).

En 64 Bits c’est encore plus la foire; Dans l’absolu l’adressage 64 bits permet d’adresser 16 Exaoctets ( bref 16484 Petaoctets, soit 16777216 Teraoctets rhaa rhaaa…)  Bref y a de quoi voir venir. Le découpage à été moins magnanime. en 64 Bits le process dispose de 0x0 à 0x7FF’FFFFFFFF  soit 8 Teraoctets et ensuite il y a un énorme No man’s land et enfin les 248 derniers Teraoctets de 0xFFF0800’00000000 à 0xFFFFFFFFFFFFFFFF sont réservés au kernel. Voila pour la base.

Maintenant faisons un exécutable 32 bits qui fait un hello world. On le compile et on le strip pour ne garder que le strict minimum des sections.

$ cat hello.c
#include <windows.h>
#include <stdio.h>
#include <string.h>

char mystring []="Hello World";

int main () {
        printf("%s is at 0x%X, main is at 0x%X.\n", mystring,&mystring,&main);
        return(0);
}

$ i586-mingw32msvc-gcc hello.c -o hello.exe
$ strip hello.exe

Cet exécutable va afficher notre string «mystring» ainsi que l’offset (l’emplacement mémoire) de la dite string et de la fonction main. Une fois compilé. J’obtient un EXE. Tous le monde dit c’est un EXE, mais en fait c’est un fichier Portable Executable (PE). Il est constitué de deux parties, une partie compatible MS-DOS (On la traine la compatibilité ascendante) qui généralement affiche juste le message “JE TOURNE PAS SOUS MS-DOS ( This program cannot be run in MS-DOS mode). Au cul de cette partie DOS, il y a une partie pour Windows avec des segments mémoires mis bout à bouts. Et oui, notre exécutable est constitué de 3 segments de mémoire qui vont être mappés dans cette mémoire virtuelle. (.text, .data, .rdata ). Une table contenu dans cet EXE nous indique qui va où et comment.

$ objdump -h hello.exe 

hello.exe:     file format pei-i386

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         0000004a  00401000  00401000  00000200  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rdata        00000024  00402000  00402000  00000400  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .data         0000005a  00403000  00403000  00000600  2**2
                  CONTENTS, ALLOC, LOAD, DATA

Faisons simple on s’intéresse au stricte minimum pour l’instant. Admettons on a un segment de code (.text) avec le programme et un autre segment de data (.data) avec notre string “hello world”. (Oubliez Rdata pour l’instant, ne demandez pas svp. :) )

Sous windows il est fort probable qu’un segment de programme soit mappé dans notre mémoire virtuelle en 0x401000. La raison est simple, généralement tous les exécutable fait pour Windows NT et > on leur adresse de base mappé en 0X400000. Sous windows 95 ils étaient prévus pour être mappé en 0x1000000. Mais rien n’est aussi simple si on regarde Notepad.exe de windows XP, il est toujours en 0x1000000 lui.

$ objdump -h notepad.exe 

notepad.exe:     file format pei-i386

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00007748  01001000  01001000  00000400  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000800  01009000  01009000  00007c00  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .rsrc         00008958  0100b000  0100b000  00008400  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

Ca c’est pour l’historique. Ce qu’il faut savoir c’est que dans le segment de code tout est relatif. Quand je dit a mon programme “saute là” ou “call ici”. les sauts sont relatifs par rapport à là ou je suis. Un “saute là” sera en fait un saute à +X octets.

Exemple non tiré de notre hello.exe :

001

Premier exemple, je suis en 0x40113E et le code assembleur est E8 DF FE FF FF. «0xE8» c’est l’opcode de «CALL». Ensuite il y a où sauter, le saut est relatif à l’instruction suivante. Ici le saut c’est 0xFFFFFEDD (Il faut lire de droite à gauche pour convertir bytes (octets) en integer (entier 32 Bits)). Si on convertit cet entier en entier signé sur 32 bits ça fait -291. Et je vous le donne en mille 0x401143 – 291, ça fait 0x401020. Bref un saut en arrière.

Idem pour le Jump if Above “JA”. instruction 0x77, Suivis de son saut relatif à la prochaine instruction sur 8 bits. Donc 0x401165 + 0x3B = 0x4011A0.

On l’a compris, le code et surtout les instructions de saut et branchement sont relatives et se foutent de connaitre à quel emplacement ils tournent. C’est ce qu’il faut retenir. Le code peut être posé potentiellement à n’importe quel offset il fonctionnera. C’est d’ailleurs ce que fait l’ASLR. L’ASLR randomise a chaque lancement l’emplacement mémoire du segment de code (et aussi de la stack). Ce qui complique les exploitations des exécutables du style : “crash pas et saute plutôt ici à met moi tous les droits”. L’ASLR est dispo depuis Vista.

Mais reprenons notre hello world, le printf va nous afficher l’offset mémoire de la procédure MAIN et l’adresse ou est stocké la chaine de texte.

Sur un XP sans ASLR

Hello World is at 0x403000, main is at 0x401004.

Sur un Seven avec ASLR

Hello World is at 0x403000, main is at 0x401004.

Damned, Fichtre..  Et oui, sous Windows, c’est pas tout d’avoir un OS ASLR. Ils faut que les exécutables le soient. Et ça c’est une compilation spécifique et un petit flag dans l’exécutable qui le dit. On y reviendra. Mais retenez aussi cela ! C’est comme les antibiotiques, c’est pas automatique.

Regardons les data maintenant; Voici comment mon programme appelle mon «printf»

002

Et oui, Il pose sur la pile toutes les chose à imprimer puis l’offset de la string, 0x401004, 0x403000, x402000 et oui c’est bien là où se situe mes «string» comme nous l’avons constaté précédemment, mais on constate que ces emplacements sont “en dur” dans l’exécutable. Autre constat donc, les emplacement mémoires des DATA sont en durs et non relatifs.

Ensuite en 0x40102E il appelle printf. Ollydbg ici nous aide et nous dit que ça appelle un JMP qui lui saute vers printf de MSVCRT. Bien on est prêt à le croire Ollydbg, mais détaillons ceci;

En 0x40102E, J’ai un saut , opcode «E8» vers 0x11 (17 en décimal) octets plus loin à partir de la prochaine instruction. J’arrive donc en 0x401044 et là j’ai un saut «long» opcode «FF». le «25» suivant indique, tu va sauter à la valeur qu’il y a dans l’emplacement mémoire qui va venir. Et enfin l’emplacement mémoire, 0x40303C . Ca ressemble à une adresse dans le segment DATA et pour cause. C’en est bien une ! Si on regarde ce qu’il y a dans cette mémoire on tombe sur une valeur fort étrange 0x77C4186A.
003

Vous venez de découvrir l’IAT. l’Import Address Table. Expliquons;

Notre exécutable utilise printf, mais printf est pas inclus dans notre exécutable. Printf sous windows est une fonction (un bout de code quoi) incluse dans une DLL (Dynamic Linked Library) nommé MSVCRT.DLL (Microsoft Visual C RunTime). Alors comment cela marche. Quand j’ai créé mon exécutable, il a été noté dedans «Heps j’aurai besoins pour fonctionner de printf de la dll msvcrt». C’est noté dans la table d’import qui est aussi une dans une section de notre PE. On peut le voir avec objdump -p.

There is an import table in .data at 0x40300c

The Import Tables (interpreted .data section contents)
 vma:            Hint    Time      Forward  DLL       First
                 Table   Stamp     Chain    Name      Thunk
 0000300c       00003034 00000000 00000000 0000304e 0000303c

        DLL Name: msvcrt.dll
        vma:  Hint/Ord Member-Name Bound-To
        3044      641  printf

Et voila, tout est là dans le PE. Au démarrage de l’exécutable Windows va donc savoir quel dll j’ai besoin et de quelles fonctions. Il va donc charger la DLL en mémoire, trouver l’offset du code des fonctions que j’ai besoin et les poser dans cette plage mémoire (l’IAT) avant de lancer le programme.

Mais alors, cette DLL elle est aussi en mémoire… Et oui, une DLL c’est comme un PE tout à fait normal, ça a une adresse de base et des segments, des table d’import IAT, et aussi des table d’export. Une table d’export (EAT) c’est une table qui dit quelles fonctions sont exportée (rendues disponible par la DLL aux autre programmes) et où on peut les trouver. regardons msvcrt.dll.

$ objdump -h msvcrt.dll 

msvcrt.dll:     file format pei-i386

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         0004bd36  77c11000  77c11000  00000400  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00004800  77c5d000  77c5d000  0004c200  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .rsrc         000003e0  77c64000  77c64000  00050a00  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .reloc        00002d74  77c65000  77c65000  00050e00  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

Et oui l’adresse de base de la DLL est 0x77C11000. Étonnamment dans le même segment mémoire que là ou notre IAT va nous faire sauter (0x77C4186A) pour le printf. Cette DLL sera elle aussi mappée en mémoire un peut plus loin que notre process. Notre process pourra utiliser ce code à son aise.

Et oui, maintenant tout s’éclaire. Si on regarde les segments mémoire sous Ollydbg, tout est plus clair.

004

On comprend comment tout (presque tout) est goupillé. Ici j’ai donc mon programme avec ses 3 sections, et 3 DLL, msvcrt.dll, kernel32.dll et ntdll.dll. Et l’IAT de mon programme a été tripotée par windows pour savoir où sauter. On remarque que les headers du PE (les EXE quoi) eux aussi sont mappés à l’addresse de base de l’exécutable.

A retenir que même si on demande rien dans l’IAT, ntdll et kernel32 sont deux DLL toujours chargée.

Passer d’un fichier PE à un exécutable placé aux bon offsets en mémoire s’appelle «Map a View of File» On comprend mieux l’existence des fonctions windows UnmapviewOfFile et MapViewOfFile. Pour une DLL que l’on souhaite charger en mémoire même si l’IAT ne dit pas de le faire, on préfèrera la fonction LoadLibrary.

Voila, j’espère que la vue d’un exécutable et des DLL en mémoire et la magie qui les passe d’executable sur le disque au mapping en mémoire, ainsi que le miracle de l’IAT est beaucoup plus clair pour tous le monde.

Prochainement, avant de désosser le format PE, on regardera en détail comment retrouver une DLL et une fonction en mémoire.

A+

Posted in Coding, Reverse | Tagged , , , , , | Leave a comment

Scouting DNS avec CHAOS.

Juste un petit post, Voici quelque tricks que l’on peut pratiquer avec un client DNS, dans notre cas DIG.

Le deux premier viennent de la classe CHAOS. la classe CHAOS permet d’avoir quelques infos sur le serveur DNS et cela ne fonctionne pas uniquement avec BIND.

Pour exemple reprenons notre tête de turque iranien habituelle (Voir Le CTF de la centrifugeuse ou on y apprenait comment lister tous les records d’un serveur DNS mal configuré, n’essayez plus c’est corrigé). On peut toujours avec une query bien sentie sortir la version. Ici le serveur DNS est un Windows 2003 semble t’il.

cyanide# dig -t txt -c chaos VERSION.BIND  @80.191.32.2            

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> -t txt -c chaos VERSION.BIND @80.191.32.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48075
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;VERSION.BIND.                  CH      TXT

;; ANSWER SECTION:
VERSION.BIND.           0       CH      TXT     "Windows Server 2003"

;; AUTHORITY SECTION:
VERSION.BIND.           0       CH      NS      VERSION.BIND.

;; Query time: 302 msec
;; SERVER: 80.191.32.2#53(80.191.32.2)
;; WHEN: Sun Dec  1 17:39:10 2013
;; MSG SIZE  rcvd: 76

La zone chaos permet aussi de demande le vrai hostname du serveur.

cyanide# dig -t txt -c chaos HOSTNAME.BIND  @80.191.32.2  

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> -t txt -c chaos HOSTNAME.BIND @80.191.32.2
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57429
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;HOSTNAME.BIND.                 CH      TXT

;; ANSWER SECTION:
HOSTNAME.BIND.          0       CH      TXT     "DNS-NS4"

;; AUTHORITY SECTION:
HOSTNAME.BIND.          0       CH      NS      HOSTNAME.BIND.

;; Query time: 303 msec
;; SERVER: 80.191.32.2#53(80.191.32.2)
;; WHEN: Sun Dec  1 17:43:34 2013
;; MSG SIZE  rcvd: 65

Et défois suivant la distrib, cela peut carrément être très très verbeux, reprenons un autre exemple d’un record que l’on pense dans le pays sans extraditions.

cyanide# dig -t txt -c chaos VERSION.BIND  @2main.ir        

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> -t txt -c chaos VERSION.BIND @2main.ir
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45423
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;VERSION.BIND.                  CH      TXT

;; ANSWER SECTION:
VERSION.BIND.           0       CH      TXT     "9.8.2rc1-RedHat-9.8.2-0.17.rc1.el6_4.6"

;; AUTHORITY SECTION:
VERSION.BIND.           0       CH      NS      VERSION.BIND.

;; Query time: 85 msec
;; SERVER: 109.203.113.188#53(109.203.113.188)
;; WHEN: Sun Dec  1 18:09:41 2013
;; MSG SIZE  rcvd: 95

Très verbeux, du bind à l’os tout y passe. Et pour le hostname là c’est le drame, … zut en europe :) !

cyanide# dig -t txt -c chaos hostname.bind  @2main.ir

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> -t txt -c chaos hostname.bind @2main.ir
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44123
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;hostname.bind.                 CH      TXT

;; ANSWER SECTION:
hostname.bind.          0       CH      TXT     "northampton.theukhost.net"

;; AUTHORITY SECTION:
hostname.bind.          0       CH      NS      hostname.bind.

;; Query time: 91 msec
;; SERVER: 109.203.113.188#53(109.203.113.188)
;; WHEN: Sun Dec  1 18:14:42 2013
;; MSG SIZE  rcvd: 83

Le plus simple pour éviter ce genre de petit leak et de créer une vue qui deny les requests.

A bientôt pour un peu plus de scouting fun sur le DNS avec Active Directory.

 

Posted in Network | Tagged , | 2 Comments

PASSIVE DNS ou l’art de logger le DNS

Comment retrouver quel était l’ip utilisée par le record www.badbadserver.com le 24 décembre d’il y a 2 ans, cet IP correspond t’elle au point d’exfiltration www.re-badserver.com vu ce matin ? Une seule réponse; le DNS Passif, alias PDNS.

Passive DNS c’est juste un logging des records DNS ainsi que leur réponses associée, le tout mis en base et consultables. Certaines implémentations vont jusqu’a logger le whois complet, c’est toujours plus rigolo pour retrouver avec leur IP toute une liste de domaines de margoulins.

Pour les plus curieux sur les uses cases, je vous conseille le PDF de Rod Rasmussen.

http://conferences.npl.co.uk/satin/presentations/satin2011slides-Rasmussen.pdf

Malheureusement, il faut bien avouer que chacun y va de son implémentation et que c’est assez la foire pour l’instant. (Et ca fait une paire d’année que cela dure.)

Coté tools, il y avait avant le tools pdns.rb qui était même disponible dans les repository Debian. Ce tools avait l’avantage de pouvoir consulter plusieurs base de données (Uniquement deux db étaient libres). Malheureusement celui ci à disparu. Il ne reste donc plus que deux sources exploitable pour les quidams que nous sommes.

L’interface Web de bfk.de

http://www.bfk.de/bfk_dnslogger.html

et surtout le whois du cert.ee (Merci l’estonie !)

Petit tuto pour l’Estonie… Quels ont été les ips de www.perdu.com

thanatos@cyanide:~/tools/passive-dns-query-tool-1.0.0$ whois -h sim.cert.ee www.perdu.com
www.perdu.com   173.236.190.252 2010-12-19 15:49:33     2010-12-19 15:49:33
www.perdu.com   208.97.189.107  2010-07-30 11:39:41     2010-08-10 11:51:16
www.perdu.com   82.165.176.145  2009-12-14 16:07:44     2009-12-14 16:07:44

Et maintentant quels sont les hosts qui on partagé cette même IP et quand.

thanatos@cyanide:~/tools/passive-dns-query-tool-1.0.0$ whois -h sim.cert.ee 173.236.190.252
www.perdu.com   173.236.190.252 2010-12-19 15:49:33     2010-12-19 15:49:33
www.hacker.org  173.236.190.252 2011-01-06 14:13:46     2012-07-18 16:02:07
perdu.com       173.236.190.252 2011-03-25 09:25:39     2011-03-25 09:25:39
cadgeek.com     173.236.190.252 2012-07-20 11:04:33     2012-07-20 11:04:33

Et encore plus fort, quels sont les hosts qui partagent le range /29 de cette IP.

thanatos@cyanide:~/tools/passive-dns-query-tool-1.0.0$ whois -h sim.cert.ee 173.236.190.248/29
www.welie.com   173.236.190.249 2010-12-02 10:23:34     2012-08-23 12:56:37
www.uncoltuitatdelume.net       173.236.190.253 2011-02-23 14:53:39     2011-02-28 13:06:27
www.perdu.com   173.236.190.252 2010-12-19 15:49:33     2010-12-19 15:49:33
www.networkfoo.org      173.236.190.254 2010-11-17 18:35:09     2012-08-27 10:31:46
www.luchafemeninaymixta.com     173.236.190.251 2011-03-11 14:10:45     2011-03-11 14:10:45
www.indiecater.com      173.236.190.251 2010-11-17 09:47:22     2012-08-16 15:33:26
www.hacker.org  173.236.190.252 2011-01-06 14:13:46     2012-07-18 16:02:07
www.allods.gipat.ru     173.236.190.255 2011-02-18 09:19:37     2011-03-15 15:31:07
www.akcentonline.com    173.236.190.255 2010-11-27 11:41:04     2011-05-03 10:08:15
www.adriansina.com      173.236.190.255 2011-01-31 23:19:12     2012-08-22 14:35:50
welie.com       173.236.190.249 2011-01-04 12:45:31     2012-06-11 11:16:32
uznaykak.info   173.236.190.254 2012-06-15 13:48:04     2012-06-15 13:48:04
perdu.com       173.236.190.252 2011-03-25 09:25:39     2011-03-25 09:25:39
networkfoo.org  173.236.190.254 2011-03-25 17:10:26     2011-04-07 15:17:34
macournoyer.com 173.236.190.249 2011-01-22 17:43:54     2012-06-12 12:51:35
images.carthain.com     173.236.190.250 2012-06-14 09:46:32     2012-06-14 09:46:32
ieatgrains.com  173.236.190.251 2011-02-16 15:14:49     2011-02-16 15:14:49
eightbar.co.uk  173.236.190.251 2010-12-14 17:08:13     2012-06-25 15:39:12
createyourproglang.com  173.236.190.249 2010-12-22 12:22:58     2011-01-22 17:43:52
courtenaybrown.com      173.236.190.253 2011-01-04 14:51:26     2011-01-04 14:51:26
code.macournoyer.com    173.236.190.249 2011-03-29 11:35:37     2012-08-16 10:41:53
codedinc.com    173.236.190.250 2012-06-20 12:29:43     2012-06-20 12:29:43
codedinc.com    173.236.190.249 2012-06-20 12:29:43     2012-06-20 12:29:43
cadgeek.com     173.236.190.252 2012-07-20 11:04:33     2012-07-20 11:04:33
bencollins.org  173.236.190.253 2010-11-17 16:11:03     2011-03-11 15:53:04
akcentonline.com        173.236.190.255 2011-03-01 16:57:24     2011-03-01 17:00:25

Pour ceux qui veulent mettre en place un pdns chez eux , je vous conseille l’implementation du Cert Luxembourgeois, une des plus complète sur le marché :)

https://github.com/GOVCERT-LU/gclu_pdns

A+

Posted in Malware, Network | Tagged , | 2 Comments

ENFIN… WordPress s’update comme un grand.

 

wordpress-automatic-updates

Posted in BlaBla, WebSecurity | Tagged , | Leave a comment