리버싱

[드림핵] Secure Mail

초코맛동산 2024. 11. 14. 23:32

 

# 문제

문제 링크 | https://dreamhack.io/wargame/challenges/92

 

Secure Mail

Description 중요한 정보가 적혀있는 보안 메일을 발견하였습니다. 보안 메일의 비밀번호는 생년월일 6자리인 것으로 파악되나, 저희는 비밀번호 정보를 가지고 있지 않습니다. 비밀번호를 알아내

dreamhack.io

중요한 정보가 적혀있는 보안 메일을 발견하였습니다.
보안 메일의 비밀번호는 생년월일 6자리인 것으로 파악되나, 저희는 비밀번호 정보를 가지고 있지 않습니다.
비밀번호를 알아내고 보안 메일을 읽어 중요한 정보를 알아내주세요!

 

1. 소스 코드 훑어보기 

맨날 rev-basic만 풀다가 처음 웹 리버싱을 접하게 되었습니다. html 코드이기에 크롬상에서 어떤 코드인지 비쥬얼적으로 한 번 살펴보고, vscode로 전체 소스코드를 훑어 봅시다. 

 

 

대-충 이렇게 긴데(...), 일단 크게 어떤 부분이 중요할 것 같은지를 살펴보자면 

 

 

button 태그를 보면, 버튼 클릭시_0x9a220함수가 실행되고, input에 입력된 값이 함께 전달되고 있는 것 같습니다. 그러면 중요한 건, 해당 함수에서 flag 값이 나오든, 어떤 연산이 진행되어서 원래 값과 비교를 하든 함수 자체를 알아보는 것이 좋을 것 같다는 생각이 드네요. 

 

 

해당 함수는 일단 난독화가 되어 있는 것 같지만 if문을 통해 어떤 값을 비교하고 다르면 Wrong을 맞으면 제대로된 flag값이 출력이 될 것이라는 추측을 한 상태로 문제를 풀 수 있게 됩니다. 

 

먼저, 6자리 생년월일이 암호값이기 때문에 브루트포스로 문제를 푸는 방법을 소개해드리겠습니다. 코드를 보고 복호화를 시도해보려고 했으나, 수련이 부족한 관계로,, 아방감자가 되어버려.

 

3. 문제 풀이

 

const format = /([0-9]{2}(0[1-9]|1[0-2])(0[1-9]|[1,2][0-9]|3[0,1]))/;

function BFC() {

    for (let yy = 0; yy <= 99; yy++) {
        let year = yy.toString().padStart(2, '0');
        
        for (let MM = 0; MM <= 12; MM++) {
            let month = MM.toString().padStart(2, '0');

            for(let DD = 0; DD <= 31; DD++) {
                let day = DD.toString().padStart(2, '0')

                let testResult = `${year}${month}${day}`;

                console.log(`테스트 중: ${testResult}`);

                // test() 메서드는 주어진 문자열이 정규 표현식을 만족하는지 판별하고, 그 여부를 true 또는 false로 반환.
                    if (_0x9a220(testResult)) {
                      console.log("flag:", testResult); 
                      return testResult; 
                }
            }
        }
    }
}

 

 

3.1 6자리 생년월일 정규식 표현

/([0-9]{2}(0[1-9]|1[0-2])(0[1-9]|[1,2][0-9]|3[0,1]))/

 

정규식 : 문자열에서 특정 문자 조합을 찾기 위한 패턴

 

해당 정규식을 만드는 방법은 총 2가지가 존재합니다. 

 

1. 정규 표현식 리터럴 

2. RegExp 객체의 생성자 호출 

 

그러나 풀이에서 사용한 정규식 생성 방법은 첫 번째 정규 표현식 리터럴로, 슬래시(/)로 패턴을 감싸주고 있습니다. 

 

 

  • [0-9]{2}
    • 0에서 9까지의 숫자가 2번 반복된다. -> YY를 찾는 부분
  • (0[1-9]|1[0-2])
    • 0[1-9]는 01 ~ 09 까지의 숫자를 의미.
    • 1[0-2]는 10 ~ 12까지의 숫자를 의미.
    • 이 둘을 |(또는) 연산자로 묶어, MM에 해당하는 월을 찾는 부분 
  • (0[1-9]|[1,2][0-9]|3[0,1])
    • 0[1-9]는 01 ~ 09 까지의 숫자를 의미.
    • [1,2][0-9]는 10 ~ 29 까지의 숫자를 의미. 
    • 3[0,1]는 30 또는 31을 의미.
    • 이 부분은 DD에 해당하는 일을찾는 부분.

 

3.2 padStart()

string 값 매서드로, 주어진 길이에 도달할 때까지 이 문자열의 시작 부분에 패딩을 채운다. 

padStart(targetLength, padString)

 

 

 

 

_0x9a220함수에 브루트포스로 1부터 flag로 넘어가는 값이 나올 때까지 값을 대입하다 보면,, 콘솔에 flag : 960229 값이 뜨고, 아래 이미지가 뜨게 됩니다. 이게 플래그겠죠?

 

 

 

일단, 너무 오랜 시간이 걸려서 가능하시다면 앞 뒤로 반반씩 반복문을 돌려보시는 방법을 추천드립니다...! 

멍청한 아방감자 대학생은,, 반성하며 다시 워게임 공부를 하러 갑니다.. 총총총