Ildasm.exe (дизассемблер il)

Инcтрукция if

Данную инструкцию довольно просто отличить в дизассемблированном виде от других инструкций. Её отличительное свойство — одиночные инструкции условного перехода je, jne и другие команды jump.

1605790962062.png1605790989407.png

Напишем небольшую программу на языке Си и дизассемблируем её с помощью radare2. Разницы между IDA PRO и radare2 при дизассемблировании этих программ не было обнаружено, поэтому я воспользуюсь radare2. Вы можете использовать IDA PRO.

Компилируем при помощи gcc. Команда . -m32 означает, что компилироваться код будет под архитектуру x86.

Чтобы посмотреть на код в radare2, напишем команду . Далее прописываем для анализа кода и переходим к функции main . Посмотрим на код с помощью команды .

1605792900362.png

Первым делом в программе происходит объявление переменных ( int x; int y ), а затем значение 1 перемещается в var_ch (это переменная x) и значение 2 в var10h (это переменная y). Далее идёт сравнение (cmp) 1 и 2 (). Эти значения не равны. Значит jne ( jump if not equal) перейдёт по адресу 0x000011e1. Проще всего инструкцию if запомнить и определить в режиме графов (команда для для radare2 или клавиша пробел для IDA).

1605792914861.png

Немного усложним задачу. Добавим вложенные инструкции. Попробуйте проанализировать этот код.

A General view of Disassembling[edit | edit source]

8 bit CPU codeedit | edit source

Most embedded CPUs are 8-bit CPUs.

Normally when a subroutine is finished, it returns to executing the next address immediately following the instruction.

However, assembly-language programmers occasionally use several different techniques that adjust the return address, making disassembly more difficult:

  • jump tables,
  • calculated jumps, and
  • a parameter after the call instruction.

parameters after the call instructionedit | edit source

Instead of picking up their parameters off the stack or out of some fixed global address, some subroutines provide parameters in the addresses of memory that follow the instruction that called that subroutine. Subroutines that use this technique adjust the return address to skip over all the constant parameter data, then return to an address many bytes after the «call» instruction. One of the more famous programs that used this technique is the «Sweet 16» virtual machine.

The technique may make disassembly more difficult.

A simple example of this is the procedure implemented as follows:

; assume ds = cs, e.g like in boot sector code
start:
        call write       ; push message's address on top of stack
        db   "Hello, world",dh,ah,00h
; return point
        ret              ; back to DOS

write proc near
        pop  si          ; get string address
        mov  ah,eh      ; BIOS: write teletype
w_loop:
        lodsb            ; read char at  and increment si
        or   al,al       ; is it 00h?
        jz   short w_exit
        int  10h         ; write the character
        jmp  w_loop      ; continue writing
w_exit:
        jmp  si
write   endp
        end start

A macro-assembler like TASM will then use a macro like this one:

_write macro message
       call write
       db message
       db 
_write endm

From a human disassembler’s point of view, this is a nightmare, although this is straightforward to read in the original Assembly source code, as there is no way to decide if the db should be interpreted or not from the binary form, and this may contain various jumps to real executable code area, triggering analysis of code that should never be analysed, and interfering with the analysis of the real code (e.g. disassembling the above code from 0000h or 0001h won’t give the same results at all).

However a half-decent tool with possibilities to specifiy rules, and heuristic means to identify texts will have little trouble.

32 bit CPU codeedit | edit source

Most 32-bit CPUs use the ARM instruction set.

Typical ARM assembly code is a series of subroutines, with literal constants scattered between subroutines.
The for subroutines is pretty easy to recognize.

  • objdump, part of the GNU binutils, can disassemble code for several processors and platforms. binutils is an important part of the toolchain as it provides the linker, assembler and other utilties (like objdump) to manipulate executables on the target platform, and is available for most popular platforms.

Нахождение всех текстовых строк внутри EXE файла

Дизассемблер отображает все найденные в сегменте данных текстовые строки в отдельной закладке Strings. Если вы пытаетесь найти какие-то зацепки в изучаемом файле в виде осмысленного текста, подобный список строк может дать вам подсказки о назначении тех или иных функций и процедур, вызываемых файлом, или даже какую-нибудь информацию о происхождении файла.

