티스토리 뷰

728x90
반응형

<실습 환경>

OX :    Windows 10

Program : Ollydbg110

 

 

Easy_CrackMe.exe 분석

파일 실행

Easy CrackMe라는 title로 창이 뜨고 입력 값을 받도록 돼있습니다.

아무 문자열이나 입력해 보면,

 

 

Incorrect Password라는 메시지를 창과 함께 띄웁니다.

현재 다른 특별한 사항은 발견할 수 없기에 일단 원하는 입력 값을 리버싱 해 찾아 넣어주면 될 것 같습니다.

 

OllyDbg – Easy_CrackMe.exe

실행 파일의 시작 지점인 Entry Point를 따로 찾지 않고 위의 화살표 모양을 눌러 주면 알아서 시작 부분을 나타내 줍니다. 많은 명령어들이 이어서 나오는데, 현재 목적은 입력한 문자열을 비교 연산해 주는 부분만 찾아 원하는 문자열 (password)를 알아내는 것입니다. 때문에 이를 다 분석하기 보다는 파일을 실행시켰을 때 얻은 정보인, Incorrect Password를 찾아 이 문자열을 출력하는 명령어로 점프하는 부분부터 분석하는 것이 좋아 보입니다.

OllyDbg의 기능 중 파일에 쓰여진 string들을 볼 수 있는 방법이 있습니다.

Text string들을 볼 수 있습니다. 아직 확인해 보지 못한 5y, R3versing같은 것들도 보이고, Cogratulation !! 이라는 문자열도 보입니다. 아마 문제를 풀면 출력해 줄 것 같습니다.

우선 Incorrect Password를 출력해 주는 부분으로 가기 위해 더블클릭 해줍니다.

이 부분이 MessageBoxA라는 함수를 콜해 Easy_Cra.00406030에 있는 Incorrect Password 문자열을 출력해주는 부분입니다.

이를 기준으로 큰 함수를 봐보면,

이런 큰 함수(Disassemble된 것들을 보면 Easy_Cra라는 함수 같습니다)를 찾을 수 있는데, 처음 SUB ESP, 64PUSH EDI를 통해 현재 스택에 0x64 (100) byte 만큼의 공간을 확보해 놓고, 문자열을 넣기 위한 준비를 하는 것으로 보입니다. 그리고 마지막에 RETN을 해주네요.

이 함수에서 더 핵심 부분을 찾아보면 우리가 문자열을 입력하는 부분과 Incorrect Password 문자열로 향하는 비교 명령어들입니다.

 

 

분기 구조 분석

GetDlgItemTextA를 호출해 문자열을 입력 받은 뒤 크게 4개의 Incorrect Password로 분기하는 곳이 있습니다. 각각 비교 명령어 CMPTEST와 같이 사용되는데, 원하는 문자열과 맞을 경우 분기하지 않고 쭉 내려가 Congratulation 메시지 박스를 띄울 것으로 예상됩니다. 따라서 이제 각각 분기하는 곳을 분석해 password를 찾으면 됩니다.

 

Password 찾기

좀 더 확실히 하기 위해 문자열을 입력하는 곳에 breakpoint를 걸어 입력한 문자열의 위치를 보면서 찾아보겠습니다.

문자열 입력 함수 바로 다음에 breakpoint를 건 후 입력한 cheeseburger의 위치를 보겠습니다.

이렇게 해주면 아래처럼 우리가 입력한 문자열과 esp 기준 스택 위치도 나와서Disassemble 된 명령어와 함께 보기 좋습니다.

ESP+4부터 입력한 cheeseburger가 차례로 들어가 있습니다.

1번 분기

CMP BYTE PTR SS:[ESP+5], 61

JNZ SHORT Easy_Cra.00401135

해석해보면 SS(스택영역의) BYTE PTR(1바이트 포인터) ESP+5에 있는 값([]로 묶여 있으므로 저장되어 있는 값)과 아스키 코드 값 0x61을 비교해, 같으면 JNZ 다음 코드 PUSH 2, 다르면 SHORT Easy_Cra.00401135(Incorrect Password)로 분기입니다. 우리가 입력한 문자열은 ESP+4부터 저장되어 있으므로 2번째 문자 1개 즉,

따라서 Password의 두 번째 문자 a를 찾았습니다.

아스키 코드 표

2번 분기

중요 명령어는 역시 비교 명령어인 TEST EAX, EAX 인데,

