정의
- Windows 파일/디렉터리/객체의 권한(Access Control)을 다루는 API
Windows 보안 구조
| 개념 | 설명 |
| SD (Security Descriptor) | 소유자, 그룹, ACL을 포함한 최상위 보안 구조체 |
| ACL (Access Control List) | 여러 ACE를 모아둔 리스트. 누가 어떤 권한을 가졌는지 저장 (DACL/SACL) |
| DACL (Discretionary ACL) | 접근 허용/거부 규칙 집합 |
| ACE (Access Control Entry) | 한 사용자/그룹의 권한 1개 규칙. (예: Everyone → READ) |
| EXPLICIT_ACCESS | ACE를 생성하기 위한 구조체 |
- Security Descriptor = 건물 전체
- DACL = 출입 통제실
- ACE = 출입 카드 한 장(권한 1개)
- EXPLICIT_ACCESS = ACE 생성 시 필요한 재료(설계서)
Windows 보안 관련 구조체
| 개념 | 설명 |
| PSECURITY_DESCRIPTOR | SD를 가리키는 포인터. malloc 등으로 메모리 할당 후 InitializeSecurityDescriptor로 초기화 |
| EXPLICIT_ACCESS | 새 ACE 생성용 구조체. Trustee·권한·상속 정보 포함 |
| PACL | ACL 구조체의 포인터 |
| ACCESS_ALLOWED_ACE | 허용 ACE를 나타내는 원형 구조체 |
| DWORD | 윈도우의 부호 없는 정수 자료형 (4byte) - int |
EXPLICIT_ACCESS
typedef struct _EXPLICIT_ACCESS {
DWORD grfAccessPermissions;
ACCESS_MODE grfAccessMode;
DWORD grfInheritance;
TRUSTEE Trustee;
}
typedef struct _TRUSTEE {
struct _TRUSTEE *pMultipleTrustee;
MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation;
TRUSTEE_FORM TrusteeForm;
TRUSTEE_TYPE TrusteeType;
LPCTSTR ptstrName;
}
// 예시
EXPLICIT_ACCESS ea;
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); // WindowsAPI 구조체는 사용 전 메모리 초기화 필수
ea.grfAccessPermissions = GENERIC_READ; // 권한(읽기만)
ea.grfAccessMode = SET_ACCESS; // 기존 ACL 제거 후 덮어쓰기
ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; // 모든 하위 파일/폴더 상속
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME; // 이름으로 대상 식별
ea.Trustee.TrusteeType = TRUSTEE_IS_USER; // 타입 : 사용자
ea.Trustee.ptstrName = L"Everyone"; // 사용자 모두에게 권한 부여
| 파라미터 | 의미 |
| grfAccessPermissions | 부여할 권한 설정 (읽기/쓰기/모든 권한 등) |
| grfAccessMode | 권한이 기존 ACL과 어떻게 합쳐지는지 설정 (추가/덮어쓰기 등) |
| grfInheritance | 하위 폴더/파일로 권한을 상속할지 여부 설정 |
| Trustee.TrusteeForm | 식별 기준 설정(SID/이름) |
| Trustee.TrusteeType | 권한을 부여할 대상 타입 지정(USER/GROUP) |
| Trustee.ptstrName | 권한을 부여할 사용자 이름 또는 SID 포인터 지정 |
Windows 보안 관련 Windows API 함수
1. GetFileSecurity
BOOL GetFileSecurity(
LPCWSTR lpFileName,
SECURITY_INFORMATION RequestedInformation,
PSECURITY_DESCRIPTOR pSecurityDescriptor,
DWORD nLength,
LPDWORD lpnLengthNeeded
);
// 예시
DWORD dwSize = 0;
// 1차 호출: 필요한 버퍼 크기 얻기
GetFileSecurity(filePath.c_str(),
DACL_SECURITY_INFORMATION,
NULL,
0,
&dwSize);
// 메모리 할당
PSECURITY_DESCRIPTOR pSD =
(PSECURITY_DESCRIPTOR)malloc(dwSize);
// 2차 호출: 실제 정보 읽기
if (!GetFileSecurity(filePath.c_str(),
DACL_SECURITY_INFORMATION,
pSD,
dwSize,
&dwSize))
{
// 에러 처리
}
- 특정 파일의 소유자, 그룹, DACL(접근 제어 목록) 을 가져오는 WinAPI 함수
- 보통 해당 보안 정보에 대비하여 필요한 버퍼의 크기를 구하기 위해 사용 -> lpnLengthNeeded에 해당 값이 담겨짐
| 파라미터 | 설명 |
| lpFileName | 보안 정보를 읽어올 파일 또는 디렉터리 경로 |
| RequestedInformation | 가져올 보안 정보의 종류 - 여러 개 적용 가능 (OWNER_SECURITY_INFORMATION, GROUP_SECURITY_INFORMATION, DACL_SECURITY_INFORMATION, …) |
| pSecurityDescriptor | 데이터를 저장할 버퍼(SECURITY_DESCRIPTOR 구조체). NULL 가능. |
| nLength | buffer 크기(바이트). 0도 가능. |
| lpnLengthNeeded | 필요한 버퍼 크기 |
2. ZeroMemory
VOID ZeroMemory(PVOID Destination, SIZE_T Length);
- 해당 메모리를 0으로 초기화하는 함수
3. malloc / free
void* malloc(size_t size);
void free(void* ptr);
- 메모리 할당 / 해제 함수
4. InitializeSecurityDescriptor
BOOL InitializeSecurityDescriptor(
PSECURITY_DESCRIPTOR pSecurityDescriptor, // 초기화할 SecurityDescriptor
DWORD dwRevision // 보안 구조체 버전 (보통 SECURITY_DESCRIPTOR_REVISION)
);
- Security Descriptor 초기화 함수
5. GetSecurityDescriptorDacl
BOOL GetSecurityDescriptorDacl(
PSECURITY_DESCRIPTOR pSecurityDescriptor,
LPBOOL lpDaclPresent,
PACL *pDacl,
LPBOOL lpDaclDefaulted
);
- Security Descriptor에서 DACL 관련 데이터를 가져오는 함수
| 파라미터 | 설명 |
| pSecurityDescriptor | 조회할 Security Descriptor 포인터 |
| lpDaclPresent | DACL이 존재하는지 여부가 반환 (TRUE/FALSE) |
| pDacl | DACL 주소가 반환 (NULL 가능) |
| lpDaclDefaulted | 기본값(default)으로 설정된 DACL인지 여부가 반환 |
6. SetEntriesInAcl
DWORD SetEntriesInAcl(
ULONG cCountOfExplicitEntries,
PEXPLICIT_ACCESS pListOfExplicitEntries,
PACL OldAcl,
PACL* NewAcl
);
- EXPLICIT_ACCESS를 기반으로 새로운 ACL(PACL)을 생성
- EXPLICIT_ACCESS 설정값에 따라 기존 ACL과 병합 혹은 대체(덮어쓰기) 가능
- 새로 생성한 ACL(NewAcl)은 LocalFree를 해줘야 하고 기존 ACL은 SD가 관리하므로 그대로 둬야 함
| 파라미터 | 설명 |
| cCountOfExplicitEntries | 추가할 EXPLICIT_ACCESS 개수 |
| pListOfExplicitEntries | 기반으로 할 EXPLICIT_ACCESS 배열 |
| OldAcl | 기존 ACL (NULL 가능) |
| NewAcl | 새로운 ACL이 반환 (자동으로 LocalAlloc을 통해 메모리 할당 -> 작업 후 LocalFree로 메모리 해제 필요) |
7. SetSecurityDescriptorDacl
BOOL SetSecurityDescriptorDacl(
PSECURITY_DESCRIPTOR pSD,
BOOL bDaclPresent,
PACL pDacl,
BOOL bDaclDefaulted
);
- Security Descriptor에 새 DACL을 등록
- 이 함수는 등록만 수행하며 ACL 메모리 해제는 하지 않음
| 파라미터 | 설명 |
| pSecurityDescriptor | 설정할 SD |
| bDaclPresent | DACL이 존재하는지 여부 (TRUE 권장) |
| pDacl | 새로 등록할 ACL |
| bDaclDefaulted | 기본값 여부 (일반적으로 FALSE 사용) |
8. LocalFree
HLOCAL LocalFree(HLOCAL hMem);
- LocalAlloc, SetEntriesInAcl, ConvertSidToStringSid 등이 할당한 메모리를 해제
9. GetLastError
DWORD GetLastError(void);
- Windows API 호출 실패 시 마지막 오류 코드를 반환 (112-디스크 용량 부족)
- 대부분의 Windows API는 실패 시 FALSE 또는 NULL을 반환하고 정확한 에러 코드는 GetLastError로 확인
댓글