В отличие от существующих разнообразных утилит, занимающихся поиском и нахождением текстовых строк в исполняемых файлах, PE Explorer делает это аккуратнее и качественнее, поскольку опирается в своем поиске на результаты анализа кода кода приложения.

Параметры

Перечисленные ниже параметры допустимы для файлов EXE, DLL, OBJ, LIB и WINMD.

Параметр Описание
/out= Создает выходной файл с заданным параметром вместо вывода результатов в графический пользовательский интерфейс.
/rtf Выводит данные в формате RTF. Не может использоваться с параметром /text.
/text Отображает результаты в окне консоли вместо вывода в графический пользовательский интерфейс или выходной файл.
/html Выводит данные в формате HTML. Может использоваться только с параметром /output.
/? Отображает синтаксис команд и параметров для средства.

Перечисленные ниже дополнительные параметры допустимы для файлов EXE, DLL и WINMD.

Параметр Описание
/bytes Отображает фактические байты в шестнадцатеричном формате в виде комментариев к инструкциям.
/caverbal Создает большие двоичные объекты настраиваемых атрибутов в текстовом виде. По умолчанию задана двоичная форма.
/linenum Включает ссылки на строки исходного файла.
/nobar Подавляет вывод всплывающего окна с индикатором хода выполнения дизассемблирования.
/noca Подавляет вывод настраиваемых атрибутов.
/project Отображает метаданные в представлении для управляемого кода, а не так, как их представляет среда выполнения Windows в машинном коде. Если параметр не является файлом метаданных Windows (WINMD-файлом), этот параметр не учитывается. См. раздел Поддержка приложений для Магазина Windows и среды выполнения Windows в .NET Framework.
/pubonly Дизассемблирует только открытые типы и члены. Эквивалентен /visibility:PUB.
/quoteallnames Заключает все имена в одинарные кавычки.
/raweh Отображает предложения обработки исключений в исходном виде.
/source Отображает строки исходного кода в виде комментариев.
/tokens Отображает токены метаданных классов и членов.
/visibility: Дизассемблирует только типы и члены с заданной областью видимости. Допустимы следующие значения аргумента :PUB — открытый;PRI — закрытый;FAM — семейство;ASM — сборка;FAA — семейство и сборка;FOA — семейство или сборка;PSC — закрытая область. Определения модификаторов видимости см. в описании MethodAttributes и TypeAttributes.

Перечисленные ниже параметры допустимы для файлов EXE, DLL и WINMD только при выводе в файл или окно консоли.

Параметр Описание
/all Задает сочетание параметров /header, /bytes, /stats, /classlist и /tokens.
/classlist Включает список классов, определенных в этом модуле.
/forward Использует прямое объявление класса.
/headers Включает сведения заголовка файла в выходные данные.
/item: ] В зависимости от заданных аргументов выполняет дизассемблирование: дизассемблируется указанный ;дизассемблируется указанный член этого класса ;дизассемблируется член класса с указанной сигнатурой . Формат выглядит следующим образом: [] (, , …, )Примечание. В .NET Framework версий 1.0 и 1.1 за атрибутом должна следовать закрывающая скобка: . В .NET Framework 2.0 и последующих версиях закрывающая скобка должна быть опущена: .
/noil Подавляет вывод кода сборки IL.
/stats Включает статистику по образу.
/typelist Создает полный список типов, чтобы сохранить упорядочение типов в круговом пути.
/unicode Использует для выходных данных кодировку Юникод.
/utf8 Использует для выходных данных кодировку UTF-8. ANSI является значением по умолчанию.

Перечисленные ниже параметры допустимы для файлов EXE, DLL, OBJ, LIB и WINMD только при выводе в файл или окно консоли.

Параметр Описание
/metadata Отображает метаданные, при этом параметр может принимать следующие значения:MDHEADER — показывать сведения и размеры заголовка метаданных;HEX — показывать сведения в шестнадцатеричном и текстовом формате;CSV — показывать количество записей и размеры кучи;UNREX — показывать неразрешенные внешние элементы;SCHEMA — показывать сведения о заголовке и схеме метаданных;RAW — показывать необработанные таблицы метаданных;HEAPS — показывать необработанные кучи;VALIDATE — проверять согласованность метаданных. Параметр /metadata можно задать несколько раз с различными значениями аргумента .

