ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2

ANTICHAT — форум по информационной безопасности, OSINT и технологиям

ANTICHAT — русскоязычное сообщество по безопасности, OSINT и программированию. Форум ранее работал на доменах antichat.ru, antichat.com и antichat.club, и теперь снова доступен на новом адресе — forum.antichat.xyz.
Форум восстановлен и продолжает развитие: доступны архивные темы, добавляются новые обсуждения и материалы.
⚠️ Старые аккаунты восстановить невозможно — необходимо зарегистрироваться заново.
Вернуться   Форум АНТИЧАТ > Программирование > Реверсинг
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

EncodePointer
  #1  
Старый 19.11.2008, 21:39
0x0c0de
Постоянный
Регистрация: 25.05.2007
Сообщений: 448
Провел на форуме:
4226446

Репутация: 1564
Отправить сообщение для 0x0c0de с помощью ICQ
По умолчанию EncodePointer

[EncodePointer].

*my system: Windows XP SP3 [тестила и на win xp2 то же]

Пишу сию небольшую заметочку про EncodePointer. Статьей это => не является.

Некогда довелось мне заниматься VEH и писать плаг под Olly, перебирающий все обработчики в дебажимом процессе. И функция EncodePointer создала мне на системах с SP (в виндах без СП, как выяснилось этой функции нет вовсе) некоторые проблемы и при получении адреса вех-обработчика я извращалась с трейсом.
Как вы можете прочесть в msdn

Цитата:
The EncodePointer function encodes the specified pointer. Encoded pointers can be used to provide another layer of protection for pointer values.
PVOID EncodePointer(
PVOID Ptr
);
Здесь все предельно понятно. И вех-обработчики в системах с SP как раз-таки подвергаются такой обработке.
Функция шифрует адрес Ptr неким значением, уникальным для каждого процесса. Теперь попробуем разобраться в общих чертах как оно работает и откуда это значение берется.

Код функции RtlEncodePointer

Код:
 
7C9133DF ntdll.RtlEncodePointer            /$  8BFF                      MOV EDI,EDI                                                ;  ntdll.7C910208
7C9133E1                                   |.  55                        PUSH EBP
7C9133E2                                   |.  8BEC                      MOV EBP,ESP
7C9133E4                                   |.  51                        PUSH ECX                                                   ;  ntdll.7C9164EE
7C9133E5                                   |.  6A 00                     PUSH 0                                                     ; /pReqsize = NULL
7C9133E7                                   |.  6A 04                     PUSH 4                                                     ; |Bufsize = 4
7C9133E9                                   |.  8D45 FC                   LEA EAX,[LOCAL.1]                                          ; |
7C9133EC                                   |.  50                        PUSH EAX                                                   ; |Buffer = NULL
7C9133ED                                   |.  6A 24                     PUSH 24                                                    ; |InfoClass = 24 (36.)
7C9133EF                                   |.  6A FF                     PUSH -1                                                    ; |hProcess = FFFFFFFF
7C9133F1                                   |.  E8 EAA3FFFF               CALL ZwQueryInformationProcess                             ; \ZwQueryInformationProcess
7C9133F6                                   |.  8B45 FC                   MOV EAX,[LOCAL.1]
7C9133F9                                   |.  3345 08                   XOR EAX,[ARG.1]
7C9133FC                                   |.  C9                        LEAVE
7C9133FD                                   \.  C2 0400                   RET 4
То есть мы вызываем ZwQueryInformationProcess с InfoClass = SystemContextSwitchInformation (36) и ксорим с адресом, переданным функции в качестве аргумента. Ясное дело, что в ntdll более нам делать нечего, надо спускаться в ядро и смотреть откуда берется этот уникальный дворд.
Загружаем ntoskrnl.exe в IDA и смотрим функцию NtQueryInformationProcess. Весь код функции, приводить, конечно, не буду, ибо нет смысла. Выделю только основные моменты. Найдем то место в функции, которое обрабатывает InfoClass = SystemContextSwitchInformation = 36 = 0x24


Код:
PAGE:0049CEFA                 mov     eax, [ebp+ProcessInformationClass]
PAGE:0049CEFD                 push    16h
PAGE:0049CEFF                 pop     ecx
PAGE:0049CF00                 cmp     eax, ecx
PAGE:0049CF02                 jg      loc_4A0E7F
PAGE:0049CF08                 jz      loc_4A1379
Ну тут ясно, что в eax в нашем случае (0049CF00) будет 24h, а в ecx 16h. Значит нам по адресу loc_4A0E7F.

Код:
loc_4A0E7F:                             ; CODE XREF: NtQueryInformationProcess(x,x,x,x,x)+53
PAGE:004A0E7F                 add     eax, -17h       ; switch 15 cases
PAGE:004A0E82                 cmp     eax, 0Eh
PAGE:004A0E85                 ja      Invalid_InfoClass ; default
PAGE:004A0E8B                 jmp     ds:off_4A18CA[eax*4] ; switch jump
Мысленно(или на калькуляторе %) ) eax(==24h) +(-17h). Получаем 0D. Далее
Выполняем джамп (при eax = 0d)

