rev-basic-3 풀이

2025. 2. 5. 01:25·Security/Reverse Engineering

문제 설명

 

문제 풀이

- 사용했던 툴 : x64dbg

- 문제 접근 : 문자열 참조 검색을 통해 main 함수를 찾고, correct나 wrong을 출력하게 만드는 비교 연산 함수 찾기

일단 다운받은 문제 파일을 x64dbg에서 열면 다음과 같은 창이 나온다.

바로 문자열 참조 검색 기능을 통해 Main 메소드를 찾아준다.

 

첫번째로 뜬 "Input : " 문자열을 클릭하면 main 메소드를 찾을 수 있다. 

조금만 밑으로 내려가면 "Correct"나 "Wrong"을 출력하는 부분을 볼 수 있는데, 140001000에서 flag 문자열과 사용자가 입력한 문자열을 비교한다는 것을 어렵지 않게 알 수 있다.

 

노란색으로 하이라이트 처리된 것들 중에 140001000을 클릭해보자.

아마 첫번째 줄부터 ret 명령을 수행하는 14000105C 부분까지가 비교 연산을 수행하는 함수인 것 같다.

 

문자열과의 비교연산은 결국 반복문을 돌며 한글자씩 이루어지기 때문에 우리가 눈여겨 볼 부분은 바로 반복을 수행하는 부분이다. 따라서 나는 이 문제를 풀 때 초기값 세팅을 하는 부분과 반복문을 돌며 연산을 수행하는 부분을 나눠서 보려고 했다.

 

(잘 알지도 못하는 어셈블리어를 여러줄 보다보면 머리 아프다.)

 

연산을 수행하는 부분은 결국 140001024부분부터이다. 그 윗부분까지는 반복문을 돌기 위해 미리 스택 포인터에서(rsp) 0x18(24)의 값을 빼두고 스택의 현재 위치에 0을 저장한다는 내용이다. 또한, 14000101A부터 140001022까지는 반복문의 조건을 설정한다는 부분으로 보면 된다. for(i = 0; i <= 0x18; i++)와 같이 말이다.

 

140001024부분부터 return을 수행하기 위해 스택을 복구하기 전의 상태인 14000104F까지(for문의 안) 라인별로 분석한 결과는 다음과 같다.

 

140001024 : rsp에서 값을 가져와 rax에 저장

140001028 : rcx를 0x140003000로 설정(배열 시작 주소)

14000102F : rcx+rax의 주소에 있는 바이트 값을 eax로 가져오기

140001033 : rsp의 값을 rcx로 가져오기

140001037 : rsp+20를 rdx에 저장 

14000103C : rdx+rcx 주소의 바이트 값을 ecx로 가져오기

140001040 : ecx 값을 rsp에 있는 값과 XOR 연산을 수행

140001043 : edx에 rsp 값을 저장

140001046 : ecx = ecx + (edx * 2)로 설정

140001049 : eax와 ecx 값을 비교

14000104B : 같으면 0x140001051로 이동(루프 돌기)

14000104D : eax = 0으로 설정

14000104F : 루프 빠져나오기

 

일단 배열의 시작 주소인 140003000이 덤프창에서 어떤 아스키 코드 값을 출력하는지 보았다.

 

뭔가 느낌 온다. 잘 조합하면 무슨 문자열이 나올 것만 같다...?

 

어셈블리어를 분석해서 적어두었지만, 사실 정확하 이해하기가 어려워서 분석해둔 부분을 복사해 ChatGPT에게 C언어로 바꾸어 달라고 했다...ㅎㅎ

#include <stdio.h>
#include <stdint.h>

int chall3(const char* input) {
    const uint8_t* data = (uint8_t*)0x140003000; // 데이터 테이블
    int i = 0;

    while (i < 24) {
        uint8_t val1 = data[i];
        uint8_t val2 = input[i] ^ i;
        val2 = val2 + (i * 2);

        if (val1 != val2) {
            return 0; // 실패
        }
        i++;
    }

    return 1; // 성공
}

 

여기서 data가 아까 그 이상했던 문자열                                                        

을 말하는데 이 문자열이 (input[i] ^ i) + (i * 2)의 연산을 통해 나온것이기 때문에 우리가 input[i]값을 구하기 위해서는 xor의 역연산을 수행해야만 한다.

 

XOR 연산은 다음과 같은 성질을 가진다.

A ^ B = C에서 임의의 값 B는 A ^ C = B를 만족한다.

 

따라서 위의 이상한 문자열들을 dump[i]라고 두면 dump[i] = (input[i] ^ i) + (i * 2)라고 볼 수 있고, 이의 역연산은

input[i] = (dump[i] - (i * 2)) ^ i라고 볼 수 있다.

 

역연산을 수행하는 C언어 코드를 간단히 정리한 결과는 다음과 같다.

#include <stdio.h>

int main() {
    char dump[] = {0x49, 0x60, 0x67, 0x74, 0x63, 0x67, 0x42, 0x66, 0x80, 0x78, 0x69, 0x69, 0x7B, 0x99, 0x6D, 0x88, 0x68, 0x94, 0x9F, 0x8D, 0x4D, 0xA5, 0x9D, 0x45};

    for (int i = 0; i < 24; ++i) {
        printf("%c\n", ((dump[i] - 2 * i) ^ i));
    }

    return 0;
}

 

그리고 실행해보면 다음과 같은 문자열이 나온다.

 

이를 플래그 형식에 맞추어 제출하면

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

rev-basic-6 풀이  (0) 2025.02.23
rev-basic-3 풀이(IDA)  (0) 2025.02.20
리버싱 기초 문제 풀이  (0) 2025.02.04
abex-crackme#2 풀이  (0) 2025.02.04
rev-basic-2 풀이  (0) 2025.01.22
'Security/Reverse Engineering' 카테고리의 다른 글
  • rev-basic-6 풀이
  • rev-basic-3 풀이(IDA)
  • 리버싱 기초 문제 풀이
  • abex-crackme#2 풀이
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
  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바