Перечисленные ниже параметры допустимы для LIB-файлов только при выводе в файл или окно консоли.

Параметр Описание
/objectfile= Вывод метаданных отдельного объектного файла из заданной библиотеки.

Примечание

Параметры программы Ildasm.exe не учитывают регистр и распознаются по первым трем буквам. Например, команда /quo эквивалентна команде /quoteallnames. Разделителем параметра и его аргумента может служить двоеточие (:) или знак равенства (=). Например, команда /output: имя_файла эквивалентна команде /output= имя_файла.

Зависимость от транслятора

Программисты на ассемблере склонны пренебрегать правилами хорошего тона, нарушать все мыслимые табу, и это создает дополнительные трудности при дизассемблировании. В качестве примера приведем фрагмент кода, выданного дизассемблером

s25	proc near 
	inc	cx			;0086b 
	add	di,bp			;0086c 
	adc	si,00			;0086e 
	add	dx,si			;00871 
	push	di			;00873 
	shl	di,1 ;00874		;Multiply by 2's 
	adc	dx,00			;00876 
	pop	di			;00879 
	ret				;0087a 

Этот фрагмент представляется совершенно невинным, и действительно, он дизассемблирован правильно. Вся беда в том, что программист задумал изменять этот фрагмент, то есть резать по живому. Оказывается, в программе есть еще такой кусок

	mov	di,086bh		;007f8 
	...................................... 
	mov	BYTE PTR ,4ah	;00800 
	mov	BYTE PTR ,0f1h	;00803 
	mov	BYTE PTR ,0d1h	;00807 
	...................................... 
	ret				;00815 

Рис.1

Так как di используется для косвенной адресации, нам прежде всего необходимо заменить 086bh на соответствующий OFFSET d0086b и пометить этой меткой начало подпрограммы s25:

s25 	proc near
d0086b:	inc	cx			;0086b
..............................................

Далее следует понять, что делают инструкции, приведенные на рис.1 с подпрограммой s25. Пусть эта подпрограмма асслемблирована с помощью TASM 1.01. Выданный ассемблером код будет таким, как показано на рисунке 2.

 41      INC CX       41       INC CX 
 03FD    ADD DI,BP    01EF     ADD DI,BP 
 83D600  ADC SI,0000  83D600   ADC SI,0000 
 03D6    ADD DX,SI    01F2     ADD DX,SI 
 57      PUSH DI      57       PUSH DI 
 D1E7    SHL DI,1     D1E7     SHL DI,1 
 83D200  ADC DX,0000  83D2000  ADC DX,0000 
 5F      POP DI       5F       POP DI 
 C3      RET          C3       RET 

Рис.2 Рис.3

Но вся беда в том, что исходная программа была ассемблирована другим ассемблером и имеет вид, показанный на рисунке 3. Как видно из сравнения рисунков 2 и 3, TASM 1.01 и неизвестный ассемблер транслируют инструкции ADD по-разному, и это приводит к катастрофическим последствиям. Действительно, посмотрим, как воздействует участок кода, показанный на Рис.1 (перед этим заменим 086bh на OFFSET d0086b) на подпрограмму s25, транслируемую TASMом (рис.4) и неизвестным ассемблером (рис.5).

 4A      DEC DX          4A      DEC DX 
 03FD    ADD DI,BP       01EF    ADD DI,BP 
 83D600  ADC SI,0000     83D600  ADC SI,0000 
 03F1    ADD SI,CX ;!!!! 01F1    ADD CX,SI ;!!!! 
 57      PUSH DI         57      PUSH DI 
 D1E7    SHL DI,1        D1E7    SHL DI,1 
 83D100  ADC CX,0000     83D100  ADC CX,0000 
 5F      POP DI          5F      POP DI 
 C3      RET             C3      RET 

Рис.4 Рис.5

Сравнение рисунков 4 и 5 показывает, что логика работы программы меняется в зависимости от того, какой ассемблер применялся. Как выкрутиться из этой ситуации, если нужного ассемблера нет под рукой? Самый простой, но не очень красивый путь — поставить «заплатку». Чтобы можно было использовать TASM, подпрогроамма s25 должна выглядеть так:

s25 	proc near 
d0086b:	inc	cx		;0086b 
	add di,bp   		;0086c 
	adc	si,00		;0086e 
	db 01,0f2   		;add	dx,si !!!!!! ;00871 
	push	di		;00873 
	shl	di,1 		;00874	;Multiply by 2's 
	adc	dx,00		;00876 
	pop	di		;00879 
	ret			;0087a 

Таблица переходов

Следующий пример ассемблерного кода часто можно встретить в больших смежных выражениях switch. Мы добавим case 4 и инструкцию по умолчанию.

Дизассемблированный вариант в radare2

1605793648917.png1605793656018.png

1 — инициализации переменной var_4h (i = 3) 2 — выполнения инструкций (add, printf)

Вот этот дизасcемблированный код довольно сложно быстро отличить от if и вообще понять что и как тут. В режиме графов всё будет более понятно.

Режим графов

1605793750977.png1605793673414.png1605793684884.png1605793691266.png

Режим графов — ваш друг в дизасcемблировании 🙂

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

Спасибо за внимание. Не болейте

Процесс дизассемблирования

Дизассемблер запускается в своём отдельном окне, и вы можете переключаться из окна дизассемблера в основное окно PE Explorer. Дизассемблер поддерживает основные наборы инструкций Intel x86 и расширения MMX, 3D Now!, SSE, SSE2 и SSE3. В начале процесса окно Options предлагает выбрать следующие опции:

Нажатие кнопки Start Now запускает процесс, кнопка Start Later откладывает запуск.

Verify Offsets — При включении этой опции дизассемблер особо тщательно проверяет, является ли анализируемое значение смещением.

Reverse Offset Checking Order — По умолчанию, дизассемблер рассматривает необработанные данные как код, и только потом как смещения к данным. При включении этой опции дизассемблер будет рассматривать необработанные данные как данные.

В большинстве случаев включение этой опции либо ничего не изменит, либо сделает качество листинга хуже. Однако, в некоторых случаях (например, с программами, написанными на Visual Basic) изменение порядка определения смещений может дать лучший результат. Автоматизировать применение этой опции затруднительно, поэтому рекомендуется использовать эту опцию только в ситуациях, когда настройки по умолчанию приводят к неудовлетворительным результатам.

Find ANSI and Unicode Strings — При включении этой опции дизассемблер автоматически обнаруживает текстовые ANSI и Unicode строки длиннее 3-х символов. В отдельных случаях, если результаты анализа позволяют однозначно интерпретировать данные как строку, эта длина может быть и менее 3-х символов.

Find Alignment — Поскольку доступ к выравненным данным происходит быстрее, многие компиляторы выравнивают код, добавляя лишние команды, не влияющие не ход выполнения программы, такие как nop, mov eax,eax и т.п.
При включении этой опции дизассемблер интерпретирует подобный код/данные как выравнивание.

Forcible Find Offsets — При включении этой опции дизассемблер автоматически обнаруживает смещения к данным в коде, который остался нераспознанным после первого прохода по файлу.
Используйте эту опцию с осторожностью, так как правильно определить, являются ли найденные данные смещением или фрагментами кода/данных, довольно сложно. Не рекомендуется использовать эту опцию без особых причин

Analyze Uprocessed Data — Во время дизассемблирования отдельные фрагменты кода по причине отсутствия явных на них ссылок могут оказаться нераспознанными. При включении данной опции дизассемблер проводит дополнительный анализ таких
блоков и пытается определить, являются ли эти фрагменты кодом или данными. Включение этой опции улучшает качество листинга.

Окно Processing Info отображает информацию о ходе процесса дизассемблирования:

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

Build

Unix

Zydis builds cleanly on most platforms without any external dependencies. You can use CMake to generate project files for your favorite C99 compiler.

git clone --recursive 'https://github.com/zyantific/zydis.git'
cd zydis
mkdir build && cd build
cmake ..
make

Building Zydis — Using vcpkg

You can download and install Zydis using the vcpkg dependency manager:

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install zydis

The Zydis port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.

Анализ строк

