Building a Deletion and Access Control Manager

.

Environment: VC++, DDK

Introduction

Deleting files can be both a heaven and a hell. Heaven is when you really need some files deleted to gather some extra space or to clean up the system's disks and you delete them. Hell is when files get deleted because of unforseen instances, such as virus activity.

Some security measures are needed to prevent a hell activity from occurring in the system. Unfortunately, Windows 95 breeds do not provide security for such activities. Hence, if important files, such as source codes, documents, spreadsheets, and so forth -- that could cost a fortune to replace -- get deleted, we can do nothing but be left in dismay. Thus, the system needs to be protected from such hell activities.

We can cherish the files in specific folders and fortunately it is not too difficult to achieve that. All the file system activities pass through a device driver that can be monitored. It is called IFSMGR.VXD (Installable File System Manager). All file monitoring programs hook onto this VxD when it runs, to monitor file activities like Encryption, Virus Sentry, and so on. This Virtual Device Driver is responsible for all the file activities that happen in the system and added to it, it does-low level disk functions, which the Scandisk utility relies on!

Utility Overview

The application that sets the permissions is named "Deletion and Access Control Manager" and it has a Windows Explorer-style interface, as shown in Figure 1. The left side lists the users who can be logged in, and the right side lists the directories they are restricted from using. It has Administrator and Guest access by default. The Administrator has access to all the directories and the Guest has permission only to certain directories. In the current version of this application, I have made it possible to also alter the values of both defaults. You can set the permission to the Administrator or even delete the default users, but I don't recommend doing so; it will cause the device driver to hang.



Click here for a larger image.

The interface and menu items are very simple to use. The users' and directories' setting are separated in the menu. The application uses the file called Protector.Dat for all the permissions and passwords. This has to be in the same directory as the application. Once the logon attributes are set using this utility, the next part is the actual logon application, which is based on the System Tray. If the computer icon in the tray is selected with a left mouse click, the logon displays a simple dialog box to enter a member name and password. The initial logon member is the Guest by default. The password is set using the permission-setting application. Any changes made after the logon utility is loaded using the permission application will not be reflected in the logon until the next loading. The device driver communicates with the logon application and logs in the user if it can; otherwise, it denies a login.

Then comes Deletion Protected Paths in the tree view, which is the entry showing all the paths that are protected from deletion. If any permanent deletion happens in one of the folders mentioned in the list, the login application displays a dialog box enquiring for a password for the specific folder. This way, all the files in the folders listed are protected. Remember that Access restriction has the higher hierarchy over deletion control; this means that if you list a directory in access protection, and then if you list the same directory for deletion also, the folder is access denied. So you would not access the folders if both attributes are given for a path. All the file operations, such as open file, rename, delete, and so forth, have their access blocked, whereas only deletion is protected in the deletion protection.

The login application is set up by the Setup.exe application, to be started at boot time itself if you have selected to do so. Otherwise, you should manually select the login application from the Start menu. However, once you set up for boot-time loading, which is safer, you can rest assured that no files in the specified folder are deleted. The important files range from simple MPEG 3 music files to important documents and spreadsheets, which can be easily protected using this application. However, it works only in Windows 95 breeds. And one more important thing that I would like to mention is that if you access deny the Windows folder, you will have problems loading the Registry, to simple ding-ding sounds, and will cause a system crash very soon. So, avoid the Windows folder in this application except that you can deletion-control it.

The important extensions can only be protected from deletion. This can be configured using the Deletion menu. This means that the temporary file creation and deletion will not cause a trap while deletion controlling a folder. You can also add the recycle bins to the deletion control, which makes it safe while the bin is being flushed because it causes a trap. However, the main idea for this utility is to control any unknown deletion in the system and not be a complete deletion control system.

The Login application has two dialog boxes, one for logging in the user and other for deleted files queueing for password enquiry. I have handled one in a thread, which is the user logging process. Thus, two threads will be running in the logging in application.

The password for activating the applications is "admin". So, for starting the permission-setting application, or for unloading or uninstalling the application, it is the same. To install the application, simply run Setup.exe.

Programming

The Ring 3 login application and the device driver communicate between themselves, using a PostMessage service available in Windows 95 -- which is _SHELL_PostMessage, used for communicating from the driver to the Ring 3 application. This service posts a message to our login window while a file is deleted; this handles the request by issuing a DeviceIoControl API to get the file name. This way, we communicate between the device driver and the login application. The VxD's hook procedure looks like the following:

