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

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

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

Распаковка Ntkrnl packer
  #1  
Старый 18.10.2007, 19:16
0x0c0de
Постоянный
Регистрация: 25.05.2007
Сообщений: 448
Провел на форуме:
4226446

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

Распаковка Ntkrnlpacker.

[Intro]

Итак, в связи с болезнью появилось свободное время, которое я трачу на реверсинг и математику. Что мне удалось написать под температурой 38 читаем ниже. Пинаемся, кусаемся и критикуем как обычно в комментариях=).

[Начнем]

Вот, что пишут про данный прот

Цитата:
NTkrnl Packer uses new and unique encryption polymorphic technology and provides software developers and publishers with an undetectable level of encryption to significantly increase their revenues.

+ Anti-cracking
NTkrnl Packer has innovative powerful routine against the reverse engineering in the business. It has new code protection features to stop the latest cracking software and cracker issues.

...

+ Code and Resource Compression
In addition to protection features, NTkrnl Packer allows you to compres

+ Compatible with several Development Tools
NTkrnl Packer is able to pack software written in Delphi, C++ Builder, Microsoft Visual C++, Visual Basic.
И все в таком духе. В общем как обычно. Раньше об этом агрегате не слышала, стало интересно посмотреть, что за зверь. А зверь оказался интересный. Начнем с entry point запакованной программы

Код:
00401061 C>  68 5D544100                  PUSH anyprog.0041545D
00401066     E8 01000000                  CALL anyprog.0040106C
0040106B     C3                           RETN
0040106C     C3                           RETN
И, черт возьми, в этом было нечто знакомое ;-) Проблема возникла с отладкой. Оля до определенного момента дебажила, а потом прога вылетала. Причем что только я не перепробовала. Конечно, возникла идея приаттачится к процессу, но об этом чуть позже. Сначала расскажу о тех анти-дебаг приемах, которые используются (встретившиеся мне до того, как Оля уперлась рогами и отказалась работать).
Ниже привожу два куска кода, которые с завидным постоянством и незначительной модификацией кочуют из сорца в сорец)
Спаливание Оли через RDTSC

Код:
00415F3D     0F31                         RDTSC
00415F3F     33C9                         XOR ECX,ECX
00415F41     03C8                         ADD ECX,EAX
00415F43     0F31                         RDTSC
00415F45     2BC1                         SUB EAX,ECX
00415F47     3D FF0F0000                  CMP EAX,0FFF
00415F4C     72 04                        JB SHORT anyprog.00415F52
00415F4E     0F31                         RDTSC
00415F50     50                           PUSH EAX
И обнуление др-регистров (через seh)

Код:
00415FE6     55                           PUSH EBP
00415FE7     8BEC                         MOV EBP,ESP
00415FE9     BB 00010000                  MOV EBX,100
00415FEE     F7D3                         NOT EBX
00415FF0     8B45 10                      MOV EAX,DWORD PTR SS:[EBP+10]
00415FF3     2198 C0000000                AND DWORD PTR DS:[EAX+C0],EBX
00415FF9     8BB8 C4000000                MOV EDI,DWORD PTR DS:[EAX+C4]
00415FFF     C740 04 00000000             MOV DWORD PTR DS:[EAX+4],0 ; обнуляем др0 регистр
00416006     3E:FF37                      PUSH DWORD PTR DS:[EDI]
00416009     64:8F05 00000000             POP DWORD PTR FS:[0]
00416010     C740 08 00000000             MOV DWORD PTR DS:[EAX+8],0 ; обнуляем др1 регистр
00416017     8380 C4000000 08             ADD DWORD PTR DS:[EAX+C4],8
0041601E     8BB8 A4000000                MOV EDI,DWORD PTR DS:[EAX+A4]
00416024     C740 0C 00000000             MOV DWORD PTR DS:[EAX+C],0 ; обнуляем др2 регистр
0041602B     89B8 B8000000                MOV DWORD PTR DS:[EAX+B8],EDI
00416031     8B5D 10                      MOV EBX,DWORD PTR SS:[EBP+10] 
00416034     33C0                         XOR EAX,EAX
00416036     8943 10                      MOV DWORD PTR DS:[EBX+10],EAX  ; обнуляем др3 регистр
00416039     8943 14                      MOV DWORD PTR DS:[EBX+14],EAX  ; обнуляем др6 
0041603C     C743 18 55010000             MOV DWORD PTR DS:[EBX+18],155 ; пишем в др7
00416043     8B83 B0000000                MOV EAX,DWORD PTR DS:[EBX+B0]
Потом проверка на бряки. Причем проверяет только первый байт функции. В общем не страшно.