Код:
PAGE:004A0E8B                 jmp     ds:off_4A18CA[eax*4]
Попадаем сюда

Код:
PAGE:004A0E92 SystemContextSwitchInformation_0:       ; DATA XREF: PAGE:off_4A18CA o
PAGE:004A0E92                 cmp     edi, edx        ; case 0x24
PAGE:004A0E94                 jnz     InfoLengthMismatch
PAGE:004A0E9A                 cmp     [ebp+Handle], 0FFFFFFFFh
PAGE:004A0E9E                 jnz     not_current_process

Обратите внимание на сделанное мной обозначение. То есть, если передан хендл не текущего процесса, то

Код:
PAGE:004A1578 not_current_process:                    ; CODE XREF: NtQueryInformationProcess(x,x,x,x,x)+3FEF j
PAGE:004A1578                                         ; NtQueryInformationProcess(x,x,x,x,x)+46BA j ...
PAGE:004A1578                 mov     eax, STATUS_INVALID_PARAMETER
Ну оно и верно. Если бы этот дворд можно было получить из другого процесса, было бы странно. Теперь продолжим. Если мы интересуемся своим процессом

Код:
PAGE:004A0EA4                 mov     eax, large fs:124h
PAGE:004A0EAA                 mov     eax, [eax+44h]
PAGE:004A0EAD                 mov     [ebp+var_34], eax
PAGE:004A0EB0 get_dw:                                 ; CODE XREF: NtQueryInformationProcess(x,x,x,x,x)+18E71 j
PAGE:004A0EB0                 mov     edi, [ebp+PEPROCESS]
PAGE:004A0EB3                 add     edi, 258h
PAGE:004A0EB9                 mov     eax, [edi]
PAGE:004A0EBB                 test    eax, eax
PAGE:004A0EBD                 jz      get_time

Некоторым первые строки покажутся очень знакомыми. В eax после их исполнения окажется указатель на структуру EPROCESS текущего процесса. Далее мы добавляем к началу EPROCESS 258h. И берем по этому адресу dword.

Если значение нулевое, то

Код:
PAGE:004A0EBB                 test    eax, eax
PAGE:004A0EBD                 jz      get_time
Получаем системное время

Код:
PAGE:004B5CF6 get_time:                               ; CODE XREF: NtQueryInformationProcess(x,x,x,x,x)+400E j
PAGE:004B5CF6                 lea     eax, [ebp+CurrentTime]
PAGE:004B5CF9                 push    eax             ; CurrentTime
PAGE:004B5CFA                 call    _KeQuerySystemTime@4 ; KeQuerySystemTime(x)
PAGE:004B5CFF                 mov     eax, large fs:_KPRCB
PAGE:004B5D05                 mov     ecx, [eax+_KPRCB.KeSystemCalls]
PAGE:004B5D0B                 xor     ecx, [eax+_KPRCB.InterruptTime]
PAGE:004B5D11                 xor     ecx, [ebp+CurrentTime.HighPart]
PAGE:004B5D14                 xor     ecx, [ebp+CurrentTime.LowPart]
PAGE:004B5D17                 xor     eax, eax
PAGE:004B5D19                 lock cmpxchg [edi], ecx
PAGE:004B5D1D                 push    4
PAGE:004B5D1F                 pop     edx
PAGE:004B5D20                 jmp     get_dw
И дубль 2 =) Пробуем снова получить дворд…
Смотрим описание функции KeQuerySystemTime

Цитата:
The KeQuerySystemTime routine obtains the current system time.
VOID
KeQuerySystemTime(
OUT PLARGE_INTEGER CurrentTime
);


Теперь мы знаем откуда берется это значение и можно написать драйвер, который по id процесса будет возвращать уникальный дворд. Использовать NtQueryInformationProcess мы не можем напрямую, поэтому просто осуществим аналогичные действия (начиная с метки get_timе я опустила, ибо лень, могу сказать, что все корректно определяется). И соответственно программа, которая этот драйвер использует. В самом драйвере пишем

Код:
ULONG ProcessDwordByProcessId(ULONG piD)
{
ULONG dwDbg;
PEPROCESS cproc;
if(NT_SUCCESS(PsLookupProcessByProcessId(piD,&cproc)))
	 {
	_asm{
	mov edi,cproc
	add edi,0x258 
	mov edi,dword ptr[edi]
	mov dwDbg,edi
	    }
return dwDbg;
}
return 0;

}
В вызывающей программе

Код:
DWORD GetPrDword(DWORD pID){
//Аргумент - id процесса
DWORD mag=0,BytesReturned=0;
	if( !DeviceIoControl(hHandle,IOCTL_GET_PROCESS_DWORD,&pID, 4,&mag,4,&BytesReturned,	NULL ))
	{
		printf("Error in DeviceIoControl\n");
		return 0;
	}
// возвращаемое значение - process dword
return mag;
}
Скрин

http://img56.imageshack.us/my.php?image=23297865ee9.jpg

Program

http://rapidshare.com/files/165383629/tst.rar.html
 
Ответить с цитированием
Ответ





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