1.NT의 보안
(1)NT의 보안모델
-시스템의 자원을 사용잡로 허가하거나 거부할 수 있어야 한다.
-프로세스에서 해제된 메모리 내용은 읽을 수 없도록 보호되어야 한다.
-시스템을 사용하는 사람은 반드시 로긴 과정을 거쳐 자신의 신분을 밝혀야 한다.
-관리자는 보안과 관련된 이벤트를 감시할 수 있다.
-운영체제는 스스로 자신의 실행코드를 보호할 수 있어야 한다.
(2)보안실습
-
2.보안설명자
(1)보안설명자
-
[보안오브젝트]
-파일/파이프/콘솔화면버퍼/프로세스/스레드/파일맵핑/액세스토큰/
레지스트리/서비스/프린터/공유폴더/이벤트/뮤텍스/세마포어
(2)SID와 액세스 토큰
-SID : 보안식별자 ,로긴하는 사용자나 그룹에 붙이는 ID
(3)ACL
-보안설명자는 두 개의 ACL을 가지고 있다. 하나는 액세스권한에 대한 목록인 DACL이며
나머지 하나는 감사 기록 작성을 통제하는 SACL이다.
(4)액세스 권한
-ACE의 정보는 누구에게 어떤 액세스 권한을 허가 또는 금지할 것인가를 지정한다.
3.보안 설명자 프로그래밍
(1)GetSecurity
-
#include <windows.h>
#include <aclapi.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass=TEXT("GetSecurity");
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
,LPSTR lpszCmdParam,int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst=hInstance;
WndClass.cbClsExtra=0;
WndClass.cbWndExtra=0;
WndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
WndClass.hInstance=hInstance;
WndClass.lpfnWndProc=WndProc;
WndClass.lpszClassName=lpszClass;
WndClass.lpszMenuName=NULL;
WndClass.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&WndClass);
hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,(HMENU)NULL,hInstance,NULL);
ShowWindow(hWnd,nCmdShow);
while (GetMessage(&Message,NULL,0,0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return (int)Message.wParam;
}
TCHAR gMes[1024]="마우스 왼쪽 버튼을 눌러 보안 정보를 보고자"
" 하는 파일을 선택하십시오";
void GetSecurity()
{
OPENFILENAME OFN;
TCHAR lpstrFile[MAX_PATH]="";
HANDLE hFile;
TCHAR Mes[255];
PSECURITY_DESCRIPTOR pSD;
PSID pOwner;
PACL pDacl;
int i;
DWORD cbName, cbDomain;
TCHAR *Name, *Domain;
SID_NAME_USE peUse;
ULONG nAce;
PEXPLICIT_ACCESS pEntry;
// 대상 파일의 이름을 얻는다.
memset(&OFN, 0, sizeof(OPENFILENAME));
OFN.lStructSize = sizeof(OPENFILENAME);
OFN.hwndOwner=hWndMain;
OFN.lpstrFilter="Every File(*.*)\0*.*\0";
OFN.lpstrFile=lpstrFile;
OFN.nMaxFile=256;
OFN.lpstrInitialDir="c:\\";
if (GetOpenFileName(&OFN)==0) {
return;
}
// 파일을 연다.
hFile=CreateFile(lpstrFile, GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return;
// 파일명을 출력한다.
wsprintf(Mes, "파일명=%s\n", lpstrFile);
lstrcpy(gMes,Mes);
// 보안 설명자를 읽는다.
if (GetSecurityInfo(hFile,SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION,&pOwner,NULL,&pDacl,NULL,
(LPVOID *)&pSD)!=ERROR_SUCCESS) {
MessageBox(hWndMain, "보안 설명자를 읽을 수 없습니다","에러",MB_OK);
return;
}
CloseHandle(hFile);
// 소유자 정보 보여주기
cbName=0;
cbDomain=0;
LookupAccountSid(NULL, pOwner, NULL, &cbName, NULL, &cbDomain, &peUse);
Name=(TCHAR *)malloc(cbName);
Domain=(TCHAR *)malloc(cbDomain);
LookupAccountSid(NULL, pOwner, Name, &cbName, Domain, &cbDomain, &peUse);
wsprintf(Mes, "소유자=%s\n", Name);
lstrcat(gMes,Mes);
wsprintf(Mes, "소유자 도메인=%s\n", Domain);
lstrcat(gMes,Mes);
free(Name);
free(Domain);
// DACL의 정보 보여주기
GetExplicitEntriesFromAcl(pDacl, &nAce, &pEntry);
wsprintf(Mes, "ACE의 개수=%d\n", nAce);
lstrcat(gMes,Mes);
for (i=0;i<(int)nAce;i++) {
cbName=0;
cbDomain=0;
LookupAccountSid(NULL, pEntry[i].Trustee.ptstrName, NULL, &cbName,
NULL, &cbDomain, &peUse);
Name=(TCHAR *)malloc(cbName);
Domain=(TCHAR *)malloc(cbDomain);
LookupAccountSid(NULL, pEntry[i].Trustee.ptstrName, Name, &cbName,
Domain, &cbDomain, &peUse);
wsprintf(Mes, "%s사용자에게 %x 액세스 권한을 %s한다.\n", Name,
pEntry[i].grfAccessPermissions,
pEntry[i].grfAccessMode == GRANT_ACCESS ? "허가":"거부");
lstrcat(gMes,Mes);
free(Name);
free(Domain);
}
// 메모리 해제하고 결과를 화면으로 출력한다.
LocalFree(pEntry);
LocalFree(pSD);
InvalidateRect(hWndMain, NULL, TRUE);
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT crt;
switch (iMessage) {
case WM_CREATE:
hWndMain=hWnd;
return 0;
case WM_LBUTTONDOWN:
GetSecurity();
return 0;
case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);
GetClientRect(hWnd,&crt);
DrawText(hdc,gMes,-1,&crt,0);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
(2)보안설명자 읽기
-
(3)소유자 정보 조사
-LookupAccountSid
(4)DACL 읽기
-GetExplicitEntriesFromAcl
(5)보안설명자 생성
-
#include <windows.h>
#include <aclapi.h>
void SetSecurity();
HINSTANCE g_hInst;
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
,LPSTR lpszCmdParam,int nCmdShow)
{
g_hInst=hInstance;
SetSecurity();
MessageBox(NULL, "보안 설명자를 생성했습니다","알림",MB_OK);
return 0;
}
void SetSecurity()
{
HANDLE hFile;
TCHAR *str="누구나 읽을 수 있으며 User1만 쓸 수 있습니다";
DWORD dwWritten;
EXPLICIT_ACCESS EA[2];
TCHAR pSid[255];
TCHAR pDomain[255];
DWORD cbSid=255,cbDomain=255;
SID_NAME_USE peUse;
PACL pAcl;
SECURITY_DESCRIPTOR SD;
SECURITY_ATTRIBUTES SA;
// Everyone의 SID를 구한다.
SID_IDENTIFIER_AUTHORITY SIDEvery=SECURITY_WORLD_SID_AUTHORITY;
PSID pEverySID;
AllocateAndInitializeSid(&SIDEvery,1,SECURITY_WORLD_RID,0,0,0,0,0,0,0,&pEverySID);
memset(EA,0,sizeof(EXPLICIT_ACCESS)*2);
EA[0].grfAccessPermissions=GENERIC_READ;
EA[0].grfAccessMode=SET_ACCESS;
EA[0].grfInheritance=NO_INHERITANCE;
EA[0].Trustee.TrusteeForm=TRUSTEE_IS_SID;
EA[0].Trustee.TrusteeType=TRUSTEE_IS_WELL_KNOWN_GROUP;
EA[0].Trustee.ptstrName=(LPTSTR)pEverySID;
// User1의 SID를 구한다.
LookupAccountName(NULL,"User1",(PSID)pSid,&cbSid,pDomain,
&cbDomain, &peUse);
// ACE를 만든다.
EA[1].grfAccessPermissions=GENERIC_ALL;
EA[1].grfAccessMode=SET_ACCESS;
EA[1].grfInheritance=NO_INHERITANCE;
EA[1].Trustee.TrusteeForm=TRUSTEE_IS_SID;
EA[1].Trustee.TrusteeType=TRUSTEE_IS_USER;
EA[1].Trustee.ptstrName=(LPTSTR)pSid;
// ACE를 ACL에 포함시키고 새 ACL을 만든다.
SetEntriesInAcl(2,EA,NULL,&pAcl);
// SD를 초기화한다.
InitializeSecurityDescriptor(&SD, SECURITY_DESCRIPTOR_REVISION);
// ACL을 SD에 포함시킨다.
SetSecurityDescriptorDacl(&SD,TRUE,pAcl,FALSE);
// 보안 속성을 만든다.
SA.nLength=sizeof(SECURITY_ATTRIBUTES);
SA.lpSecurityDescriptor=&SD;
SA.bInheritHandle=FALSE;
// 파일을 생성한다.
hFile=CreateFile("c:\\User1Only.txt", GENERIC_ALL, 0, &SA,
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
WriteFile(hFile,str,lstrlen(str),&dwWritten,NULL);
CloseHandle(hFile);
// 실행중에 할당한 메모리를 해제한다.
FreeSid(pEverySID);
LocalFree(pAcl);
}
4.특권
(1)특권의 종류
-
void EnumPrivileges(HDC hdc)
{
int i;
int y=10;
TCHAR buf[255],Mes[255];
DWORD size;
DWORD LangID;
TCHAR arPri[][50]={
SE_CREATE_TOKEN_NAME,SE_ASSIGNPRIMARYTOKEN_NAME,SE_LOCK_MEMORY_NAME,
SE_INCREASE_QUOTA_NAME,SE_UNSOLICITED_INPUT_NAME,SE_MACHINE_ACCOUNT_NAME,
SE_TCB_NAME,SE_SECURITY_NAME,SE_TAKE_OWNERSHIP_NAME,SE_LOAD_DRIVER_NAME,
SE_SYSTEM_PROFILE_NAME,SE_SYSTEMTIME_NAME,SE_PROF_SINGLE_PROCESS_NAME,
SE_INC_BASE_PRIORITY_NAME,SE_CREATE_PAGEFILE_NAME,SE_CREATE_PERMANENT_NAME,
SE_BACKUP_NAME,SE_RESTORE_NAME,SE_SHUTDOWN_NAME,SE_DEBUG_NAME,SE_AUDIT_NAME,
SE_SYSTEM_ENVIRONMENT_NAME,SE_CHANGE_NOTIFY_NAME,SE_REMOTE_SHUTDOWN_NAME
};
for (i=0;i<sizeof(arPri)/sizeof(arPri[0]);i++) {
size=255;
LookupPrivilegeDisplayName(NULL,arPri[i],buf,&size,&LangID);
wsprintf(Mes,"특권=%s,설명=%s",arPri[i],buf);
TextOut(hdc,10,y,Mes,lstrlen(Mes));
y+=20;
}
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (iMessage) {
case WM_CREATE:
hWndMain=hWnd;
return 0;
case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);
EnumPrivileges(hdc);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
(2)시스템 재부팅
-
void MyRebootSystem()
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES |
TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL,"SeShutdownPrivilege",&luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
ExitWindowsEx(EWX_REBOOT,0);
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
TCHAR *Mes="마우스 왼쪽 버튼을 누르면 재부팅합니다";
switch (iMessage) {
case WM_LBUTTONDOWN:
if (MessageBox(hWnd, "지금 재부팅하시겠습니까?","질문",
MB_YESNO) == IDYES) {
MyRebootSystem();
}
return 0;
case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);
TextOut(hdc,50,50,Mes,lstrlen(Mes));
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}