Сейчас на форуме: UniSoft, bartolomeo (+6 невидимых)

 eXeL@B —› Программирование —› SEH.
Посл.ответ Сообщение

Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 03 января 2011 00:30
· Личное сообщение · #1

Здрасте.
Записываем мы свой сех в системный модуль, например в ntdll. Он вызван не будет. В чём причины и как это обойти ?




Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 03 января 2011 02:24
· Личное сообщение · #2

Темы у тебя интересные , но ты их так быстро закрываешь , не у всех так много времени чтобы посмотреть , прошлую тему взял закрыл. Писал бы подробнее , без системного слэнга , читать трудно иногда , хотя код полезный когда вникнешь что ты имел ввиду)

Что значит записываешь свой сех , на примере той же нтдлл , до финал екзепшн ты же все равно вернешься в нтдлл , нельзя ли это дело перехватить?

На какой винде ты это делаешь? Может тому виной SEHOP ? Для чего ты ставишь СЕХ? Если можешь , прикладывай с кодом рабочий пример , так удобнее для тех к кому ты обращаешься

-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube




Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 03 января 2011 05:02
· Личное сообщение · #3

mak
Допустим записываем мы свой сех в кодосекцию, либо вобще определяем как сех любой адрес в этом модуле, который не является системным сех(там нэйтив тоже несколько хэндлеров использует). Такой сех вызван никогда не будет. Вот интересно как это поломать ?



Ранг: 27.7 (посетитель), 2thx
Активность: 0.01=0.01
Статус: Участник

Создано: 03 января 2011 05:32
· Личное сообщение · #4

структуры EXCEPTION_REGISTRATION должны лежать в своем стеке с выравниванием на DWORD и по-порядку.



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 03 января 2011 07:35
· Личное сообщение · #5

ant_man
Всё валидно, только адрес сех находится в пределах ntdll.



Ранг: 27.7 (посетитель), 2thx
Активность: 0.01=0.01
Статус: Участник

Создано: 03 января 2011 10:23 · Поправил: ant_man
· Личное сообщение · #6

значит SafeSEH

IMAGE_LOAD_CONFIG_DIRECTORY32_2.SEHandlerTable[SEHandlerCount]

| Сообщение посчитали полезным: Clerk


Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 03 января 2011 14:26
· Личное сообщение · #7

Тема есть ... Manual Mapping and SEH Handler Validation (aka SafeSEH)

I'm currently in the process of writing a manual mapper and have hit an interesting problem... I noticed that when trying to use exception handling in my manually mapped module the handler would never get called and the process would be terminated. After a bit of scanning through the PE file format I noticed the section on load configuration data and then it became clear the problem was SafeSEH.

For anyone who does not know what SafeSEH is:
msdn.microsoft.com/en-us/library/9a89h429(VS.80).aspx
uninformed.org/index.cgi?v=9&a=4&p=7

Please note that this is different to SEHOP, described here:
blogs.technet.com/srd/archive/2009/02/02/preventing-the-exploitation-of-seh-overwrites-with-sehop.aspx

The problem is that SEH does not work in my manually mapped modules because it fails the checks performed by the exception dispatcher (see Ntdll.RtlIsValidHandler for more information).

To give you an idea of what's happening, here's the pseudocode from the Blackhat 2008 paper 'How to Impress Girls with Browser Memory Protection Bypasses':

Code:
  1. BOOL RtlIsValidHandler(handler) 
  2.     if (handler is in an image) { 
  3.         if (image has the IMAGE_DLLCHARACTERISTICS_NO_SEH flag set) 
  4.             return FALSE;
  5.  
  6.         if (image has a SafeSEH table) 
  7.             if (handler found in the table) 
  8.                 return TRUE;
  9.             else 
  10.                 return FALSE;
  11.  
  12.         if (image is a .NET assembly with the ILonly flag set) 
  13.             return FALSE;
  14.  
  15.         // fall through 
  16.     } 
  17.  
  18.     if (handler is on a non-executable page) { 
  19.         if (ExecuteDispatchEnable bit set in the process flags) 
  20.             return TRUE;
  21.         else 
  22.             raise ACCESS_VIOLATION; // enforce DEP even if we have no hardware NX
  23.     } 
  24.  
  25.     if (handler is not in an image) { 
  26.         if (ImageDispatchEnable bit set in the process flags) 
  27.             return TRUE;
  28.         else 
  29.             return FALSE; // don't allow handlers outside of images
  30.     } 
  31.  
  32.     // everything else is allowed 
  33.  
  34.     return TRUE;
  35. }


