출처: http://blog.naver.com/blue7red?Redirect=Log&logNo=100054684295

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));
}




AND