프로그램 동작 방식

Delphi
- 마이크로소프트 윈도우 응용프로그램을 위한 통합개발환경(고속개발도구)

- serial을 입력하는 창
GetVolumeInformation() 함수
: 지정된 루트 디렉터리가 속한 파일 시스템 정보와 볼륨 정보를 가져오는 함수
BOOL GetVolumeInformationA(
[in, optional] LPCSTR lpRootPathName,
[out, optional] LPSTR lpVolumeNameBuffer,
[in] DWORD nVolumeNameSize,
[out, optional] LPDWORD lpVolumeSerialNumber,
[out, optional] LPDWORD lpMaximumComponentLength,
[out, optional] LPDWORD lpFileSystemFlags,
[out, optional] LPSTR lpFileSystemNameBuffer,
[in] DWORD nFileSystemNameSize
);
- in은 입력변수, optional은 선택적으로 사용한다는 의미
- out은 실행 결과가 저장될 변수를 지정하는 것
lpRootPathName은 입력 변수로, 선택적으로 사용할 수 있다. optional이므로 반드시 사용해야하는 것은 아니다.
nVolumeNameSize은 입력 변수지만 반드시 사용해야한다. 함수 사용시 nVolumeNameSize을 지정하지 않으면 오류가 발생한다.
lpVolumeNameBuffer는 함수 호출 시 변수 이름을 넣어주면, 함수가 실행되고 그 결과로 찾아낸 볼륨 이름을 지정한 변수에 담아준다.


- 출력 값이 저장된 모든 변수에 0이 저장되어 있는 것을 알 수 있다.

- GetVolumeInformation() 함수까지 실행시 출력 변수에 다양한 값이 저장되는 것을 확인할 수 있다.
디버깅 과정에서 다양한 윈도우 API를 만나게 되는데, 그 때 가장 먼저 해야하는 것이 MSDN에서 함수의 기능을 살펴보는 것
입력 값과 출력 값이 어디에 저장되고 이 값들이 이후 프로그램에서 어떻게 사용되는지 조사하면 해결의 실마리를 찾을 수 있다.
반복문을 통한 문자열 변경
반복문 구성 → 초깃값, 한계 값, 증가 값

① 004010AD
DL 레지스터에 2를 복사한다.
DL은 나중에 반복문의 종료를 체크하는 변수로 사용된다.
자바 코드에서 int i = 2와 같은 역할
② 004010AF ~ 004010C4
반복문이 수행하는 로직
③ 004010CB
DL 레지스터를 하나씩 감소시킨다.
DEC 명령어는 차감하는 대상이 0이 되면 ZF를 1로 설정한다.
자바 코드에서 i--와 같은 역할
④ 004010CD
ZF가 1이 아니면 주소 004010AF(반복문 수행 로직 처음 주소)로 점프한다.
DL 레지스터가 0이 되면 ZF가 1로 설정되고 반복문이 종료된다.
프로그램 구조 분석


① 파일 시스템 정보와 볼륨 정보를 가져와서 일련번호를 만들기 위한 입력 값으로 사용

② 파일 시스템 정보와 프로그램 내부에 들어 있는 문자열을 결합해서 만든 새로운 문자열을 반복문을 통해 다른 문자열로 변형
ADD DWORD PTR DS:[40225C], 1
ADD DWORD PTR DS:[40225D], 1
ADD DWORD PTR DS:[40225E], 1
ADD DWORD PTR DS:[40225F], 1
- 연속된 메모리 주소의 값을 각각 1씩 더함.
- 총 4개의 주소 (0x40225C ~ 0x40225F)에 대해 각각 +1 수행
⇒ 반복문을 2번 수행하므로, 결론적으로 4개의 주소에 대해 각각 +2를 수행하는 것

③ 앞에서 생성한 새로운 문자열을 가지고 프로그램 내부의 문자열과 결합해 일련번호를 생성함, 프로그램 내부에는 2가지의 문자열이 있고, 파일 시스템 정보와 결합하고 변형해서 일련변호를 생성

④ 생성한 일련번호와 사용자가 입력한 값이 일치하는 지 확인
문제 해결

- 프로그램을 실행하면 일련번호를 입력하는 창이 나오는데, abcd를 입력하고 GetVolumeInformationA 함수를 실행시킨다.
- 0040225C에 있는 데이터가 일련번호를 만드는 데 사용됨을 일련번호를 만드는 부분을 보면 알 수 있다.

- 원래는 드라이브 이름이 저장되어야하는데 인식을 못하는 건지 아무것도 들어가있지 않다. 그래도 계속 진행하겠다.

- 다음 코드를 실행시켜보면 0040225C에 들어있는 값 + 4562-ABEX이 0040225C에 저장된다.
- 0040225C에 아무것도 들어가 있지 않았어서 0040225C에 4562-ABEX라는 문자열이 저장되었다.


- 다음 반복문은 0040225C부터 4개의 문자값에 해당하는 숫자를 1만큼 2번 증가시킨다.

- 원래는 4562가 들어있었는데 2씩 증가하여 6784가 되었다.

- 먼저 00402000에 L2C-5781이라는 문자열을 저장한다.
- 다음 0040225C에 저장되어있는 앞에서 생성한 문자열을 00402000에 저장된 문자열에 붙인다.
- 마지막으로 사용자가 입력한 문자열과 00402000에 저장된 문자열을 비교한다.
lstrcmpiA()함수는 두 개의 인수를 입력받는데, 함수 실행 결과는 EAX 레지스터에 저장되며 두 인자의 값이 같으면 0, 다르면 1이 입력된다.

- 내 컴퓨터에서 생성되는 일련번호는 L2C-57816784-ABEX임을 알 수 있다.


'Reversing > Introduction to reversing' 카테고리의 다른 글
| Lena Reversing tutorial 17 - Removing NAGs (0) | 2025.05.05 |
|---|---|
| abex crackme 4 (0) | 2025.05.05 |
| abex crackme 3 (1) | 2025.05.05 |
| abex crackme 2 (0) | 2025.05.05 |
| abex crackme 1 (2) | 2025.05.05 |