Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 12 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Распаковка beria v0.07 public

Обсудить статью на форуме

Очень удобно, когда все крэкерские инструменты, книги и статьи в одном месте. Используйте сборник от EXELAB - вот тут.

Автор: PE_Kill <PE_Kill@mail.ru>

Инструменты

OllyDbg 1.10 + ODbgScrypt
ImpREC
PE Tools

Жертва

Простая программа HelloWorld мною написанная, мною и взломанная :)

Вступление

Beria-это протектор исполняемых файлов, работающий по принципу отладчика. Но реализация весьма странная. Все операции выполняются в родительском процессе по запросу процесса – потомка, что позволяет не отлаживать второй процесс, а, анализируя ответные действия родителя, исправлять процесс потомок. Вся защита сводится к защите импорта и защите от дампа.

Go, go, go!

При загрузке в отладчик вы можете наблюдать такое

401660  sub esp,18
401663  push ebx
401664  mov ebx,dword ptr ds:[<&KERNEL32.GlobalAlloc>]
40166A  push ebp
40166B  push esi
40166C  push edi
40166D  push 730
401672  xor ebp,ebp
401674  push ebp
401675  call ebx

Как видите код протектора находится прямо в секции кода целевой программы.
Прокрутив окно кода вниз видим следующее

4017BE call dword ptr ds:[<&KERNEL32.GetCommandLineA>]
4017C4 push unpackme.004043C0
4017C9 push unpackme.004040A8
4017CE push ebp
4017CF push ebp
4017D0 mov edx,eax
4017D2 push 4000022	 ; DEBUG_ONLY_THIS_PROCESS | NORMAL_P…
4017D7 xor eax,eax
4017D9 push ebp
4017DA push ebp
4017DB mov ecx,11
4017E0 mov edi,unpackme.004040A8
4017E5 rep stos dword ptr es:[edi]
4017E7 mov dword ptr ds:[4043C0],eax
4017EC push ebp
4017ED mov dword ptr ds:[4043C4],eax
4017F2 push edx
4017F3 mov esi,1
4017F8 mov dword ptr ds:[4043C8],eax
4017FD push ebp
4017FE mov dword ptr ds:[4040A0],edx
401804 mov dword ptr ds:[4040A8],44
40180E mov dword ptr ds:[4040D4],esi
401814 mov word ptr ds:[4040D8],si
40181B mov dword ptr ds:[4043CC],eax
401820 call dword ptr ds:[<&KERNEL32.CreateProcessA>]

Так протектор запускает себя второй раз, но на этот раз уже как отладчик. Раз так, то, после загрузки, Windows будет сообщать протектору обо всех событиях, которые будут происходить в процессе – потомке, на что протектор должен сообщать Windows, обработал ли он это событие или передать его на обработку программе. Для этого где то должен быть цикл, в котором ожидаются отладочные сообщения (WaitForDebugEvent) и подтверждаются или опровергаются (ContinueDebugEvent). И действительно его можно обнаружить чуть ниже CreateProcess

00401958 mov     esi, ds:WaitForDebugEvent
0040195E mov     edi, ds:ContinueDebugEvent
00401964 wait_debug_event:
00401964 push    INFINITE        ; dwMilliseconds
00401966 push    offset DebugEvent ; lpDebugEvent
0040196B call    esi ; WaitForDebugEvent
0040196D test    eax, eax
0040196F jz      check_exit
00401975 mov     eax, ds:DebugEvent
0040197A dec     eax
0040197B cmp     eax, 6          ; switch 7 cases
0040197E ja      proc_continue   ; default
00401984 jmp     off_401AB8[eax*4] ; switch jump

0040198B set_int3_in_ep:               
0040198B cmp     ds:dword_40440C, ebp ; case 0x2
00401991 jnz     short proc_continue ; default
00401993 mov     ecx, ds:off_40401C
00401999 mov     edx, ds:ProcessInformation.hProcess
0040199F lea     eax, [esp+28h+var_4]
004019A3 push    eax             ; lpNumberOfBytesWritten
004019A4 push    1               ; nSize
004019A6 push    offset dword_403050 ; lpBuffer
004019AB push    ecx             ; lpBaseAddress
004019AC push    edx             ; hProcess
004019AD call    ds:WriteProcessMemory
004019B3 jmp     short proc_continue ; default
004019B5 ; ---------------------------------------------------------------------------
004019B5 switch_handler:
 004019B5 mov     eax, ds:dword_40404C ; case 0x0
