lhywk 님의 블로그

[실습] crackme4_find_password_type 본문

Malware Analysis

[실습] crackme4_find_password_type

lhywk 2026. 7. 9. 17:18

문제 바이너리를 실행한다.

6개의 문자를 입력하는 패스워드란이 나오는 프로그램이고 입력하면 Incorrect Password. Try Again 문자열이 나오고 프로그램이 종료된다.

 

x64디버거로 분석을 진행해본다.

문자열을 스택에 넣고 call하고 ebp-8의 주소를 eax에 넣고 스택에 저장, %6s라는 포맷문자열을 스택에 저장한 후 call을 하는 것은 전형적인 printf 함수와 scanf 함수의 동작이기 때문에 라벨링을 해주었다.

그 다음 동작을 살펴보면 je 분기가 있고 equal이 아니어야 밑의 명령줄을 실행하면서 Congratulations! 문자열을 만날 수 있다. 그렇다면 그 위에 call 401000이 검증하는 함수로 볼수 있다. 해당 함수의 내부로 진입한다.

이것 또한 함수이기 때문에 프롤로그가 진행된다.

ebp+8에는 우리가 입력한 문자열이 들어있다. 덤프에서 보면 다음과 같다.

eax에 주소값을 복사하고 아래 함수를 호출하면 strlen 레이블을 달아놨다. 그 이유는 다음과 같다.

함수를 호출하고 나면 return 값으로 6이 오는데 이는 문자열의 길이이다.

cmp eax,6: eax와 6을 비교한다. 즉 문자열의 길이가 6이어야한다.

mov ecx, [ebp+8]: 주소를 ecx에 복사한다.

movsx edx, [ecx]: 첫 번째 인덱스의 문자를 edx에 복사한다.

cmp edx, 41: 첫 번째 문자와 41 = 'A'를 비교한다. 즉 첫 번째 문자는 'A'이어야한다.

 

지금까지 얻은 정보는 6자리 문자열과 첫 번째 문자가 'A'이어야 한다는 것이다.

플래그를 조작하여 분석을 계속 진행한다.

jmp 401043: 401043으로 무조건 점프

mov eax, [ebp-8]: eax에 현재 인덱스 값 로드

add eax, 1: 인덱스 증가

mov [ebp-8], eax: 증가된 인덱스 값을 다시 [ebp-8]에 저장 -> i++;

cmp [ebp-8], 6: 인덱스와 6을 비교

jge 40105C: >=6 이라면 루프 탈출 [1]~[5]까지 반복

 

mov ecx, [ebp+8]: ecx에 입력문자열 시작 주소 복사

add ecx, [ebp-8]: ecx=문자열의 시작주소 + 인덱스 -> 입력 위치 계산

movsx edx, byte ptr ds:[ecx]: 해당 인덱스 1바이트 읽어서 edx에 복사

mov eax, [ebp-4]: eax에 현재까지의 누적 합산값 복사

add eax, edx: 누적합 계산

mov [ebp-4], eax: 새 누적합을 ebp-4에 다시 복사

jmp 40103A: 루프 시작으로 다시 점프

 

C언어로 표현하면 다음과 같다.

for (j = 1; j < 6; j++) {
    sum += input[j];    // ASCII 누적 합산
}

cmp dword ptr ss:[ebp-4], 0x12C: 누적 합산값과 0x12C(300)을 비교

jge 401069: 300 이상이면 분기

mov ecx, [ebp+8]: ecx에 입력 문자열 시작 주소 복사

movsx edx, byte ptr de:[ecx+5]: 마지막 6번째 문자 1바이트 읽어서 edx에 저장

cmp edx, 21: 0x21인 !와 비교

je 401079: 성공 분기

 

조건을 정리하면 다음과 같다.

input[0] 'A' (0x41)
input[1]~[5] 합 300 (0x12C)
input[5] '!' (0x21 = 33)
input[1]~[4] 합 = 300 - 33 = 267
267 / 4 = 66.75

→ 'B'(66) × 3 + 'E'(69) × 1
= 66+66+66+69 = 267

정답: ABBBE!