Obviously manually mapped modules will fail the first check, as the handler is not inside an 'image' as far as Windows is concerned (from memory it checks to see if the region the handler resides in is marked as MEM_IMAGE), and even if it was, we still wouldn't be in the relevant list (ntdll.LdrpInvertedFunctionTable) so it doesn't matter anyway.

The second check fails because the manually mapped module's code is marked as executable (obviously). Besides, even if that first check did succeed, the second would fail and an access violation would be raised because ExecuteDispatchEnable is disabled.

The third check succeeds at first (because the handler is not in an image), but then fails because the ImageDispatchEnable flag is not set.

So, whilst brainstorming for solutions to this problem with a friend (thanks Greyman!) we came up with a few solutions:
Try to enable the ImageDispatchEnable flag. This failed however as every time I tried to set it I got a STATUS_INVALID_PARAMETER error. I dove into the implementation of ntoskrnl.NtSetInformationProcess and found that the responsible function seems to be ntoskrnl.MmSetExecuteOptions. At first glance it seems that you cannot enable or disable that particular flag from usermode. Unless of course I just plain fucked something up when calling it, which is also possible, but unlikely.
Hook NtQueryInformationSystem and 'lie' to ntdll.RtlIsValidHandler by simply returning the ImageDispatchEnable flag as always set. I have not yet tested this solution but I assume it should work, however I want to avoid it as it's quite invasive and defeats the purpose of manually mapping to begin with.
Implement your own exception dispatcher via VEH. Vectored exception handlers are called before structured exception handlers, so it should/would be possible to register a VEH and perform the necessary dispatching for the manually mapped module. This solution is imo the best one I know of so far, however from both a reliability and performance standpoint I can see it being a potential issue. Plus, it would be an asshole to do the initial implementation (very tedious).

Does anyone know of any better solutions? So far number 3 seems to be the best, but I'm still hanging out for a better solution...

Any ideas/suggestsions/etc would be appreciated. Thanks.

Источник www.gamedeception.net/threads/19650-Manual-Mapping-and-SEH-Handler-Validation-(aka-SafeSEH)?p=132697#post132697

-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube





Ранг: 331.1 (мудрец), 561thx
Активность: 0.190.06
Статус: Участник

Создано: 03 января 2011 15:10
· Личное сообщение · #8

Моя проблемка похоже попадает под описанный случай. Имеем следующий код:
Code:
  1. DWORD DivLong(DWORD v1, DWORD v2, DWORD v3, DWORD& val1, DWORD& val2)
  2. {
  3.          DWORD res;
  4.          LARGE_INTEGER div;
  5.          __try
  6.          {
  7.                  DWORD vl1, vl2;
  8.                  _asm
  9.                  {
  10.                         mov     edx, v1
  11.                         mov     eax, v2
  12.                         mov     ecx, v3
  13.                         div     ecx
  14.                         mov     vl1, eax
  15.                         mov     vl2, edx
  16.                         pushfd
  17.                         pop     res
  18.                  }
  19.                  val1 = vl1;
  20.                  val2 = vl2;
  21.          }
  22.          __except(VmException(GetExceptionCode()))
  23.          {
  24.                  if(!v3)
  25.                         v3 = 1;
  26.                  div.LowPart = v2;
  27.                  div.HighPart = v1;
  28.                  val1 = (DWORD)(div.QuadPart / v3);
  29.                  val2 = div.QuadPart % v3;
  30.                  res = 0;
  31.          }
  32.          return res;
  33. }
  34.  
  35. // Обработчик исключения
  36. int VmException(int n_except)
  37. {
  38.          // Pass on most exceptions
  39.          if((n_except != STATUS_INTEGER_OVERFLOW) && (n_except != STATUS_FLOAT_OVERFLOW))
  40.                  return EXCEPTION_CONTINUE_SEARCH;
  41.          // Execute some code to clean up problem
  42.          return EXCEPTION_EXECUTE_HANDLER;
  43. }

