rev-basic-5 풀이

2025. 2. 24. 19:39·Security/Reverse Engineering

문제 설명


문제 풀이(x64dbg)

문제 파일을 x64dbg에서 열고 '모든 문자열 참조 검색' 기능을 통해 main 메소드를 찾은 결과는 다음과 같다.

이전 단계의 rev-basic 문제를 풀었다면 어디가 문자열 비교 함수인지 쉽게 알 수 있을 것이다. 

140001000 주소로 들어가보자.

대충 어디서부터 어디까지가 문자열에 대한 연산을 수행하는지 보일 것이다.

140001024부터 140001053까지만 봐도 충분할 것 같다.

 

한줄씩 분석해보자.

 

1. movsxd rax,dword ptr ss:[rsp] : 스택의 값을 부호 확장하여 rax에 저장(rax는 1, 현재 루프 인덱스)

2. mov rcx,qword ptr ss:[rsp+20] : 스택의 [rsp + 20]에서 값을 rcx로 이동(사용자 입력의 시작 주소)

3. movzx eax,byte ptr ds:[rcx+rax] : rcx + rax에서 바이트를 읽어 eax에 제로 확장하여 저장(사용자 입력 문자 배열을 a라고 선언 할 때,  a[i]의 값이라고 할수있음)

4. mov ecx,dword ptr ss:[rsp] : 스택의 [rsp]에서 값을 읽어 ecx에 저장

5. inc ecx : ecx++(루프 인덱스 증가)

6. movsxd rcx,ecx : ecx의 값을 부호 확장하여 rcx에 저장

7. mov rdx,qword ptr ss:[rsp+20] : 스택의 [rsp + 20]에서 값을 읽어 rdx에 저장

8. movzx ecx,byte ptr ds:[rdx+rcx] : rdx + rcx에서 바이트를 읽어 ecx에 제로 확장하여 저장(a[i + 1]라고 볼 수 있음)

9. add eax,ecx : eax와 ecx의 값을 더하여 eax에 저장(a[i] + a[i + 1]이라고 볼 수 있음)

10. movsxd rcx,dword ptr ss:[rsp] : 스택의 [rsp]에서 값을 부호 확장하여 rcx에 저장

11. lea rdx,qword ptr ds:[140003000] : 주소 0x140003000의 값을 rdx에 로드

12. movzx ecx,byte ptr ds:[rdx+rcx] : rdx + rcx에서 바이트를 읽어 ecx에 제로 확장하여 저장

13. cmp eax,ecx : eax와 ecx 비교(a[i] + a[i + 1]과 140003000[i]를 비교)

 

사용자 입력을 배열로 나타낸 것을 a라 하고 기존에 저장된 문자열을 byte_140003000이라고 할 때, 다음과 같은 일반항이 구해진다.

a[i] + a[i + 1] = byte_140003000[i]

 

그리고 이 식은 다음과 같이 변형될 수 있다.

a[i + 1] = byte_140003000[i] - a[i]

 

우리는 dump창을 통해 byte_140003000가 어떤 HEX값을 가지는지 알 수 있다. 하지만 a[i]는 어떻게 구할 수 있을까? 그냥 우리가 정해주면 된다. a는 결국에 FLAG 값이 될 것이고 문자열의 범위를 넘어서지 않을 것이다. 

 

따라서 a[i]의 값을 임의로 지정해줄때 아스키코드 범위 내에서만 해주면 된다.

나는 그냥 a~Z까지가 그 범위라 생각하고 풀었다.

 

이건 손수 노가다로 풀기에 너무 오랜시간이 걸리기 때문에 파이썬 코드를 작성하여 풀었다. 내가 작성한 코드는 다음과 같다.

# byte_140003000 = [
#    AD, D8, CB, CB, 9D, 97, CB, C4, 92,
#    A1, D2, D7, D2, D6, A8, A5, DC, C7,
#    AD, A3, A1, 98, 4C
# ]

byte_140003000 = [
    173, 216, 203, 203, 157, 151, 203, 196, 146, 
    161, 210, 215, 210, 214, 168, 165, 220, 199, 
    173, 163, 161, 152, 76
]

sample = [
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 
    'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 
    'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
    'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
    'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]

for s in sample:
    temp = [ord(s)]

    valid = True  
    for i in range(23):  
        next_value = byte_140003000[i] - temp[i] 
        if not (0 <= next_value <= 255): 
            valid = False
            break
        temp.append(next_value)

    if valid: 
        result = "".join(chr(x) for x in temp)
        print(result)

 

코드를 작성하며 적어도 문자열 하나는 제대로 나오겠지 했던 것 같다.

실행을 해보니 단 한 개의 문자열이 나왔다. 그리고 딱봐도 FLAG가 되기에 충분(?)해보였다.

 

FLAG : 

DH{All_l1fe_3nds_w1th_NULL}

 


문제 풀이(IDA)

문제 파일을 IDA로 열어보자.

 

디컴파일 시키고 바로 문자열 비교 함수 내부로 들어가보았다.

 

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

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

 

이미 x64dbg로 풀 때 함수 내부 구조를 확인해보았기 때문에 바로 이해가 되었다. 그리고 내가 작성했던 코드와 크게 다르지 않았다.

 

여기서 우리는 다음과 같은 일반항을 얻을 수 있다.

*(a1 + i + 1) + *(a1 + i) = byte_140003000[i]

 

그리고 다음과 같이 변형 될 수 있다.

*(a1 + i + 1) = byte_140003000[i] - *(a1 + i)

 

그 뒤의 풀이는 똑같이 코드를 작성하고 실행시켜보는 과정이기 때문에 생략하려고 한다.

왜 IDA로 풀기전에 x64dbg로 분석해보라는지 알 것 같다...

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

rev-basic-8 풀이  (0) 2025.03.05
rev-basic-7 풀이  (0) 2025.02.28
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-8 풀이
  • rev-basic-7 풀이
  • 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
  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바