Files
Kubok-Regionov/MetamorphicCore-Reverse/solve/writeup.md
2025-12-22 05:19:38 +03:00

290 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Writeup: Metamorphic Core Crackme
## **Используемые инструменты**
- **DnSpy**
- **Detect It Easy**
- **UPX**
- **ExtremeDumper**
- **.NET Reactor Slayer**
---
## **Шаг 1. UPX упаковка**
Загружаем файл в **Detect It Easy** и видим, что он упакован **UPX**.
Попытка распаковать через `upx.exe -d <file>` неудачна — заголовок повреждён.
Открываем бинарь в **Hex Editor** и сравниваем заголовок с эталонным.
Находим строку `MCVM` вместо `UPX0`. Исправляем байты на **UPX0** и успешно распаковываем через `upx -d`.
---
## **Шаг 2. Native-загрузчик .NET Reactor**
Повторная проверка в **Detect It Easy** показывает: код нативный, обфусцирован **.NET Reactor**.
Это значит, что бинарь упакован в **native loader**.
Открываем EXE в **DnSpy (32-bit)** и запускаем. На точке **CreateProcess** видно, что процесс распакован и висит в памяти.
Используем **ExtremeDumper** → находим `task.exe` → делаем дамп. Получаем два файла:
- **_.dll**
- **VmHost.exe**
---
## **Шаг 3. Деобфускация .NET Reactor**
Открываем **VmHost.exe** в **DnSpy** или **Detect It Easy** — видим сильную обфускацию.
Запускаем **.NET Reactor Slayer**, выбираем все опции и запускаем деобфускацию.
Теперь бинарь читаем и доступен для отладки.
---
## **Шаг 4. Отладка VM**
Открываем **VmHost.exe** в **DnSpy**.
Ставим брейкпоинт в произвольном месте и смотрим окно **Local Variables**.
Видим переменные:
- **this.dictionary_***
- **this.list_***
- **this.stack_***
- **this.object_***
Здесь хранятся строки с именами функций виртуальной машины: **SHA256**, **ExitProcess**, **sha256_hex**, **tohex** и др.
Значит, вызовы идут через опкод **CALL** в VM.
---
## **Шаг 5. Поиск вызовов функций**
Находим функцию, отвечающую за вызов методов:
```csharp
private void method_3(int int_3, int int_4)
{
Class3.Struct0 @struct;
for (;;)
{
IL_177:
@struct = this.struct0_0[int_3];
int num = 0; <-------------------------- Тут ставим брейкпоинт
if (<Module>{3a1b6496-e3bc-4dd9-bc7f-29db217cfc86}.m_b53c11d96ca540509b6b9be7f90e8419 != 0)
{
goto IL_F4;
}
Class3.Struct1 struct2;
for (;;)
{
IL_123:
int num2;
switch (num)
{
case 0:
goto IL_B5;
case 1:
goto IL_F4;
case 2:
goto IL_177;
case 3:
case 4:
goto IL_A0;
case 5:
num2--;
num = 2;
if (<Module>{3a1b6496-e3bc-4dd9-bc7f-29db217cfc86}.m_656fb7edff9a4bc3a280e41bdde428a0 != 0)
{
goto IL_A0;
}
continue;
case 6:
goto IL_6B;
case 7:
goto IL_D4;
case 8:
goto IL_197;
case 9:
goto IL_4F;
case 10:
return;
case 11:
goto IL_44;
case 12:
goto IL_62;
case 13:
goto IL_47;
case 14:
num2 = @struct.int_1 - 1;
num = 0;
if (<Module>{3a1b6496-e3bc-4dd9-bc7f-29db217cfc86}.m_9fc4e4f74325466da9db2cc7afcf1357 == 0)
{
goto IL_A0;
}
continue;
case 15:
goto IL_1B4;
case 16:
goto IL_30;
case 17:
break;
default:
goto IL_B5;
}
IL_06:
struct2.object_0[num2] = this.stack_0.Pop();
num = 5;
if (<Module>{3a1b6496-e3bc-4dd9-bc7f-29db217cfc86}.m_61742430ed914e4ca05833d60e3db39b == 0)
{
break;
}
continue;
IL_A0:
if (num2 >= 0)
{
goto IL_06;
}
num = 0;
if (<Module>{3a1b6496-e3bc-4dd9-bc7f-29db217cfc86}.m_4090cbdba33d4db1ba74b2a9eac02aa1 == 0)
{
continue;
}
IL_B5:
this.stack_1.Push(struct2);
num = 3;
if (<Module>{3a1b6496-e3bc-4dd9-bc7f-29db217cfc86}.m_fe002c72199d46f0b4a52d0c2bff689e == 0)
{
goto Block_4;
}
}
continue;
IL_30:
Class3.Struct1 struct3;
struct2 = struct3;
num = 14;
if (<Module>{3a1b6496-e3bc-4dd9-bc7f-29db217cfc86}.m_0425df13f0c045d99d31a6db275fbd9e == 0)
{
goto IL_44;
}
goto IL_123;
IL_6B:
struct3.int_1 = 0;
num = 3;
if (<Module>{3a1b6496-e3bc-4dd9-bc7f-29db217cfc86}.m_d940aa626e044e7a9f22554ba2f6bb07 == 0)
{
goto IL_30;
}
goto IL_123;
IL_62:
int num3;
struct3.int_0 = num3;
goto IL_6B;
IL_4F:
struct3.object_0 = new object[@struct.int_2];
goto IL_62;
IL_47:
struct3 = default(Class3.Struct1);
goto IL_4F;
IL_45:
int num4;
num3 = num4;
goto IL_47;
IL_D4:
num4 = this.int_0;
goto IL_45;
IL_F4:
if (int_4 != @struct.int_1)
{
goto Block_6;
}
if (this.stack_1.Count != 0)
{
goto IL_D4;
}
num = 4;
if (<Module>{3a1b6496-e3bc-4dd9-bc7f-29db217cfc86}.m_b0871c76b442400c9823273656177106 == 0)
{
goto IL_123;
}
IL_44:
num4 = -1;
goto IL_45;
}
Block_4:
goto IL_1B4;
Block_6:
IL_197:
throw new Exception(Class5.smethod_17(656) + @struct.string_0);
IL_1B4:
this.int_0 = @struct.int_0;
}
```
В локальной переменной **@struct** появляются названия функций, которые будут выполняться.
Здесь видим вызов **exists**, и в **object_0** лежит строка:
```
C:\Users\user\AppData\Local\Temp\.password\metamorphic.core
```
Значит, программа требует этот файл. Создаём его с любыми данными:
```
test1
test2
test3
```
## **Шаг 6. Работа с файлом**
Перезапускаем отладку. Теперь программа не падает, т.к. файл найден.
Следующий вызов — **"read_all_ascii"**. В **object_0** появляются строки из файла.
Затем вызываются **slice** и вспомогательные функции, которые берут первые две строки.
После вызывается **abort**, и программа завершается.
## **Шаг 7. Проверка условий (IF)**
Ищем в коде VM функции условий IF:
```csharp
[CompilerGenerated]
private bool method_21(object object_2, object object_3)
{
return this.method_8(object_2, object_3); // Equals
}
[CompilerGenerated]
private bool method_22(object object_2, object object_3)
{
return !this.method_8(object_2, object_3); // Equals
}
```
Ставим брейкпоинты и видим сравнение строк:
```csharp
object_2 = "test1"
object_3 = "MetamorphicVirtualMachine"
```
Значит, первая строка файла должна быть MetamorphicVirtualMachine.
## **Шаг 8. XOR-дешифровка второй строки**
Дальше вызывается функция **xorstr**.
В **object_0** лежит строка **+)8$)/e%+':-zxz}** и ключ **0x48**.
Расшифровка XOR даёт строку:
```
caplag-mcore2025
```
Эта строка сравнивается со второй строкой файла.
Итого, правильное содержимое файла **metamorphic.core**:
```
Metamorphic Core :: crackme
Привет: DESKTOP-6IRVEAN, user user
OK: заголовки валидны
caplag{6ed9095fc6d38efbdea82031d16150c1b80c16cd641a135f117bdc411dbba68a}
Готово
```
✅ Флаг:
```
caplag{6ed9095fc6d38efbdea82031d16150c1b80c16cd641a135f117bdc411dbba68a}
```