[BombLab] secret_phase 풀이

안우진·2024년 2월 20일

BombLab

목록 보기
8/9

secret_phase 진입 방법 및 공통 풀이입니다.
끝까지 다 읽으면 secret_phase 가 노잼이 될 수 있습니다..

[main]

위 사진은 disas main 했을 때 마지막 부분이다. 관찰해보면 각 페이즈를 call 하고
바로 다음 phase_defused를 call 하는 것을 알 수 있다.
main의 어딜 봐도 secret_phase를 call 하는 부분이 없다.

+) edi 에 문자열을 저장하고 puts@plt 를 call해서 출력하는 듯 하다.

[phase_defused]

<+20> 에서 0x6과 0x2030e1(%rip)를 비교하고 있다.
값의 출처는 모르겠으나 phase를 통과할 수록 0x2030e1(%rip) 값이 1씩 증가한다.

2024-10-25 추가

read_line을 보면 num_input_string * 80 을 offset으로 하여 input_strings에 저장한다.
C 코드로 따지면 char input[6][80] 이런 느낌일 것이다.
또한, 밑부분에는 num_input_string을 1 늘리는 부분이 있다.

phase_defused에서,
input_strings+240 의 값을 가져와서 “%d %d %s”와 sscanf를 한다.
한 페이즈당 char 80개를 받는다고 했으니 +240이면 phase_4의 입력이다.

<+39> 는 phase_4의 1번째 입력 값,
<+34> 는 phase_4의 2번째 입력 값이다
<+29> 는 그럼 phase_4의 3번째 값이라 봐도 되지 않을까 싶다.

<+44>에서 x/s 0x4026d9 를 해보면 %d %d %s 가 나온다.
<+49>에서 x/s 0x604890 을 해보면 밑의 사진과 같이 나온다.

밤랩 1251056 에서 phase_4의 입력 값을 그대로 가져왔다.

read_line 의 skip의 fgets@plt의 __GI__IO_getline의 __GI__IO_getline_info 에서 __GI___uflow 에서 입력을 받고 바로 0x604890 에 저장되는 게 아닌 루프를 돌다가 0x7ffff7c28620 을 call 하더니 뿅하고 생겼다.
__GI___uflow 의 save_for_backup 여기서 뭔갈 할 것 같은데 엄청 길다.
여기에 페이즈 별 입력 값을 저장하는 로직이 있을텐데.. 그만 알아보도록 하자..

사실 0x6047a0 부터 0x50 마다 입력 값이 저장되어 있다.. 신기하네

쨋든 다시 맨 위의 사진을 보면 3번째 인자 = DrEvil이면 secret_phase를 call한다.
결론 얘기하기 참 힘드네..

[secret_phase]

x/60gx 0x604110 을 하면 위 사진처럼 뜰 것이다. 다행인 점은 모든? 밤랩 secret_phase 에서 값이 전부 똑같다는 것이다.
<nii> 은 그 노드의 값을, <nii+8> 은 좌측 자식의 주소값, <nii+16> 은 우측 자식의 주소값을 가지고 있다.

위 그래프는 0x604110을 시각적으로 표현한 것이다.

이제 fun7을 보자. 왜 func4인데 얘는 func7이 아닌지 모르겠지만 일단 넘어가자

여기서 입력 값은 %esi, 0x604110은 %edi 이다. edi는 처음엔 당연히 <n1>이다.

<+4>에서 %rdi 가 0이라면 %eax를 0xffffffff 으로 한다.
그 이후로는..

  • %esi <= %edx 일 때,
    • %esi == %edx 일 때, 뭐 없이 끝
    • %esi == %edx 가 아닐 때, 우측 자식으로 가고 재귀가 끝나면 %eax를 2배에 +1을 한다.
  • %esi <= %edx 가 아닐 때, 좌측 자식으로 가고 재귀가 끝나면 %eax를 2배로 한다.

우상향이면 2eax, 좌상향이면 2eax + 1이라 쉽게 생각하자.

예를 들어 입력값을 31로 줬다 할 때 %eax의 값을 확인해보자.
n1 에서 36보다 작으니 n21 로.
n21 에서 8보다 크니 n32 로.
n32 에서 22보다 크니 n44 로.
n44 에서 35보다 작으니 좌측으로 빠진다.
이 때 %rdi가 0이므로 %eax는 0xffffffff가 된다.
빠진 곳에서 우상향, 그 다음 좌상향, 좌상향, 우상향으로..
최종 %eax의 값은 0xfffffffffffffff6 으로 -10이 나온다.
수식으로 나타내면 (((12)2+1)2+1)2=10(((-1*2)*2 + 1)*2 + 1)*2 = -10 가 되겠다.

secret_phase를 할 때 %eax 값을 음수로 주지 않기 때문에 트리에 있는 값을 입력값으로 넣어야하긴 한다.

예를 들어 test %eax %eax je 로 점프해야 폭탄이 터지지 않는다면,
%eax는 0이 되어야 하고 우상향으로만 이동하면 된다.
이 때, 정답은 1, 6, 8, 36 중에 아무거나 선택하면 된다.

또 예를 들어 %eax가 7이라면 좌상향 3번을 하면 되므로 1001이 답이 된다.

%eax : (정답)

0 : (1, 6, 8, 36)
1 : (40, 45, 50)
2 : (20, 22)
3 : (99, 107)
4 : (7)
5 : (47)
6 : (35)
7 : (1001)

위의 리스트는 정확하지 않을 수 있으니 직접 계산해보자.

끝!!

0개의 댓글