본문 바로가기
Pwnable/Pwnable CTF

[Pwnable.kr] Toddler's Bottle_leg

by Y06 2021. 4. 27.

문제를 보니 문제의 ssh 다운로드 주소가 보인다.

ssh는 원격지 호스트 컴퓨터에 접속하기 위해 사용되는 인터넷 프로토콜이다.

기본 포트로 22번을 사용한다.

leg.c 코드

key1부터 3까지의 함수들은 ARM 어셈블리어로 작성이 되어 있는 것을 알 수 있다. 먼저, mian 함수를 보면 위 3개의 함수 값을 모두 더한 값을 맞추면 플래그를 얻을 수 있을 것 같다.

leg.asm main 함수

함수를 통해 구한 r0 값을 모두 더해서 최종적으로 r2에 들어간다.

 

각 함수를 자세히 살펴보자.

leg.c의 key1() 함수
leg.asm key1()

key1() 함수의 c와 어셈블리 코드이다.

pc 값을 r3에 넣고 다시 그 r3을 r0에 넣었다.

pc 값이 key1 값이라는 것을 알 수 있다.

 

그렇다면 pc란 무엇일까?

cpu가 명령어 하나를 수행할 때 fetch > decode > execute의 과정을 거친다.

 

2개의 opcode를 실행하려면 fetch > decode > execute > fetch > decode > execute 총 6번의 작업이 필요하다. 하지만, pipe line이라는 것을 이용해서

 

1 2 3 4
fetch decode execute  
  fetch decode execute

이렇게 병렬적으로 단계를 수행하면 2개의 opcode를 실행할 때 6번의 작업이 필요했던 것이 4번으로 줄일 수 있다. 직렬보다 효율적이다.

 

pc는 fetch 할 주소를 담고 있다.

현재 명령어가 execute 단계라면, 다음 명령어는 decode 단계, 그 다음 명령어는 fetch 단계이다. 그래서 pc는 다다음번째 명령어의 주소를 담고 있게 된다.

 

따라서, 우리는 key1() 함수에서 pc의 값이 0x00008ce4가 된다는 것을 알 수 있다.

 

key2를 살펴보자.

leg.c key2() 함수
leg.asm key2()

r3에 pc 값(0x00008d08)을 대입하고, 4를 더해서 r0에 대입한다.

key2의 값은 0x8d00008 + 4 = 0x8d0c 이다.

 

leg.c key3() 함수
leg.asm key3()

lr이라는 값을 r3에 대입하고, r3의 값을 r0에 대입한다.

그러면 lr이라는 값을 구하면 key3을 구할 수 있을 것 같다.

 

lr은 함수 호출 전에 다시 되돌아가 실행할 주소를 담고 있다.

 

main 함수를 보면, 

leg.asm main

lr의 값은 0x00008d80이 된다.

따라서, key3의 값은 0x00008d80이다.

 

정리하면

key 1 : 0x00008ce4

key 2 : 0x8d0c

key3 : 0x00008d80 

이다.

 

모두 더하면 0x1a770이다. 이것을 10진수로 바꾸면 108400 이라는 값을 갖는 것을 알 수 있다.

 

플래그 값을 찾았다.

 

FLAG: My daddy has a lot of ARMv5te muscle!