Код:
00415FA7     55                           PUSH EBP
00415FA8     8BEC                         MOV EBP,ESP
00415FAA     8B45 08                      MOV EAX,DWORD PTR SS:[EBP+8]
00415FAD     0340 3C                      ADD EAX,DWORD PTR DS:[EAX+3C]
00415FB0     05 80000000                  ADD EAX,80
00415FB5     8B08                         MOV ECX,DWORD PTR DS:[EAX]
00415FB7     034D 08                      ADD ECX,DWORD PTR SS:[EBP+8]
00415FBA     83C1 10                      ADD ECX,10
00415FBD     8B01                         MOV EAX,DWORD PTR DS:[ECX]
00415FBF     0345 08                      ADD EAX,DWORD PTR SS:[EBP+8]
00415FC2     8B18                         MOV EBX,DWORD PTR DS:[EAX]
00415FC4     803B CC                      CMP BYTE PTR DS:[EBX],0CC ; проверочка
00415FC7     74 18                        JE SHORT anyprog.00415FE1
00415FC9     8B55 0C                      MOV EDX,DWORD PTR SS:[EBP+C]
00415FCC     891A                         MOV DWORD PTR DS:[EDX],EBX
00415FCE     83C0 04                      ADD EAX,4
00415FD1     8B18                         MOV EBX,DWORD PTR DS:[EAX]
00415FD3     803B CC                      CMP BYTE PTR DS:[EBX],0CC ; проверочка
00415FD6     74 09                        JE SHORT anyprog.00415FE1
00415FD8     8B55 10                      MOV EDX,DWORD PTR SS:[EBP+10]
00415FDB     891A                         MOV DWORD PTR DS:[EDX],EBX
00415FDD     5D                           POP EBP
Себя защита распаковывает долго и извратно. Там очень большой цикл (повторяющийся много раз), который здесь не приводится. А теперь вернемся к нашему процессу. Аттачимся. Оля ругнется на невалидный файл, так как присутствует антидамп, но о нем чуть позже. Теперь вопрос, как в такой ситуации найти oep? Ответ – посмотреть в стек. Кстати, как в самом протекторе, так и в нескольких тестовых запакованных программах с oep байт не крадется, что для нас большой плюс. Значит скролим окно стека вниз к самому началу и ищем первый адрес возврата, принадлежащий коду программы. Этот адрес будет находиться в непосредственной близости от oep. Будете ворчать, что способ нехороший. Знаю я, знаю) Но тем не менее в сработал успешно (несколько раз, а это уже статистика). Опять же. Дамп снимать еще пока нельзя. Так как у нас уже искажены переменные и с немалой долей вероятности программа будет работать неправильно, а некоторые (и много таких) программы вообще проверяют значение переменных. Так как в таком случае нам получить правильный дамп? Заинжектить длл, которая будет перехватывать какую-либо функцию, вызывающуюся непосредственно в oep-процедуре. Если,например, это делфи-программа, то идельно подходит GetModuleHandleA (в зависмости от компилятора это может быть __set_app_type или GetVersion). Причем нужно проверять адрес возврата, который мы знаем точно. И после этого (если все совпало), зацикливаем программу и дампим. В мое тестовом примере была прога на MingWin32 GCC 3.x. Оставим пока эту идею с dll и поговорим об импорте. Часть функций есть, а часть адресов нет. Смотрим (привожу кусок).

Код:
00407120  00F00000
00407124  00F00084
00407128  00F00108
0040712C  00F0018C
00407130  00F00210
00407134  00F00294
00407138  00F00318
0040713C  00F0039C
00407140  00F00420
00407144  00000000
00407148  00000000
0040714C  77C0EEEB  msvcrt.__getmainargs
00407150  77C0F1C5  msvcrt.__p__environ
00407154  77C0F1DB  msvcrt.__p__fmode
00407158  77C2537C  msvcrt.__set_app_type
Что у нас по адресу 00F00000?

