Есть программа которую надо защитить. У этой программы по конкретному адресу в памяти надо не дать чужим программам менять "jl" на "jmp". Как это реализовать без использования дров ? В голову приходит только один метод - каждую секунду проверять этот адрес.. Есть-ли другие способы решения данной проблемки? Звучит фантастически, но могет вожможно сместить этот адрес куда-нить другое место ?
Теоретически можно перебазировать сегмент кода где-нибудь по-тихому, а потом обращаться с учетом смещения, и адрес, который будет виден в дизассемблере, не будет соответствовать реальному линейному, можно почитать тут немного.
Перемещать бесполезно. Если прога чемто защищена (запакована), то реверсироваться будет дамп. Так что остается только постоянно считать контрольную сумму своего кода в памяти, и надеяться что код который эту сумму сравнивает не найдут.
Velheart У меня тоже когдато была эта идея. Оказывается вызов сервиса через Sysenter(KiFastCallEntry), либо Int2e(KiSystemService) восстановит при возврате все сигментные регистры в нормальные значения. Поток сможет обращаться к защищённой памяти только до вызова любого сервиса. Как вариант - необходимо перезагружать контекст(сег. регистры) по возврату из сервиса. Если он юзается через Sysenter(KiFastCallEntry), проблем не будет, так как адрес возврата не зависит от адреса Sysenter. По дефолту она и юзается. Просто перехватить KiFastSystemCallRet, либо подменить адрес возврата. Энди ну это ты сам хорошо знаешь. Если юзаетсь Int2e то есть проблема. Обычно приложение может юзать KiIntSystemCall(), тогда тут перехват очевиден. Но приложения юзающие 2е шлюз инструкция вызова которого отличается от KiIntSystemCall - тут могут появиться проблемы. Возврат из прерывания выполняется на следующую инструкцию. Поэтому если ты его юзаешь стави после Int2e инструкцию перехода на хэндлер(если макро то удобно). Хэндлер будет перезагружать контекст. GoldFinch Не бесполезно, дизасмом это не разобрать. Есть функция MmSecureVirtualMemory, один из теневых сервисов позволяет её заюзать, тока не помню какой. Но это наверно не то, защитит память от удаления и изменения прав доступа.
Clerk, не совсем понял Речь не антихуковских трюках.. если я правильно понял тебя.. А о том что, есть по статистическому адресу 01D60127h - инструкция "jl" Любая иная программа делав вот так Код (Text): mov byte ptr [JmpBuf],0ebh ;jmp invoke ZwWriteVirtualMemory,ProcessHandle,01D60127h,addr JmpBuf,1,0 смогет изменить jl на jmp. Как этого защитится
Clerk И действительно, прикольно, а в каком месте это происходит, если не секрет, ну т.е. в KiServiceExit вроде бы достаются из стека сегментные регистры, которые там вроде как должны сохраняться, или я чего-то не догоняю/не замечаю ? UPD: все, посмотрел сисером, он действительно жестко забивает в ds, es 23h, но cs - то по идее должен восстанавливаться...
Flasher Советую глянуть в сторону ВМ протов (например VMP). При этом никаких дров и сложность реверсинга.
Velheart Flasher Не правильно понял. Хук чтобы восстанавливать сегментные регистры. Velheart Восстанавливается в EXIT_ALL. Загружается в ENTER_SYSCALL.
Может баян, и точно оффтоп ), заметил странную штуку: при трассировке в сисере такой вот фигни: Код (Text): LDT_Entry dw 0ffffh db 0,10h,40h db 11111010b db 11000000b db 0 ntdll db "ntdll", 0 NtSetLdtEntries db "NtSetLdtEntries",0 NtClose db "NtClose", 0 .code start: invoke GetModuleHandle, offset ntdll push eax invoke GetProcAddress, eax, offset NtSetLdtEntries push 0 push 0 push 0 push dword ptr [LDT_Entry+4] push dword ptr [LDT_Entry] push 1111111b call eax pop eax invoke GetProcAddress, eax, offset NtClose ;push cs push 01111111b push offset lbl - 401000h retf lbl: nop mov eax, 19h ; NtClose mov edx, 7FFE0300h ; sub edx, 401000h ;Если раскомментировать -- будет бсод при трассировке в Сисере ;call edx call wer wer: mov edx, esp db 0fh, 34h ;sysenter end start выскакивает бсод при попытке call edx, а еще когда-то замечал, что если в коде каллгейта в ядре поставить в сисере брэйк, то после "отпускания" по ф5 тоже бсод..
Velheart Странно очень, позже проверю. Тут шлюзы вызовов не причём, если юзается калгейт с установленным TF в юзермоде то конечно будет бсод, ибо начинает исполнятся код с DPL=0, а хэндлер исключений не установлен. Походу это кривые хуки сисера. Стоит взглянуть. Посмотри аварийный дамп, почему падает и поставь на оригинальный хэндлер исключений(Int ?) бряк в сисире, чтобы узнать контекст и стек сразу после исключения. Условие для точки останова: (PID == #).]
Clerk Вот что выяснил: бсодит только при обращении к 7FFE0300h и близлежащим адресам, это же вроде бы и есть shared memory, или я что-то путаю? Эксепшн происходит в ядре, в обработчике 0хd прерывания(upd: выяснил, что не знал=) ) припопытке /*тут наврал сначала*/ читать по адресу 0x51, а это -- eip инструкции jmp edx, которая все и бсодит. вот анализ: Код (Text): Microsoft (R) Windows Debugger Version 6.8.0004.0 X86 Copyright (c) Microsoft Corporation. All rights reserved. Loading Dump File [D:\WinRvrs\MEMORY.DMP] Kernel Summary Dump File: Only kernel address space is available Symbol search path is: srv*d:\symbols*http://msdl.microsoft.com/download/symbols Executable search path is: C:\windows Windows XP Kernel Version 2600 (Service Pack 2) UP Free x86 compatible Product: WinNt, suite: TerminalServer SingleUserTS Built by: 2600.xpsp_sp2_rtm.040803-2158 Kernel base = 0x804d7000 PsLoadedModuleList = 0x805531a0 Debug session time: Fri Oct 10 12:05:17.178 2008 (GMT+3) System Uptime: 0 days 18:52:59.671 Loading Kernel Symbols ............................................................................................................ Loading User Symbols PEB is paged out (Peb.Ldr = 7ffdf00c). Type ".hh dbgerr001" for details Loading unloaded module list ... ******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* Use !analyze -v to get detailed debugging information. BugCheck A, {51, 1e, 0, 8053f3be} PEB is paged out (Peb.Ldr = 7ffdf00c). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 7ffdf00c). Type ".hh dbgerr001" for details Probably caused by : ntkrnlpa.exe ( nt!KiTrap0D+48e ) Followup: MachineOwner --------- kd> !analyze -v ******************************************************************************* * * * Bugcheck Analysis * * * ******************************************************************************* IRQL_NOT_LESS_OR_EQUAL (a) An attempt was made to access a pageable (or completely invalid) address at an interrupt request level (IRQL) that is too high. This is usually caused by drivers using improper addresses. If a kernel debugger is available get the stack backtrace. Arguments: Arg1: 00000051, memory referenced Arg2: 0000001e, IRQL Arg3: 00000000, bitfield : bit 0 : value 0 = read operation, 1 = write operation bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status) Arg4: 8053f3be, address which referenced memory Debugging Details: ------------------ PEB is paged out (Peb.Ldr = 7ffdf00c). Type ".hh dbgerr001" for details PEB is paged out (Peb.Ldr = 7ffdf00c). Type ".hh dbgerr001" for details READ_ADDRESS: 00000051 CURRENT_IRQL: 1e FAULTING_IP: nt!KiTrap0D+48e 8053f3be ac lods byte ptr [esi] DEFAULT_BUCKET_ID: DRIVER_FAULT BUGCHECK_STR: 0xA PROCESS_NAME: tst.exe TRAP_FRAME: f793dce0 -- (.trap 0xfffffffff793dce0) ErrCode = 00000000 eax=0000000d ebx=817897e8 ecx=0000000f edx=7fbdf300 esi=00000051 edi=00000051 eip=8053f3be esp=f793dd54 ebp=f793dd64 iopl=0 nv up ei ng nz na po cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010283 nt!KiTrap0D+0x48e: 8053f3be ac lods byte ptr [esi] ds:0023:00000051=?? Resetting default scope LAST_CONTROL_TRANSFER: from 8053f3be to 8053f853 STACK_TEXT: f793dce0 8053f3be badb0d00 7fbdf300 00401033 nt!KiTrap0E+0x233 f793dd64 00000051 badb0d00 7fbdf300 0000003c nt!KiTrap0D+0x48e WARNING: Frame IP not in any known module. Following frames may be wrong. 0012fff0 00000000 00000000 00000000 00000000 0x51 STACK_COMMAND: kb FOLLOWUP_IP: nt!KiTrap0D+48e 8053f3be ac lods byte ptr [esi] SYMBOL_STACK_INDEX: 1 SYMBOL_NAME: nt!KiTrap0D+48e FOLLOWUP_NAME: MachineOwner
Прикольно получается, бсодит, насколько я понял, в обработчике GP, при попытке читать инструкцию вызвавшую исключение, но при этом eip естественно невалидный, но при чем тут трассировка, ну т.е. должен бсод как бы всегда возникать..
Velheart Это кривые хуки сисера. При трассировке с заходом в процедуру бсод не возникает. Если не заходить в процедуру, то падает. В этом случае сисер записывает 0xCC(Int3) после Call Edx. Тут неопределённый момент, возникает исключение, которое хэндлеры сисера неправильно обрабатывают. Непонятно почему.