woonadz :)

WIN32 API 프로그래밍 - 폴더 경로 가져오기(SHGetKnownFolderPath) 본문

IT/malware dev

WIN32 API 프로그래밍 - 폴더 경로 가져오기(SHGetKnownFolderPath)

C_scorch 2023. 10. 25. 21:22
반응형

SHGetKnownFolderPath 함수 : 폴더의 KNOWNFOLDERID로 식별된 알려진 폴더의 전체 경로를 검색합니다.

HRESULT SHGetKnownFolderPath(
  [in]           REFKNOWNFOLDERID rfid,
  [in]           DWORD            dwFlags,
  [in, optional] HANDLE           hToken,
  [out]          PWSTR            *ppszPath
);

[in] rfid

폴더를 식별하는 KNOWNFOLDERID 에 대한 참조

⇒ 검색을 원하는 폴더의 경로에 알맞는 상수 값을 위 링크에서 찾아 지정해주면 됩니다.

 

[in] dwFlags

특수 검색 옵션을 지정하는 플래그입니다. 이 값은 0일 수 있습니다. 그렇지 않으면 하나 이상의 KNOWN_FOLDER_FLAG 값입니다.

⇒ 특수 검색(절대 경로를 가져올 것인지, 폴더가 없다면 폴더를 생성할 것인지 등) 행위를 DWORD 값으로 지정해주면 됩니다.

 

[in, optional] hToken

특정 사용자를 나타내는 액세스 토큰 입니다.

NULL : 현재 사용자에 대해 알려진 폴더를 요청합니다.

-1 : 기본 사용자 폴더를 대상으로 경로를 찾을 수 있습니다. 이렇게 하면 SHGetKnownFolderPath 의 클라이언트가 기본 사용자에 대한 폴더 위치(예: 데스크톱 폴더)를 찾을 수 있습니다. 기본 사용자 사용자 프로필은 새 사용자 계정을 만들 때 중복되며 문서 및 데스크톱과 같은 특수 폴더를 포함합니다. 기본 사용자 폴더에 추가된 모든 항목도 새 사용자 계정에 표시됩니다. 기본 사용자 폴더에 액세스하려면 관리자 권한이 필요합니다.

그 외 : 해당 사용자의 hToken 을 전달하여 특정 사용자의 폴더를 요청합니다. 이 작업은 일반적으로 지정된 사용자의 토큰을 검색할 수 있는 충분한 권한이 있는 서비스의 컨텍스트에서 수행됩니다. 해당 토큰은 TOKEN_QUERY 및 TOKEN_IMPERSONATE 권한으로 열어야 합니다. 경우에 따라 TOKEN_DUPLICATE 포함해야 합니다. 사용자의 hToken을 전달하는 것 외에도 해당 특정 사용자의 레지스트리 하이브를 탑재해야 합니다. 액세스 제어 문제에 대한 자세한 내용은 Access Control 참조하세요.

⇒ 보통 optional은 NULL 값으로 처리해주곤 합니다.

 

[out] ppszPath

이 메서드가 반환될 때 알려진 폴더의 경로를 지정하는 null로 끝나는 유니코드 문자열에 대한 포인터의 주소를 포함합니다. 호출 프로세스는 SHGetKnownFolderPath의 성공 여부와 관계없이 CoTaskMemFree를 호출하여 더 이상 필요하지 않은 경우 이 리소스를 해제할 책임이 있습니다. 반환된 경로에는 후행 백슬래시가 포함되지 않습니다. 예를 들어 "C:\Users"는 "C:\Users\" 대신 반환됩니다.

⇒ SHGetKnownFolderPath API를 호출한 후 반환된 경로를 포함하는 문자열은 내부적으로 CoTaskMemAlloc로 할당됩니다. 따라서 오버플로우가 나지 않도록 문자열을 모두 사용한 이후에는 CoTaskMemFree를 사용하여 명시적으로 해제를 해줘야합니다.

 

반환값

형식: HRESULT

성공하면 S_OK(0x00000000)를 반환하고, 그렇지 않으면 오류 값을 반환합니다.

 

 

저는 다음과 같이 매개변수 설정을 하겠습니다.

HRESULT SHGetKnownFolderPath(
  [in]           REFKNOWNFOLDERID FOLDERID_Documents,
  [in]           DWORD            NULL,
  [in, optional] HANDLE           NULL,
  [out]          PWSTR            document_path
);

 

위에서 설정한 매개변수를 이용해 아래와 같이 간단한 코드를 만들었습니다. 

#include <stdio.h>
#include <Windows.h>
#include <shlobj_core.h>
#include <combaseapi.h>

int main (void) {
	PWSTR document_path = NULL;
	REFKNOWNFOLDERID ID = &FOLDERID_Documents; //documents의 경로를 가져옴
	HRESULT result;

	result = SHGetKnownFolderPath(ID, 0, NULL, &document_path);
	if (result == 0) { //폴더 경로를 가져오는 것을 성공했다면 경로 출력
		printf("%ls", document_path);
	}
	else { //폴더 경로를 가져오는 것을 실패했다면 에러 메시지 출력
		printf("해당 경로는 존재하지 않습니다.");
	}

	//API로 받아온 documnet_path 사용

	CoTaskMemFree(document_path); //메모리 해제

	return 0;
}

출력 화면

 

악성코드에서 SHGetKnownFolderPath 함수를 사용하는 이유는 특정 사용자의 폴더 경로를 확인하고 폴더에 액세스하기 위함입니다. 제가 만들 랜섬웨어에서는 documents 폴더에 있는 모든 파일을 암호화할 것이기 때문에 documents 폴더의 경로를 가져옵니다.

반응형