<Bomb Lab이란?>
https://studyforall.tistory.com/98
[Bomb Lab]Bomb Lab이란?
Bomb Lab은 컴퓨터 사이언스로 유명한 카네기 멜론 대학교에서 만든 실습 프로그램이다. 이 프로그램을 통해 디버거 사용법을 익히고 바이너리 분석을 연습해볼 수 있다. 폭탄을 터뜨리지 않고 안
studyforall.tistory.com
실습 환경에 대해서는 위의 게시물 하단에 적어놓았다.
phase1에 이어 이제 phase2를 시작해본다.
disassemble phase_2 명령어를 입력하여 phase_2 함수를 처음부터 끝까지 어셈블리 코드로 출력해보았다.

첫인상은 비교(cmp)와 분기(je, jmp)가 많다는 것이다.
안전지대를 확인해보자.
<+64>까지 도달하면 <explode_bomb>을 실행할 가능성이 없어지므로 안전지대라고 볼 수 있다.
그리고 <+50>에서 무조건 <+64>로 jump하므로 <+50>도 안전지대라고 볼 수 있다.
다음으로는 read_six_numbers 함수를 분석해보자.
특정 함수를 실행한 직후 어떤 레지스터를 참조한다면 그 함수의 실행결과로 해당 레지스터에 어떤 값을 설정해놓았을 확률이 높다.
read_six_numbers 함수를 실행한 직후 rsp에 있는 값에 대해 연산을 수행하므로 이 부분을 염두에 두자.
disassemble read_six_numbers를 입력해보았다.

가장 눈에 띠는 함수는 <+56>에 있는 explode_bomb이다.
폭탄을 터뜨리지 않으려면 <+56>을 밟지 않고 <+61>까지 가야하고
그러려면 <+54>에서 jump해야 한다.
jg이므로 앞선 cmp문에서 전자가 후자보다 큰 값을 가지고 있어야 한다.
즉, eax가 0x5보다 큰 값인 6 이상의 값을 가지고 있어야 한다.
<+46>에 sscanf 함수가 있는데 보통 이런 상황에서는
-이런 상황이란 sscanf 함수 다음에 eax가 연산에 사용되는 경우-
sscanf 가 받은 입력값의 개수가 eax에 들어가는 경우가 많다.
따라서 sscanf 함수에 6개 이상의 인자를 줘야하는 것으로 추측해볼 수 있다.
게다가 이 함수의 이름이 read_six_numbers인 것으로 미루어봤을 때
이 함수에 6개의 숫자를 주어야 하는 것으로 추측해볼 수 있다.
바로 동적분석을 해보자.

먼저 b *read_six_numbers로 bp를 걸었다.
run으로 프로그램 실행 후 phase1에 대한 정답을 입력하여 phase2로 넘어왔다.
앞에서 추측한 것을 바탕으로 임의의 6개의 숫자를 입력하였다.
*숫자를 6개로 읽게 하려면 각 숫자 사이에 공백을 입력해야 한다.
phase1에서 함수에 준 argument는 rdi와 rsi를 통해 전달됨을 학습했다.

역시나 입력값이 rdi에 들어있다.
ni를 입력하며 rdi의 값의 변화를 살펴보았다.

한줄씩 실행하다보면 sscanf 실행 직후인 <+51> 지점에 왔을 때 rdi 값이 바뀌는 것을 확인할 수 있다.
우선 여기까지 탐색하고 finish 명령어를 입력해서 read_six_numbers 함수에서 빠져나왔다.
내가 입력한 '1 2 3 4 5 6'은 어디로 갔을까?
read_six_numbers 실행 후 다음 명령어에서 rsp 레지스터를 연산에 사용했다.
rsp는 스택의 가장 윗부분을 가리키는 레지스터이다.
그래서 [STACK] 영역을 확인해보았다.

[STACK] 영역에 1,3,5가 보인다.
내가 입력한 값일까?
확인을 위해 examine 명령어를 입력해보았다.

x/6wd $rsp의 의미는 다음과 같다.
$rsp를 기준으로 word단위의 데이터 6개를 decimal(10진수)로 examine(출력해서 검토) 하겠다.
출력된 값을 보니 해당 주소에 있는 값들이 내가 입력한 값이 맞다.
이제 이 값을 어떻게 연산하는지 로직분석을 해보자.
분석의 목표는 어떤 숫자 6개를 입력해야 flow를 <+50>지점으로 이끌 수 있는가를 찾는 것이다.
다시 disassemble phase_2 하여 정적분석을 한다.
이번에는 read_six_numbers 이후에 rsp에 들어있는 입력값을 어떤 식으로 다루는지를 상세하게 분석할 것이다.

분석 결과를 설명하기 편하게 코드를 4개의 구역으로 나누어봤다.
read_six_numbers 함수 실행 후 처음으로 실행되는 구역은 A구역이다.
<A구역>
rsp에 들어있는 8byte(DWORD)가 1이어야 폭탄을 피할 수 있다.
폭탄을 피하면 D구역으로 간다.
<D구역>
rbx에 두번째 숫자 주소를 입력하고 rbp에는 여섯번째 숫자 다음 주소 즉, 끝부분의 주소를 입력한다.
그리고 B구역으로 간다.
<B구역>
eax에 rbx 바로 이전 숫자를 입력하고 그것을 두 배한 뒤, rbx와 비교한다.
같아야 폭탄을 피할 수 있다.
따라서 두번째 숫자는 첫번째 숫자를 두배한 값인 2가 되어야 한다.
폭탄을 피하면 C구역으로 간다.
<C구역>
rbx가 다음 숫자를 가리키도록 한다.
rbx가 끝부분에 도달하지 않았으면 다시 B구역으로 가서 반복한다.
끝부분에 도달했으면 안전지대인 <+50>을 실행한다.
즉 이 알고리즘에 따르면 6개의 숫자는 1로 시작해서 두 배씩 커지는 숫자여야한다.
따라서 1 2 4 8 16 32를 입력하면 폭탄을 해체할 수 있다.

폭탄을 해체했다.
'Bomb Lab' 카테고리의 다른 글
[Bomb Lab] phase4 (0) | 2024.05.10 |
---|---|
[Bomb Lab] Phase3 (0) | 2024.03.24 |
[Bomb Lab] Phase1 (0) | 2024.03.24 |
[Bomb Lab]Bomb Lab이란? (1) | 2024.03.24 |