Итак, мы имеем не зарегистрированную и упакованную программу. Наша
задача - распаковать и зарегистрировать программу.

Как обычно, эта статья состоит из двух независимых друг от друга этапов: 

1. Распаковка - требует навыков работы с отладчиком sice и опыта
по распаковке.
2. Исследование и взлом уже распакованной программы, будет
очень полезно начинающим.

Для скачивания доступны как запакованная, так и
распакованная версия подопытной программы.

Распаковка

Инструменты, которые я использовал:

  • отладчик SoftIce
  • дизассемблер IDA
  • PE редактор PEEditor 1.7
  • ImpRec 1.4.3+
  • идентификатор файлов PEID v. 0.8

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

Для начало узнаем, чем запакована наша программа. Воспользуемся для этого все
тем же Peid'ом. Запустим peid и откроем в нем наш файл. Мне он показал.

Armadillo 1.xx - 2.xx -> Silicon Realms Toolworks

Как видите достаточно широкий диапазон, возможно существуют более новые версии PEID'а, которые скажут точнее,
но у меня есть только версия 2.67.

Чем запакованы мы знаем, теперь поговорим о самом протекторе, что он из себя представляет.

Armadillo является достаточно мощным средством защиты. Особенностями его является
то, что он запускает себя в двух копиях (процессах). Первый, главный процесс, запускает
второй процесс в отладочном режиме, таким образом в памяти находятся сразу два процесса.
Код же самого протектора никак не шифруется и не скрывается, это является большим плюсом
для нас, т.к. мы с легкостью можем изучить его из дизассемблера, просто дизассемблировав
защищенный .exe файл. Теперь у нас есть представление с чем имеем дело, так что перейдем от теории к практике.

Для начала найдем OEP. Для этого вызовем SoftIce и поставим точку останова на SetProcessWorkingSetSize, 
введем в окно отладчика bpx SetProcessWorkingSetSize и выйдем из
SoftIce. Запускаем нашу программу и оказываемся в отладчике, сработал SetProcessWorkingSetSize, нажмем F12
и окажемся здесь:

017F:008C10D1 E985000000 JMP 008C115B 
017F:008C10D6 E8413FFFFF CALL 008B501C 
017F:008C10DB 6AFF PUSH FF 
017F:008C10DD 6AFF PUSH FF 
017F:008C10DF FF151C918C00 CALL [008C911C] 
017F:008C10E5 50 PUSH EAX 
017F:008C10E6 FF15F4918C00 CALL [008C91F4] 
017F:008C10EC FF1510918C00 CALL [008C9110] ;
здесь мы будем находиться 
017F:008C10F2 A3A01D8D00 MOV [008D1DA0],EAX 
017F:008C10F7 E8284FFFFF CALL 008B6024 
017F:008C10FC 6A00 PUSH 00 
017F:008C10FE E8FA6DFFFF CALL 008B7EFD 
017F:008C1103 8B06 MOV EAX,[ESI] 
017F:008C1105 59 POP ECX 
017F:008C1106 85C0 TEST EAX,EAX ;
пройдем все эти инструкции по F10 
017F:008C1108 7523 JNZ 008C112D 
017F:008C110A E867E2FFFF CALL 008BF376 
017F:008C110F 8B0D941D8D00 MOV ECX,[008D1D94] 
017F:008C1115 FF7614 PUSH DWORD PTR [ESI+14] 
017F:008C1118 8B5154 MOV EDX,[ECX+54] 
017F:008C111B FF7610 PUSH DWORD PTR [ESI+10] 
017F:008C111E 335144 XOR EDX,[ECX+44] 
017F:008C1121 FF760C PUSH DWORD PTR [ESI+0C] 
017F:008C1124 33513C XOR EDX,[ECX+3C] 
017F:008C1127 03C2 ADD EAX,EDX 
017F:008C1129 FFD0 CALL EAX 
017F:008C112B EB2C JMP 008C1159 
017F:008C112D 83F801 CMP EAX,01 
017F:008C1130 7529 JNZ 008C115B 
017F:008C1132 E83FE2FFFF CALL 008BF376 
017F:008C1137 FF7604 PUSH DWORD PTR [ESI+04]
017F:008C113A 8BF8 MOV EDI,EAX
017F:008C113C A1941D8D00 MOV EAX,[008D1D94] 
017F:008C1141 FF7608 PUSH DWORD PTR [ESI+08] 
017F:008C1144 8B4854 MOV ECX,[EAX+54] 
017F:008C1147 334844 XOR ECX,[EAX+44] 
017F:008C114A 6A00 PUSH 00 
017F:008C114C 33483C XOR ECX,[EAX+3C] 
017F:008C114F 03F9 ADD EDI,ECX 
017F:008C1151 E820E2FFFF CALL 008BF376 
017F:008C1156 50 PUSH EAX ;
пока не окажемся 
017F:008C1157 FFD7 CALL EDI ;
здесь, в edi находится адрес OEP, запомним или запишем его 
017F:008C1159 8BF8 MOV EDI,EAX 
017F:008C115B 8BC7 MOV EAX,EDI 
017F:008C115D 5F POP EDI 
017F:008C115E 5E POP ESI 
017F:008C115F C3 RET ;
возврат

