본문 바로가기

Bomb Lab

[Bomb Lab] phase4

<Bomb Lab이란?>

https://studyforall.tistory.com/98

 

[Bomb Lab]Bomb Lab이란?

Bomb Lab은 컴퓨터 사이언스로 유명한 카네기 멜론 대학교에서 만든 실습 프로그램이다. 이 프로그램을 통해 디버거 사용법을 익히고 바이너리 분석을 연습해볼 수 있다. 폭탄을 터뜨리지 않고 안

studyforall.tistory.com

 

<위의 게시물에서 GuestOS 변경>

가상머신: virtualbox

GuestOS: Ubuntu 22.04 -> Kali Linux 2024.1

디버거: pwndbg 플러그인 설치한 gdb

 

먼저 disassemble phase_4 명령어를 입력하여 phase_4 함수를 어셈블리 코드로 출력해보았다.

<+24> 에서 sscanf 함수를 호출하고

<+29>에서 eax에 들어있는 함수의 반환값을 0x2와 비교한다.

같지 않으면 <+41>로 jump하여 explode_bomb 함수가 실행되므로

eax에 들어있는 함수의 반환값은 0x2와 같아야 한다.

sscanf 함수는 주로 eax에 입력받은 인자의 개수를 저장하므로 인자를 2개 전달해야 함을 알 수 있다.

이것이 첫번째 조건이다.

 

<+34>에서는 [rsp+0x8]에 있는 4바이트 크기의 데이터와 0xe (십진수로 14)를 비교한다.

<+39>의 jbe 명령어는 전자의 값이 후자의 값보다 작거나 같으면 jump하는 명령어이다.

jump하지 않으면 explode_bomb 함수가 실행되므로

[rsp+0x8]에 있는 데이터는 14보다 작거나 같아야 한다.

 

break *phase_4+34

명령어를 통해 <+34> 지점에 중단점을 걸고 해당 부분까지 실행시켜본다.

입력값은 임의로 5와 6으로 주었다.

 

중단점까지 실행된 상태에서

x/wx $rsp+0x8

명령어를 통해 [rsp+0x8]에 어떤 값이 들어있는지 확인한다.

내가 입력한 첫번째 숫자가 들어있다.

혹시나 해서 이후에 있는 데이터까지 출력해봤는데 이번에는 6이 출력되는 것을 보니

이것이 내가 입력한 5, 6인 것을 확신해도 될 것 같다.

 

그렇다면 <+34>는 내가 입력한 첫번째 인자와 14를 비교하는 명령어이므로

여기에서 첫번째 인자는 14보다 작거나 같아야 한다는 두번째 조건을 찾을 수 있다.

 

이어지는 코드는 <+46>부터 edx, esi, edi에 파라미터를 저장하고 func4 함수를 호출하는 코드이다.

func4 함수에서 돌아온 후 <+65>, <+67>에 eax값이 0이 아니면 explode_bomb 함수로 가는 명령어가 있다.

따라서 func4의 반환값은 반드시 0이어야 한다는 세번째 조건을 확인할 수 있다.

(그런데 풀고나서 보니 이 세번째 조건은 고려할 필요가 없었다.)

 

이후 <+74>에서 explode_bomb 함수를 건너뛰려면

<+69>에서 [rsp+0xc]의 값이 0이어야 함을 알 수 있다.

[rsp+0xc]에는 앞에서 출력해본 것에서 알 수 있듯 나의 두번째 입력값이 저장되어 있다.

따라서 두번째 입력값은 0이어야 한다는 네번째 조건을 확인할 수 있다.

 

disassemble func4

를 입력해서 func4의 코드를 살펴본다.

eax와 ecx를 이용해 연산을 하고 그 결과값에 따라 특정 조건으로 분기한다.

<+27>, <+48>을 보면 함수의 처음부분으로 돌아가는 명령어를 볼 수 있다.

이를 통해 func4함수는 재귀함수의 구조를 갖고 있다는 것을 알 수 있다.

 

eax, ecx를 이용한 연산을 훑어보면 이미 함수에 주어진 값으로만 연산하므로

재귀호출이 반복됨으로써 초기 결과와 다른 변화가 생기는 일은 없어보인다.

즉 한번 재귀호출이 발생하면 계속 무한 루프를 돈다는 뜻이다.

 

우리는 재귀호출이 일어나는 <+27>, <+48>을 피해갈 수 있는 흐름을 찾아야 한다.

<+22>에서 <+36>으로 jump하고

<+43>에서 <+57>로 jump하면 func4 함수를 빠져나올 수 있다.

 

eax, ecx를 이용한 연산이 이루어짐에 따라 해당 레지스터의 값이 어떻게 바뀌는지 표로 그려봤다.

오프셋 주소 eax ecx 연산
<+4> 14   mov eax, edx
<+6> 14   sub eax, esi
<+8>   14 mov ecx, eax
<+10>   0 shr ecx, 0x1f
<+13> 14   add eax, ecx
<+15> 7   sar eax,1
<+17>   7 lea ecx, [rax+rsi*1]

 

<+17>에서 ecx값이 7이 확실한지 확인하기 위해

break *func4+17

로 중단점을 찍어 해당 시점에서의 레지스터 값을 확인해보았다.

rip가 가리키고 있는 <func4+17>줄을 보면

이 명령어를 실행했을 때 ECX에는 7이 저장되는 것을 확인할 수 있다.

 

<+20>,<+22>에서는 <+36>으로 jump하려면

ecx 값이 edi 값보다 작거나 같아야 함을 알 수 있고,

<+41>,<+43>에서는 <+57>로 jump하려면

ecx 값이 edi 값보다 크거나 같아야 함을 알 수 있다.

 

둘 사이에 ecx, edi의 값이 변하지 않으므로 ecx와 edi는 두가지 조건을 한번에 만족시킬 수 있는 값을 가져야 한다.

'작거나 같다'와 '크거나 같다'를 동시에 충족시킬 수 있는 조건은 '같다'이므로

ecx와 edi가 같은 값을 가져야 함을 알 수 있다.

이것이 다섯번째 조건이다.

 

ecx는 앞에서 살펴본 바와 같이 7이고

edi는 <phase_4+56>을 참고하면 나의 첫번째 입력값임을 알 수 있다.

즉 첫번째 입력값은 7이어야 한다.

 

7 0 을 입력하니 phase4 폭탄이 해제되었다.

 

 

'Bomb Lab' 카테고리의 다른 글

[Bomb Lab] Phase3  (0) 2024.03.24
[Bomb Lab] Phase2  (0) 2024.03.24
[Bomb Lab] Phase1  (0) 2024.03.24
[Bomb Lab]Bomb Lab이란?  (1) 2024.03.24