BombLab - Phase 5

beans_I·2024년 2월 23일
0

Phase5

Phase 5의 경우 유형이 3개인데, 이 포스트에서는 그 중 하나만을 다룬다.

이 유형에서의 핵심은 입력된 문자열을 특정 규칙에 따라 정수 배열의 인덱스로 변환하고, 그 값들을 합산하여 미리 정해진 값과 비교하는 로직을 파악하는 것이다.

1. 입력

  • <+4> ~ <+12>: string_length 함수를 호출하여 %rbx에 저장된 입력된 문자열의 길이가 정확히 6인지 검사한다. 길이가 6이 아니면 폭탄이 터진다. abcdef를 예로 입력해보면 $eaxstring_length 함수의 결과값으로 문자열 길이인 6이 저장되고, %rbx에 문자열이 저장됨을 확인할 수 있다.

2. 반복문을 통한 값 변환 및 누적

문자열 길이 검사를 통과하면, 루프를 실행하기 위한 사전 설정 작업 후 <+33>부터 본격적인 반복문이 시작된다.

루프 사전 설정

  • <+14> mov %rbx, %rax: %rax에 사용자 입력 문자열의 시작 주소(%rbx)를 저장한다.
  • <+17> lea 0x6(%rbx), %rdi: %rdi에 문자열의 끝 주소(시작 주소 + 6)를 저장한다.
  • <+21> mov $0x0, %ecx: %ecx 레지스터를 0으로 초기화한다.

추후 분석 후에 확인되는, 반목문에서 각 레지스터의 용도는 다음과 같다.

  • %rax: 루프를 돌며 입력 문자를 한 글자씩 이동
  • %rdi: 루프 종료 조건 판별
  • %ecx: 합계 누적

  • <+26> lea 0x1664(%rip), %rsi: %rsi0x555555402c20 주소를 로드한다. 이 주소는 어떠한 정수 배열의 시작 주소이다.

루프 본문

  • <+33> movzbl (%rax), %edx: %rax(초기 기준 입력한 문자열의 시작 주소)가 가리키는 현재 문자(1바이트)를 %edx 레지스터(4바이트)로 zeroExtend하여 읽어온다.
  • <+36> and $0xf, %edx: AND 연산을 통해 하위 4비트만 남기고 나머지는 모두 0으로 만든다.
  • <+39> add (%rsi, %rdx, 4), %ecx: %rsi(배열 시작 주소)에 %rdx x 4 x (인덱스( %rdx값) x 데이터 크기)를 더하여 배열에서 값을 찾아낸 후, 그 값을 %ecx(누적 합계)에 더한다.

계속해서 나아가본다.

루프 제어

  • <+42> add $0x1, %rax: 문자열 포인터 %rax를 1 증가시켜 다음 문자를 가리키게 한다.
  • <+46> cmp %rdi, %rax: 현재 문자열 포인터(%rax)와 문자열의 끝 주소(%rdi)를 비교한다.
  • <+49> jne <phase_5+33>: 두 주소가 같지 않으면(아직 처리할 문자가 남았으면) 루프의 시작점인 <+33>으로 다시 점프한다.

최종 조건

  • <+51> ~ <+56> 최종 누적 합계(%ecx)가 0x38(10진수 56)과 같은지 비교하고, 같으면 폭탄이 해체되어 페이즈를 마무리한다.

3. 정리하면은…

앞선 어셈블리 코드 분석을 통해 Phase 5의 해체 조건은 다음과 같이 요약할 수 있다.

입력한 6개 문자의 ASCII 값에서 각각 하위 4비트를 추출한다. 이 6개의 값을 인덱스로 삼아 미리 정의된 정수 배열에서 값을 꺼낸 뒤, 그 값들의 총합이 56이 되어야 한다.

이제 답을 도출해보자.

1. 조합 찾기

먼저, GDB로 확인한 정수 배열에서 6개의 숫자를 (중복을 허용하여) 골라 그 합이 56이 되는 조합을 찾아야 한다.

  • 정수 배열:
    인덱스0123456789101112131415
    21061121693471451181513
    1 ~ 16의 값이 중복없이 들어있음을 확인할 수 있다.
  • 조합 예시: 중복을 허용하여 합이 56이 되는 조합은 여러 가지가 가능하다. 그중 한 예시로 16 + 16 + 16 + 4 + 2 + 2 = 56을 선택한다.

2. 인덱스 매핑

다음으로, 위에서 선택한 숫자 조합을 배열의 인덱스로 변환한다.

  • 16은 배열의 인덱스 5에 있다. (3개 필요)
  • 4는 배열의 인덱스 8에 있다. (1개 필요)
  • 2는 배열의 인덱스 0에 있다. (2개 필요)

3. 문자열 생성

마지막으로, 각 인덱스 값을 하위 4비트로 갖는 ASCII 문자 6개로 문자열을 조합한다. 문자의 순서는 상관없다.

  • 필요한 하위 4비트: 0x5 (3개), 0x8 (1개), 0x0 (2개)
  • 해당 문자 예시:
    • 하위 4비트가 5 (0x5): %(0x25), 5(0x35), E(0x45). U(0x55), e(0x65), u(0x75)
    • 하위 4비트가 8 (0x8): ( (0x28), 8(0x38), H(0x48), X(0x58), h(0x68), x(0x78)
    • 하위 4비트가 0 (0x0): 0(0x30), @(0x40), P(0x50), (0x60), p(0x70)` 등

이 문자들을 조합하여 6자리 문자열을 만들면 된다.

: EEEH@@, HE%Ep@ 등 위 조건을 만족하는 모든 6자리 문자열이 정답이 될 수 있다.

profile
노션으로 옮겼습니다. https://beans-i.notion.site/main?pvs=74

0개의 댓글