GPE.

Тема в разделе "WASM.PROJECTS", создана пользователем Clerk, 21 окт 2010.

  1. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
  2. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    построитель графов инструкций.
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Данный механизм можно успешно использовать при эскалациях. Если вы когдато использовали их, то должны хорошо понимать проблему отката состояния потока и ресурсов. Не факт что вы вобще сплоет можите заюзать, именно изза сложности отката состояния системы. Вы уже всюду видите вирмейкерские техники и аверские засады, это паранойя.

    Уже множество задач было описано, последний не описанный пример тут http://www.wasm.ru/forum/viewtopic.php?pid=400991#p400991. Опишу матчасть. Не следует понимать как конечное и частное решение, дальнейший пример призван показать основные принципы.

    Последовательность процедур при вызове InitRoutine() из CreateProcessA():
    Код (Text):
    1. CreateProcessA
    2.    CreateProcessInternalA
    3.       CreateProcessInternalW
    4.          GetProcAddress("CreateProcessAsUserSecure")
    5.             LdrGetProcedureAddress
    6.                LdrpGetProcedureAddress
    7.                   LdrpSnapThunk
    8.                   if !(LDR_DATA_TABLE_ENTRY.Flags & LDR_ENTRY_PROCESSED)
    9.                      LdrpRunInitializeRoutines
    10.                         LdrpCallInitRoutine
    11.                            InitRoutine()
    Причём NL(GetProcAddress) > NL(CreateProcessInternalW) и (NL(InitRoutine) - NL(CreateProcessA)) = Const.

    Для того чтобы создать поток остановленным и выполнить некоторые действия с процессом необходимо установить флажёк CREATE_SUSPENDED во входном параметре процедуры в которой находится вызов NtResumeThread, в данной версии это 7-й параметр CreateProcessInternalW():
    Код (Text):
    1. $       test byte ptr ss:[ebp + 20],4
    2. $+4     jnz short $+19
    3. $+6     lea eax,dword ptr ss:[ebp-6AC]
    4. $+C     push eax
    5. $+D     push dword ptr ss:[ebp-67C]
    6. $+13        call NtResumeThread
    7. $+19        mov eax,dword ptr ss:[ebp-674]
    Так как функция может измениться и номер параметра также(например изза появления промежуточных процедур), то необходимо вычислять номер параметра и функцию динамически. Целью определения функции является определение стекового фрейма из InitRoutine() принадлежащего данной функции, в нём находятся её параметры, в частности флажки.

    Во первых определение смещения флажков(номер параметра функции). Эта часть кода в графе будет описана 5-ю входами(при оптимизации):
    Код (Text):
    1. 1   [$]
    2. 2   [$ + 4]
    3. 3   [$ + 6,C,D]
    4. 4   [$ + 13]
    5. 5   [$ + 19]
    Так эта ветвь не завершается, то все эти описатели будут соеденены между собой прямыми и обратными ссылками. Второй описатель будет иметь ссылку на 5-й, так он описывает ветвление. Благодаря обратным ссылкам можно трассировать граф в обратном направлении, таким образом раскрыв три обратные ссылки мы окажемся на инструкции test byte ptr ss:[ebp + 20],4
    Точнее её можно представить так:
    test byte(dword) ptr ss:[ebp + ArgId*4 + 4],CREATE_SUSPENDED
    Из этой инструкции извлекаем номер параметра. Псевдокод следующий(логично и понятно):
    Код (Text):
    1.    RE:PGRAPH_ENTRY
    2.    GE = RE
    3.    GE:PGRAPH_ENTRY
    4.     if GE.Type = TYPE_CALL
    5.        if GE.BranchAddress = @NtResumeThread
    6.           GE = GE.Link.Blink
    7.           if GE.Type = TYPE_LINE
    8.              GE = GE.Link.Blink
    9.              if GE.Type = TYPE_JXX
    10.               ; if GE.BranchLink = RE.Link.Flink
    11.                    GE = GE.Link.Blink
    12.                    if Opcode(GE.Address) = (test byte(dword) ptr ss:[ebp + Disp],CREATE_SUSPENDED)
    13.                       ArgId = Disp/4 - 1
    Теперь необходимо определить саму процедуру, тоесть фрейм принадлежащий ей. Для этого можно использовать два различных метода, статический и динамический. При статическом способе выполняется трассировка уже созданного графа и поиск в нём инструкции принадлежащей процедуре. Также можно определить адрес возврата и искать его в SFC. GPE экспортирует необходимый для этого сервис, это псевдофункция FindCallerBelongToGraph(разворачивает цепочку стековых фреймов и проверяет вхождение в граф каждого адреса возврата).
    Динамический способ позволяет определить начало функции на этапе создания графа. Предыдущая версия движка это не поддерживала. Для каждой инструкции ведётся список процедур в порядке их вызова. Тоесть мы извлекаем ссылку из начала списка. Затем при первом вызове InitRoutine() ищем необходимый фрейм и сохраняем его NL(он является константой). Для последующих калбэков просто извлекаем фрейм с ранее определённым NL(выполняем бактрейс из NL итераций).
    После определения необходимого фрейма взводим бит CREATE_SUSPENDED по смещению [ArgId*4 + 1] в фрейме и заменяем в нём адрес возврата на хэндлер(2ndDispatch()).
     
  4. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Изменил на пару байт. Удалил один параметр из калбэка(мешал) и добавил флажёк определяющий тип списка. Теперь задача выше решается полноценно, тоесть двиг уже полноценный фактически.
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Опишу семпл. Непосредственно процедура Main:
    Код (Text):
    1. $PsName CHAR "d:\windows\system32\calc.exe",0
    2.  
    3. $Fn CHAR "Ip: 0x%p, Flg: 0x%x", CR, LF, 0
    4. Ep proc
    5. Local Snapshot:GP_SNAPSHOT
    6. Local GpSize:ULONG
    7. Local OldProtect:ULONG
    8. Local StartupInfo:STARTUPINFO
    9. Local ProcessInfo:PROCESS_INFORMATION
    10.     mov Snapshot.GpBase,NULL
    11.     mov GpSize,1000H * X86_PAGE_SIZE
    12.     invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr Snapshot.GpBase, 0, addr GpSize, MEM_COMMIT, PAGE_READWRITE
    13.     mov ebx,Snapshot.GpBase
    14.     %NTERR
    15.     add Snapshot.GpBase,0FFFH * X86_PAGE_SIZE
    16.     mov GpSize,X86_PAGE_SIZE
    17.     invoke ZwProtectVirtualMemory, NtCurrentProcess, addr Snapshot.GpBase, addr GpSize, PAGE_NOACCESS, addr OldProtect
    18.     %NTERR
    19.     mov Snapshot.GpLimit,ebx
    20.     mov Snapshot.GpBase,ebx
    21.     lea ecx,Snapshot.GpLimit
    22.     push eax
    23.     push eax
    24.     push 1234H
    25.     push offset PARSE_CALLBACK_ROUTINE
    26.     push eax
    27.     push 8
    28.     push GCBE_PARSE_DISCLOSURE
    29.     push ecx
    30.     push dword ptr [_imp__CreateProcessA]
    31.     %GPCALL GP_PARSE
    32.     .if !Eax
    33.     mov eax,STATUS_NOT_FOUND
    34.     Int 3
    35.     .elseif Eax != STATUS_WAIT_1
    36.     Int 3
    37.     .endif
    38.     .if !StAddress
    39.     Int 3
    40.     .endif
    41.     invoke DbgPrint, addr $Fn, StAddress, StFlagsOffset
    42.     invoke LdrSetDllManifestProber, offset LdrpManifestProberRoutine
    43.     invoke GetStartupInfo, addr StartupInfo
    44. ; !CREATE_SUSPENDED
    45.     invoke CreateProcess, addr $PsName, NULL, NULL, NULL, FALSE, 0, NULL, NULL, addr StartupInfo, addr ProcessInfo
    46.     %APIERR
    47.     invoke Sleep, 3000
    48.     invoke ZwResumeThread, ProcessInfo.ThreadHandle, NULL
    49.     %NTERR
    50.     ret
    51. Ep endp
    Вместо InitRoutine() используется LdrpManifestProberRoutine, по сути разницы нет. Вызывается конструктор, затем регается калбэк и создаётся процесс, причём не с остановленным потоком и должен сразу начать исполняться.

    На построение и разбор графа уходит малое время, не измеримое через системные тики(t < 64ms), так как построение завершается принудительно. Его цель - определение адреса возврата(var StAddress) из внутренней функции в которой находится ZwResumeThread и смещение(var StFlagsOffset) флажков в фрейме принадлежащем процедуре(номер параметра).

    Конструктор на каждой итерации вызывает калбэк PARSE_CALLBACK_ROUTINE, вот он:
    Код (Text):
    1. ; o !GCBE_PARSE_SEPARATE
    2. ; o !GCBE_PARSE_OPENLIST
    3. ;
    4. PARSE_CALLBACK_ROUTINE proc uses ebx Graph:PVOID,   ; Ссылка на граф.
    5.  GraphEntry:PVOID,  ; Ссылка на описатель инструкции.
    6.  SubsList:PVOID,    ; Список описателей входов процедур в порядке вызова.
    7.  SubsCount:ULONG,   ; Число процедур в списке является уровнем вложенности(NL).
    8.  PreOrPost:BOOLEAN, ; Тип вызова.
    9.  Context:PVOID
    10. ; Def. Flags offset.
    11.     mov ebx,GraphEntry
    12.     mov eax,dword ptr [ebx + EhEntryType]
    13.     and eax,TYPE_MASK
    14.     cmp eax,HEADER_TYPE_CALL
    15.     jne @f
    16. ; (!BRANCH_DEFINED_FLAG)
    17.     mov eax,dword ptr [ebx + EhAddress]
    18.     cmp word ptr [eax],15FFH
    19.     jne @f
    20.     mov eax,dword ptr [eax + 2]
    21.     mov eax,dword ptr [eax]
    22.     cmp dword ptr [_imp__ZwResumeThread],eax
    23.     jne @f
    24.     mov ebx,dword ptr [ebx + EhBlink]
    25.     and ebx,NOT(TYPE_MASK)
    26.     jz @f
    27.     test dword ptr [ebx + EhEntryType],TYPE_MASK
    28.     jnz @f
    29.     mov ebx,dword ptr [ebx + EhBlink]
    30.     and ebx,NOT(TYPE_MASK)
    31.     jz @f
    32.     mov eax,dword ptr [ebx + EhEntryType]
    33.     and eax,TYPE_MASK
    34.     cmp eax,HEADER_TYPE_JXX
    35.     jne @f
    36.     mov ebx,dword ptr [ebx + EhBlink]
    37.     and ebx,NOT(TYPE_MASK)
    38.     jz @f
    39.     mov ebx,dword ptr [ebx + EhAddress]
    40.     cmp byte ptr [ebx + 1],45H
    41.     jne @f
    42.     movzx eax,byte ptr [ebx]
    43.     sub eax,0F6H
    44.     jb @f
    45.     .if Zero?
    46.     movzx eax,byte ptr [ebx + 3]
    47.     .else
    48.     dec eax
    49.     jnz @f
    50.     mov eax,dword ptr [ebx + 3]
    51.     .endif
    52.     cmp eax,CREATE_SUSPENDED        ; 4
    53.     jne @f
    54.     movzx eax,byte ptr [ebx + 2]
    55.     cmp eax,4
    56.     jna @f
    57.     mov StFlagsOffset,eax
    58. ; Def. STACK_FRAME.Ip
    59.     mov ecx,SubsList
    60.     cmp SubsCount,2
    61.     jb @f
    62.     mov ecx,dword ptr [ecx] ; PCALL_HEADER
    63.     mov ecx,dword ptr [ecx + EhFlink]
    64.     and ecx,NOT(TYPE_MASK)
    65.     jz @f
    66.     mov ecx,dword ptr [ecx + EhAddress]
    67.     mov eax,STATUS_WAIT_1
    68.     mov StAddress,ecx
    69.     jmp Exit
    70. @@:
    71.     xor eax,eax
    72. Exit:
    73.     ret
    74. PARSE_CALLBACK_ROUTINE endp
    Псевдокод его в #9. Он находит StAddress и StFlagsOffset, после чего прерывает дальнейший анализ. Далее граф не нужен и может быть удалён.

    Вторичный хэндлер:
    Код (Text):
    1. .data
    2. StFlagsOffset   ULONG ?
    3. StAddress       PVOID ?
    4.  
    5. .code
    6. $Ch CHAR "2nd'f called..", CR, LF, 0
    7.  
    8. Fn2ndDispatch proc C
    9.     pushad
    10.     invoke DbgPrint, addr $Ch
    11.     popad
    12.     jmp StAddress
    13. Fn2ndDispatch endp
    14.  
    15. TbStackBase equ 4
    16. TbStackLimit    equ 8
    17.  
    18. $Ld CHAR "SFC Frame: 0x%p", CR, LF, 0
    19.  
    20.     assume fs:nothing  
    21. LdrpManifestProberRoutine proc DllBase:PVOID, FullDllPath:PCWSTR, ActivationContext:PVOID
    22.     mov eax,STACK_FRAME.Next[ebp]
    23.     mov ecx,StAddress
    24.     assume eax:PSTACK_FRAME
    25. @@:
    26.     cmp eax,-1
    27.     je @f
    28.     cmp fs:[TbStackBase],eax
    29.     jna @f
    30.     cmp fs:[TbStackLimit],eax
    31.     ja @f
    32.     cmp [eax].Ip,ecx
    33.     je Load
    34.     mov eax,[eax].Next
    35.     jmp @b
    36. Load:
    37.     mov ecx,StFlagsOffset
    38.     mov [eax].Ip,offset Fn2ndDispatch
    39.     or dword ptr [eax + ecx],CREATE_SUSPENDED
    40.     invoke DbgPrint, addr $Ld, Eax
    41. @@:
    42.     xor eax,eax
    43.     ret
    44. LdrpManifestProberRoutine endp
    Гдето в глубине целевой функции вызывается этот загрузочный калбэк, оттуда он вызывается не имеет значения. Он выполняет бактрейс и находит фрейм с известным адресом возврата StAddress найденным ранее. После этого загружает в фрейм адрес возврата на Fn2ndDispatch, это стаб и взводит в фрейме по определённому ранее смещению(StFlagsOffset) флажёк CREATE_SUSPENDED. Далее управление отдаётся, при возврате из целевой функции получает управление вторичный хэндлер. Он заглушка и ничего не делает кроме вывода сообщения.
    Доп. макро:
    Код (Text):
    1. %NTERR macro
    2.     .if Eax
    3.     Int 3
    4.     .endif
    5. endm
    6.  
    7. %APIERR macro
    8.     .if !Eax
    9.     Int 3
    10.     .endif
    11. endm
    12.  
    13. CR  equ 13
    14. LF  equ 10
    После отработки CreateProcess() поток будет остановлен, выполняется задержка и его ресум. В результате лог:
    [​IMG]
     
  6. user1

    user1 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2009
    Сообщения:
    22
    Clerk, поясните, пожалуйста, мне, как нубу и школоте, что дает такая технология (построение графа инструкций) и как ее можно использовать (сейчас и в перспективе)? Спасибо.
    ps. На Вашем сайте log.txt отдает 404
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    user1
    Это мощная технология, в дальнейшем позволит вам решать задачи, которые никто решить не может, тоесть иного оптимального пути решения не существует. Например:
    o Поиск процедуры по имени сообщения.

    Код (Text):
    1. PARSE_CALLBACK_ROUTINE(GE:PGRAPH_ENTRY, CallList:PCALL_ENTRY):
    2.    if GE.Type = TYPE_CALL
    3.       if GE.BranchAddress = @DbgPrint()
    4.          GE = GE.Blink
    5.          if GE.Type = TYPE_LINE
    6.             if BYTE[GE.Address] = 0x68
    7.                   if StrCmp(TargetMessage, DWORD[GE.Address + 1])
    8.                      Routine = CallList[0]
    Напр.(используется только часть строки):
    Код (Text):
    1.   "LDR: Tls Found in %wZ at %p" -> LdrpInitializeTls()
    2.   "[%x,%x] LDR: Real INIT LIST for process %wZ pid %u 0x%x" -> LdrpRunInitializeRoutines()
    3.   "LDR: Tls Callbacks Found. Imagebase %p Tls %p CallBacks %p" -> LdrpCallTlsInitializers()
    4.   "Failed to initialize a new segment (%x)" -> RtlpInitializeHeapSegment()
    Это всевозможные перехваты(не то фуфло с патчами, а нормальные способы), поиск переменных, анализ кода и пр. Весь васм должен признать что задачи подобные описанным выше решить не способен.

    С моим сайтом сейчас траблы, точнее с хостом. Они не могут исправить проблемы, либо не хотят.
     
  8. user1

    user1 New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2009
    Сообщения:
    22
    Clerk, спасибо за ответ. Тем не менее, много непонятного. Исходники красивые, везде комменты, тем не менее, читать асм тяжелее, чем VC. вопрос, почему Вы не пишите сразу все на VC со всеми настройками по уменьшению размера файла, в итоге получится тоже небольшие файлики, зато повысится удобство чтения (и редактирования) кода плюс переносимость. Вы меня конечно извините, но Вы не могли бы добавить более полную документацию к Вашей технологии. То, что сейчас есть в архиве (файл help.txt) достаточно сложен для понимания, если не вникал до этого в исходники, либо предполагается, что надо садиться и внимательно читать все исходники. Из представленной документации мне, как профессиональному нубу, не совсем понятны исчерпывающие возможности движка. Из названия технологии (построение графа) я сначала думал, Вы берете прогу, и запускаете под своим отладчиком, потом все значения регистров в каждом eip сохраняете в список, которым можете манипулировать в последствии. Но, насколько я понял, речь идет о более серьезной технологии. Был бы Вам очень признателен за более подробную документацию по возможностям движка, тк направление очень интересное, в котором Вы работаете. В любом случае, спасибо, что проводите исследования в таких направлениях, в которые не многие работают, и уже тем более спасибо, что делитесь своими проектами (исходниками) и идеями. Вы упомянули перехваты, если речь идет не о сплайсинге кода, значит Вы подменяете какие-то элементы в секции данных? (или что Вы имели ввиду?). Спасибо.
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    user1
    У вас очень обширные вопросы, я не могу кратко ответить. Если есть вопросы по движку, то я обьясню.
     
  10. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Видимо, движок настолько безапеляционно крут, что даже сам клерк не знает, для чего он нужен и что он умеет :) Сосредоточьтесь
     
  11. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    MSoft
    Уже много описал, вы не я и если не знаете, то читайте. Кстате вы тоже там про крипторы в теме отписались вроде, так мб скажите как найти две функи чтоб тлс заюзать - LdrpInitializeTls() & LdrpAllocateTls() ?

    У меня очень просто(опорная LdrInitializeThunk()), сейчас проверил:
    Код (Text):
    1. .data
    2. NtBase  PVOID ?
    3. NtLimit PVOID ?
    4. gRef1   PCALL_HEADER ?
    5. gRef2   PCALL_HEADER ?
    6.  
    7. .code
    8. $Fn1    CHAR "Tls Found in %wZ",0   ; LdrpInitializeTls()
    9. $Fn2    CHAR "TlsVector %x",0       ; LdrpAllocateTls()
    10.  
    11. ; o GCBE_PARSE_OPENLIST
    12. ;
    13. PARSE_CALLBACK_ROUTINE proc uses ebx Graph:PVOID,
    14.  GraphEntry:PVOID,
    15.  SubsList:PVOID,
    16.  SubsCount:ULONG,
    17.  PreOrPost:BOOLEAN,
    18.  Context:PVOID
    19.     mov ebx,GraphEntry
    20.     mov eax,dword ptr [ebx + EhEntryType]
    21.     and eax,TYPE_MASK
    22.     cmp eax,HEADER_TYPE_CALL
    23.     jne @f
    24. ; (!BRANCH_DEFINED_FLAG)
    25.     mov ecx,dword ptr [ebx + EhAddress]
    26.     cmp byte ptr [ecx],0E8H
    27.     jne @f
    28.     mov eax,dword ptr [ebx + EhBranchAddress]
    29.     cmp dword ptr [_imp__DbgPrint],eax
    30.     jne @f
    31.     cmp byte ptr [ecx - 5],68H
    32.     jne @f
    33.     mov ebx,dword ptr [ecx - 4]
    34.     cmp NtBase,ebx
    35.     jnb @f
    36.     cmp NtLimit,ebx
    37.     jbe @f
    38.     cmp gRef1,NULL
    39.     jne Check2
    40.     invoke InString, 1, Ebx, addr $Fn1
    41.     test eax,eax
    42.     jle Check2
    43.     mov eax,SubsList
    44.     mov eax,dword ptr [eax]
    45.     mov gRef1,eax
    46. @@:
    47.     xor eax,eax
    48. Exit:
    49.     ret
    50. xBreak:
    51.     mov eax,STATUS_WAIT_1
    52.     jmp Exit
    53. Check2:
    54.     cmp gRef2,NULL
    55.     jne xBreak
    56.     invoke InString, 1, Ebx, addr $Fn2
    57.     test eax,eax
    58.     jle @b
    59.     mov eax,SubsList
    60.     mov eax,dword ptr [eax]
    61.     mov gRef2,eax
    62.     jmp @b
    63. PARSE_CALLBACK_ROUTINE endp
     
  12. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Т.е. твой движок умеет пролистывать список адресов возврата, анализировать вызванные функции и по тем строкам, к которым идет обращение, движок может найти адрес нужной функции? Т.е. суть - найти строку, характерную для определенной функции?
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    MSoft
    Это одна из основных задач. В IDP была описана базовая проблема:
     
  14. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Был бы написан на си, я бы почитал, а так. Ну хоть алгоритм бы подробно описали.
     
  15. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Да было б чудно, если б кто-то из форумчан, кто применил сие чудо, написал бы статейку по использованию, полученному результату и т.д. И да, на си для ленивых было б классно
     
  16. CrystalIC

    CrystalIC New Member

    Публикаций:
    0
    Регистрация:
    26 июл 2008
    Сообщения:
    500
  17. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    CrystalIC
    Чем там си не подходит? граф нельзя построить на си?
     
  18. CrystalIC

    CrystalIC New Member

    Публикаций:
    0
    Регистрация:
    26 июл 2008
    Сообщения:
    500
    spa
    Среда значения не имеет. Стройте, решайте в чём проблема.
     
  19. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    CrystalIC
    вы вообще к чему? что за бред вы пишете.
     
  20. CrystalIC

    CrystalIC New Member

    Публикаций:
    0
    Регистрация:
    26 июл 2008
    Сообщения:
    500
    spa
    Не всё бред, что вам не понятно. Вот простая задача http://www.wasm.ru/forum/viewtopic.php?pid=403996, собственно нужно сформировать трап фрейм. Как решать будем ?
    Отношение к сабжу имеет прямое - необходимо скопировать часть кода начиная с хэндлера сискала до инструкции размаскирующей прерывания. Все паразитные ветвления за пределы кода присекаются если обнаружена инструкция перезагружающая селекторы. В остальном тривиально, граф компилится. Ну разумеется нужно немного допилить, введя описатели ветвлений, дабы они стали псевдокодом и конструктор не использовал непосредственно их опкоды:
    Код (Text):
    1. JCC_SHORT_OPCODE_BASE   equ 70H
    2. JCC_NEAR_OPCODE_BASE    equ 80H
    3.  
    4. JCC_O   equ 0   ; OF
    5. JCC_NO  equ 1   ; !OF
    6. JCC_C   equ 2   ; CF
    7. JCC_B   equ 2   ; CF
    8. JCC_NAE equ 2   ; CF
    9. JCC_NC  equ 3   ; !CF
    10. JCC_NB  equ 3   ; !CF
    11. JCC_AE  equ 3   ; !CF
    12. JCC_Z   equ 4   ; ZF
    13. JCC_E   equ 4   ; ZF
    14. JCC_NZ  equ 5   ; !ZF
    15. JCC_NE  equ 5   ; !ZF
    16. JCC_NA  equ 6   ; CF | ZF
    17. JCC_BE  equ 6   ; CF | ZF
    18. JCC_A   equ 7   ; !CF & !ZF
    19. JCC_NBE equ 7   ; !CF & !ZF
    20. JCC_S   equ 8   ; SF
    21. JCC_NS  equ 9   ; !SF
    22. JCC_P   equ 0AH ; PF
    23. JCC_PE  equ 0AH ; PF
    24. JCC_NP  equ 0BH ; !PF
    25. JCC_PO  equ 0BH ; !PF
    26. JCC_L   equ 0CH ; SF != OF
    27. JCC_NGE equ 0CH ; SF != OF
    28. JCC_NL  equ 0DH ; SF = OF
    29. JCC_GE  equ 0DH ; SF = OF
    30. JCC_NG  equ 0EH ; ZF | (SF != OF)
    31. JCC_LE  equ 0EH ; ZF | (SF != OF)
    32. JCC_G   equ 0FH ; !ZF & (SF = OF)
    33. JCC_NLE equ 0FH ; !ZF & (SF = OF)
    34.  
    35. ; o Jump short: 0x70 + JCC_*
    36. ; o Jump near: 0x0F 0x80 + JCC_*
    Без оптимизации собирается на коленке за пять минут. Предложите своё решение или снова идите лесом.