ImagePcr
The program compares a drawing against a bitmap held in its resources; the flag is the image it expects.
프로그램을 실행해보자! 그림을 그리고 검사를 받는다. 아무렇게나 그림을 그려 넣으면 Wrong!, 탈락한 것 같다.
x32dbg 로 먼저 열어본다. 문자열 찾기에서 Wrong 을 사용하는 주소로 가본다. 일단 GetDIBits 로 비트맵 이미지를 가져온다. 아마 내가 그린 그림이다! 그리고 FindResourceA, LoadResource 로 비교할 파일을 가져온다. 비트 하나씩 비교해서, 틀리면 바로 Wrong 을 출력하는 것 같다. 그렇다면, 그 파일에 정답이 있을 거다!
PE Viewer 로 열어봤는데, .rsrc 섹션에 리소스 데이터가 있다. 정답 이미지의 파일을 위의 정보들로 알아낼 수 있다.
0960 (f 가 시작하는 곳) ~ (0960 + 15FF0)
비트맵 이미지 파일이다. 밑으로 쭉 내려보니까 중간에 00 도 있다는 걸 확인했다. 그러기 위해선 높이와 너비를 알아야 한다. 다시 코드를 분석해보자. 주변 위쪽을 찾아보니까 GetDIBits 가 있다. GetDIBits 는 비트맵(Bitmap)의 실제 픽셀 데이터를 메모리 버퍼로 가져오는 Windows GDI API 이다.
push edx, GetDIBits 주소의 hex 값을 (첫 번째 줄) 보면 데이터들을 볼 수 있다. BITMAPINFOHEADER 구조체는 이렇게 생겼다.
typedef struct tagBITMAPINFOHEADER {
DWORD biSize; // 0x00
LONG biWidth; // 0x04
LONG biHeight; // 0x08
WORD biPlanes; // 0x0C
WORD biBitCount; // 0x0E
} BITMAPINFOHEADER;
이걸 정리하면:
| Offset | HEX | Size | 필드 | 의미 | 값 |
|---|---|---|---|---|---|
| +0x00 | 28 00 00 00 | 4B (DWORD) | biSize | 구조체 크기 | 0x28 = 40 bytes |
| +0x04 | c8 00 00 00 | 4B (LONG) | biWidth | 가로 픽셀 | 0xC8 = 200 px |
| +0x08 | 96 00 00 00 | 4B (LONG) | biHeight | 세로 픽셀 | 0x96 = 150 px |
| +0x0C | 01 00 | 2B (WORD) | biPlanes | 플레인 수 | 1 (고정값) |
| +0x0E | 18 00 | 2B (WORD) | biBitCount | 색 깊이 | 0x18 = 24 bit |
이 정보들을 가지고 그림판에서 비트맵을 만든다. (24 비트맵으로 저장해야 함; 픽셀 사이즈도 맞추고)
이제 비트맵의 내용을 채워 플래그(답 이미지) 를 볼 차례다. 헥스 에디터에 ImagePcr.exe 파일과 bmp 파일을 열어준다. 아까 구한 오프셋으로 ImagePcr.exe 에서 원하는 헥스 부분을 추출한다.
카피앤페이스트한 다음에, 헤더가 끝나고 바디가 시작하는 주소인 0x36 에 클릭 후 페이스트해준다. (딱 맞는다)
이렇게 저장 후 bmp 파일을 열어주면 플래그를 볼 수 있다.
모자이크 처리함!







