Dans toutes les étapes du dévelopement d’un sploit ou encore de la résolution d’un challenge (dans l’applicatif comme toujours :)) on se rend compte que notre meilleur ami après Google est notre débuggueur adoré (avant tous les autres tools de reversing :)).

Je vais ici décrire mon environnement de travail (qui est sommaire pour l’instant vu que je commence à peine à jouer avec les real world exploits …).

C’est une liste de tools qui est loin d’être exhaustive, mais je vais vous présenter ce que j’utilise.

Sous Linux

Pas de miracle ou de mystère, le débugueur roi est ici GDB!

C’est pas une panacé à utiliser mais avec l’habitude on s’y fait et c’est mine de rien une bien puissante bête :).

J’ai toujours trouvé un peu lourd à devoir retaper les habituels ‘i r’, etc après chaque break mais coup de chance, on peut tuner GDB! Un bon script existe : Plugin GDB :). Oui de zolies couleurs ^^.

GDBInit

Et pis bon, le débuguer fait pas tout, parfois on a besoin de choper des addresses de fonctions rapidos : nm.

On oublie pas de mater les bibliothèque loadées avec : ldd.

objdump est assez pratique pour dumper des listings asm entiers (et faire une recherche d’instructions intéressantes ;)).

nasm est indispensable pour l’assembly … sans compter ndisasm.

Ou si on veut analyser les shellcodes utilisés dans les sploits, voilà 3 scripts shells de ma conception qui pourraient vous être utiles. Le premier sert à cleaner les outputs de ndisasm :

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh

sed -r -e '
1 i bits 32\
\
section .text\
    global _start\
\
_start:

s/([0-9A-F]+\s+){2}/    /g
'

Le second à passer en unicode les payload unicode en ASCII :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/sh

if [ "$#" -lt 1 ]
then
    echo "Usage : $0 (ascii2unicode|unicode2ascii)"
fi

case "$1" in
    ascii2unicode)
        sed -r 's/(\w)/\1\x00/g'
    ;;
    unicode2ascii)
        sed -r 's/(\w)\x00/\1/g'
    ;;
esac

Le dernier sert juste à me sortir n’importe quel fichier en hex escaped.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/python

import sys
import struct

if len(sys.argv) < 2:
    filename = '-'
else:
    filename = sys.argv[1]

if filename == '-':
    data = sys.stdin.read()
else:
    fp = open(filename, 'r')
    data = fp.read()
    fp.close()

# let's form the shellcode in C form
escaped = ''.join ("\\x%02x" % ord(c) for c in data)
shellcode = 'char shellcode[] = "' + escaped + '"'

print "shellcode size : %i" % len(data)
print shellcode

Ainsi en utilisant la ligne de commande on est mine de rien assez versatile :

1
2
3
4
5
6
7
8
9
10
11
12
m_101@m_101-laptop $ printf "CC" | ./ascii2unicode.sh ascii2unicode | ndisasm -b 32 - | ./clean_nasm.sed 
bits 32

section .text
    global _start

_start:
    inc ebx
    add [ebx+0x0],al
m_101@m_101-laptop $ printf "JUNK" | ./shellcode2arrayopt.py -
shellcode size : 4
char shellcode[] = "\x4a\x55\x4e\x4b"

On peut instrumenter GDB avec Python : PythonGDB. Au pire il suffit de créer un fichier de commande GDB et de le lancer comme ça :

1
$ gdb -ex 'source cmds.gdb'

C’est la méthode que j’utilise pour dumper par exemple :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/usr/bin/python

# Author  : m_101
# email   : m101.sec at gmail.com
# Target  : Linux
# Depends : gdb, python
# Name    : iDumpMem
# Purpose : Dumping memory portion out of some process
# Version : 0.1
# License : GPL
# Greetz to people for which hacking is a way to live
# Thanks to 2600 Montreal folks for bringing this script idea
# The code is a bit crappy but it works at least :)

from os.path import *
from os import *
from sys import *
from commands import *
from string import *

# arguments check
if len(argv) < 3:
    # example: iDumpMem python heap
    print 'Usage: ' + argv[0] + 'proc_name memory_section [dump_file]'
    exit(1)

proc_name = argv[1]
mem_section = argv[2]

if len(argv) == 4:
    dump_file = argv[3]
else:
    dump_file = 'dump_' + proc_name + '_' + mem_section

# process information
proc_ps_line = getoutput('ps aux | grep ' + proc_name + ' | grep -Ev
"(grep|' + argv[0] + ')"')
if proc_ps_line == '':
    print 'Process ' + proc_name + " doesn't exist"
    exit(1)

# process id
proc_id = split(proc_ps_line)[1]
if proc_id == '':
    print "Didn't found proc_id ... exiting"
    exit(1)

# getting the memory section of interest
proc_maps_mem = getoutput('cat /proc/' + proc_id + '/maps | grep ' +
mem_section)
if proc_maps_mem == '':
    print 'No ' + mem_section + ' found ... exiting'
    exit(1)

# memory addresses
mem_range = split(proc_maps_mem)[0]

mem_start = '0x' + split(mem_range, '-')[0]
mem_end = '0x' + split(mem_range, '-')[1]

# printing the informations gained
print 'Process name : ' + proc_name
print 'Process id   : ' + proc_id
print 'Process ' + mem_section + ' : ' + mem_range
print '[+] Dumping process ' + mem_section + ' memory ... '

cmds_file_existed = exists(getcwd() + '/cmds.gdb')

# we create gdb commands file if the file doesn't exist yet
# we delete it afterward
if cmds_file_existed == False:
    gdb_cmds_file = file('cmds.gdb', 'w')
    gdb_cmds_file.write('attach ' + proc_id + '\n')
    gdb_cmds_file.write('dump mem ' + dump_file + ' ' + mem_start + '
' + mem_end + '\n')
    gdb_cmds_file.write('detach\n')
    gdb_cmds_file.write('quit\n')
    gdb_cmds_file.close()

# we execute gdb cmds for dumping targeted memory
gdb_dump_mem = getoutput("gdb -ex 'source cmds.gdb'")

# we delete the created gdb cmds file
if cmds_file_existed == False:
    unlink('cmds.gdb')

print '[+] ' + proc_name + ' ' + mem_section + ' was dumped'
print '[+] Bye bye ;)'

Sous Windows?

C’est pas les tools qui manquent!

Jouer avec les PEs

On pensent à identifier un éventuel packer avec PEiD ou RDG Packer Detector.

PEiD

On peut ensuite faire du diffing avec DarunGrim. En terme de patching engine, le meilleur que j’ai trouvé est diablo2oo2’s Universal Patcher.

dUP2

On peut aussi dumper ses process’ avec LordPE:

LordPE

Pour reconstruire ses dump, ImpREC est toujours aussi utile.

ImpREC

Les debuggers :

Immunity debug

ImmDbg

OllyDBG

OllyDBG

WinDBG IDA PRO.

IDA Pro

En termes de plugins :

D’autres tools peuvent être utiles :

  • PAIMEI : Reverse engineering framework
  • ROPEME : ROP Exploit Made Easy

Et pour finir l’un des tools qui est très utile :

Et vous, quels tools utilisez-vous?

m_101