Так вот проблема в том, что если этот код вставлен в exe, то исключение деления на 0 обрабатывается нормально, но если этот код вставлен в dll, то получаем исключение без вызова обработчика.
Как сделать, чтобы в dll срабатывал обработчик исключения?

-----
Everything is relative...





Ранг: 355.4 (мудрец), 55thx
Активность: 0.320
Статус: Uploader
5KRT

Создано: 03 января 2011 16:24
· Личное сообщение · #9

VEH нельзя использовать?

-----
Gutta cavat lapidem. Feci, quod potui. Faciant meliora potentes




Ранг: 27.7 (посетитель), 2thx
Активность: 0.01=0.01
Статус: Участник

Создано: 03 января 2011 16:39
· Личное сообщение · #10

Vamit, если это твоя dll, то надо убедиться, что она скомпилировалась без флага DllCharacteristics.IMAGE_DLLCHARACTERISTICS_NO_SEH




Ранг: 331.1 (мудрец), 561thx
Активность: 0.190.06
Статус: Участник

Создано: 03 января 2011 17:08
· Личное сообщение · #11

ant_man пишет:
если это твоя dll

Моя, убедился что DllCharacteristics = 0. Dll является плагином Ольки, может в этом дело?

-----
Everything is relative...





Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 03 января 2011 17:46
· Личное сообщение · #12

Если try на HLL написан (а это так), должно работать на любой системе и в любом виде ПЕ, проще отладить, начиная с передачи исключения в ринг3 на KiUserExceptionDispatcher, чем гадать.



Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 03 января 2011 17:51
· Личное сообщение · #13

Vamit
Насколько я помню "ничто мешает одному SEH-обработчику послать остальные на хрен"... На системных длл'ках система ставит(по крайней мере должна) "свой" обработчик. А вообще если видимых камней нет, может попробовать try явно заменить на:
push dword seh_handler
push dword [fs:0]
mov dword [fs:0], esp



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 03 января 2011 18:18
· Личное сообщение · #14

ant_man
Верно, респект!

