SPR I (SecuROM Profiler I)
----------------------------------
Версия 1.2 (20.04.2014)

(С) ELF, 2011-2014
https://exelab.ru/f/index.php?action=vthread&forum=13&topic=19719

					============== КРАТКИЙ ГАЙД (nfo.txt)==============

~ Описание ~
__________

Программа SPR I предназначена для контроля и визуалзации работы виртуальной машины(VM) защиты DMR SecuROM 7 и SecuROM 8.
Разбивка идет по ключевым хранилищам(структурам):
*Красное(RED ONE). Ключевые регистры VM(struct) + зона обмена данными между хендлами. Сюда же можно отнести сохраняемые, после зоны обмена регистры CPU, т.к. Original_CPU_EFLAGS(+8) связан с ними(для SecuROM 8).
*Желтое(YELLOW DELTA). Хранение зашифрованных delta-смещений, если VM в выделенной памяти (в большей степени, актуально для SecuROM 7).
*Синее(BLUE P-CODE). Лента p-code (виртуальный стек)
*Белое(WHITE MULTI-MAIN). Для мультипоточного использования или рекурсии вызовов(SecuROM 8). Хранит адреса всех главных хранилищ(RED ONE). VM выбирает первое свободное(not LOCK) главное хранилище.
Дополнительно предоставляются возможности:
-Обламывание SecuROM Anti-Attach(A.A.). Дает возможность убрать A.A. и присоединиться к запущенному процессу отладчиком.
-Сбор (snapshot) всех известных обращений(CALL VM) в целевом образе и генерация отчета, в папку указанную в config.ini

~ Структура главного хранилища ~
____________________________

*SecuROM 8
struct SecuRom_Main_Supply
{
//////// главные регистры VM ///////////
	LPDWORD Supl_15; //+0
	LPDWORD Virutal_ESP; //+4
	DWORD Original_CPU_EFLAGS; //+8
	VOID Enter_to_VM; //+12
	DWORD Control_Byte; //+16
	LPDWORD Enter_Main_Supply; //+20
	LPDWORD Wrapper_V_EBP; //+24
	DWORD Stack_Pointer; //+28
	LPCVOID NEXT_Subprimitive; //+32
	DWORD lock; //+36
	LPDWORD RESERVED_2; //+40
//////////////// зона обмена данными между примитивами(хендлами, островками) ////////
	DWORD Supply_Save_Area[245]; //(0x400)1024-44=980/4=245
//////////////////
	LPVOID Next_Handle_8; //0x400
//////////// Хранимые CPU (Outside_call_REG) регистры для внешних вызовов ////////
	DWORD Outside_call_REG_EBP; //0x404
	DWORD Outside_call_REG_ESI; //0x408
	DWORD Outside_call_REG_EDI; //0x40C
	DWORD Outside_call_REG_EDX; //0x410
	DWORD Outside_call_REG_ECX; //0x414
	DWORD Outside_call_UNKNOWN_414; //0x414
	DWORD Outside_call_REG_EBX; //0x41C
	DWORD Outside_call_REG_EAX; //0x420
	DWORD Outside_call_UNKNOWN_Area[11];
	DWORD Outside_call_REG_ESP; //0x450 
	
};


*SecuROM 7
struct SecuRom_Main_Supply
{
//////// главные регистры VM ///////////
	LPDWORD Supl_15; //+0
	LPDWORD Virutal_ESP; //+4
	DWORD Original_CPU_EFLAGS; //+8
	VOID Enter_to_VM; //+12
	DWORD Control_Byte; //+16
	LPDWORD Enter_Main_Supply; //+20
	LPDWORD Wrapper_V_EBP; //+24
	DWORD Stack_Pointer; //+28
	LPDWORD RESERVED_1; //+32
	DWORD lock; //+36
	LPDWORD RESERVED_2; //+40
//////////////// зона обмена данными между примитивами(хендлами, островками) ////////
	DWORD Supply_Save_Area[245]; //(0x400)1024-44=980/4=245
	
};

~ Ключевые асм конструкции в VM ~
_____________________________

~~ Связанные с инициализацией VM (самый первый хендл)~~

