본문 바로가기
Windows

Windows Security API

by Mecodata 2025. 12. 8.

정의

- 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로 확인

 

댓글