int   _cdecl OurFileHook(pIFSFunc pfn, int nFunction, int nDrive, \
      int nResources, int Cp, pioreq pir)
{
    int iRet;
    unsigned long fHan;
    DWORD pAction;
    DWORD iLen;

    iRet=0;
    switch(nFunction){
        case IFSFN_OPEN:
        case IFSFN_RENAME:
        case IFSFN_DIR:
          if(AlreadyInside==1)
            break;
          if(pir->ir_options & OPEN_FLAGS_REOPEN)
            break;
          AlreadyInside = 1;

          if((nDrive & 0xFF) != 0xFF){
             FileNm[0]= nDrive + '@';
             FileNm[1]=':';
             iLen=2;
             iLen+=UniToBCSPath(&FileNm[2], \
                 pir->ir_ppath->pp_elements, MAX_PATH, BCS_OEM);
          }
          else{
             iLen=FormNetPath(FileNm, pir);
          }
          if(ComparePath(FileNm) == FALSE){
             iRet=(*(*ppPrevHook))(pfn, nFunction, nDrive, nResources \
                , Cp, pir);
             AlreadyInside=0;
              return iRet;   //Do the normal work
          }
          else{

             iRet = 5;
             pir->ir_error = 5; //If path protected "access denied"
             AlreadyInside=0;
             return iRet;
          }
          AlreadyInside=0;
          break;
        case IFSFN_DELETE:
          if(AlreadyInside==1)
             break;
          AlreadyInside = 1;
          if((nDrive & 0xFF) != 0xFF){
             FileNm[0]= nDrive + '@';
             FileNm[1]=':';
             iLen=2;
             iLen+=UniToBCSPath(&FileNm[2], \
                pir->ir_ppath->pp_elements, MAX_PATH, BCS_OEM);
          }
          else{
             iLen=FormNetPath(FileNm, pir);
          }
          if(ComparePath(FileNm) == TRUE){
             iRet = 5;
             pir->ir_error = 5; //If path protected "access denied"
             AlreadyInside = 0;
             return iRet;
          }
          if(CompareDeletePath(FileNm)==FALSE){
            iRet=(*(*ppPrevHook))(pfn, nFunction, nDrive, nResources, \
                Cp, pir);
             AlreadyInside = 0;
             return iRet;   //Do the normal work
          }
          else{
             if(((DWORD)DeleteFreeBuffer - (DWORD)DeleteFileBuffer)> \
                MIN_LIMIT){
            //If buffer fill exceeds minimum limit, free the memory
                if(DeleteFilesProcessed == DeleteFiles){
//If all the files have been processed by Ring 3, just set the
//pointer to the start.
                   DeleteFilePtr = DeleteFreeBuffer = \
                           DeleteFileBuffer;
                }
                else{  //Else move the required buffer to the top
                   int Tmp = (int)DeleteFreeBuffer - \
                           (int)DeleteFilePtr;
                   unsigned char *TmpPtr, *TmpPtr1;
                   for(TmpPtr=DeleteFileBuffer, TmpPtr1= \
                           DeleteFilePtr; Tmp>0; Tmp--){
                      *(TmpPtr++) = *(TmpPtr1++);
                   }
//Move the memory fully to the top of buffer
                   DeleteFreeBuffer -= (DeleteFilePtr - \
                        DeleteFileBuffer);
                   DeleteFilePtr = DeleteFileBuffer;
                }
             }
             strcpy(DeleteFreeBuffer, FileNm);
             DeleteFreeBuffer += strlen(FileNm) + 1;
             DeleteFiles++;
             PostMessageAsm(hWnd, FILE_BEING_DELETED, 0, 0, NULL, 0);
             iRet = 0;
             pir->ir_error = 0;       //If the path is deletion
             \\protected return false success
             AlreadyInside = 0;
             return iRet;
          }
          AlreadyInside = 0;
          break;
    }
    iRet=(*(*ppPrevHook))(pfn, nFunction, nDrive, nResources, Cp, pir);
    return iRet;
}

The files that are being deleted are stored in a buffer and the caller is returned with the mark of success. This way we simply trick the system into thinking that the deletion operation was successful. Then, we call the login application by sending a message to it. The login application handles this message and issues a DeviceIoControl API to get the file name that is to be deleted. The full path is passed on to the login application. The buffer is adjusted if it overflows the memory buffer; then this process continues until all the messages have been processed by the Ring 3 login application. The login application displays a dialog box for the deleted files, one by one, and it requires a password. If the correct password for the folder is given, it then deletes the file. This is done by first turning off the driver and calling the DeleteFile API. This is because we will cause a deadlock if the driver is again sent a message to delete the same file.