[------------ ВЫБОР ПЕРВОГО СВОБОДНОГО ГЛАВНОГО ХРАНИЛИЩА ИЗ WHITE MULTI-MAIN (для MT машин)-------------]
01363DAE  |> >B8 FCFFFFFF   /MOV EAX,-4
01363DB3  |. |B9 64000000   |MOV ECX,64
01363DB8  |> |83C0 04       |/ADD EAX,4
01363DBB  |. |8BB8 E471D302 ||MOV EDI,DWORD PTR DS:[EAX+2D371E4] //где 0x2D371E4 - адрес WHITE MULTI-MAIN. Запишите в Profiler.cfg, если отсуствует
01363DC1  |. |817F 24 66666 ||CMP DWORD PTR DS:[EDI+24],66666666
01363DC8  |. |75 06         ||JNE SHORT 01363DD0
01363DCA  |.^|E2 EC         |\LOOP SHORT 01363DB8
01363DCC  |. |F390          |PAUSE
01363DCE  |.^\EB DE         \JMP SHORT 01363DAE

[------------ БЛОКИРОВАНИЕ ВЫБРАННОГО  ГЛАВНОГО ХРАНИЛИЩА-------------]
01363DD3  |.  8D53 24       LEA EDX,[EBX+24]
01363DD6  |.  C702 66666666 MOV DWORD PTR DS:[EDX],66666666

[------------ ОЧИСТКА  ВЫБРАННОГО  ГЛАВНОГО ХРАНИЛИЩА-------------]
01363DDC  |.  B9 00010000   MOV ECX,100
01363DE1  |.  31C0          XOR EAX,EAX
01363DE3  |>  39D7          /CMP EDI,EDX
01363DE5  |.  75 05         |JNE SHORT 01363DEC
01363DE7  |.  8D7F 04       |LEA EDI,[EDI+4]
01363DEA  |.  EB 01         |JMP SHORT 01363DED
01363DEC  |>  AB            |STOS DWORD PTR ES:[EDI]
01363DED  |>^ E2 F4         \LOOP SHORT 01363DE3


[------------ИНИЦИАЛИЗАЦИЯ КЛЮЧЕВЫХ РЕГИСТРОВ VM В ДАННОМ ГЛАВНОМ ХРАНИЛИЩЕ-------------]
01363E27  |.  8903          MOV DWORD PTR DS:[EBX],EAX
01363E29  |.  58            POP EAX
01363E2A  |.  8943 04       MOV DWORD PTR DS:[EBX+4],EAX
01363E2D  |.  8B0424        MOV EAX,DWORD PTR SS:[ESP]
01363E30  |.  8943 08       MOV DWORD PTR DS:[EBX+8],EAX
01363E33  |.  8953 0C       MOV DWORD PTR DS:[EBX+0C],EDX
01363E36  |.  C643 10 95    MOV BYTE PTR DS:[EBX+10],95
01363E3A  |.  895B 14       MOV DWORD PTR DS:[EBX+14],EBX
01363E3D  |.  8963 1C       MOV DWORD PTR DS:[EBX+1C],ESP
01363E40  |.  B8 8478D302   MOV EAX,OFFSET 02D37884
01363E45  |.  8943 20       MOV DWORD PTR DS:[EBX+20],EAX
01363E48  |.  B8 7C73D302   MOV EAX,OFFSET 02D3737C
01363E4D  |.  8943 28       MOV DWORD PTR DS:[EBX+28],EAX

~~ ДЕФОЛТНЫЕ ОПЕРАЦИИ С РЕГИСТРАМИ VM, ВЫПОЛНЯЕМЫЕ ЛЮБЫМ ХЕНДЛОМ (за исключеныем хендлов выхода из VM)~~

[ извлечение указанного DWORD из ленты (виртуального стека) ]
MOV ESI,DWORD PTR DS:[EBX+4] //LPDWORD Virutal_ESP; 
ADD ESI,DWORD PTR DS:[EBX+0C]        //Virutal_ESP+Enter_to_VM
MOV EAX, DWORD PTR DS:[ESI] //лента p-code, для примера = 0x32EC63B7

[ Подготовка Control_Byte для следующего хендла ]
PUSH EAX
MOV CL,BYTE PTR DS:[EBX+10] DWORD (IRL - BYTE) Control_Byte
SHR EAX, 0 //eax = 0x32EC63B7 -- один или несоклько байтов предназначены для изменения Control_Byte
SHR EAX, 18 //eax = 0x00000032 --- ...
XOR AL,29 //eax = 0x0000001B --- типичная операция XOR. реже бывают ADD и SUB
ADD BYTE PTR DS:[EBX+10],AL //установка нового  Control_Byte для следующего хендла
POP EAX