004019BA cmp     eax, EXCEPTION_GUARD_PAGE
004019BF jz      short proc_guard
004019C1 cmp     eax, EXCEPTION_BREAKPOINT
004019C6 jz      short proc_breakpoint
004019C8 cmp     eax, EXCEPTION_ACCESS_VIOLATION
004019CD jnz     short proc_continue ; default
004019CF loc_4019CF:
 004019CF mov     ds:dword_4043DC, ebp ; case 0x4
004019D5 jmp     short proc_continue ; default
004019D7 ; ---------------------------------------------------------------------------
004019D7 proc_breakpoint:
 004019D7 mov     eax, ds:NumberOfBytesWritten
004019DC mov     ecx, ds:dword_404058
004019E2 push    eax
004019E3 mov     eax, ds:dwThreadId
004019E8 push    ecx
004019E9 call    sub_401AE0
004019EE add     esp, 8
004019F1 jmp     short proc_continue ; default
004019F3 ; ---------------------------------------------------------------------------
004019F3 proc_guard:
 004019F3 mov     edx, ds:NumberOfBytesWritten
004019F9 mov     ebx, ds:dword_404030
004019FF push    edx             ; NumberOfBytesWritten
00401A00 call    unlock_page
00401A05 proc_continue:
00401A05 mov     eax, ds:dwThreadId ; default
00401A0A mov     ecx, ds:dwProcessId
00401A10 push    DBG_CONTINUE    ; dwContinueStatus
00401A15 push    eax             ; dwThreadId
00401A16 push    ecx             ; dwProcessId
00401A17 call    edi ; ContinueDebugEvent
00401A19 check_exit:
00401A19 cmp     ds:dword_4043DC, ebp
00401A1F jnz     wait_debug_event

По адресу 0040196B вызывается WaitForDebugEvent. Давайте поставим бряк ниже этого вызова и запустим программу. Процесс создался и произошло первое отладочное событие.
Ниже по адресу 00401975 происходит чтение в eax ExceptionCode. Давайте дотрассируем до этого места и посмотрим что же произошло.
В eax находится идентификатор события.

1 =  EXCEPTION_DEBUG_EVENT
2 =  CREATE_THREAD_DEBUG_EVENT
3 =  CREATE_PROCESS_DEBUG_EVENT
4 =  EXIT_THREAD_DEBUG_EVENT
5 =  EXIT_PROCESS_DEBUG_EVENT
6 =  LOAD_DLL_DEBUG_EVENT
7 =  UNLOAD_DLL_DEBUG_EVENT
8 =  OUTPUT_DEBUG_STRING_EVENT
9 =  RIP_EVENT

В eax 3, значит произошло создание процесса. Теперь протектор хочет остановить выполнение дочернего процесса на точке входа в программу, как это делают большинство отладчиков. Для этого он записывает по адресу EntryPoint+ImageBase байт 0xCC (INT 3). Немного потрассировав мы выходим на адрес 004019A3. Здесь как раз и происходит запись байта 0xCC посредством функции WriteProcessMemory и происходит прыжок на адрес 00401A05, где вызывает функцию ContinueDebugEvent c параметром DBG_CONTINUE, что означает, что протектор обработал данное исключение. И так, одно событие обработано. Давайте поставим бряк сразу на 00401975, где происходит чтение в eax ExceptionCode, и будем следить за кодами исключений. Запускаем программу в eax 6, значит в дочернем процессе грузится DLL, ни протектору, ни нам это не интересно, поэтому снова запускаем программу. В eax снова 6, F9. Теперь в eax 1, значит произошло исключение. Давайте посмотрим, как протектор его обработает. Пройдя небольшой switch блок мы попадаем на 004019D7, где обрабатывается событие STATUS_BREAKPOINT.

004019D7  mov eax,dword ptr ds:[404064]
004019DC mov ecx,dword ptr ds:[404058]    ;  ntdll.DbgBreakPoint
004019E2  push eax
004019E3  mov eax,dword ptr ds:[404048]
004019E8  push ecx
004019E9  call unpackme.00401AE0