The above mentioned process is described in the following piece of code:

  case FILE_BEING_DELETED:{
      PUCHAR ExtsPtrTmp = ExtsPtr;
      if(!DeviceIoControl(hCVxD, FILE_DELETE_EXTRACT,
                          (LPVOID)0, 0,
                          (LPVOID)DelePathBuffer, 4,
                          &cbBytesReturned, NULL)){
         MessageBox(NULL, "Unable to extract!" ,
                    "Deletion & Access Control Manager Login",
                    MB_OK|MB_ICONEXCLAMATION);
         return FALSE;
      }
      PUCHAR TmpPtr = (PUCHAR)(DelePathBuffer + \
                      strlen(DelePathBuffer));
      while(*(TmpPtr--)!='\\')
        ;
      while((*(TmpPtr)!= '.') && *TmpPtr)
        TmpPtr++;
      if(*TmpPtr){
        TmpPtr++;
        while(*(BYTE *)ExtsPtrTmp != 0xFF)
        {
            if(stricmp((char *)TmpPtr, (char *) ExtsPtrTmp)==0)
               break;
             ExtsPtrTmp += strlen((char *) ExtsPtrTmp) + 1;
         }
      }
      if(*ExtsPtrTmp != 0xFF){
        ShowWindow(hWnd, SW_SHOW);
        SendMessage(GetDlgItem(hWnd, IDC_DELETION), \
                               LB_ADDSTRING, 0, \
                               (LPARAM)DelePathBuffer);
        SendMessage(GetDlgItem(hWnd, IDC_DELETION), \
                               LB_SETCURSEL, 0, 0);
        SetForegroundWindow(hWnd);
      }
      else{
        DWORD AlreadyInside = 1;
        if(!DeviceIoControl(hCVxD, DRIVER_TEMP_CLOSE,
                            (LPVOID)&AlreadyInside, 4,
                            (LPVOID)0, 0,
                            &cbBytesReturned, NULL)){
            MessageBox(NULL,\
                    "Unable to switch off Driver!",
                    "Deletion & Access Control Manager Login", \
                    MB_OK|MB_ICONEXCLAMATION);
            return FALSE;
        }
        SetFileAttributes(DelePathBuffer, 0);
        DeleteFile(DelePathBuffer);
        AlreadyInside = 0;
        if(!DeviceIoControl(hCVxD, DRIVER_TEMP_CLOSE,
           (LPVOID)&AlreadyInside, 4,
           (LPVOID)0, 0,
           &cbBytesReturned, NULL)){
           MessageBox(NULL,
                     "Unable to switch on Driver!",
                     "Deletion & Access Control Manager Login", \
                     MB_OK|MB_ICONEXCLAMATION);
           return FALSE;
        }
      }
      break;
    }

Because we cannot pass on a Ring 0 pointer to Ring 3, we need the extra DeviceIoControl to extract the path/filename which lets the device driver get the Ring 3 pointer and copy the file name into that buffer and return. This way, we communicate between the device driver and the login application. Once we are in the login application, we can do as we wish with any enhanced GUI screen, but here I have only provided a simple list box.

This is how we load the Ring 3 pointer with the file name of the deleted file:

DWORD _stdcall ExtractDeleteFile(DWORD dwDDB, DWORD hDevice, \
        LPDIOC lpDIOCParms)
{
  PDWORD pdw;
  DWORD FilePtr;
    pdw = (PDWORD)lpDIOCParms->lpvOutBuffer;
  FilePtr = pdw;
  strcpy(FilePtr, DeleteFilePtr);
  DeleteFilePtr += strlen(DeleteFilePtr) + 1;
  DeleteFilesProcessed++;
  return 0;
}

The deleted files are acknowledged this way as being successful and they are added in the Ring 3 list box. The Ring 3 application keeps on enquiring for a password for each file and deletes the file in the top of list box one by one until all the files have been deleted. This way, deletion is controlled using the Ring 0 program. Note that here we have a variable called AlreadyInside. This means that if this variable is set to nonzero, the device driver becomes inactive; this allows switching off the driver momentarily. There is no way to wait for the Ring 3 thread to complete and for us to get the notification at Ring 0, so we adopt this method. Moreover, Ring 0 should not wait for a Ring 3 thread to complete before continuing; hence, we allow Ring 0 to proceed with a false success.

The following is the Ring 3 code for handling the real file deleting from the list box. The files are deleted if you give the correct password; otherwise, all the files are skipped and not deleted.