TEST는 보통 두 OperandAND연산 해 모두 0인지 아닌지 판단할 때 사용됩니다. , EAX에 들어있는 값이 0이면 JNZ(Jump if not zero)에 의해 분기하지 않고 0이 아니면 분기합니다. 따라서 EAX의 값을 알아야 하는데 이는 위의 CALL하고 있는 Easy_Cra.00401150에 가봐야 합니다. 그 전에 유추를 해보자면,

함수 콜을 하기 전에 두 번의 PUSH가 있습니다.

Easy_Cra.00406078, ECX인데 하나는 옆에 ASCII“5y”인 것을 알 수 있습니다. 사실 이게 Password 같은데 위치는 알 수 없습니다.

ECX 값이 무엇인지는 위의 LEA ECX, DWORD PTR SS:[ESP+A]를 봅니다.

MOV는 값을 저장하는 명령어고, LEA는 주소 값을 저장하는 명령어입니다. 따라서 ESP+A의 주소 값을 저장합니다. 콜하는 곳에 breakpoint를 걸고 AaAAAAAAAAA를 입력해 보겠습니다.

ESP 주소 0x0019F6EC A를 더한 0019F6F6ECX에 들어가 있는 것을 확인할 수 있습니다.

이는 Byte Ordering에 의해  0019F6F4가 첫 번째 A, 0019F6F5가 두 번째 a 이므로 세 번째 문자 A부터 나타냅니다. 이를 통해 굳이 Easy_Cra.00401150에 가지 않고 사실 3번째 문자부터 5y가 들어갈 것이라고 유추가 가능해서 Aa5yAAAAAA를 넣고 f4로 실행해보면,

해당 분기를 넘어갔습니다. 따라서 3,4번째 문자열은 5y겠네요.

 

3번 분기

역시 핵심은 TESTJNZ를 통한 비교 분기인데, 이것도 옆에 ASCII “R3versing” 문자열을 보여주네요. 여기도 반복문이 보입니다. 좀 보기 쉽게 정리해 보겠습니다.

이 반복문은 3번의 관문이 있는데, R3versing 문자열의 2개 씩 비교하고, 첫 문자가 NULL인지를 검사하는 3가지중 하나라도 걸리면

SBB EAX, EAX

SBB EAX, -1

명령어를 수행해야 합니다. 이 명령어를 수행하면 뒤의 EAXFFFFFFFF가 들어가 TEST EAX, EAX 연산 결과 1이므로 JNZ에 의해 Easy_Cra.00401135로 분기해 버립니다.

따라서 이 명령어로 분기하지 않고

XOR EAX, EAX

JMP SHORT Easy_Cra.00401107

을 실행해 EAX0으로 만들고 바로 POP ESI로 분기해야 합니다. 그러면 뒤의 분기를 통과할 수 있게 됩니다.

구조는 알았으니 간단하게 첫 반복문만 분석해 위치를 알아보겠습니다. R3versing이 들어갈 위치를 알아보겠습니다.

위의 명령어까지 실행하고 그 상태의 레지스터와 주소 값을 보겠습니다.

 

이 상태에서 처음으로 DL BL의 값을 비교합니다.

DL = BYTE PTR DS:[EAX] = A(0x0019F6F8) = 5번 째 문자

BL = BYTE PTR DS:[ESI] = R3versing의 첫 문자 R

R3versing이 입력한 문자열의 5번째 위치부터 들어가야 한다는 걸 바로 찾았습니다.

현재까지 찾은 password?a5yR3versing?... 겠네요

 

4번 분기

이 분기는 처음과 비슷합니다.

ESP+4의 값과 0x45(E)를 비교합니다. ESP+4의 값은 입력한 문자열의 맨 처음 같지만 확실히 하기 위해 해당 부분까지 실행시키고 레지스터를 보겠습니다.

ESP+4 = 0x41 = A로 첫 번째 문자열인 것을 확인할 수 있습니다. 따라서 여기에는 E가 들어가야합니다.

이게 마지막 분기이므로 찾은 문자열을 통해 Password를 조합해 보면

Ea5yR3versing

728x90
반응형

'Security > 시스템 해킹' 카테고리의 다른 글

어셈블리로 구구단 짜기(nasm)  (1) 2019.04.02
RTL (Return to Libc)  (0) 2019.02.05
리버싱 실습(Easy_ELF)  (0) 2019.01.24
버퍼오버플로우 실습  (0) 2019.01.23
쉘 코드(/bin/sh  (0) 2019.01.16
댓글