Теперь уберем bpx, для этого введем команду bc* и поставим точку останова на
WriteProcessMemory, bpx WriteProcessMemory. Отпустим SoftIce, нажмем F5 сработает bpx, затем два раза F12 и окажемся
здесь:

017F:004123FF 6A00 PUSH 00 ;
если 0 - расшифровывает, 1 - зашифровывает 
017F:00412401 8B4D0C MOV ECX,[EBP+0C] 
017F:00412404 51 PUSH ECX 
017F:00412405 8B5508 MOV EDX,[EBP+08] 
017F:00412408 52 PUSH EDX 
017F:00412409 E876010000 CALL 00412584 ;
функция расшифровки\зашифровки 
017F:0041240E 83C40C ADD ESP,0C ;
здесь мы будем находиться 
017F:00412411 25FF000000 AND EAX,000000FF 
017F:00412416 85C0 TEST EAX,EAX 
017F:00412418 7507 JNZ 00412421 
017F:0041241A 32C0 XOR AL,AL 
017F:0041241C E95D010000 JMP 0041257E 
017F:00412421 A188DA4100 MOV EAX,[0041DA88] ;
вычисление ключа для расшифровки 
017F:00412426 83C001 ADD EAX,01 ;
увеличиваем eax для расшифровки следующего блока 
017F:00412429 A388DA4100 MOV [0041DA88],EAX 
017F:0041242E 8B0D84DA4100 MOV ECX,[0041DA84] 
017F:00412434 8D148DFCFFFFFF LEA EDX,[ECX*4-0004] 
017F:0041243B 52 PUSH EDX 
017F:0041243C A18CDA4100 MOV EAX,[0041DA8C] 
017F:00412441 50 PUSH EAX 
017F:00412442 8B0D8CDA4100 MOV ECX,[0041DA8C] 
017F:00412448 83C104 ADD ECX,04 
017F:0041244B 51 PUSH ECX 
017F:0041244C E83F1A0000 CALL 00413E90 ;
вычисление 
017F:00412451 83C40C ADD ESP,0C 
017F:00412454 8B158CDA4100 MOV EDX,[0041DA8C] 
017F:0041245A 8B4508 MOV EAX,[EBP+08] 
017F:0041245D 8902 MOV [EDX],EAX 
017F:0041245F 8B4D10 MOV ECX,[EBP+10] 
017F:00412462 81E1FF000000 AND ECX,000000FF 
017F:00412468 85C9 TEST ECX,ECX 
017F:0041246A 0F850C010000 JNZ 0041257C 
017F:00412470 8B1588DA4100 MOV EDX,[0041DA88] 
017F:00412476 3B1570A64100 CMP EDX,[0041A670]
017F:0041247C 0F8EFA000000 JLE 0041257C ;
если прыжка не происходит, функция зашифровывает блоки 

Защита расшифровывает блоки, причем с каждым шагом вычисляет новый ключ расшифровки и по
ходу их зашифровывает. Зашифровывать их нам не надо, поэтому изменим условный переход по
адресу 0041247C: 

JLE 0041257C 0F8EFA000000 

на 

JGE 0041257c 7DFE 90909090

прыжок будет происходить всегда и блоки зашифровываться не будут.

Находясь в SoftIce нажмем еще раз F12 и окажемся в отладочном цикле, главной копии программы.

Исходник

Количество блоков можно узнать разделив размер кодовой секции на 1000
hex.
1000 hex - размер блока.
Размер же кодовой секции можно узнать из таблицы секции, вычесть из Virtual Offset секции
DATA, Virtual Offset секции CODE.