case IDOK:
                    SendMessage(GetDlgItem(hWnd, IDC_DELETION), \
                            LB_GETTEXT, 0, (LPARAM)FirstFilePath);
  GetDlgItemText(hWnd, IDC_DELEPASSWORD, PassStr, 50);
  for(i=0; i<strlen(PassStr); i++){
    Checksum += PassStr[i];
  }
  if(Checksum!=ExtractDeletePathPassword(FirstFilePath)){
                            MessageBox(hWnd, \
"Incorrect password!  Cannot delete the file", \
"Deletion & Access Control Manager", MB_OK|MB_ICONEXCLAMATION);
                            SendMessage(GetDlgItem(hWnd, IDC_DELETION), \
                                    LB_RESETCONTENT, 0, 0);
  }
  else{
    DWORD AlreadyInside = 1;
    if(!DeviceIoControl(hCVxD, DRIVER_TEMP_CLOSE,
        (LPVOID)&AlreadyInside, 4,
        (LPVOID)0, 0,
        &cbBytesReturned, NULL)){
           MessageBox(NULL, \
           "Unable to switch off Driver!", \
           "Deletion & Access Control Manager Login",
           MB_OK|MB_ICONEXCLAMATION);
               return FALSE;
    }
    SetFileAttributes(FirstFilePath, 0);
    DeleteFile(FirstFilePath);
    AlreadyInside = 0;
    if(!DeviceIoControl(hCVxD, DRIVER_TEMP_CLOSE,
        (LPVOID)&AlreadyInside, 4,
        (LPVOID)0, 0,
        &cbBytesReturned, NULL)){
      MessageBox(NULL, \
                 "Unable to switch on Driver!", \
                 "Deletion & Access Control Manager Login",
                 MB_OK|MB_ICONEXCLAMATION);
        return FALSE;
    }
    SendMessage(GetDlgItem(hWnd, IDC_DELETION), \
                LB_DELETESTRING, 0, 0);
    SendMessage(GetDlgItem(hWnd, IDC_DELETION), \
                LB_SETCURSEL, 0, 0);

  }
  if((int)SendMessage(GetDlgItem(hWnd, IDC_DELETION), \
                      LB_GETCOUNT, 0, 0)<=0)
  ShowWindow(hDlg, SW_HIDE);
  break;

There are three data files used by these applications and device driver: Protector.dat, DeleProt.dat, and Exts.dat. The first two are used by the device driver, but Exts.dat is used by the login application for filtering the extensions that are to be protected.

Protector.dat contains folders for access restrictions and the entire file has the following format:

ASCIIZ  UserName  = Null terminated user name
WORD    Password  = Simple Checksum of the Password
ASCIIZ  Path[n]   = Null terminated strings of paths 
                    terminated by a extra 0 for end of user

DeleProt.dat is the file containing all the folders that are deletion protected and the entire file has the following format:

ASCIIZ Path     = Contains a single folder
WORD   Password = Contains the checksum of the 
                  password characters (Case Sensitive)

Exts.dat is the file containing all the extensions that are to be protected by the application in the folders mentioned in DeleProt.dat. It has a simple format:

ASCIIZ Extension = Contains a single extension

If you are using Windows Explorer, the files, when deleted, will appear as though they have been deleted from the predefined folder, but in reality they are not deleted. This can be proved; if you refresh the explorer screen, the files will reappear. But all the files that you deleted will appear in the deletion list box for you to delete one by one. Remember that once the hook is placed, any delete anywhere within Windows will be reflected in Ring 0 and will ensure that the dialog box for deletion pops up. This also includes the DOS prompt within Windows. If you manually DEL certain files, it will also appear here; even a DELTREE pops up the dialog box, but with some strange results. The files in the folder appear deleted, but finally the collapse of the branch cannot happen (which of course uses RD -- Remove Directory) because there actually are files in the folder. This means that the protected directory cannot be collapsed just like that. This is the true protecting nature of this utility.

Conclusion

All in all, this utility will be very useful for controlling deletion on your machines. Whether it is MPEG 3 music files or highly valuable documents like mails and spreadsheets, they can be deleted in a controlled way. So, you can rest assured that the files are safe and sound from any digital attacks or accidents.

Downloads

Download source -- 51 KB



About the Author

Vinoj Kumar

I have been programming for the past 16 years. I started programming in 1990. I came to Windows in 1993. I have authored a book called, "Classic Utilities Using Assembly Language" , 1995. In my free time I listen a lot to Kenny G sax all the albums and Valentine Classics Songs. I like to watch a lot of TinTin adventure Comics. I am currently working in K7 Computing antivirus company (www.k7computing.com) as Senior Technical Lead. My contact is: Phone: +91 944 411 7353

Comments

  • Need help

    Posted by kmashif on 03/09/2004 09:25am

    This article is excellent, but i could not run this project..How can i control the access to any text file, only my program should access the locked file..please help me as soon as possible..Ashif

    Reply
  • Resources Missing in HideDir zip

    Posted by Legacy on 02/24/2004 12:00am

    Originally posted by: L.Ravikumar

    I am a Final Year CSE Student working for my project in File Watcher Component. I was Looking For an Deletion And Access control manager type program and i saw yours. I downloaded the source file and started building in VC++. but errors occured as

    1. Resource rc2 and rc1 missing not found
    2. .bmp files missing

    could you please send me the full working code again as i needed it very soon.

    thank you
    bye for now

    Reply
  • how to copy any file into new created folder

    Posted by Legacy on 01/27/2004 12:00am

    Originally posted by: Nasir

    please help me that how we can copy any existing file in new created folder

    Reply
  • Request from engineering students

    Posted by Legacy on 03/22/2003 12:00am

    Originally posted by: abishek

    We are a group of undergraduate students doing our final year B.E in Information Science & Engineering (ISE),BMS College of Engineering, Bangalore, India.
    
    We happened to come across the product that you developed namely "Deletion and Access Control Manager" which is available on the technical website "www.codeguru.com". We are novices to Windows Programming and have started using VC++ very recently.

    We faced number of problems running the product: -
    1. The source that we downloaded did not contain the "setup.exe"
    that is needed to install the product.
    2. The sample dat files namely "Protector.dat", "DeleProt.dat", "Exts.dat" are missing.
    3. Understanding the code in the vxd folder that we downloaded.

    We are required to develop a similar product as part of our final semester project the only major difference being that the password dialog that pops up during accessing the system is replaced by a request for a "Finger-Print Scan" thereby introducing biometrics so as to supplement authorization.

    We would be extremely grateful if you can take the trouble of sending us a detailed documentation on the product that you have developed and also suggest the relevant books/sources of information to refer especially those regarding: -
    1.) Creating and hooking onto VXDs.
    2.) Usage of hooks.
    3.) Concepts related to ring 0, ring 3 etc.

    I hope you will be kind enough to share the required information and assist us in the appropriate way at the earliest so that we shall be able to accomplish the first part of our project.

    Regards,
    B. A. Abishek (abi369@yahoo.com)
    R. Ugandhar Reddy (reddyist@yahoo.com)
    Abhijit S. Mane (abhijitsmane@yahoo.com)

    Reply
  • File manipulation

    Posted by Legacy on 10/13/2002 12:00am

    Originally posted by: SEB

    I am looking for a sample code that replaces a string.
    ex. file.txt contains "I have a big dog"
    program search for word "big" and replaces it with "small"
    Any help will be greatly appreciated
    using VC++

    Reply
  • Send me the sample .dat files

    Posted by Legacy on 09/19/2002 12:00am

    Originally posted by: Hitesh Jain

    hi
    please send me the three .dat files if u can?
    Although I'm trying to write it in the given format, but it fails.

    Reply
  • Deletion Manager

    Posted by Legacy on 07/24/2002 12:00am

    Originally posted by: Sergio Perez

    Please could you tell me where find the hidedir files ?
    thank's we are students and we are been thankful about your work.

    Sergio.

    Reply
  • Do you support such cases as FILE_DELETE_ON_CLOSE and overwrite during rename?

    Posted by Legacy on 06/04/2002 12:00am

    Originally posted by: Valery A. Boronin

    well, but what about NT kernel driver? :)

    Reply
  • It does not work on NT

    Posted by Legacy on 05/30/2002 12:00am

    Originally posted by: Shrishail Rana

    It does not work on NT Based systems. will like to port the code on NT based system

    Reply
  • Resources missing in the HideDir (or DeleteMgr) project (?)

    Posted by Legacy on 05/30/2002 12:00am

    Originally posted by: Zi�

    Maybe i'm not able to find them, but
    in the HideDir (DeleteMgr) project resources are missing
    (the entire Res subfolder is missing).

    Could you please update the zip files?

    Thank you.

    Zi�.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • On-demand Event Event Date: October 29, 2014 It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this webcast, Gene Kim discusses these survey findings and shares woeful tales of artifact management gone wrong! Gene also shares examples of how high-performing DevOps …

Most Popular Programming Stories

More for Developers

RSS Feeds