Код:
00F00000     60                           PUSHAD
00F00001     E8 00000000                  CALL 00F00006
00F00006     5D                           POP EBP
00F00007     81ED 0F469400                SUB EBP,94460F
00F0000D     FFB5 81469400                PUSH DWORD PTR SS:[EBP+944681]
00F00013     FFB5 85469400                PUSH DWORD PTR SS:[EBP+944685]
00F00019     FFB5 89469400                PUSH DWORD PTR SS:[EBP+944689]
00F0001F     FFB5 79469400                PUSH DWORD PTR SS:[EBP+944679]
00F00025     FFB5 7D469400                PUSH DWORD PTR SS:[EBP+94467D]
00F0002B     E8 08000000                  CALL 00F00038
00F00030     894424 1C                    MOV DWORD PTR SS:[ESP+1C],EAX
00F00034     61                           POPAD
00F00035     FFE0                         JMP EAX
00F00037     C3                           RETN
Джамп еах передает управление оригинальной функции. Все переходники одинаковые. То же самое по адресу 00F0018C и всем остальным.
Из этого всего делаем вывод. Запросто теперь напишем скрипт, восстанавливающий импорт. Он попросит ввести начало таблицы и ее конец. Принцип такой. Проходимся по всей таблице, берем невалидный адрес, устанавливаем eip на него ищем опкод jmp eax, ставим на него точку останова, выполняем… Кладем значение eax на место невалидного адреса.

Код:
var iat_begin
var iat_end
var element
var iat_end_
var jaddr

ask "Iat begin"
mov iat_begin,$RESULT
cmp iat_begin,0
je fin

ask "Iat end"
mov iat_end,$RESULT
add iat_end,4
mov iat_end_,$RESULT
add iat_end_,4
cmp iat_end,0
je fin
mov element,iat_begin
mov eip,[element]

start:
findop eip,#FFE0#  ; jmp eax
mov jaddr,$RESULT 
bphws jaddr,"x" ; хардвар на джамп еах
run
mov [element],eax 
add element,4
cmp element,iat_end_
je fin 
cmp [element],0 ; ноль? пропускаем
je add_
cmp [element],50000000 ; адрес уже есть? пропускаем
ja add_
mov eip,[element]
bphwc jaddr
jmp start

fin:
msg "Done" 
ret

add_:
add element,4
cmp element,iat_end_
je fin 
je fin 
cmp [element],0
je add_
cmp [element],50000000 ; адрес уже есть? пропускаем
ja add_
mov eip,[element]
bphwc jaddr 
jmp start
Получаем нормальную таблицу. А теперь снова о dll. В моем случае oep

Код:
00401240     55                           PUSH EBP
00401241     89E5                         MOV EBP,ESP
00401243     83EC 08                      SUB ESP,8
00401246     C70424 02000000              MOV DWORD PTR SS:[ESP],2
0040124D     FF15 58714000                CALL DWORD PTR DS:[407158]                            ; msvcrt.__set_app_type
00401253     E8 A8FEFFFF                  CALL anyprog.00401100
Значит интересует нас функция __set_app_type из msvcrt.dll. Ее и будем перехватывать. Далее код искомой dll. Ассемблер …. Я здесь ничего не оптимизировала и писала на скорую руку. Важно было быстро получить результат

Код:
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib kernel32.lib
includelib user32.lib
.data
lib db "msvcrt.dll",0
proc_ db "__set_app_type",0
buffersbytes db 6 dup (?)
func_ dword ?
.code
unhook proc
mov esi,offset buffersbytes
mov edi,func_
mov ecx,6
rep movsb
ret
unhook  endp

hook_ proc
mov edi,func_
mov byte ptr[edi],068h
mov dword ptr [edi+1],offset hooked_
mov byte ptr[edi+5],0c3h
ret
hook_ endp