017F:00410700 A1ACA24100 MOV EAX,[0041A2AC] 
017F:00410705 33054CA24100 XOR EAX,[0041A24C] 
017F:0041070B 33057CA24100 XOR EAX,[0041A27C] 
017F:00410711 05FF0F0000 ADD EAX,00000FFF ;
деление на 1000 hex 
017F:00410716 C1E80C SHR EAX,0C ; 
017F:00410719 A384DA4100 MOV [0041DA84],EAX ;
помещаем по адресу [0041DA84] 

Чтобы сделать нормальный дамп нам потребуется расшифровать все блоки кодовой секции.
Для этого будем вызывать цикл распаковки начиная с адреса 0041192D для каждого блока.
Сделаем в SoftIce следующие, находясь по адресу 004119DF введем: 


a eip
inc dword ptr, [EBP+FFFFFA18]
jmp 0041192D

Мы сделали цикл распаковки, теперь изменим номер блока по адресу [EBP+FFFFFA18]
на 0, чтобы начать расшифровывать с первого блока.

Выход из цикла обеспечивают инструкции:


017F:0041192D 8B8D18FAFFFF MOV ECX,[EBP+FFFFFA18] ;
номер текущего расшифрованного блока 
017F:00411933 3B0D84DA4100 CMP ECX,[0041DA84] ;
сравнивается с количеством 
017F:00411939 0F8DB5000000 JGE 004119F4 ;
если больше или равно прыжок на 004119F4

Заменим инструкцию JGE 004119F4 на прыжок на себя, введем в
SoftIce'e 411939 и впишем EBFE. Теперь, когда все блоки будут расшифрованы, программа зациклится
на 00411939 и нам останется только снять дамп.

Запустим PEEditor, нажмем "browse" и сделаем нашему процессу full dump.

Теперь восстановим импорт. Для защиты импорта aramdillo переадресовывает таблицу импорта. Наша задача
найти место где происходит переназначение и сделать так, чтобы импорт не был переадресован.

Поставим bpx на GetProcAddress, bpx GetProcAddress и запустим нашу программу,
когда сработает bpx мы окажемся в этом месте.


017F:008B5E54 750B JNZ 008B5E61 
017F:008B5E56 FF76F8 PUSH DWORD PTR [ESI-08] 
017F:008B5E59 FF1504918C00 CALL [008C9104] 
017F:008B5E5F 8906 MOV [ESI],EAX 
017F:008B5E61 391E CMP [ESI],EBX 
017F:008B5E63 7419 JZ 008B5E7E 
017F:008B5E65 8B7EFC MOV EDI,[ESI-04] 
017F:008B5E68 391F CMP [EDI],EBX 
017F:008B5E6A 7412 JZ 008B5E7E ; 
017F:008B5E6C FF37 PUSH DWORD PTR [EDI] ;
имя функции 
017F:008B5E6E FF36 PUSH DWORD PTR [ESI] ;
модуль 
017F:008B5E70 FF1500918C00 CALL [008C9100] ;
вызов GetProcAddress 
017F:008B5E76 89470C MOV [EDI+0C],EAX ;
мы будем находиться здесь 
017F:008B5E79 83C710 ADD EDI,10 
017F:008B5E7C EBEA JMP 008B5E68 ;
прыжок на 008B5E68 
017F:008B5E7E 83C60C ADD ESI,0C 
017F:008B5E81 395EF8 CMP [ESI-08],EBX 
017F:008B5E84 75C1 JNZ 008B5E47 
017F:008B5E86 E998000000 JMP 008B5F23 
017F:008B5E8B 381DE8108D00 CMP [008D10E8],BL 
017F:008B5E91 0F858C000000 JNZ 008B5F23 
017F:008B5E97 895DDC MOV [EBP-24],EBX 
017F:008B5E9A 8B45DC MOV EAX,[EBP-24] 
017F:008B5E9D 3B05F4108D00 CMP EAX,[008D10F4]

Сделаем по-простому, просто пропустим пару прыжков по адресу 008B5E6A.
Запускаем ImpRec, выбираем наш процесс, вводим OEP: 00003F00, жмем IAT AutoSearch
и GetImport и получаем полный импорт. Теперь нам остается лишь вставить его в наш дамп.

Можно еще уменьшить размер программы, отрезав ненужные секции протектора и сделав
rebuild.

Check Also

Дырявые диски. Эксплуатируем уязвимости в сетевых хранилищах Synology

Защита данных, приватность и соответствие нормам безопасного хранения информации — то, над…

Оставить мнение