Кратко: Анализ строк может помочь составить примерный план исследования двоичного файла.

  • Операционная система – FreeRTOS;
  • Наличие форматных строк – скорее всего используются printf-подобные функции, можно будет установить назначение регистров/переменных;
  • Названия задач (тасков) – можно предположить назначение этих самых тасков и связанных с ними функций;
  • Использование AT-команд – предположительно так строится взаимодействие микроконтроллера и Bluetooth-модуля.

Далеко не всегда всё так радужно при анализе прошивок – строк и debug-информации может не быть совсем или они малоинформативны, но при создании прошивки мы намеренно не стали усложнять процесс обратной разработки.

Архитектура виртуальной машины ассемблера

Ассемблер fasmg (архитектура CALM-инструкций)

Является наследником ассемблера flat assembler (fasm) со схожим синтаксисом, но в отличие от fasm не привязан ни к какой архитектуре процессора. Его парадигмой является формирование посредством макросов выходных файлов любых форматов и с машинным кодом под любые архитектуры процессоров. Помимо макросов в fasmg присутствуют т. наз. CALM-инструкции (букв. «инструкции компилируемой сборки, подобные макросам») — собственные инструкции виртуальной машины ассемблера, эквивалентные макросам, которые преобразуются транслятором в байт-код. Архитектуру этих CALM-инструкций можно считать «родной» архитектурой ассемблера fasmg. В комплекте имеются наборы CALM-инструкций для эмуляции поддержки инструкций архитектур x86, x64, 8052, AVR; разработчиком могут быть описаны наборы CALM-инструкций для поддержки любой другой архитектуры, поддержки любых выходных форматов файлов. Имеются вариации транслятора для Mac OS, Linux и Windows.

Внешний осмотр

Кратко: на этом этапе производится внешний осмотр устройства с целью поиска маркировок, доступных разъемов.

  • Микроконтроллер STM32F042 – тут сразу стоит обратиться к документации на микроконтроллер (если такая есть), откуда можно узнать архитектуру, разрядность микроконтроллера и много чего полезного (для нашего случая – 32 разрядный микроконтроллер на архитектуре ARM);
  • На тыльной стороне имеется разъем без обозначений – те, кто работал с микроконтроллерами, могут сделать верное предположение, что это разъем для прошивки устройства (во-первых, он не промаркирован; во-вторых, он имеет 5 контактов, что соответствует необходимому количеству контактов для перешивки микроконтроллера);
  • Контакты GND, TX;
  • USB-разъем для питания устройства (об этом говорится и в «Инструкции»);
  • Неизвестный разъем XP2 на лицевой стороне устройства;
  • Непонятная желтая блямба на ноге носорога – вероятно, сенсорная кнопка.

RHINOCEROS-220x

Проблемы разборки

Возможно написание дизассемблера, который производит код, который после сборки дает в точности исходный двоичный файл; однако часто бывают различия. Это предъявляет требования к выразительности ассемблера. Например, ассемблер x86 делает произвольный выбор между двумя двоичными кодами для чего-то столь же простого, как . Если исходный код использует другой вариант, исходный код просто не может быть воспроизведен в любой данный момент времени. Однако даже при полностью правильной разборке проблемы остаются, если программа требует модификации. Например, та же самая инструкция перехода на машинном языке может быть сгенерирована ассемблерным кодом для перехода в указанное место (например, для выполнения определенного кода) или для перехода на указанное количество байтов (например, для пропуска нежелательной ветви) . Дизассемблер не может знать, что предназначено, и может использовать любой синтаксис для создания дизассемблера, воспроизводящего исходный двоичный файл. Однако, если программист хочет добавить инструкции между инструкцией перехода и ее местом назначения, необходимо понимать работу программы, чтобы определить, должен ли переход быть абсолютным или относительным, то есть должно ли его место назначения оставаться в фиксированном месте или быть перемещен так, чтобы пропустить как исходную, так и добавленную инструкции.

Как мыслит процессор

Что­бы понять, как рабо­та­ет Ассем­блер и поче­му он рабо­та­ет имен­но так, нам нуж­но немно­го разо­брать­ся с внут­рен­ним устрой­ством про­цес­со­ра.

