해보자고

[드림핵] rev-basic-6 본문

리버싱

[드림핵] rev-basic-6

초코맛동산 2024. 5. 6. 22:38

# 문제

https://dreamhack.io/wargame/challenges/20

 

rev-basic-6

Reversing Basic Challenge #6 이 문제는 사용자에게 문자열 입력을 받아 정해진 방법으로 입력값을 검증하여 correct 또는 wrong을 출력하는 프로그램이 주어집니다. 해당 바이너리를 분석하여 correct를 출

dreamhack.io

이 문제는 사용자에게 문자열 입력을 받아 정해진 방법으로 입력값을 검증하여 correct 또는 wrong을 출력하는 프로그램이 주어집니다.
해당 바이너리를 분석하여 correct를 출력하는 입력값을 찾으세요!

 


1. main 함수 찾기 

 

main 함수 찾는 법은 이전 글들 참고.

 

 

2. 실행 흐름 파악하기

좌: 문자열 참조 검색 / 우: IDA 그래픽뷰

 

basic 단계는 비슷한 실행 구조를 지니고 있다. test eax eax로 eax값이 0인지 확인하고, 0이면 jz(=je) 명령어로 인해 wrong이 출력되고, 0이 아닌 값이면 correct가 출력된다. 

 

늘 이야기 하지만 eax값이 결정되는 이전 함수 call chall6 - copy.7FF6FE0C1000 을 확인해보자. 

 

3. 디버깅

 

rax로 0x12, 즉 18번 반복하여 비교를 하고 있는 것을 확인할 수 있다. 

 

 

그리고 중요한(본격적인) 단락이 시작된다. 

 

 

rsp값이 rax에 mov 되는 것을 어셈블리어를 통해 확인할 수 있는데, 레지스터 윈도우상 rsp에는 0이(아무 값X) 들어있고, 해당 주소까지도 확인할 수 있었다. 

 

 

그리고 다음 줄에서는 rsp+20의 값을 rcs에 mov하고 있는데, rsp+20에는 내가 INPUT에서 입력한 'ABCEDF' 문자열이 들어있었다. 따라서 rcx의 값도 'ABCDEF'가 되었다. 

 

 

rax에는 0이, rcx에는 'ABCDEF'가 들어있었으니 이 둘을 더하면 문자열의 첫 자인 A가 eax에 들어가게 되는 것을 알 수 있고, 이는 레지스터 윈도우를 통해서도 확인할 수 있다. 

 

 

그 다음 명령어는 lea 임으로 7FF6FE0C3020의 주소 값을 rcx로 옮겼음을 확인할 수 있다. 

 

 

rcx 값은 7FF6FE0C3020 주소 값이고, rax 값은 나의 입력 값이었다. 해당 값을 더한 주소의 값이 eax에 들어가는 어셈블리 명령어 이고 실제 확인을 해보면... 

 

 

 7FF6FE0C3020 + 41(A의 10진수) = 7FF6FE0C3061 이고, 해당 주소의 값은 덤프를 따라가서 확인했을 때 83임을 확인할 수 있었고, 레지스터 뷰의 rax값도 83인 것을 알 수 있었다. 

 

 

rsp 값은 초반에 말했듯 0이고, 이 값이 rcx에 들어가므로 rcx도 0이 된다. 7FF6FE0C3000 주소값은 rdx에 저장되고, 아까와 마찬가지로 해당 주소값 + 0(rcx) 이 ecx에 저장된다. 즉 그냥 7FF6FE0C3000 주소값이 ecx에 저장되는 구나~

 

 

위에서 구한 ecx값 (7FF6FE0C3000 주소값) 과 eax값((7FF6FE0C3020 주소 값 + 나의 입력값 )의 데이터) 를 18번 비교하여 같으면 eax에 1을 반환(correct로 분기) 한다. 

 

(위: 7FF6FE0C3020 주소 값, 아래: 7FF6FE0C3000 주소 값)

 

따라서 7FF6FE0C3000 과 7FF6FE0C3020의 아스키 값을 랜덤으로 대입하여 값이 같을 때를 flag 값이구나 생각하면 된다. 총 18번 반복하니 18글자가 나와야 할 것이며, 아스키 값이기에 128번의 대입이 있음을 간단히 생각해볼 수 있고, 이를 코드로 구현하면 아래 코드와 같다. 

 

4. 마무리 코딩 작업

#include <stdio.h>

int main() {
    char num_300[] = {0x00, 0x4D, 0x51, 0x50, 0xEF, 0xFB, 0xC3, 0xCF, 0x92, 0x45, 0x4D, 0xCF, 0xF5, 0x04, 0x40, 0x50, 0x43, 0x63};
    char num_3020[] = {0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,  0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
        0xCA ,0x82 ,0xC9 ,0x7D ,0xFA ,0x59 ,0x47 ,0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
        0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
        0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
        0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
        0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
        0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
        0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2};
    
    char flag[19] = {0};

    for(int i =0; i<18; i++) {
        for(int j =0; j<sizeof(num_3020) / sizeof(num_3020[0]); j++) {
            if (num_3020[j] == num_300[i]) {
                flag[i] = j;
            } 
        }
    }

    printf("flag is :");

    for(int i = 0; i<18; i++) {
        printf("%c", flag[i]);
    }

    return 0;


}

 

 

'리버싱' 카테고리의 다른 글

[드림핵] rev-basic-8  (0) 2024.08.31
[드림핵] simple-operation  (0) 2024.05.13
[리버싱] rev-basic-4  (0) 2024.04.28
[드림핵]rev-basic-3  (0) 2024.04.27
[드림핵]rev-basic-2  (0) 2024.04.27