В ecx считывается адрес, где произошло исключение. Сейчас видим что произошло оно в ntdll.DbgBreakPoint (SystemBreakPoint в OllyDbg). При инициализации процесса, Windows вызывает DbgBreakPoint, чтобы отладчик мог произвести какие то действия до запуска процесса. По адресу 004019E9 вызывается функция (00401AE0) как раз и обрабатывающая данное исключение. Давайте войдем в нее и посмотрим, что там такое. F7 и чуть ниже видим

00401AFA  mov ecx,dword ptr ds:[ecx+14]
00401AFD  add ecx,54
00401B00  /mov edi,dword ptr ss:[esp+20]
00401B04  |cmp edi,dword ptr ds:[ecx]
00401B06  |je short unpackme.00401B12
00401B08  |inc eax
00401B09  |add ecx,58
00401B0C |cmp eax,edx
00401B0E \jb short unpackme.00401B00
00401B10 jmp short unpackme.00401B2D

Видим, что в ecx читаются адреса блоков размером 58 байт и первые 4 байта сравниваются с edi. Давайте дотрассируем до этого места и посмотрим что же с чем сравнивается.
В edi находится адрес ntdll.DbgBreakPoint, [ecx]==0. В ecx 00175C4C, давайте посмотрим что же это за блоки такие. Пишем d 00175C4C и вим следующее:

00175C3C  01 00 00 00 23 00 00 00 00 00 00 00 18 31 05 00    ...#....... 1 .
00175C4C  00 00 00 00 4C 65 61 76 65 43 72 69 74 69 63 61  ....LeaveCritica
00175C5C  6C 53 65 63 74 69 6F 6E 00 00 00 00 00 00 00 00  lSection........
00175C6C  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00175C7C  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00175C8C  00 00 00 00 00 00 00 00 01 00 00 00 23 00 00 00  ........ ...#...
00175C9C  00 00 00 00 1C 31 05 00 00 00 00 00 45 6E 74 65  .... 1 .....Ente
00175CAC  72 43 72 69 74 69 63 61 6C 53 65 63 74 69 6F 6E  rCriticalSection

Это явно директория импорта, конвертированная в формат, понятный протектору и непонятный Windows. Выделенные адреса явно адреса IAT целевой программы. Потрассировав этот цикл я заметил, что DWORD по адресу из ecx всегда равен 0. Значит время для работы этого цикла еще не настало. После того, как цикл отработал происходит прыжок на 00401B2D, где видим следующее

00401B29  mov edi,dword ptr ss:[esp+20]
00401B2D mov eax,dword ptr ds:[40440C]
00401B32  test eax,eax
00401B34  push ebp
00401B35  jnz unpackme.00401D89
00401B3B cmp edi,dword ptr ds:[40401C]     ;  unpackme.<ModuleEntryPoint>
00401B41 jnz unpackme.00402088

Потрассировав, замечаем, что первый прыжок не выполнится. Дальше проверяется, произошло ли исключение на EntryPoint дочернего процесса, и если нет, то выполняется прыжок на выход из процедуры. Ставим бряк после условного перехода и жмем F9. Ну вот сработал бряк на EntryPoint. Смотрим, что будет делать протектор:

00401B57  push eax                          ; /pOldProtect
00401B58  mov eax,dword ptr ds:[4043C0]
00401B5D push PAGE_EXECUTE_READWRITE|PAGE_GUARD
00401B62 push ecx                          ; |Size => 62000 (401408.)
00401B63 push edx                          ; |Address => unpackme.00401000
00401B64 push eax                          ; |hProcess => 00000034
00401B65 call dword ptr ds:[VirtualProtectEx]

Он устанавливает права доступа для страниц памяти начиная с 00401000 размером 62000. Флаг PAGE_GUARD означает, что при любом обращении к этой памяти будет происходить исключение STATUS_GUARD, и в доступе к этой области будет отказано. При этом флаг PAGE_GUARD будет сброшен и при повторном обращении к этой области памяти уже ничего не произойдет. Это и есть AntiDump. Но не советую здесь менять права доступа, т.к. исключение STATUS_GUARD протектор использует для распаковки программы. Давайте вернемся к циклу ожидания отладочных сообщений и найдем, где протектор проверяет, что произошло исключение STATUS_GUARD.