Кро­ме того, что про­цес­сор уме­ет выпол­нять мате­ма­ти­че­ские опе­ра­ции, ему нуж­но где-то хра­нить про­ме­жу­точ­ные дан­ные и слу­жеб­ную инфор­ма­цию. Для это­го в самом про­цес­со­ре есть спе­ци­аль­ные ячей­ки памя­ти — их назы­ва­ют реги­стра­ми.

Реги­стры быва­ют раз­но­го вида и назна­че­ния: одни слу­жат, что­бы хра­нить инфор­ма­цию; дру­гие сооб­ща­ют о состо­я­нии про­цес­со­ра; тре­тьи исполь­зу­ют­ся как нави­га­то­ры, что­бы про­цес­сор знал, куда идти даль­ше, и так далее. Подроб­нее — в рас­хло­пе ↓

Какими бывают регистры

Обще­го назна­че­ния. Это 8 реги­стров, каж­дый из кото­рых может хра­нить все­го 4 бай­та инфор­ма­ции. Такой регистр мож­но раз­де­лить на 2 или 4 части и рабо­тать с ними как с отдель­ны­ми ячей­ка­ми.

Ука­за­тель команд. В этом реги­стре хра­нит­ся толь­ко адрес сле­ду­ю­щей коман­ды, кото­рую дол­жен выпол­нить про­цес­сор. Вруч­ную его изме­нить нель­зя, но мож­но на него повли­ять раз­лич­ны­ми коман­да­ми пере­хо­дов и про­це­дур.

Регистр фла­гов. Флаг — какое-то свой­ство про­цес­со­ра. Напри­мер, если уста­нов­лен флаг пере­пол­не­ния, зна­чит про­цес­сор полу­чил в ито­ге такое чис­ло, кото­рое не поме­ща­ет­ся в нуж­ную ячей­ку памя­ти. Он туда кла­дёт то, что поме­ща­ет­ся, и ста­вит в этот флаг циф­ру 1. Она — сиг­нал про­грам­ми­сту, что что-то пошло не так.

Фла­гов в про­цес­со­ре мно­го, какие-то мож­но менять вруч­ную, и они будут вли­ять на вычис­ле­ния, а какие-то мож­но про­сто смот­реть и делать выво­ды. Фла­ги — как сиг­наль­ные лам­пы на пане­ли при­бо­ров в само­лё­те. Они что-то озна­ча­ют, но толь­ко само­лёт и пилот зна­ют, что имен­но.

Сег­мент­ные реги­стры. Нуж­ны были для того, что­бы рабо­тать с опе­ра­тив­ной памя­тью и полу­чать доступ к любой ячей­ке. Сей­час такие реги­стры име­ют по 32 бита, и это­го доста­точ­но, что­бы полу­чить 4 гига­бай­та опе­ра­тив­ки. Для про­грам­мы на Ассем­бле­ре это­го обыч­но хва­та­ет.

Так вот: всё, с чем рабо­та­ет Ассем­блер, — это коман­ды про­цес­со­ра, пере­мен­ные и реги­стры.

Здесь нет при­выч­ных типов дан­ных — у нас есть толь­ко бай­ты памя­ти, в кото­рых мож­но хра­нить что угод­но. Даже если вы поме­сти­те в ячей­ку какой-то сим­вол, а потом захо­ти­те рабо­тать с ним как с чис­лом — у вас полу­чит­ся. А вме­сто при­выч­ных цик­лов мож­но про­сто прыг­нуть в нуж­ное место кода.

Дизассемблеры и эмуляторы

Динамический дизассемблер может быть включен в выходные данные эмулятора или гипервизора, чтобы построчно «отслеживать» выполнение в реальном времени любых выполняемых машинных инструкций. В этом случае, а также строки, содержащие дизассемблированный машинный код, регистр (ы) и / или изменение (я) данных (или любые другие изменения « состояния », такие как коды условий), которые вызывает каждая отдельная инструкция, могут быть показаны рядом или под разобранной инструкцией. Это обеспечивает чрезвычайно мощную отладочную информацию для окончательного решения проблемы, хотя размер результирующего вывода иногда может быть довольно большим, особенно если он активен для выполнения всей программы. OLIVER предоставлял эти функции с начала 1970-х годов как часть своего предложения продуктов для отладки CICS, и теперь они включены в продукт XPEDITER от Compuware .