rev-basic-8 풀이

2025. 3. 5. 18:02·Security/Reverse Engineering

문제 설명

 

문제 풀이

문제 파일을 IDA로 열어서 디컴파일을 해보면 다음과 같은 화면이 나온다.

main 메소드 내에서는 별다른 분석거리가 없기 때문에 바로 분기 처리를 하는 sub_140001000 메소드 내부로 들어왔다.

코드는 다음과 같다.

 

__int64 __fastcall sub_140001000(__int64 a1)
{
  int i; // [rsp+0h] [rbp-18h]

  for ( i = 0; (unsigned __int64)i < 0x15; ++i )
  {
    if ( (unsigned __int8)(-5 * *(_BYTE *)(a1 + i)) != byte_140003000[i] )
      return 0LL;
  }
  return 1LL;
}

 

그리고 우리는 다음과 같은 식을 얻을 수 있다.

-5 * a1[i] = byte_140003000[i]

 

근데 한가지 이상한 점이 있다. byte_140003000 주소에 있는 HEX 값들을 10진수로 변환한다고 했을 때,

(음수) * x = (양의 정수)

가 되어야 하는데 그렇다면 x는 음수가 되어야 한다는 걸까...???

 

이상해서 어셈블리 코드를 살펴보았다.

어셈블리 코드에서는 imul eax, eax, FB 로 사용자가 입력한 문자에 0xFB를 곱해주고 있다. 또한, 곱셈 결과를 & 0xFF(하위 8비트만 취함)로 처리하고 있다.

 

imul 연산은 꼭 음수를 곱하겠다는 뜻이 아니라 부호 있는 정수 곱셈을 수행하겠다는 의미이다.

따라서 나는 IDA가 제공해준 코드를 그대로 사용하지 않고 -5를 0xFB로 나타내기로 했다.

 

그렇다면 & 연산은 어떻게 처리해줘야 할까?

& 0xFF(1111 1111)는 하위 8비트 즉, 0부터 255까지만 처리하겠다는 의미이기 때문에 % 256으로 치환하여 사용할 수 있다.

 

예를 들어,

int x = 300;  // 0x12C (16진수)
int y = x & 0xFF;  // 하위 8비트만 남김
printf("%d\n", y); // 결과: 44 (0x2C)

0x12C에 & 0xFF를 한 결과가 44일 때

int x = 300;
int y = x % 256;
printf("%d\n", y); // 결과: 44

% 256을 한 결과도 44가 나오는 것을 볼 수 있다.

 

이 모든 것을 종합하면 다음과 같은 식이 나온다.

a1[i] * 251 % 256 == byte_140003000[i]

 

근데 여기서 a1[i] * 251을 256으로 나눈다고 했을 때 그 결과는 정수가 되어야 한다. byte_140003000[i]가 정수이기 때문이다.

우리는 x * 251 % 256 의 결과가 byte_140003000[i] 라는 정수가 될 수 있게 만드는 x를 찾아야 한다.

 

마지막으로 이런 질문이 떠오를 수 있다. 

"그렇다면 x의 범위를 어떻게 설정해 주어야 할까?"

 

x는 결국 사용자의 입력으로 나온 문자이기 때문에 아스키코드 표의 문자 범위를 벗어나지 않는다.

아스키코드에서 문자의 범위는 33부터 126이다.

 

위 정보들을 취합하여 C 코드로 나타낸다면 다음과 같이 작성할 수 있겠다.

#include <stdio.h>

int main() {
    unsigned int byte_140003000[] = {
        172, 243, 12, 37, 163, 16, 183, 37, 22, 198,
        183, 188, 7, 37, 2, 213, 198, 17, 7, 197
    };

    char result[21];
    int idx = 0;
    for(int i = 0; i < 21; i++){
        for(int j = 33; j < 127; j++){
            if(j * 251 % 256 == byte_140003000[i]){
                result[idx++] = j;
            }
        }
    }

    for(int i = 0; i < idx; i++){
        printf("%c", result[i]);
    }
    
    return 0;
}

 

그리고 실행시켜보면 다음과 같은 FLAG를 얻을 수 있다.

 

FLAG : 

DH{Did_y0u_brute_force?}

 

'Security > Reverse Engineering' 카테고리의 다른 글

rev-basic-7 풀이  (0) 2025.02.28
rev-basic-5 풀이  (0) 2025.02.24
rev-basic-4 풀이  (0) 2025.02.24
rev-basic-6 풀이  (0) 2025.02.23
rev-basic-3 풀이(IDA)  (0) 2025.02.20
'Security/Reverse Engineering' 카테고리의 다른 글
  • rev-basic-7 풀이
  • rev-basic-5 풀이
  • rev-basic-4 풀이
  • rev-basic-6 풀이
switch_user
switch_user
나의 공부 기록
  • switch_user
    while(true)
    switch_user
  • 전체
    오늘
    어제
    • 분류 전체보기
      • C
      • C++
      • Java
      • Python
      • Web
      • App
      • Security
        • Web Hacking
        • Reverse Engineering
      • DB
      • Machine Learning
      • Computer Science
      • Linux
      • Algorithm
      • 진로
      • 기타
  • 블로그 메뉴

    • 홈
    • 태그
    • velog
    • Github
  • 링크

    • velog
    • Github
  • 공지사항

  • 인기 글

  • 태그

    Web 기초
    비트연산
    ml
    리버싱
    배치 학습
    xss
    CSS
    사례 기반 학습
    SQL
    모델 기반 학습
    인터프리팅
    cin.getline
    어셈블리
    Hacking Process
    코드 패치
    클래스 외부에 함수 구현
    쿠키
    SQLi
    웹
    race condition
    반복문
    어셈블리어
    HTML
    IDA
    x64dbg
    생성자와 소멸자
    HTTP
    머신러닝
    디컴파일
    웹해킹
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
switch_user
rev-basic-8 풀이
상단으로

티스토리툴바