본문 바로가기

리버스 엔지니어링

abex' 2nd crackme 분석

지난번에는 크랙프로그램인 abex' crack#1을 분석했는데 이번에는 시리얼 코드를 받는 프로그램을 분석해봅시다.


abexcm2.exe

 

일단은 프로그램을 실행해봅시다.



이름과 시리얼코드를 입력하라고 나오는데 일단은 아무거나 넣어봅시다.



아무 수나 입력하면 틀렸다고 하는 메시지가 나오는군요.


그러면 본격적으로 디버깅을 해보자.



처음으로 문자열 검색 기능을 사용하면 다음과 같은 창이 나온다. 보면 Wrong serial과 Congratulations이라는 문자열이 나오는 것을 봐서는 조건에 따라 메시지가 다르게 나오는 것을 생각할 수 있다. 그렇다면 조건의 분기문을 찾아보자.



Congratulations에서 조금 위로 올려 보면 0040329에서 보면 __vbaVarTstEq()함수를 호출해서 리턴 값(AX)를 비교(Test명령)한 후에 JE 명령에 의해서 참, 거짓을 구분하게 하는 역할을 한다.


어셈블리 명령어를 잠깐설명해보면

TEST:논리비교(Logical Compare) : bit-wise logical 'AND'연산과 동일. 두 operand(변수)중에 하나가 0이면 AND 연산 결과는 0 -> ZF =1로 세팅된다

JE: 조건 분기(Jump if equal)

ZF=1이면 점프



그 위를 보면(00403321) [EBP-44]라고 되어있는 부분인데 이는 SS:[EBP-44]인데 SS는 스택 세그먼트이고 EBP는 베이스 포인터 레지스터이다. 즉 의미하는 것은 스택 내의 주소를 말하는데 바로 함수에서 선언된 로컬 객체의 주소이다.




여기서 EBP-44을 Stack 창(우측 하단)에 입력해보면 유니코드로 값이 보입니다. 첫번째는 본적이 없고 두번째는 처음에 임의로 넣은 값이 보이네요. 일단은 이 값을 가져와서 한번 넣어봅시다.



넣어보니 키가 맞다고 나오는군요. 그렇다면 Name의 값에 상관없이 시리얼 값이 같은지 확인 하기 위해서 test대신 다른 이름을 넣고 시리얼을 똑같이 넣어봤는데 틀렸다고 나왔다. 즉 Name과 시리얼의 상관관계가있다는 것을 알 수 있다.


그렇다면 문자열을 어떻게 받아서 시리얼을 생성하는지 그 알고리즘을 살펴봅시다.



디버깅을 진행하면 다음과 같은  코드를 볼 수 있다.  00402F8E의 [EBP-88]인 부분을 스택 창에 따라가봅시다.



스택 창에서 EBP-44라고 입력하면 test라고 입력 한 부분을 확인 할 수 있습니다. 이 주소에 Name 문자열이 저장되어있는 것을 볼 수 있습니다.


이 부분이 Name 문자열을 읽는 코드라고 볼 수 있겠군요




디버깅을 계속 해나가면 아래와 같은 반복문을 볼 수 있습니다. 일단은 EBX는 loop count를 의미하는데 여기서 4라고 되어있는 것은 4번 반복한 다는 것을 의미합니다.



다음 TEST EAX,EAX 이 부분이 나오는데 여기서 loop가 시작하는 것을 알 수 있습니다.

여기까지가 암호화 루프라는 것을 알 수 있습니다. 4번을 반복하는 루프인 것을 보아서 Name의 4자리만 사용하는 것을 알 수 있습니다.



tes라고 입력하면 4자리를 입력하라고 경고창이 나오는 것을 보면 확실히 알수 있겠군요. 




다음 디버깅을 진행하면 다음화면을 볼 수 있습니다. 여기는 암호화 방법에 관한 구간입니다. 일단은 0040323D부분까지 디버깅을 해보고 스택창을 화인해봅시다.



일단은 우리가 볼것은 ECX,EAX,EDX입니다.




스택창에서 ctrl+G를 입력하고 ECX를 입력한 결과입니다. 여기는 큰 것은 없지만 0019F200에 결과 저장용 버퍼입니다.



다음은 EAX를 입력했을때 0019F1C0에 d라는 문자가 들어있는데 이는 암호화 키 64를 의미합니다. 




마지막으로 EDX를 입력했을때 0019F248에 t가 들어있는데 이는 Name에서 첫문자 t를 의미합니다.




여가소 00403243 이부분의 CALL을 실행해봅니다. [4010AC] 메모리 주소로 되어있는데 이 콜은 변수를 더해주는 역할을 합니다. 즉 t의 ASCII코드 값은 74 아까 암호화 키의 d의 키는 64번입니다. 이 둘을 더하면 16진수로 나타내면 D8이란 값이 나올 것입니다.



저 call을 실행하고 ECX를 참고해봅시다. 보시면 00000DB로 바뀐것을 볼 수 있습니다. 아까 결과 저장용 버퍼라고 했는게 결과값이 들어있군요.




다음은 0040325B의 CALL함수가 있는데 이는 유코드로 바꿔주는 역할을 합니다. 저 부분이 메모리로 나와있지만 실제로는 &MSVBVM60.$573이라는 의미를 담고있습니다.

이는 D8이라고 나온 값을 유니코드 문자로 바꿉니다.



저 함수를 실행하면 t라는 문자를 D8이라고 바꿉니다. 옆의 값의 004ABF84 주소값을 찾아가보시면



다음과 같이 D8이라는 문자가 들어있는것을 알수 있습니다.




아까 루프를 4번 돈다고 하는데 루프가 돌떄마다 값이 추가됩니다.









4번 루프를 돌게 되면 test라는 Name을 통해서 D8C9D7D8이라는 값이 나오는데 이 값을 이제 시리얼로 사용하게 됩니다.




이렇게 abex' 2nd crakme를 분석해봤습니다. 본격적으로 어려워지는것 같은데 여러번 돌려보면 이해가 갈 것이라 생각이 듭니다.

'리버스 엔지니어링' 카테고리의 다른 글

함수 호출 규약  (0) 2018.01.10
Process Explorer란?  (0) 2018.01.10
abex' crackme#1 분석  (0) 2018.01.04
스택이란?  (0) 2018.01.04
IA-32 Register 기본 설명  (0) 2018.01.04