004019B5  |mov eax,dword ptr ds:[40404C]    ;  Case 1 of switch 0040197A
004019BA |cmp eax,80000001	 ; STATUS_GUARD
004019BF |je short unpackme.004019F3
004019C1 |cmp eax,80000003	 ; STATUS_BREAKPOINT
004019C6 |je short unpackme.004019D7
004019C8 |cmp eax,C0000005	 ; STATUS_ ACCESS_VIOLATION
004019CD|jnz short unpackme.00401A05

Смотрим, что по адресу 004019F3.

004019F3  |mov edx,dword ptr ds:[404064]
004019F9  |mov ebx,dword ptr ds:[404030]
004019FF  |push edx
00401A00  |call unpackme.00402690

Ставим бряк на 00401A00 и запускаем программу. Видим, что в edx 0044FB18. Это секция кода целевой программы, возможно, что OEP. Жмем F7. Видим, длинную процедуру, в которой по порядку вызываются
VirtualProtectEx с параметром PAGE_EXECUTE_READWRITE, размером 1000h байт
ReadProcessMemory
WriteProcessMemory
VirtualProtectEx с параметром PAGE_EXECUTE_READWRITE|PAGE_GUARD

Это и есть распаковка дочернего процесса и защита от дампа. Давайте выполним все эти функции и выйдем из данной процедуры. Теперь посмотрим, где же произошло исключение. Для этого запустим PE Tools и сдампим дочерний процесс. Теперь загружаем дамп в OllyDbg и тормозимся на EntryPoint. Видим только нули. Всё правильно, защита от дампа сработала и мы сдампили только ту область памяти, где произошло исключение. Теперь перейдем на 0044FB18, именно там произошло обращение к защищенной памяти, и видим:

0044FB18    push ebp
0044FB19    mov ebp,esp
0044FB1B    add esp,-10
0044FB1E    mov eax,Dumped.0044F938
0044FB23    call Dumped.00406064
0044FB28    mov eax,dword ptr ds:[450FF4]
0044FB2D   mov eax,dword ptr ds:[eax]
0044FB2F    call Dumped.0044E098

Классическое начало программ, написанных на Borland Delphi. Значит, первое обращение к памяти происходит на OEP. Теперь закроем отладчик и подумаем, как мы можем обойти AntiDump. Всё, что мне пришло в голову, это симитровать исключение STATUS_GUARD.
При этом надо пропатчить параметр NewProtect при вызове второй VirtualProtectEx, чтобы память больше не защищалась. Перейдем на адрес 00402787, где вызывается VirtualProtectEx второй раз.

00402787  push edx                          
00402788  mov eax,ecx
0040278A xor edx,edx
0040278C div esi
0040278E mov eax,dword ptr ds:[ebx]
00402790 mov edi,dword ptr ds:[ VirtualProtectEx]
00402796  push 140 PAGE_EXECUTE_READWRITE|PAGE_GUARD
0040279B  push esi
0040279C  sub ecx,edx
0040279E  push ecx 
0040279F  push eax
004027A0 call edi                          ; \VirtualProtectEx

И заменим push 140, на push 40. Теперь вернемся на 004019FF, как раз перед вызовом unlock_page и установим счетчик eip на этот адрес (Ctrl+*). Теперь впишем по адресу 404064 (адрес, где произошло исключение) 00401000. И изменим код после вызова unlock_page следующим образом

004019F3  mov edx,dword ptr ds:[404064]
004019F9  mov ebx,dword ptr ds:[404030]
004019FF  push edx
00401A00  call unpackme.00402690 ; unlock_page
00401A05  add dword ptr ds:[404064],1000
00401A0F  cmp dword ptr ds:[404064],unpackme.00463000
00401A19  jnz short unpackme.004019F3

За раз протектор разблокирует страницу размером 1000 байт, и таких страниц у нас 62 (помните параметр Size 62000 у первой VirtualProtectEx?) . Поэтому я сделал цикл, который увеличивает адрес исключения на 1000 при каждой итерации. Теперь ставим бряк после jnz и запускаем программу. Теперь AntiDump убран и можно снова сдампить программу на диск. Дампим и загружаем в OllyDbg. Olly останавливается где то в ntdll, но нам это пока не важно. Перейдем на 0044FB18 (OEP). Первый call вызывает инициализацию программы, выглядит он так:

