흰싸라기 2022. 3. 13. 23:53

8.1 abex’ crackme #2 실행

실행화면

  • 시리얼 키(serial key)를 알아내느 프로그램
    • 전형적인 crackme의 형태
  • Name과 Serial을 적절히 입력 후 [Check] 버튼

  • “Wrong serial!” 메시지 박스 출력

8.2 Visual Basic 파일 특징

8.2.1 VB 전용 엔진

  • VB 전용 엔진 사용 : MSVBVM60.dll (Microsoft Visual Basic Virtual Machine 6.0)
    • 사용 예 : 메시지 박스 호출 시 소스코드에서 MsgBox() 함수 사용, 함수 내부에서 Win32 API인 user32.dll!MessageBoxW() 함수를 호출하는 방식으로 동작

 

8.2.2 N(Native) code, P(Pseudo) code

  • 컴파일 옵션에 따라 N code와 P code로 컴파일이 가능
  • N code : 일반적인 디버거에서 해석 가능한 IA-32 Instruction 사용
  • P code : 인터프리터(interpreter) 언어 개념으로 VB 엔진으로 가상머신을 구현하여 자체적으로 해석 가느안 명령어(바이트 코드) 사용
    • P code의 정확한 해석은 VB 엔진을 분석해야함
    • Java, Python과 유사한 형태

 

8.2.3 Event Handler

  • VB는 주로 GUI 프로그래밍을 할 때 사용됨
    • Windows 운영체제의 Event Driven 방식으로 작동
    • 따라서, main()이 아닌 event handler에 사용자 코드가 존재

 

8.2.4 undocumented 구조체

  • VB에서 사용되는 각종 정보(Dialog, Module, Function 등)은 내부적으로 구조체 형식으로 파일에 저장
  • 이러한 구조를 정식 공개하지 않아 VB 파일의 디버깅에 어려움이 존재

 

8.3 디버깅 시작

OllyDbg를 실행시켜 abex’ crackme #2 디스어셈 코드 살펴보기

Entry Point

  • PUSH 401E14 : RT_MainStruct 구조체 주소(401E14)를 스택에 입력
    • RT_MainStruct 구조체
      • MS에서 공개하지 않았지만, 리버서들이 분석하여 공개함
      • 해당 구조체 멤버 : 또 다른 구조체의 주소들

RT_MainStruct

  • EP 코드에서 VB 엔진의 메인함수(ThunRTMain)를 호출함을 알 수 있음
    • 40123D 주소의 명령어(CALL)에 이해 401232 주소의 명령어(JMP)가 실행
    • JMP 명령어에 의해 메인 함수로 이동
    • 스택에 입력한 401E14 값은 함수의 파라미터
      • 구조체를 통해 프로그램 실행에 필요한 모든 정보를 얻어옴
  • 간접 호출 : CALL 401232
    • 메인 함수로 직접 가는 것이 아는 중간의 JMP 명령을 통해서 가능 방식

8.4 crackme 분석

8.4.1 문자열 검색

: 패치해야 할 코드를 찾기 위해 에러 메시지 박스와 그 문자열을 이용하기

 

1) 문자열 검색 기능(All referenced text strings) 사용

  • 실행했을 때 본 메시지 박스의 문자열 찾기

2) 찾은 문자열 더블클릭하여 주소 이동

302458 주소

  • 시리얼 키와 사용자가 입력한 키를 비교하는 코드를 예상할 수 있음
  • 즉, 위 코드 전후에 문자열 비교 코드 및 키가 맞았을 때 성공 메시지 박스 호출 코드가 존재할 것임

3) 분기문 찾기

  • 주소 403458에서 스크롤을 올리다보면 분기문을 발견할 수 있음

  • TEST AX, AX : AX를 비교 후 조건 분기(JE)에 이해 참, 거짓으로 분기
    • AX : 함수 리턴값
    • TEST : AND 연산과 동일, 두 오퍼레이터 중 하나가 0이면 ZF = 1로 세팅됨
    • JF(조건 분기) : ZF =1이면 점프
  • AX는 함수 리턴 값, 403329 주소에서 호출한 함수(__vbaVarTstEq) 리턴 값을 비교한 것

8.4.2 문자열 주소 찾기

  • 403329 주소 함수가 문자열 비교 함수라면 그 위의 PUSH 명령어는 비교 함수의 파라미터, 즉 비교 문자열이 될 것

1) 403329 주소까지 디버깅 진행

입력값

  • 403321 주소의 SS:[EBP-44]
    • SS는 스택 세그먼트, EBP는 베이스 포인터
    • 즉, SS:[EBP-44] 주소는 스택 내의 주소 → 함수에서 선언된 로컬 객체의 주소
      • 로컬 객체는 스택 영역에 저장됨

2) 스택 확인

  • EDX : [EBP-44], EAX : [EBP-34] 확인

3) 스택에 저장된 메모리 주소로 이동

4) 문자열 표시 (마우스 우측 - Long - Address with ASCII dump)

  • EDX는 실제 serial 값이고, EAX는 사용자가 입력한 serial 값임을 알 수 있음

5) 실행

  • Name = “hello”, Serial = “CCC9D0D0”