메가IT아카데미 국기과정/리버싱과 악성코드 분석
[1-9] PE 파일 분석(API&DLL)
한님폐하
2022. 9. 13. 12:23
- 분석 파일 : user32.dll, lock_1.exe, lock_2.exe, lock_3_import.ext, lock_3_export.dll
- 분석 도구 : VS2008, PEview, CFF Explorer, Dependency Walker
1. API
- Application Programming Interface
- 운영체제, 프로그램 언어가 응용 프로그램에서 사용할 수 있도록 기능을 제공하는 인터페이스(함수)
- MSDN 문서 참조
2. 컴파일
- 모든 헤더와 소스 파일 내용을 합쳐서 하나의 기계어 코드를 생성하는 기능을 수행한다.
- 소스 코드에 오류가 있는지를 검사한다.
3. DLL
- Dynamic Linked Library
- 여러 프로그램에서 동시에 사용할 수 있는 코드, 데이터, 함수를 포함한 라이브러리이다.
- DLL을 사용하면 디스크/메모리에 로드되는 중복된 코드를 최소화, 리소스 사용 최소화, 다른 프로그램 성능을 향상시킬 수 있다.
4. Static Linking & Dynamic Linking
- Static Linking
- 컴파일 진행시 함수가 링커에 의해서 실행 파일에 연결되는 방식이다.
- 실행 파일에 함수의 코드가 복사되므로 파일 크기가 증가된다.
- 실행 파일에 함수 코드가 포함되기 때문에 완전한 단독 실행 파일로 생성된다.
- 그렇기 때문에 컴파일이 끝나면 라이브러리 파일이 필요없다.
- Dynamic Linking
- 프로그램 실행시 함수가 연결된다.
- 컴파일 진행시 호출할 함수의 정보만 포함하고 실제 함수 코드 정보는 포함되지 않는다.
- 그렇기 때문에 파일 크기가 증가되지 않는다.
- 단, 실행 파일에서 사용할 함수를 갖고 있는 라이브러리 파일이 꼭 있어야 한다.
4. DLL 로드 방식(동적 링킹)
- 명시적 링킹
- 프로그램에서 필요한 시점에 DLL/함수 정보를 로드하고 사용한 이후 해제한다.
- 다음과 같은 3개의 함수를 이용하여 DLL를 로드한다.
- LoadLibrary() 필요한 DLL을 프로세스 가상 메모리에 매핑/로드하는 함수(DLL 불러옴)
- GetProcAddress() DLL 함수의 포인터/주소를 획득하는 함수(DLL로부터 함수를 불러옴)
- FreeLibrary() 프로세스 가상 메모리에서 DLL를 반환/언로드하는 함수(DLL 해제함)
- 암시적 링킹
- 실행 파일 자체에서 사용할 DLL과 함수 정보를 포함한 이후 프로그램 실행시 로드한다.
- 즉, 프로그램이 시작되면서 해당 DLL를 바로 로드하는 방식이다.
- PE 로더가 PE 파일 안에 있는 함수 내용/목록을 확인하여 DLL 파일을 메모리에 로드한다.
5. 화면 잠금 프로그램 'lock_1.exe' 제작
- VB 2008을 이용하여 'lock_1.exe' 파일을 제작한다.
- 파일 -> 새로 만들기 -> 프로젝트 -> 빈 프로젝트 -> 위치(04_테스트) & 이름(lock_1) -> 확인
- '소스 파일' 우클릭 -> 추가 -> 새 항목 -> 'C++ 파일(.cpp)' 선택 -> 이름(lock_1) -> 추가
#pragma comment(lib, "user32.lib")
#include <windows.h>
#include <stdio.h>
void main()
{
if (!LockWorkStation()) // 성공이면 '0'이 아닌 값 리턴, 실패하면 '0' 리턴
printf("LockWorkStation failed with %d\n", GetLastError());
} - 빌드 -> lock_1 빌드
- Release 선택 -> ▶(디버깅 시작) 버튼 클릭 -> 화면 잠김 확인
- 파일 -> 모두 저장
- 'lock_1.exe' 파일에서 사용하는 DLL/함수를 확인한다.
- PEview, CFF Explorer, Dependency Walker
6. 화면 잠금 프로그램 'lock_2.exe' 제작
- VB 2008을 이용하여 'lock_2.exe' 파일을 제작한다.
- 파일 -> 새로 만들기 -> 프로젝트 -> 빈 프로젝트 -> 위치(04_테스트) & 이름(lock_2) -> 확인
- '소스 파일' 우클릭 -> 추가 -> 새 항목 -> 'C++ 파일(.cpp)' 선택 -> 이름(lock_2) -> 추가
#include <windows.h>
#include <stdio.h>
BOOL (*funP1) (void);
void main()
{
HMODULE hModule;
PVOID pVoid;
hModule = LoadLibrary("user32.dll");
// 'LoadLibrary' 함수를 이용하여 'user32.dll'를 로드
if (!hModule) {
printf("failed to load dll");
exit(1);
}
pVoid = GetProcAddress(hModule, "LockWorkStation");
// 'GetProcAddress' 함수를 이용하여 '"LockWorkStation' 주소를 'pVoid' 변수에 대입
if (pVoid == NULL) {
printf("failed to load function");
exit(1);
}
funP1 = pVoid; // 함수 포인터 주소를 'pVoid'로 연결
(*funP1)(); // 함수 호출 실시
} - 소스 파일 -> 'lock_2.cpp' 우클릭 -> 속성 -> C/C++ -> 고급 -> 컴파일 옵션 -> 'C 코드로 컴파일' 선택 -> 확인
- 빌드 -> lock_2 빌드
- 소스 파일 -> 'lock_2.cpp' 우클릭 -> 속성 -> C/C++ -> 고급 -> 컴파일 옵션 -> 'C 코드로 컴파일' 선택 -> 확인
- Release 선택 -> ▶(디버깅 시작) 버튼 클릭 -> 화면 잠김 확인
- 파일 -> 모두 저장
- 'lock_2.exe' 파일에서 사용하는 DLL/함수를 확인한다.
- PEview, CFF Explorer, Dependency Walker
7. 화면 잠금 프로그램 'lockws.dll' 제작
- VB 2008을 이용하여 'lockws.dll' 파일을 제작한다.
- 파일 -> 새로 만들기 -> 프로젝트 -> Win32 콘솔 응용 프로그램 -> 위치(04_테스트) & 이름(lockws) -> 확인
- 마법사 시작 -> 다음 -> 'DLL & 빈 프로젝트' 선택 -> 마침
- '소스 파일' 우클릭 -> 추가 -> 새 항목 -> 'C++ 파일(.cpp)' 선택 -> 이름(lockws) -> 추가
#pragma comment(linker, "/export:LockWS=user32.LockWorkStation")
#pragma comment(lib, "user32.lib") - '헤더 파일' 우클릭 -> 추가 -> 새 항목 -> '헤더 파일 (.h)' 선택 -> 이름(lockws_h) -> 추가
#include <windows.h>
#include <stdio.h>
//extern "C" __declspec(dllexport)
int LockWS(void) {
if (!LockWorkStation()) {
printf("LockWorkStation failed with %d\n", GetLastError());
return 1;
}
return 0;
} - 빌드 -> lock_3_export 빌드
- Release 선택 -> ▶(디버깅 시작) 버튼 클릭 -> 파일 -> 모두 저장
- C:\리버싱\04_테스트\lockws\Release -> 'lockws.lib', 'lockws.dll'
- 'lockws.dll' 파일에서 사용하는 DLL/함수를 확인한다.
- PEview, CFF Explorer, Dependency Walker
- PEview, CFF Explorer, Dependency Walker
8. 화면 잠금 프로그램 'lock_3.exe' 제작
- VB 2008을 이용하여 'lock_3.exe' 파일을 제작한다.
- 파일 -> 새로 만들기 -> 프로젝트 -> 빈 프로젝트 -> 위치(04_테스트) & 이름('lock_3.exe') -> 확인
- '소스 파일' 우클릭 -> 추가 -> 새 항목 -> 'C++ 파일(.cpp)' 선택 -> 이름('lock_3.exe') -> 추가
#pragma comment(lib, "lockws.lib")
#include <windows.h>
#include <stdio.h>
#include "C:\리버싱\04_테스트\lockws\lockws\lockws_h.h"
void main()
{
if (!LockWS())
printf("call dll error");
} - 좌측 'lock_3' 마우스 우클릭 -> 속성
구성 속성 -> 링커 -> 입력 -> 추가 종속성 -> 'lockws.lib' 추가 -> 확인
구성 속성 -> 링커 -> 일반 -> 추가 라이브러리 디렉터리 -> '04_테스트\lockws\Release' 추가 -> 확인
구성 속성 -> C/C++ -> 일반 -> 추가 포함 디렉터리 -> '04_테스트\lockws\lockws' 추가 -> 확인 - 빌드 -> lock_3 빌드
- 좌측 'lock_3' 마우스 우클릭 -> 속성
구성 속성 -> 링커 -> 입력 -> 추가 종속성 -> 'lockws.lib' 추가 -> 확인
구성 속성 -> 링커 -> 일반 -> 추가 라이브러리 디렉터리 -> '04_테스트\lockws\Release' 추가 -> 확인
구성 속성 -> C/C++ -> 일반 -> 추가 포함 디렉터리 -> '04_테스트\lockws\lockws' 추가 -> 확인 - Release 선택 -> ▶(디버깅 시작) 버튼 클릭 -> 화면 잠김 확인
- 파일 -> 모두 저장
- 'lock_3.exe' 파일에서 사용하는 DLL/함수를 확인한다.
- PEview, CFF Explorer, Dependency Walker