00406064    push ebx
00406065    mov ebx,eax
00406067    xor eax,eax
00406069    mov dword ptr ds:[45009C],eax
0040606E    push 0
00406070    call 00405FA0

Здесь первый call вызывает GetModuleHandleA. Смотрим, что у нас по адресу 00405FA0.

00405FA0  jmp dword ptr ds:[4531E4]
00405FA6  mov eax,eax
00405FA8  jmp dword ptr ds:[4531E0]
00405FAE  mov eax,eax
00405FB0  jmp dword ptr ds:[4531DC]

Видим переходники на API функции. По адресу 4531E4 должен находится адрес функции GetModuleHandleA. Смотрим, что у нас там.

004531E4  2F003500 00000000 30003500 31003500
004531F4  32003500 00000000 33003500 34003500
00453204  35003500 36003500 37003500 4224807C 
00453214  39003500 3A003500 3B003500 3C003500
00453224  3D003500 3E003500 3F003500 40003500
00453234  41003500 42003500 43003500 44003500

Ну как всегда переходники. Запускаем PE Tools и дампим страницу памяти начиная с 00350000 размером 1000h байт. Смотрим что там у нас.

CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

А она вся нашпигована INT 3 бряками. Получается, что при вызове функции генерируется исключение STATUS_BREAKPOINT и протектор меняет контекст дочернего процесса, подставляя в eip нужный адрес. Сначала я уцепился за эту идею и разобрал протектор на кусочки, вникая в способ получения адреса API. Затем написал скрипт и всё восстановил, но затем меня смутило, что по адресу 00453204 + 0C находится адрес не переходника, а самой API, хотя ни одной функции дочерний процесс еще не вызвал. Выходит, что некоторые функции протектор не обрабатывает. Давайте посмотрим, где протектор записывает 7C802442 по адресу 00453210. Перезапускаем программу и переходим на WriteProcessMemory. Теперь жмем Shift+F2 (поставить условный бряк) и пишем в условии
([esp+8]==00453210h) && ([[esp+0Ch]]==7C802442h). Жмем F9, Olly немного подумает и тормознет. Переходим на адрес возврата и смотри выше

00401E79  push esi                          ;  Case 1 of switch 00401E27
00401E7A call unpackme.00402170

Olly показывает, что это один из вариантов switch блока, находящегося по адресу 00401E27. Смотрим, что там у нас.

00401E05  test byte ptr ds:[eax+44],4
00401E09  je short unpackme.00401E3F
00401E0B mov edi,dword ptr ds:[eax+50]
00401E0E push ebx
00401E0F mov eax,edi
00401E11 call unpackme.004011B0
00401E16 mov dword ptr ss:[esp+1C],eax
00401E1A mov eax,ebx
00401E1C call unpackme.00401240
00401E21 mov ecx,dword ptr ds:[4043D0]
00401E27 cmp ecx,4                         ;  Switch (cases 0..4)
00401E2Amov dword ptr ss:[esp+18],eax
00401E2E ja unpackme.00402088
00401E34 jmp dword ptr ds:[ecx*4+402098]
00401E3B test eax,eax                      ;  Case 0 of switch 00401E27
00401E3D je short unpackme.00401E57

Поставив бряк на 00401E09 и потрассировав я понял, что если прыжок выполняется, то функция эмулируется, иначе вписать настоящий адрес API. Поэтому если мы заменим je на nop;nop, то у нас будет нормальная IAT. Теперь перезапускаем программу, переходим на 00401E09 и меняем je на nop;nop. Переходим на адрес 00402796 и меняем push 140, на push 40. Ставим бряк на обработчике STATUS_GUARD (004019F3) жмем F9, разблокируем память, как было показано выше и дампим дочерний процесс на диск. Адрес IAT мы примерно знаем. Переходим туда, прокручиваем окно вверх, вниз и определяем размер IAT. 004536D4-00453118=5BC. Запускаем ImpREC, OEP=0004FB18, IAT Start = 00051318, IAT Size = 5BC. GetImport, FixDump. Enjoy!

Чтобы не мучиться с поиском IAT можно написать скрипт. Помните тот цикл, где читаются блоки по 58 байт? Так вот по адресу ecx-4 находится адрес функции в IAT. Поэтому проанализировав и отсортировав все найденные адреса мы легко можем найти начало и конец IAT, ну и конечно можно автоматизировать весь процесс распаковки.

