Анализ современного программного обеспечения

Современное программное обеспечение сочетает в себе как Native, так и Managed программный код. Из вышеуказанного видно, что удобный анализ на основе декомпилированного кода не всегда возможен, на основе дизассемблированных в код СIL листингов так же затруднителен. Можно заметить, что в общем случае, анализ высокоуровневого программного кода гораздо удобнее анализа CIL инструкций и Native ассемблера. Однако, было так же показано, что не во всех случаях высокоуровневый код является удобным для понимания.

Управляемые сборки хранят в своем составе множество метаинформации. Такая метаинформация используется различными декомпиляторами для восстановления структуры кода. Генерация управляемых средой CLR объектов происходит во время выполнения кода. К таким объектам относятся как структуры данных различных типов, так и различные функциональные объекты.

Распространенные расширения SOS и SOSEX для отладчика WinDBG, как показали исследования, имеют ряд недостатков. Задача анализа смешанного (Native и Managed) кода значительно усложняется в случае отсутствия доступа к файлам символов.

В [12] изложено введение в функционирование программного модуля создания Rut-Time объектов в платформе .NET Framework. Генерируемый JIT-компилятором код так же является динамически создаваемым объектом и располагается в куче. The just-in-time (JIT) compiler generates x86 instructions and stores them on the JIT Code Heap [12]. На рис. 5 изображен снимок распределения памяти, полученный утилитой VMMap пакета SysinternalsSuite [13]

Рис. 5. Снимок распределения памяти управляемого процесса

Из рис. 5 мы видим, что управляемая куча (Managed Heap) имеет установленные флаги, разрешающие выполнение (Execute), запись (Write) и чтение (Read) процессом. Отметим, что переход на 64-х битную архитектуру частично обосновывался и необходимостью в защите страниц памяти с применением NX-бита (XD-бита в терминологии Intel), запрещающего выполнение кода на страницах с данными [14].

Важно отметить, что генерируемый в режиме Run-Time код и данные не фиксированы по определенным участкам памяти и могут быть перемещены исполняющей средой в процессе работы. С другой стороны, CIL код, можно обнаружить с помощью отладчика отступив от базового адреса загрузки исполняемого модуля в память смещение секции кода и смещение функции. Это проиллюстрировано на рис. 6.

Рис 6. IL код функции main в Ida Pro (сверху) и снятый с дампа в WinDBG (внизу)

Заключение

Современное программное обеспечение совмещает в себе как Native, так и Managed программные модули. Кроме того, компилятор Microsoft Visual C++ позволяет формировать Mixed код, хранящий в одном исполняемом модуле и платформозависимый и байт-код. Существующие инструменты анализа смешанного (Native и Managed) кода являются в значительной степени разрозненными и не совершенными. С другой стороны, программное обеспечение, несмотря на наличие байт-кода в некоторых программных модулях, с помощью ряда методик организуется в однообразный (с точки зрения процессора) исполняемый машинный код. .NET сборки содержат в себе метаданные и код на языке CIL.

В ряде случаев доступ к исходным кодам исследуемого проекта затруднителен или невозможен. Кроме того, важно учитывать именно особенности фактически выполняемого кода, полученного, в том числе, после JIT компиляции. В связи с этим видится важным развитие средств анализа программного обеспечения, способных обрабатывать не только Native или Managed, но и Mixed сборки.

Список литературы

[1] http://ru.wikipedia.org/wiki/.NET_Framework (дата обращения: 01.10.2013)

[2] http://developer.android.com/sdk/index.html (дата обращения: 01.10.2013)

[3] https://www.hex-rays.com/products/ida/index.shtml (дата обращения: 01.10.2013)

[4] http://www.red-gate.com/products/dotnet-development/reflector/ (дата обращения: 01.10.2013)

[5] http://www.jetbrains.com/decompiler/ (дата обращения: 01.10.2013)

[6] Fuzzing. Исследование уязвимостей методом грубой силы, Автор: Майкл Саттон, Адам Грин, Педрам Амини, Издательство: Символ-Плюс, ISBN 978-5-93286-147-9; 2009 г.

[7] http://en.wikipedia.org/wiki/Assembler_(computing)#Assembler (дата обращения: 01.10.2013)

[8] http://msdn.microsoft.com/ru-ru/library/c1h23y6c.aspx (дата обращения: 02.10.2013)

[9] http://en.wikipedia.org/wiki/Common_Intermediate_Language (дата обращения: 02.10.2013)

[10] http://msdn.microsoft.com/ru-ru/library/f7dy01k1.aspx (дата обращения: 02.10.2013)

[11] http://technet.microsoft.com/en-us/sysinternals/bb842062.aspx (дата обращения: 02.10.2013)

[12] http://msdn.microsoft.com/en-us/magazine/cc163791.aspx (дата обращения: 02.10.2013)

[13] http://technet.microsoft.com/en-us/sysinternals/bb842062.aspx (дата обращения: 02.10.2013)

[14] http://ru.wikipedia.org/wiki/NX_bit (дата обращения: 02.10.2013)

Приложение 1. Программа из рис.1.

#include <Windows.h>

int main(int argc, char** argv)

{

MessageBox(0, TEXT("WinAPI message from unmanaged C/C++."), TEXT("Message"), MB_YESNO | MB_ICONQUESTION);

return 0;

}

Приложение 2. Программа из рис.2-3.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.InteropServices;

using System.Text;

using System.Threading.Tasks;

namespace CSharp_MessageBoxWinAPI

{

class Program

{

[DllImport("user32.dll", CharSet = CharSet.Unicode)]

public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

enum MsgType : ulong

{

MB_ABORTRETRYIGNORE = 0x00000002L,

MB_CANCELTRYCONTINUE = 0x00000006L,

MB_HELP = 0x00004000L,

MB_OK = 0x00000000L,

MB_OKCANCEL = 0x00000001L,

MB_RETRYCANCEL = 0x00000005L,

MB_YESNO = 0x00000004L,

MB_YESNOCANCEL = 0x00000003L

};

enum IconType : ulong

{

MB_ICONEXCLAMATION = 0x00000030L,

MB_ICONWARNING = 0x00000030L,

MB_ICONINFORMATION = 0x00000040L,

MB_ICONASTERISK = 0x00000040L,

MB_ICONQUESTION = 0x00000020L,

MB_ICONSTOP = 0x00000010L,

MB_ICONERROR = 0x00000010L,

MB_ICONHAND = 0x00000010L

};

static void Main(string[] args)

{

MessageBox(IntPtr.Zero, "WinAPI message from c#.", "Message", (uint)((ulong)MsgType.MB_YESNO | (ulong)IconType.MB_ICONQUESTION));

}

}

}

Приложение 3. Программа из рис.4.

#using <mscorlib.dll>

#include <stdio.h>

using namespace System;

#pragma unmanaged

void print(char *message)

{

printf("%s\n", message);

}

#pragma managed

int main()

{

Console::WriteLine("Managed write line.");

print("Unmanaged write line.");

Console::ReadLine();

return 0;

}

Наши рекомендации