PUSH EAX
.... ключевые операции, определяющие назначение хендла (визуализация инстр. MOV, XOR и тд)
POP EAX

... Подготовка к прыжку на следующий хендл (операции с 0x400 для SecuROM 8; операции с YELLOW DELTA для SecuROM 7)

// ADD V-esp, 8 кол-во DWORD в ленте использованных этим хендлом (4 байт- управляющий DWORD, 8 байт-управляющий DWORD + в подавляющем большинстве случаев закодированный адрес какой-либо фукнции в программе или значения-константы)
ADD DWORD PTR DS:[EBX+4],8

// Переход к слеюущему хендлу(примитиву)
JMP EAX

~~ ВЫХОДЫ из VM ~~

[ Для SecuROM 8 ]
03C30060    C743 24 0000000 MOV DWORD PTR DS:[EBX+24],0 //сброс блокировки у текущего главного хранилища
03C30067    8B9B 1C040000   MOV EBX,DWORD PTR DS:[EBX+41C] //EBX - аналог EAX после выхода из любой фукнции, т.е. return EBX
03C3006D    68 DBBD8601     PUSH 186BDDB
03C30072    C3              RETN

~~ СПЕЦИАЛЬНЫЕ ДЛЯ MT МАШИН~~
[ ПЕРЕКЛЮЧАТЕЛЬ (VM-switcher) ИСПОЛЬЗУЕМЫХ ГЛАВНЫХ ХРАНИЛИЩ]
03C3003C    52              PUSH EDX
03C3003D    9C              PUSHFD
03C3003E    64:8B1D 0400000 MOV EBX,DWORD PTR FS:[4]
03C30045    83EB 04         SUB EBX,4
03C30048    832B 04         SUB DWORD PTR DS:[EBX],4
03C3004B    8B1B            MOV EBX,DWORD PTR DS:[EBX]
03C3004D    83C3 04         ADD EBX,4
03C30050    64:8B15 0400000 MOV EDX,DWORD PTR FS:[4]
03C30057    83EA 04         SUB EDX,4
03C3005A    29DA            SUB EDX,EBX
03C3005C    8B1A            MOV EBX,DWORD PTR DS:[EDX]
03C3005E    9D              POPFD
03C3005F    5A              POP EDX


~ Начало работы ~
_______________
!!! Если Вы в отладчике и контролируйте работу VM, установите точку останова после инициализации текущего главного хранилища на первом хендле. Лучше всего на переход ко 2му хендлу - JMP EAX !!!
!!! так гарантируется правильная первичная инициализация SPR I !!!

1. Необходим запущенный защищенный процесс. В главном окне(Жертва), введите имя процесса(dem2.exe например)  или выберите целевой процесс из списка (combobox). Если в файл Profiler.cfg уже занесен адрес MT хранилища (WHITE MULTI-MAIN)
для этого имени файла, то возможен быстрый старт с помощью командной строки (SPR_I.exe /DEM2.EXE).

2. Если адрес MT или одного главного хранилища (для SecuROM 7) указан верно, то SPR I отобразит текущее состояние RED ONE. Надпись на кнопке "Открыть" поменяется на "Закрыть". По возможности-будет определен
идентефикатор виртуальной машины по ASCII строке, он укажется в заголовке окна(например: <space for rent> для SecuROM 7 или для послдених VM без вступительной ASCII, будет указана 2я строка "cut my life into pieces (:" )

3. Обновление состояния VM может происходить по нажатию соотвествующей кнопки или автоматически.

4. Навигация по всем главным хранилищам происхдит по нажатию соотвествующих кнопок "<" и ">" возле указателя номера текущего главного.

5. Предыдущие состояние VM отбражается с помощью кнопки "<" возле переключателя "Регистры VM/зона обмена данными"

~ ФАЙЛЫ, ПОСТВЛЯЕМЫЕ В КОМПЛЕКТЕ ~
__________________________________