Скрипт


//====================================================================
// Beria v0.07 unpacker by PE_Kill
//====================================================================
var temp
var addr
var addr2
var ibase
var pi
var prot
var STATUS_BREAKPOINT
var STATUS_GUARD
var iat_start
var iat_end
var protect_start
var protect_size
var OEP
  // Запоминаем текущий eip
  mov prot,eip
  // Получаем ImageBase
  gmi eip,MODULEBASE
  mov ibase,$RESULT
  
  // Ищем CreateProcess и запоминаем адрес структуры ProcessInformation
  find eip,#E8????????FF15????????68????????68#
  go $RESULT
  sto
  sto
  mov pi,eip
  inc pi
  mov pi,[pi]

  // Ищем магик джамп и меняем его на nop;nop
  find prot,#74348B7850538BC7#
  repl $RESULT,#7434#,#9090#,2
  
  // Ищем обработчик STATUS_GUARD
  find prot,#EB128B15????????8B1D????????52E8#
  mov STATUS_GUARD,$RESULT
  add STATUS_GUARD,2
  // Ищем обработчик STATUS_BREAKPOINT
  find prot,#EB??A1????????8B0D????????50A1#
  mov STATUS_BREAKPOINT,$RESULT
  add STATUS_BREAKPOINT,D
  bp STATUS_BREAKPOINT
  // Дожидаемся когда сработает бряк на EntryPoint
@wait_ep:
  run
  cmp ecx,prot
 jne @wait_ep
  // Ставим бряк на VirtualProtectEx
  gpa "VirtualProtectEx","kernel32"
  mov temp,$RESULT
  bp temp
  run
  bc temp
  // Запоминаем адрес защищаемой памяти и ее размер
  mov protect_start,esp
  add protect_start,8
  mov protect_start,[protect_start]
  mov protect_size,esp
  add protect_size,C
  mov protect_size,[protect_size]

@iat_hooker:
  // Запускаем программу и мы на STATUS_BREAKPOINT
  run
  // Заходим в обработчик
  sti
  sti
  sti
  sti
  // Ищем цикл проверки IAT
  find eip,#83C1548B7C24203B39#
  go $RESULT
  mov addr2,$RESULT
  add addr2,7
  bphws addr2,"x"
  mov addr,$RESULT
  add addr,13
  // Ставим бряк на выходе из цикла
  bphws addr,"x"
  mov iat_start,FFFFFFFF
  mov iat_end,0
  // Ищем начало и конец IAT
@calc_iat:
  run
  cmp eip,addr
 je @end_calc
  mov temp,ecx
  sub temp,4
  mov temp,[temp]
  cmp temp,iat_start
  jae @check_iat_end
  mov iat_start,temp
  jmp @calc_iat
@check_iat_end:
  cmp temp,iat_end
  jbe @calc_iat
  mov iat_end,temp
jmp @calc_iat

@end_calc:  
  add iat_end,4  
  bphwc addr
  bphwc addr2
  
  bc STATUS_BREAKPOINT
  bp STATUS_GUARD
@wait_page_guard:
  run
  // Ищем push 140
  find prot,#6840010000562BCA5150FFD7#
  mov addr,$RESULT
  inc addr
  // Меняем на push 40
  mov [addr],00000040
  bc STATUS_GUARD
  add STATUS_GUARD,6
  sti
  mov OEP,edx
  add protect_size,1000
  sub protect_start,1000
  // Разблокируем память
@decrypt:
  sub protect_size,1000
  cmp protect_size,0
  je @end_decrypt
  add protect_start,1000
  mov edx,protect_start
  sto
  sto
  sto
  mov eip,STATUS_GUARD 
jmp @decrypt

@end_decrypt:    
  bc STATUS_BREAKPOINT
  bc STATUS_GUARD
  add pi,8
  mov pi,[pi]
  sub OEP,ibase
  sub iat_end,iat_start
  eval "File unpacked! PID: {pi}, OEP: {OEP}, IAT:(RVA: {iat_start},SIZE: {iat_end})"
  log $RESULT
  msg $RESULT
  pause
ret




Обсуждение статьи: Распаковка beria v0.07 public >>>


Материалы находятся на сайте https://exelab.ru



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS