Написание программы «Защита от несанкционированного доступа к файлам»

Страницы работы

Фрагмент текста работы

Теперь мы должны скопировать нашу DLL, которая находится там же где и EMBEDDING.EXE по пути который мы указали в реестре. В случае не имения прав открывать реестр и что-то туда записывать Вас предупредят.

void CembeddingDlg::OnBnClickedButton2()

{

HKEY hk1;

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows",0,KEY_ALL_ACCESS,&hk1)

==ERROR_SUCCESS)

{       

char s[57];     

_tcscpy((char *)&(s[0]), "c:\\WINNT\\System32\\intercpt.dll");

RegSetValueEx(hk1,"AppInit_DLLs",0,REG_SZ,(LPBYTE)s,57);       

RegCloseKey(hk1);        

char *cmd, *str, *stl;

cmd = GetCommandLine();

int path = strlen(cmd);

while (cmd[path] != '\\')

{

cmd[path] = '\0';

path--;           

}

cmd[path+1] = 'i';

cmd[path+2] = 'n';

cmd[path+3] = 't';

cmd[path+4] = 'e';

cmd[path+5] = 'r';

cmd[path+6] = 'c';

cmd[path+7] = 'p';

cmd[path+8] = 't';

cmd[path+9] = '.';

cmd[path+10] = 'd';

cmd[path+11] = 'l';

cmd[path+12] = 'l';

stl = &(cmd[1]);       

int path1 = strlen(stl);   

str = "c:\\winnt\\system32\\intercpt.dll";  

CopyFile(stl,str, FALSE);

}

else

{

MessageBox("Извините у Вас нет прав, обратитесь к администратору.");

return;

}

}

Функция обрабатывающая нажатие на кнопку «Снять защиту». Снова открываем реестр и стираем там путь к нашей DLL.

void CembeddingDlg::OnBnClickedButton3()

{

HKEY hk1;

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows",0,KEY_ALL_ACCESS,&hk1)

==ERROR_SUCCESS)

{         

char s[57];          

_tcscpy((char *)&(s[0]), "");

RegSetValueEx(hk1,"AppInit_DLLs",0,REG_SZ,(LPBYTE)s,2);         

RegCloseKey(hk1);

}

else

{

MessageBox("У Вас нет прав, обратитесь к администратору.");

return;

}

}

Рассмотрим поближе DLL. Называется она intercpt.dll. В ней используется первый метод перехвата API-функций “Перехват API непосредственной записью в код системной функции.”, который был описан выше. Перехватывает она функцию CreateFileA находящуюся с системной библиотеке KERNEL32.DLL

Подключим библиотеки:

#include "stdafx.h"

#include "intercpt.h"

#include "string.h"

#include <stdlib.h>

#include <stdio.h>

Далее подготовим структуру, содержащую код дальнего перехода на нашу функцию-двойник. Практика показала, что вместо обычного jmp лучше применять комбинацию:

push xxxxxxxx 
ret 
 

где хххххххх – это адрес функции-двойника. В результате структура, которая будет хранить нужный код перехода, выглядит так:

struct jmp_far
{
  BYTE instr_push;  //здесь будет код инструкции push
  DWORD arg;         //аргумент push
  BYTE  instr_ret;    //здесь будет код инструкции ret

};

Зададим нужные переменные:

BYTE old[6]; //область для хранения 6-ти затираемых байт начала функции
DWORD adr_CreateFileA //будущий адрес оригинальной функции
DWORD written; //вспомогательная переменная
jmp_far jump; //здесь будет машинный код инструкции перехода

Зададим так же массив под список файлов: char m_Files[90][40]; И это значит что наша система может защищать не более сорока файлов по девяносто символов в каждом файле(пути к файлу).

Если система подключает DLL к какому либо процессу, она сначала вызовет главную функцию DLL с параметром DLL_PROCESS_ATTACH на что мы сразу открываем файл winfs.ini со списком файлов  которые нужно защитить. И вызываем нашу функцию InterceptFunctions, которая произведет подмену стандартной API функции CreateFileA  нашей функцией Intercept_CreateFileA.

ВOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID lpReserved )

{

            if(ul_reason_for_call == DLL_PROCESS_ATTACH )     

                {                        

                    FILE *f;

                    f = fopen("C:\\WINNT\\System32\\winfs.ini","r");

                    if (f == NULL)                     

                    else

                        {

                            c = 0;                    

                            do

                            {

                                fgets(m_Files[c++],90,f);                                                               

                            }

                            while (!feof(f));

                            fclose(f);                      

                            InterceptFunctions();

                        }                    

                }

    return TRUE;

}

Функция, которую мы только что вызвали InterceptFunctions(); и которая выполняет основную хитрость, перехват API перезаписью начальных байт стандартной функции, выглядит следующим образом:

void InterceptFunctions(void)

    adr_CreateFileA = (DWORD)GetProcAddress(GetModuleHandle("KERNEL32.dll"), "CreateFileA");

    if(adr_CreateFileA == 0) 

    {

        Merror("Can`t get CreateFileA");

        return;

    }

    jump.instr_push = 0x68;

    jump.arg = (DWORD)&Intercept_CreateFileA;

    jump.instr_ret = 0xC3;

    ReadProcessMemory(GetCurrentProcess(),(void*) adr_CreateFileA, (void*)&old, 6, &written);   

    WriteProcessMemory(GetCurrentProcess(), (void*)adr_CreateFileA, (void*)&jump, sizeof(jmp_far), &written);

    if(written!=sizeof(jmp_far)) Merror("Unable to write memory");

}

Немного опишу что там происходит. Сначала получаем абсолютный адрес функции для перехвата. Далее зададим машинный код инструкции перехода, который затем впишем в начало полученного адреса. Затем прочитаем и сохраним первые шесть байт стандартной API функции. И наконец запишем команду перехода на нашу функцию поверх этих шести байт.

Теперь посмотрим, как выглядит сама функция-двойник. Она должна заменить стандартную CreateFileA, поэтому её тип и состав параметров должны точно соответствовать оригиналу:

HANDLE WINAPI Intercept_CreateFileA(

LPCSTR lpFileName,

DWORD dwDesiredAccess,

DWORD dwShareMode,

LPSECURITY_ATTRIBUTES lpSecurityAttributes,

DWORD dwCreationDisposition,

DWORD dwFlagsAndAttributes,

HANDLE hTemplateFile)

{

WriteProcessMemory(GetCurrentProcess(), (void*)adr_CreateFileA, (void*)&old, 6, &written); 

bool find = false;

int sdf;

for (int i=0; i < c; i++)

int lp, m_F;     

m_F = strlen(m_Files[i]);    

lp = strlen(lpFileName);           

sdf = strcmp(m_Files[i],lpFileName);

if(m_Files[i][m_F-6] == lpFileName[lp-4])

if(m_Files[i][m_F-7] == lpFileName[lp-5])

if(m_Files[i][m_F-8] == lpFileName[lp-6])

if(m_Files[i][m_F-9] == lpFileName[lp-7])

find = true;

if (sdf == 0)

{

find = true;

break;

}

}   

if (find)

{

MessageBox(NULL,"Нет доступа к файлу","перехват",MB_OK);      

WriteProcessMemory(GetCurrentProcess(), (void*)adr_CreateFileA, (void*)&jump, 6,&written);

return NULL;

}

else

HANDLE hp = ((HANDLE (__stdcall *)(LPCSTR ,

DWORD ,

DWORD ,

LPSECURITY_ATTRIBUTES ,

DWORD ,

DWORD ,

HANDLE ))  adr_CreateFileA)( lpFileName,

dwDesiredAccess,

dwShareMode,

lpSecurityAttributes,

dwCreationDisposition,

dwFlagsAndAttributes,

hTemplateFile);

WriteProcessMemory(GetCurrentProcess(), (void*)adr_CreateFileA, (void*)&jump, 6,&written); 

return hp;

}

}

Теперь подробнее. Сначала восстанавливаем первых шесть байт оригинальной функции что бы можно было ее вызвать. Затем сравниваем параметр lpFileName, передаваемый функции со списком файлов, которые нужно защитить. Если имя хотя бы одного их защищаемых файлов совпало с lpFileName то высылаем окошко – «нет доступа к файлу» и игнорируем вызов функции и открытие файла. Снова заменяем первых шесть байт оригинальной функции, на случай повторного

Похожие материалы

Информация о работе