SPR_I.exe - главный исполняемый (CheckSum = 0x00048CC4, md5=0xd37f34fd338693687f294807b40b47b1)
olly_disasm.dll - дизасемблер OllyDbg, подогнанный под SPR I ((CheckSum = 0x00020DA5, md5 = 0xedcd204e32b2221243027d76d25007d2)
Profiler.cfg - файл профилей DRM SecuROM
Config.cfg - файл конфигурации SPR I
olly_disasm.md5, SPR_I.md5 - для сверки (например, в Total Commander)

(!) НЕ используйте файлы, не соответвсующие заявленным контрольным суммам. В ОРИГИНАЛЬНЫХ файлах НЕ содержится вредоносго кода и других фукнций, вызывающих деструктивную деятельность (!)
(!) Возможны срабатывания антивирусов при использовании WINAPI ReadProcessMemory и WriteProcessMemory (при управлении SecuROM Anti_attach или записе Вашего перехватичка в Хранилище №1.5) (!)

~ Настройка конфигурации в Config.cfg ~
__________________________________

Раздел [SecuROM_MT_Options]	 (актуально для SecuROM 8)
	
		Quantity_of_Cells=100  
>>> Тип: DWORD. Система счисления: Hex <<<
	Размерность массива хранилища WHITE MULTI-MAIN. Обычно 0x100. В первых билдах было 0x19

		LOCK_DWORD=66666666
>>> Тип: DWORD. Система счисления: Hex <<<
	Контрольное значение, записываемое регистры VM в главном хранилище. Означает, что текущее  RED ONE заблокировано и его использование при других вызовах VM невозможно.
	Стандартное значение 0x66666666. В ранних билдах в lock(+0x24) забивался мусор, поэтому в след. ключе...

		Cell_blocked_if_not_zero=0
>>> Тип: Bool . Система счисления: Dec . Вариации: 0-false, 1-True <<<
	Считать главное хранилище заблокированным, если lock(+0x24) НЕ РАВЕН нулю.

Раздел [SecuROM_VStack_Options]		(BLUE P-CODE)

		Short_View_Enable=1
>>> Тип: Bool . Система счисления: Dec . Вариации: 0-false, 1-True <<<
	Разрешать короткое представление ленты p-кода, для быстроты работы SPR I при показе. Ввиду того, что в некоторых случаях, ближе к выходу из VM
	 длина ленты достигает нескольких килобайт, показ всей ленты(заполнение Clist) занимает длительное время. Укороченый вариант показывает соседние DWORD ленты
	по текущему указателю LPDWORD Virutal_ESP (+4) и первый V-EBP ( [Wrapper_V_EBP] )

		Min_Distance_when_Enable=10
>>> Тип: DWORD. Система счисления: Dec .<<<
	Минимальная разница в DWORD между V-ESP и V-EBP, при которой активируется короткое представление. Действует, приу условии разрешенного короткого представления(Short_View_Enable=1)

		Quantity_of_Cells_after_VSPointer=7
>>> Тип: DWORD. Система счисления: Dec .<<<
	Кол-во DWORD в ленте, показываемое после V-ESP. Т.к. определение точного размера текущей ленты требует рабочего виртуализатора VM, то за неимением оного, просто показывается след. DWORD.

Раздел [SecuROM_Supply15_Options] 	(YELLOW DELTA)

		Use_my_crypt_byte=0
>>> Тип: Bool . Система счисления: Dec . Вариации: 0-false, 1-True <<<
	Если VM была сдамплена на другой машине, где другой CPUID . Для корректного отображения таблицы delta-смещений (YELLOW DELTA).

		Manual_CPUID_Crypt_byte=92
>>> Тип: DWORD(byte). Система счисления: Hex <<<
	Собственно значение Control_Byte (+0xC)

Раздел [SPR_I]		(параметры непосредственно SPR I)

	HideWindowsCaption=0
>>> Тип: Bool . Система счисления: Dec . Вариации: 0-false, 1-True <<<
	Если SecuROM занесет в черный список и начнет палить SPR I по тексту в окнах. Используйте данный параметр, чтобы запретить SPR I выводить какую-либо информацию в window text, оставляя его пустым.

	SavePath=C:\SPR_Save_VMCALLS\
>>> Тип: String . Система счисления: char .  <<<
	Папка, в которой кладутся отчеты о найденных вызовах VM.

~ ОТЧЕТЫ О ВЫЗОВАХ ВИРТУАЛЬНОЙ МАШИНЫ В ОБРАЗЕ ~
_______________________________________________

Отчет генерируется на основе поиска в секциях кода с атрибутами Executable, в целевом образе. Обнаруживаются следующие конструкции:
C (PUSH OFFSET LP | CALL VM): 					[Адрес вызова] [Ссылка на ленту p-кода] [Первое DWORD ленты] [Тип вызова]
C* (PUSH REG32 | MOV DWORD SS:[EBP-const] | CALL VM): 		[Адрес вызова]  [Кол-во инструкций MOV DWORD PTR SS] [Регистр CPU в стек] [Тип вызова] 
C? (PUSH REG32 | CALL VM): 					[Адрес вызова] [Регистр CPU в стек] [Тип вызова]
J [] (JMP DWORD PTR DS:[adress], [adress] = VM): 			[Адрес вызова] [Адрес-указатель на вход VM] [Тип вызова] 

~ olly_disasm ~
____________

#define DISASM_SIZE    0               // Determine command size only
#define DISASM_DATA    1               // Determine size and analysis data
#define DISASM_FILE    3               // Disassembly, no symbols
#define DISASM_CODE    4               // Full disassembly

#define TEXTLEN        256 
  typedef struct t_disasm {              // Results of disassembling
  DWORD          ip;                   // Instrucion pointer
  char           dump[TEXTLEN];        // Hexadecimal dump of the command
  char           result[TEXTLEN];      // Disassembled command
  char           comment[TEXTLEN];     // Brief comment
  long            cmdtype;              // One of C_xxx
  long            memtype;              // Type of addressed variable in memory
  long            nprefix;              // Number of prefixes
  long            indexed;              // Address contains register(s)
  DWORD          jmpconst;             // Constant jump address
  DWORD          jmptable;             // Possible address of switch table
  DWORD          adrconst;             // Constant part of address
  DWORD          immconst;             // Immediate constant
  long            zeroconst;            // Whether contains zero constant
  long            fixupoffset;          // Possible offset of 32-bit fixups
  long            fixupsize;            // Possible total size of fixups or 0
  long            error;                // Error while disassembling command
  long            warnings;             // Combination of DAW_xxx
} t_disasm;

	ulong Disasm(char *src,ulong srcsize,ulong srcip, t_disasm *disasm,int disasmmode) 

[!] Рабочий пример использования в SPR I:	 
		{
		static t_disasm da;
		Disasm((char*)&Read_Proc_DATA[0],16,VM_Struct.NEXT_Subprimitive,&da,DISASM_CODE);
		::SetWindowText(m_sub_primitive_dissam.m_hWnd,da.result);
		}

~ ВАШИ ПОЖЕЛАНИЯ И ПРЕДЛОЖЕНИЯ, БАГРЕПОРТЫ И ЗАМЕЧАНИЯ ~
________________________________________________________
С УДОВОЛЬСТВИЕМ ПРИНИМАЮТСЯ НА ФОРУМЕ "EXELAB.RU". МНЕ ВАЖНО ВАШЕ МНЕНИЕ И ВАШЕ УЧАСТИЕ!


~ ТИБЕРИУМНЫЙ РЕВЕРСИНГ ~
_________________________
https://youtu.be/U3yZCAnzzVE
https://youtu.be/AcVTF1HfTb8


~ См. также diff_trace ~
___________________
diff_trace также создавался для SecuROM. Основная задача: сравнение двух трейс-логов больших размеров, полученных от OllyDbg 2.0
Последняя версия на данный момент: 0.74
Распространяется с сорцами!
https://ssl.exelab.ru/f/index.php?action=vthread&forum=3&topic=20942





		напоследок
~ ЕСЛИ ВЫ ПЛОХО ПОНИМАЕТЕ, КАК РАБОТАЕТ VM СЕКУРОМА ... ~
____________________________________________________
то позвольте дать один хороший совет! Как говорил Крис Касперски "данные ключ ко всему". Необязательно знать и разбирать саму суть, когда ее можно определить/догадаться по данным с которыми она
работает! Опирайтесь на зону обмена данными между хендлами(CListBox в RED ONE) для 7 и 8 секурома. Особенно будьте внимательны, когда SPR подсвечивает связанные данные! Для SecuROM 8 не 
забывайте посматривать на сохраненные нормальные регистры CPU в VM(сопоставляйте появление адресов фукнций в зоне обмена)  и EFLAGS(+8)-для получения ссылок на условные переходы внутри VM. 
Помните о выходах из VM (lock +0x24) и о свитчерах VM-ТЕПЕРЬ(в 8 секуроме) это ОЧЕНЬ ВАЖНЫЙ буфер данных между вызовами внешних фукнций вируатльной машиной!