상세 컨텐츠

본문 제목

[HackCTF-Reversing#7] BabyMIPS - 400 points

Reversing/HackCTF

by bing_su 2021. 3. 10. 20:30

본문

반응형
SMALL

HackCTF reversing 분야의 마지막 문제다. 언제 다 푸나 했는데 결국 다 풀어버렸다.

기드라로 파일을 분석했다. main 함수부터 살펴봤다.

undefined4 main(void)

{
  char cVar1;
  size_t sVar2;
  int local_38;
  char cStack49;
  int local_30;
  uint local_2c;
  undefined4 local_28;
  char local_24 [28];
  
  memset(local_24,0,0x1a);
  printf((char *)0xdf0);
  __isoc99_scanf(0xdfc,local_24);
  sVar2 = strlen(local_24);
  if (sVar2 == 0x19) {
    local_38 = 0;
    while (local_38 < 6) {
      local_30 = 0x18;
      while (cVar1 = local_24[24], -1 < local_30) {
        if (local_30 == 0) {
          local_24[0] = cStack49;
        }
        else {
          if (local_30 == 0x18) {
            local_24[24] = local_24[23];
            cStack49 = cVar1;
          }
          else {
            local_24[local_30] = local_24[local_30 + -1];
          }
        }
        local_30 = local_30 + -1;
      }
      local_38 = local_38 + 1;
    }
    local_2c = 0;
    while ((int)local_2c < 0x19) {
      if ((*(uint *)(data + local_2c * 4) ^ local_2c ^ (int)local_24[local_2c]) !=
          *(uint *)(comp + local_2c * 4)) {
        puts((char *)0xe10);
        return 0;
      }
      local_2c = local_2c + 1;
    }
    local_28 = 0;
    while (local_28 < 0x19) {
      _IO_putc((int)(char)*(undefined4 *)(comp + local_28 * 4),stdout);
      local_28 = local_28 + 1;
    }
    puts((char *)0xe1c);
  }
  else {
    puts((char *)0xe00);
  }
  return 0;
}

변수명이 유사하게 설정되어 있고, 구조 정리가 잘 안되어서 부분 부분 나눠서 정리를 했다.

  if (sVar2 == 0x19) {
    local_38 = 0;
    while (local_38 < 6) {
      local_30 = 0x18;
      while (cVar1 = local_24[24], -1 < local_30) {
        if (local_30 == 0) {
          local_24[0] = cStack49;
        }
        else {
          if (local_30 == 0x18) {
            local_24[24] = local_24[23];
            cStack49 = cVar1;
          }
          else {
            local_24[local_30] = local_24[local_30 + -1];
          }
        }
        local_30 = local_30 + -1;
      }
      local_38 = local_38 + 1;
    }

평문의 위치를 바꿔주는 기능을 하는 것 같다. 암호화의 Logic이라고 하면 할 수는 있겠지만, 직접 평문을 암호화하는 Logic은 아닌 것 같아서 밑의 부분을 이어서 살펴봤다.

 while ((int)local_2c < 0x19) {
  if ((*(uint *)(data + local_2c * 4) ^ local_2c ^ (int)local_24[local_2c]) != *(uint *)(comp + local_2c * 4)) {
    puts((char *)0xe10);
    return 0;
 }

XOR 연산을 이용해 암호화하는 것 같다. XOR 연산은 배타적인 특성을 지니므로 이를 통해 우리가 알아내야 할 입력값을 알 수 있다. 즉, 이를 이용해 복호화하면 플래그 값을 얻을 수 있는 것이다.

data[i * 4] ^ i ^ input[i] == comp[i * 4];

변수명을 수정해서 암호화 방식을 정리하면 위와 같다. 입력 받아야 하는 값을 구해야 하므로 다시 정리해보자.

input[i] = data[i * 4] ^ i ^ comp[i * 4];

 

data와 comp에 있는 값들을 확인할 수 있다. 존재하는 데이터, 복호화 방식을 알았으니 코드를 짜면 된다.

#include <stdio.h>

void main() {
	char data[25] = { 0x72, 0x09, 0x04, 0x10, 0x49, 0x19, 0x3a, 0x1c, 0x34, 0x3b, 0x26, 0x2a, 0x15, 0x30, 0x52, 0x1b, 0x0d, 0x0c, 0x12, 0x38, 0x49, 0x04, 0x02, 0x69, 0x4b };
	char comp[25] = { 0x43, 0x6f, 0x6e, 0x67, 0x72, 0x61, 0x74, 0x7a, 0x5f, 0x59, 0x6f, 0x75, 0x5f, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x46, 0x6c, 0x61, 0x67, 0x21, 0x21 };
	char input[25] = { 0, };

	for (int i = 0; i < 25; i++)
		printf("%c", data[i] ^ i ^ comp[i]);
}

위의 코드를 실행하면 플래그 값이 나오는데 위치만 살짝 바꾸면 정상적인 플래그 값을 볼 수 있다. (앞의 일부 문자열을 "HackCTF{ ~~" 문자열 뒤로 붙이면 된다.)

드디어 리버싱 분야의 문제를 다 풀었다. 나머지 분야도 마저 풀어야겠다.

반응형
LIST

관련글 더보기

댓글 영역