이 파일 다운받아서 시작해보겠습니다..
시리얼 키 알아내는 프로그램이다.
암거나 눌러보았는데 wrong serial 메시지 박스가 출력된다.
Visual Basic 파일 특징
위에 파일은 Visual Basic으로 제작됨
VB 전용 엔진
VB 파일은 MSVBVM60.dll (Microsoft Visual Basic Virtual MAchine 6.0)이라는 VB 전용 엔진 사용
N(Native) code, P(Pseudo) code
VB 파일은 컴파일 옵션에 따라 N code와 P code로 컴파일이 가능
N code: IA-32 Instruction 사용
P code: Interpreter 언어 개념으로서 VB 엔진으로 가상 머신을 구현하여 자체적으로 해석 가능한 명령어(바이트 코드)를 사용
∴ P code를 정확히 해석하기 위해서는 VB 엔진을 분석하여 에뮬레이터를 구현해야 함
Event Handler
VB 프로그램은 Windows 운영체제의 Event Driven 방식으로 동작하기 때문에 event handler에 사용자 코드가 존재할 것
undocumented 구조체
VB에서 사용되는 각종 정보들은 내부적으로 구조체 형식으로 파일에 저장되는데 이러한 구조체 정보는 공개되지 않았음
디버깅,..
프로그램 첫 실행 시 EP코드에서 VB 엔진의 메인함수를 먼저 호출함
- 코드가 엔트리 포인트 401238에서 시작
- 런타임 구조체(RT_MAINStruct, 401E14 주소)가 스택에 푸시
- 코드가 401232 위치로 점프
- 401232에서 동적 점프가 발생하며, Visual Basic 런타임 초기화 함수인 ThunRTMain()으로 이동
- 40123D주소의 CALL 401232 명령은 ThunRTMain()함수 간접호출(Indirect Call)
crackme 분석
패치해야할 코드 찾기
- RT_MainStruct 구조체 분석은 어려움
- 에러 메시지 박스와 문자열을 이용하도록 함
문자열 검색하면 아래와 같이 확인할 수 있음
해당 주소로 가보면
사용자가 입력한 시리얼 번호를 확인하고, 잘못된 시리얼을 입력하면 오류 메시지를 표시하는 보호 메커니즘의 일부
조금 더 위를 보면 분기문이 나오는 것을 확인 할 수 있음
문자열 주소 찾기
403329 주소의 __vbaVarTstEq() 함수가 문자열 비교 함수면 위에 두개 PUSH가 비교문자열 될것.
403329까지 디버깅 진행
SS:[EBP-44]주소는 함수에서 선언된 로컬 객체의 주소
VB 문자열은 가변 길이 문자열 타입 사용
위 명령은 메모리 차으이 보기 형식을 스택창처럼 변경해줌, 문자열 주소인 경우 해당 문자열을 표시해줌
스택에 저장된 메모리 주소로 가서 확인해주면 name이랑 serial값을 알 수있다.
Serial 생성 알고리즘
함수 시작 찾기
함수 시작할 때 나타나는 스택 프레임을 구성하는 코드
코드 예측하기
- Name 문자열 읽기(GetWindowText, GetDlgItemText 등의 API 사용)
- 루프를 돌면서 문자 암호화하기(XOR, ADD, SUB 등)
Name 문자열 읽는 코드
- 00402FE8: 8D95 78FFFFFF LEA EDX,DWORD PTR SS:[EBP-88]
- EBP-88h에 있는 값을 계산하여 그 주소를 EDX 레지스터에 로드. 이 경우, 스택의 EBP(Base Pointer, 베이스 포인터) 레지스터 기준으로 -88 오프셋에 있는 변수를 참조
- 00402FEF: 52 PUSH EDX
- 이 명령어는 EDX 레지스터의 값을 스택에 푸시(push).
- 00402FF0: 56 PUSH ESI
- ESI 레지스터의 값을 스택에 푸시
- 00402FF1: 8B06 MOV EAX,DWORD PTR DS:[ESI]
- ESI에 저장된 포인터를 역참조하여 그 값을 EAX에 저장
- 00402FF3: FF91 A0000000 CALL DWORD PTR DS:[ECX+A0]
- 간접 CALL 명령어. ECX 레지스터 값에 A0h를 더한 메모리 주소에 있는 함수의 주소로 호출을 수행.
암호화 루프
특정 메모리 주소에서 데이터를 로드하고, 연산한 결과를 저장하는 방식으로 암호화 알고리즘을 구현하고 있음.
1. 메모리 주소 및 연산
주로 EBP 레지스터를 기준으로 한 오프셋을 통해 메모리 위치를 참조
주요 메모리 주소 패턴:
- MOV EAX, DWORD PTR SS:[EBP-D4]
- MOV EBX, DWORD PTR SS:[EBP-DC]
- MOV ECX, DWORD PTR SS:[EBP-FC]
메모리 오프셋 설명:
- EBP-D4h, EBP-DC, EBP-FC 등의 메모리 위치에서 데이터를 로드하거나 저장.
- 각각의 메모리 오프셋은 프로그램이 처리하고 있는 변수 또는 데이터를 참조하며, 이 변수들이 암호화 알고리즘에 사용되고 있음을 알 수 있음
2. ECX 레지스터의 역할
- 코드에서 ECX 레지스터는 종종 계산된 주소나 결과를 저장하는 데 사용. 특히, LEA(Load Effective Address) 명령어를 통해 메모리 주소를 계산하여 ECX에 로드한 다음, 그 주소를 기준으로 데이터를 참조하거나 연산.
- LEA ECX, DWORD PTR SS:[EBP-FC]
- LEA ECX, DWORD PTR SS:[EBP-34]
위의 예시는 ECX 레지스터가 EBP 기준으로 -FC 또는 -34 위치에 있는 데이터를 가리키고 있음을 나타냄. 즉, 암호화 알고리즘의 중간 연산에서 ECX는 결과를 저장할 메모리 주소를 가리키는 포인터로 사용됨.
3. 함수 호출
- MSVBVM60.__vbaVarTstLt: 변수를 비교
- MSVBVM60.__vbaLenVar: 문자열의 길이를 구하는 함수
- MSVBVM60.__vbaFreeStr: 문자열 변수를 해제하는 함수
4. 조건부 분기 및 루프 제어
- CMP DWORD PTR SS:[EBP-XX], EBX : 메모리 값과 레지스터 값을 비교
- JNZ : 비교 결과가 같지 않으면 루프를 탈출하거나 다른 분기문으로 넘어감
루프가 끝날 때까지 문자열의 각 문자가 처리되고, 최종적으로 암호화된 결과가 출력
5. ECX가 가리키는 버퍼에 암호화된 값 저장
- MOV [ECX], AL : AL 레지스터에 있는 값을 ECX가 가리키는 메모리 주소에 저장
암호화된 값은 주로 ECX 또는 다른 레지스터에서 연산된 결과로 나옴, 이후 ECX가 가리키는 위치에 저장
요약하면
1. 주어진 Name 문자열을 앞에서부터 한 문자씩 읽기(총 4회)
2. 문자를 숫자(아스키 코드)로 변환
3. 변환된 숫자에 64를 더함
4. 숫자를 다시 문자로 변환
5. 변환된 문자를 연결시킴
'공부해요 > 리버싱_핵심원리' 카테고리의 다른 글
10장. 함수 호출 규약 (0) | 2024.09.22 |
---|---|
9장. Process Explorer - 최고의 작업 관리자 (0) | 2024.09.22 |
7장. 스택 프레임 (1) | 2024.09.18 |
5장. 스택 (0) | 2024.09.17 |
4장. IA-32 Register 기본 설명 (0) | 2024.09.11 |