loop_ proc
local dwOldProtect:dword
invoke VirtualProtectEx,-1,00401253h, 3, PAGE_EXECUTE_READWRITE,addr dwOldProtect
mov edi,00401253h
mov word ptr[edi],0feebh ; бесконечный цикл
ret
loop_ endp

hooked_ proc par1:dword
cmp dword ptr[esp+4],00401253h ; адрес возврата
jnz ret_ 
call loop_
ret_:
call unhook
push par1
call func_
pop par1
call hook_
ret
hooked_ endp

DllEntry proc hInstance:HINSTANCE, reason:DWORD, reserved1:DWORD
local dwOldProtect:dword
	cmp  reason,DLL_PROCESS_ATTACH
	jnz ret__
	pushad
	invoke GetModuleHandleA,offset lib
	test eax,eax
	jnz gaddress_
	invoke LoadLibrary,offset lib
	test eax,eax
	je ext
	gaddress_:
	invoke GetProcAddress,eax,offset proc_
	test eax,eax
	je ext
	mov func_,eax
	invoke VirtualProtectEx,-1,func_, 6, PAGE_EXECUTE_READWRITE,addr dwOldProtect
	test eax,eax
    jz ext
    mov edi,func_
    mov esi,offset buffersbytes
    mov dl,byte ptr[edi]
    mov byte ptr[esi],dl
    mov edx,dword ptr[edi+1]
    mov dword ptr[esi+1],edx
    mov dl,byte ptr[edi+5]
    mov byte ptr[esi+5],dl
    mov byte ptr[edi],068h
    mov dword ptr [edi+1],offset hooked_
    mov byte ptr[edi+5],0c3h
	ext:
	popad
	jmp ret_
	ret__:
	call unhook
	ret_:
	ret
DllEntry Endp
End DllEntry
Вот. Ее и заинжектим.
Дамп. Выбираем опцию LordPE: Active dump engine->IntelliDump->Select! И дампим. Импорт восстанавливаем с помощью Imprec и нашего скрипта… На этом этапе последнее- это исправление двух байт, использующихся для зацикливания по адресу 00401253h (адрес возврата из функции). EBFE на E8A8.
Все.

-----------------------Добавлено-------------------------------
Мешало отладке то, что прот устанавливал на память аттрибут PAGE_EXECUTE_READ|PAGE_GUARD. В Phantom plugin надо включить опцию Custom handler exceptions, тогда все будет норм отлаживаться. Антиотладка

Код:
00416957     6A 04                        PUSH 4
00416959     68 00100000                  PUSH 1000
0041695E     68 00100000                  PUSH 1000
00416963     6A 00                        PUSH 0
00416965     E8 78FFFFFF                  CALL CyberPro.004168E2                                ; JMP to kernel32.VirtualAlloc
0041696A     C600 C3                      MOV BYTE PTR DS:[EAX],0C3
0041696D     8985 9F029D01                MOV DWORD PTR SS:[EBP+19D029F],EAX
00416973     8D85 9B029D01                LEA EAX,DWORD PTR SS:[EBP+19D029B]
00416979     50                           PUSH EAX
0041697A     68 20010000                  PUSH 120
0041697F     6A 10                        PUSH 10
00416981     FFB5 9F029D01                PUSH DWORD PTR SS:[EBP+19D029F]
00416987     E8 50FFFFFF                  CALL CyberPro.004168DC                                ; JMP to kernel32.VirtualProtect
0041698C     8B85 9F029D01                MOV EAX,DWORD PTR SS:[EBP+19D029F]
00416992     FFD0                         CALL EAX
00416994     0F31                         RDTSC
00416996     50                           PUSH EAX
00416997     C3                           RETN
(с) 0x0c0de 2007

Последний раз редактировалось 0x0c0de; 21.10.2007 в 15:42..
 
Ответить с цитированием
 



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Private Personal Packer 1.02 Isis Forum for discussion of ANTICHAT 3 25.08.2007 21:50
Распаковка PESpin 0.7 taha Авторские статьи 1 11.12.2006 01:10
Распаковка Upx'ов для новичков KindEcstasy Авторские статьи 0 29.11.2006 22:45
Ручная распаковка и взлом HP-crackme ProTeuS Авторские статьи 2 14.08.2006 16:23



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


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




ANTICHAT.XYZ