Wargame/LOB

LOB assassin Write-Up

0xe82de_ 2019. 8. 1. 09:14
728x90
728x90
728x90

LOB assassin 풀어보자.

 

[사진 1]

이전 문제와 달리 strncpy 함수로 48bytes만 buffer 변수에 저장한다. 따라서 ret 지점까지만 변조가 가능하다. hint를 보면 FEBP라고 되어 있는데 Fake EBP를 뜻한다. ret 지점을 명령어 leave 또는 ret 또는 leave + ret 주소로 변조하여 ebp를 조작하면 된다. 여기선 leave + ret 명령어의 주소로 변조해야 한다.

 

 

[사진 2]

먼저 mainn 함수의 어셈블리어 코드를 보면 strcnpy 함수를 호출하기 전에 ebp-0x28 주소를 eax 레지스터에 저장한다. 즉, 이 곳이 buffer 변수의 시작점이다.

 

 

[사진 3]

따라서 스택은 위와 같이 형성될 것이고, buffer 변수부터 44bytes를 입력하면 ebp까지 변조할 수 있다. 그리고 명령어 leave + ret 의 주소로 ret 지점을 변조해야 한다.

 

 

[사진 4]

leave + ret 가젯은 objdump 명령어로 쉽게 찾을 수 있다. 주소는 0x08048311이다.

 

 

[사진 5]

먼저 buffer 변수의 주소를 알아야 한다. 디버깅하기 위해 zombie_assassin 파일을 다른 이름(kombie_assassin)으로 복사했다. 그리고 임의의 값 "\x90" 44bytes와 ret를 변조할 "ABCD" 문자열을 입력하고 실행했다.

위와 같이 0xbffffaa0 주소가 buffer 변수의 시작점이고, 0xbffffac8 주소가 ebp임을 확인할 수 있다.

 

 

[사진 6]

buffer 변수의 주소를 알아냈으니 다시 gdb로 실행한다. buffer+4 주소 4bytes와 nop "\x90" 11bytes, shellcode 25bytes를 입력하여 ebp 직전까지 변조하고 buffer-4 주소로 ebp를 변조한다. 그리고 ret는 leave + ret 가젯의 주소로 변조한다.

 

 

[사진 7]

정리하면 위와 같다. ebp는 buffer 변수 주소보다 4bytes 작은 지점을 가리키고 buffer 변수 주소보다 4bytes 작은 지점은 buffer 변수의 주소가 저장되어 있다. 그리고 buffer 변수의 시작점에는 buffer 변수보다 4bytes 큰 지점을 가리키는 데 이 지점은 shellcode의 시작점이다.

 

 

[사진 8]

main 함수 에필로그 직전에 브레이크 포인트를 설정했으므로 다음 명령어는 위와 같이 leave 명령어이다.

leave 명령어의 기능은 다음과 같다.

 1) move esp, ebp // ebp 레지스터의 값을 esp 레지스터에 저장한다.

 2) pop ebp // 현재 esp 레지스터가 가리키는 스택의 값을 ebp 레지스터에 저장한다.

 

 

[사진 9]

leave 명령어가 수행되기 전 ebp 레지스터에 저장된 값은 buffer 변수보다 4bytes 작은 지점을 가리킨다. leave 명령어를 수행하면 먼저 move 명령어로 ebp 레지스터의 값이 esp 레지스터에 저장된다. 그리고 pop 명령어로 esp 레지스터가 가리키는 스택의 값을 ebp 레지스터에 저장하며, 스택에서 값을 뺐으므로 esp 레지스터의 값은 4bytes 증가한다.

따라서 ebp 레지스터에는 0xbffffa9c 값이 저장되고 esp 레지스터에는 0xbffffacc 값이 저장된다. 그리고 해당 값은 ret 지점을 가리키고 leave + ret 가젯의 주소이다.

 

 

[사진 10]

다음 명령어인 ret가 수행되면 esp 레지스터가 가리키는 스택의 값을 eip 레지스터에 저장한다. 현재 esp 레지스터가 가리키는 스택의 값은 leave + ret 가젯의 주소이므로 다시 한 번 leave 명령어와 ret 명령어가 수행되는 것이다.

 

 

[사진 11]

위와 같이 ret 명령어를 수행하면 eip 레지스터에 leave + ret 가젯의 주소가 저장되고 esp 레지스터의 값은 4bytes 증가한다.

 

 

[사진 12]

leave 명령어를 수행하면 move 명령어로 ebp 레지스터의 값 0xbffffa9c가 esp 레지스터에 저장된다. 그리고 pop 명령어로 esp 레지스터가 가리키는 스택의 값인 0xbffffaa0이 ebp 레지스터에 저장되며, 스택에서 값을 뺐으므로 esp 레지스터의 값은 4bytes 증가하여 0xbffffaa0이 된다. 참고로 0xbffffaa0 값은 buffer 변수의 주소이다.

이 지점에 저장된 값은 buffer 변수의 주소보다 4bytes 큰 값인데 shellcode를 가리킨다.

 

 

 

[사진 13]

ret 명령어를 수행하면 현재 esp 레지스터의 값 0xbffffaa0이 가리키는 지점인 0xbffffaa4 값이 eip 레지스터에 저장된다. 0xbffffaa4 값은 buffer 변수의 주소보다 4bytes 큰 값으로 shellcode의 주소이다.

따라서 shellcode가 실행되는 것이다.

 

 

[사진 14]

따라서 페이로드는 다음과 같다.

| &buffer+4 4bytes | nop 11bytes | shellcode 25bytes | &buffer-4 4bytes | leave+ret 가젯 주소 4bytes |

하지만 실행하면 세그멘테이션 오류가 발생하고 core 파일이 생성되는데 gdb로 core 파일을 열어보면 실제 buffer 변수의 주소가 0xbffffab0 값임을 확인할 수 있다.

 

 

[사진 15]

위와 같이 정확한 buffer 변수를 참고하여 값을 변경해주면 zombie_assassin 계정의 password를 확인할 수 있다.

728x90
728x90