Code:
  1. ; +
  2. ; Настройка директории конфигурации. Регистрация SEH.
  3. ; o SysStub - адрес системного стаба(напр. call dword ptr ds:[RtlpStartThreadFunc]).
  4. ;
  5. ConfigureConfigDirectory proc uses ebx esi edi SysStub:PVOID, pZwProtectVirtualMemory:PVOID
  6. Local RegionAddress:PVOID, RegionSize:ULONG, Protect:ULONG
  7.          mov eax,fs:[TEB.Peb]
  8.          mov eax,PEB.Ldr[eax]
  9.          mov eax,PEB_LDR_DATA.InLoadOrderModuleList.Flink[eax]
  10.          mov eax,LDR_DATA_TABLE_ENTRY.InLoadOrderModuleList.Flink[eax]
  11.          mov ebx,LDR_DATA_TABLE_ENTRY.DllBase[eax]   ; ntdll.dll
  12.          mov edi,ebx
  13.          add edi,IMAGE_DOS_HEADER.e_lfanew[ebx]
  14.          assume edi:PIMAGE_NT_HEADERS
  15.          mov esi,[edi].OptionalHeader.DataDirectory.VirtualAddress[IMAGE_DIRECTORY_ ENTRY_LOAD_CONFIG  * sizeof(IMAGE_DATA_DIRECTORY)]
  16.          mov RegionAddress,edi
  17.          test esi,esi
  18.          jz Error
  19.          add esi,ebx      ; _load_config_used
  20.          assume esi:PIMAGE_LOAD_CONFIG_DIRECTORY
  21.          cmp [esi]._Size,sizeof(IMAGE_LOAD_CONFIG_DIRECTORY)
  22.          jne Error
  23.          cmp [esi].SEHandlerCount,0
  24.          movzx ecx,[edi].FileHeader.NumberOfSections
  25.          je Error
  26.          test ecx,ecx
  27.          jz Error
  28. Scan:
  29.          cmp dword ptr IMAGE_SECTION_HEADER._Name[edi + sizeof(IMAGE_NT_HEADERS)][0],"tad."
  30.          jne Next
  31.          cmp dword ptr IMAGE_SECTION_HEADER._Name[edi + sizeof(IMAGE_NT_HEADERS)][4],"a"
  32.          jne Next
  33.          mov eax,IMAGE_SECTION_HEADER.Characteristics[edi + sizeof(IMAGE_NT_HEADERS)]
  34.          and eax,IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_READ or IMAGE_SCN_CNT_INITIALIZED_DATA
  35.          cmp eax,IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_READ or IMAGE_SCN_CNT_INITIALIZED_DATA
  36.          jne Error
  37.          mov eax,IMAGE_SECTION_HEADER.VirtualSize[edi + sizeof(IMAGE_NT_HEADERS)]
  38.          mov ecx,[esi].SEHandlerCount
  39.          and eax,(X86_PAGE_SIZE - 1)
  40.          lea ecx,[ecx*4 + sizeof(IMAGE_LOAD_CONFIG_DIRECTORY) + 4]
  41.          not eax
  42.          lea eax,[eax + X86_PAGE_SIZE + 1]
  43.          cld
  44.          cmp eax,ecx
  45.          mov edx,IMAGE_SECTION_HEADER.VirtualAddress[edi + sizeof(IMAGE_NT_HEADERS)]
  46.          jb Error
  47.          mov edi,IMAGE_SECTION_HEADER.VirtualSize[edi + sizeof(IMAGE_NT_HEADERS)]
  48.          add edi,edx
  49.          mov RegionSize,4
  50.          add edi,ebx
  51.          mov ecx,sizeof(IMAGE_LOAD_CONFIG_DIRECTORY)/4
  52.          mov edx,edi
  53.          assume edx:PIMAGE_LOAD_CONFIG_DIRECTORY
  54.          rep movsd
  55.          mov esi,[edx].SEHandlerTable
  56.          mov ecx,[edx].SEHandlerCount
  57.          mov [edx].SEHandlerTable,edi
  58.          mov eax,SysStub
  59.          rep movsd
  60.          sub eax,ebx
  61.          mov esi,RegionAddress
  62.          stosd
  63.          inc [edx].SEHandlerCount
  64.          lea eax,Protect
  65.          lea ecx,RegionSize
  66.          mov edi,edx
  67.          push eax
  68.          push PAGE_READWRITE
  69.          lea eax,RegionAddress
  70.          push ecx
  71.          push eax
  72.          push NtCurrentProcess
  73.          %APICALL pZwProtectVirtualMemory
  74.          test eax,eax
  75.          jnz Exit
  76.          sub edi,ebx
  77.          mov IMAGE_NT_HEADERS.OptionalHeader.DataDirectory.VirtualAddress[IMAGE_DIR ECTORY_ENTRY_LOAD_CONFIG  * sizeof(IMAGE_DATA_DIRECTORY)][esi],edi
  78.          lea eax,Protect
  79.          lea ecx,RegionSize
  80.          push eax
  81.          push Protect
  82.          lea eax,RegionAddress
  83.          push ecx
  84.          push eax
  85.          push NtCurrentProcess
  86.          %APICALL pZwProtectVirtualMemory
  87.          xor eax,eax
  88.          jmp Exit
  89. Next:
  90.          add edi,sizeof(IMAGE_SECTION_HEADER)
  91.          dec ecx
  92.          jnz Scan
  93. Error:
  94.          mov eax,STATUS_UNSUCCESSFUL
  95. Exit:
  96.          ret
  97. ConfigureConfigDirectory endp




Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 03 января 2011 18:20
· Личное сообщение · #15

Это даёт возможность зарегать сех, который не принадлежит модулям. Иначе необходимо изменить флаги, которые из юзермода не доступны(единожды можно выполнить насройку при инициализации процесса).




Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 03 января 2011 18:24
· Личное сообщение · #16

ELF_7719116
Ты пишешь неправильные вещи.
Во-первых, СЕХ вызывается по цепочке, а он ставит свой обработчик последним, стало быть, вызван он будет первым (не считая хуков и вех).
И заменять на асм-вставку явно не стоит, хотя бы потому, что тогда не будут инициализированы поля SEHOP, если он включён.


 eXeL@B —› Программирование —› SEH.
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати