Вход

Просмотр полной версии : Дизасм DECOBJ



nzeemin
05.11.2022, 17:17
DECOBJ - программа для RT-11, позволяет по объектному модулю (.OBJ) получить его дизасм.
Сама DECOBJ написана на Паскале, исходников нет.

Я сделал дизасм DECOBJ - разобрал где какие модули Паскаля, откоментировал использование паскалевских вызовов в основном коде.
Полученный DECOBJ.MAC компилируется байт-в-байт в тот же SAV файл.
https://github.com/nzeemin/uknc-various/blob/master/DECOBJ/DECOBJ.MAC

UPDATE:
Ассемблерный код раскодирован в исходник на Паскале, силами Alex_K и меня:
https://github.com/nzeemin/uknc-various/tree/master/DECOBJ-PASCAL

Alex_K
05.11.2022, 20:34
Начал где-то год назад или чуть более также дизассемблировать DECOBJ. Сделал много, но завяз. Довольно сложные типы переменных, много множеств. Выкладываю то, что успел сделать. Может пригодится.

nzeemin
06.11.2022, 02:42
Начал где-то год назад или чуть более также дизассемблировать DECOBJ. Сделал много, но завяз. Довольно сложные типы переменных, много множеств. Выкладываю то, что успел сделать. Может пригодится.

Спасибо, это большой труд. Буду изучать.

nzeemin
07.11.2022, 12:09
Восстановленный исходник на Паскале будет тут:
https://github.com/nzeemin/uknc-various/blob/master/DECOBJ-PASCAL/DECOBJ.PAS

Alex_K
07.11.2022, 14:32
Восстановленный исходник на Паскале будет тут:
https://github.com/nzeemin/uknc-various/blob/master/DECOBJ-PASCAL/DECOBJ.PAS
Не надо там тип PRECF, надо аргумент в процедурах описать со словом var. Это как раз означает передачу не по значению, а по ссылке.
И кстать этот DECOBJ слинкован очень интересно. Сначала идут два внешних модуля, а уже потом основной.

Alex_K
07.11.2022, 23:12
Что-то типа такого:


procedure L01000;
var DEVSPC: array [0..38] of integer;
DEFEXT: array [1..4] of integer;
I: integer;
begin
for I:=1 to 4 do
DEFEXT[I]:=0;
{$C
MOV SP, R2
ADD #DEVSPC, R2
MOV SP, R3
ADD #DEFEXT, R3
MOV #^ROBJ, @R3
MOV #^RMAC, 2(R3)
.MCALL .RCTRLO
.RCTRLO
MOV #^O1000,@#^O46
MOV SP, R1
.MCALL .CSIGEN
1$: .CSIGEN R2,R3,#0
MOV R1,SP
BCS 1$
}
for I:=0 to 15 do
VAR00[I]:=CHST00;
end;


procedure L01304(var RECIO: RECF1012; CHN: integer; CHS: CHSTATE);
begin
if VAR00[CHN]<>CHST00 then
else
with RECIO do
begin
RF04:=CHN;
RF02:=0;
RF02:=0;
if CHS = CHST01 then
begin
RF06:=-1;
RF1010:=512;
end
else
if CHS = CHST02 then
begin
RF06:=0;
RF1010:=1;
end;
VAR00[CHN]:=CHS;
end;
end;

nzeemin
08.11.2022, 00:44
Alex_K, про var я помню, ага.
Сейчас первый внешний модуль я грубо уже выписал.

Стратегия такая: сначала первый проход, при котором могут быть отличия в смещениях, мелкие неточности.
Я смотрю на бинарное сравнение оригинального .SAV и полученного, "островки" в 1-3 байта различий пока оставляю как есть, если дальше совпадает. Эти островки я соберу их на втором проходе, тогда это будет уже легче сделать, когда адреса вызовов в паскалевских модулях встанут на место.

Alex_K
10.11.2022, 23:32
Черновой вариант двух внешних модулей.

Alex_K
11.11.2022, 17:58
По ошибке сделал архив с МАС-файлами. Пересобрал с исходниками на Паскале. Файл в сообщении выше.

nzeemin
11.11.2022, 22:32
Вот тут не срастается по типам, в procedure L06772:
RE00:=RG02;

То что есть запушил на гитхаб - https://github.com/nzeemin/uknc-various/tree/master/DECOBJ-PASCAL

Alex_K
11.11.2022, 22:39
Вот тут не срастается по типам, в procedure L06772:
RE00:=RG02;
Посмотри мои новые файлы. Там я сделал корректировку в том числе и по типам. Есть четыре места, где по типам не срастается: L03004, L05306 (2 раза) и L05740. Там у меня сделаны вставки на ассемблере. Либо в программе было точно так же (автор тогда знал хорошо структуру данных на Паскале), либо объявлять тип через RECORD CASE. Сейчас у меня все типы вроде расставлены правильно.

nzeemin
11.11.2022, 23:30
Понял. Обновил код на гитхабе.

Alex_K
12.11.2022, 00:17
Начал делать основной модуль.

Alex_K
12.11.2022, 19:53
Продолжение основного модуля.
Пока пауза, надо сделать комментарии в disasm.txt, начиная с 025560 и дальше.

nzeemin
13.11.2022, 14:56
Я пока начал раскодировать основную процедуру, коммичу время от времени на гитхаб.

Предложения:
1. L10516 - Переименовать в WriteCRLF
2. L10544 - Переименовать в WriteTab

Alex_K
13.11.2022, 15:05
Я пока начал раскодировать основную процедуру, коммичу время от времени на гитхаб.
Да, видел. Посматриваю время от времени. Я пока работаю в диапазоне 25560-33364. Это процедура со многими вложенными функциями и процедурами.

Предложения:
1. L10516 - Переименовать в WriteCRLF
2. L10544 - Переименовать в WriteTab
Я пока ничего не буду переименовывать. Надо следить за адресами. Пока я транслирую Паскалем и смотрю, чтобы подпрограммы и функции были нужного размера. А потом после линковки буду сравнивать с оригиналом, ошибки будут, надо будет исправлять. А уж после того как всё будет причесано, то можно понимать что за что значит и переименовывать. В тех процедурах, где я сейчас копаюсь, вырисовывается дизассемблер команд.

Alex_K
13.11.2022, 23:20
Завершил работу с процедурами и функциями в диапазоне 25560-33364.

nzeemin
13.11.2022, 23:36
Отлично. Добавил на гитхаб.
Осталось два куска примерно по 1000 слов.
Я пока продолжаю по основной процедуре, в районе 043770-047234

Alex_K
14.11.2022, 00:00
Отлично. Добавил на гитхаб.
Осталось два куска примерно по 1000 слов.
Я пока продолжаю по основной процедуре, в районе 043770-047234
Группа следующих вложенных процедур и функций в диапазоне 33366-37002 немного пугает. В главной процедуре по адресу 035532 командой SUB #106,SP выделяется целая куча места под локальные переменные. Это зачем же столько надо?

nzeemin
14.11.2022, 02:11
А я сегодня умер на логическом выражении под IF - L44326..L44570 - составные части правильные, но дерево построил неправильное. Пока отложил на потом.

Oleg N. Cher
14.11.2022, 03:17
В главной процедуре по адресу 035532 командой SUB #106,SP выделяется целая куча места под локальные переменные. Это зачем же столько надо?Там могут быть вложенные процедуры. Для доступа из них к параметрам внешней процедуры во фрейме стека обычно генерится дополнительная внутренняя структура.

Alex_K
14.11.2022, 11:48
Там могут быть вложенные процедуры. Для доступа из них к параметрам внешней процедуры во фрейме стека обычно генерится дополнительная внутренняя структура.
Да, там вложенные процедуры и функции. Главной является 035532, в неё вложены 033406, 033720 и 035326. Доступ к локальным переменным главной процедуры осуществляется через регистр R4. В зависимости от уровня вложенности во вложенных процедурах/функциях в самом начале стоит целая куча команд MOV (R4),R4. Обычно они пропускаются при запуске, но если вызов происходит из другой вложенной процедуры/функции, то смотря от уровня вложенности, точка запуска смещается вверх и исполняются команды MOV (R4),R4. А команда SUB #106,SP реально выделяет место для локальных переменных главной процедуры. Уже разобрался, все числа восьмеричные:
LOC00: array [1..74] of char;
LOC74,LOC76: integer;
LOC100: boolean;
LOC101: char;
LOC102,LOC104: integer;

Alex_K
14.11.2022, 23:16
Добил диапазон 33366-37002. Логическое выражение в процедуре L35532 дало повод помучиться. Сначала разбирал на ассемблере, что, где и от чего. Вроде бы понял всё, написал на Паскале. В итоге транслятор Паскаля падал, а эмулятор RT-11 закрывался. Закомментировал его и получил ошибку, что строка слишком длинная (188 символов). Пришлось разнести на три строки, трансляция прошла успешно.

Alex_K
15.11.2022, 19:16
Добавил процедуру 37004. Остался главный модуль.
Заметил, что при сравнении строк, они меняются местами. Уже подзабыл про это. Но эти ошибки подправятся потом при двоичном сравнении с оригиналом.

nzeemin
15.11.2022, 19:42
Главный модуль - в состоянии "почти готово", но ошибок ещё много.
Табы заменил на два пробела. Локально я табы любой длины могу делать, а на гитхабе неудобно смотреть когда много их.

- - - Updated - - -


Добавил процедуру 37004.

Залил всё вместе на гитхаб.

- - - Updated - - -

Ещё нашёл правильный PASCAL.OBJ для этой программы, вот отсюда: https://archive.pdp-11.org.ru/ukdwk_archive/dwkwebcomplekt/MY.DSK

Alex_K
15.11.2022, 19:48
Главный модуль - в состоянии "почти готово", но ошибок ещё много.
Я буду свой делать. Потом сравним. Мне также после линковки ошибки надо будет вычищать. А их будет много: где-то из восьмеричного в десятичное не перевёл, логические выражения, если там есть переменная BOOLEAN, ну и т.д. и т.п.

nzeemin
15.11.2022, 19:50
Я займусь доделкой основной процедуры и исправлением ошибок в ней.
Пока показывает ~140 различающихся байт - на всём файле.

Alex_K
15.11.2022, 19:57
Ещё нашёл правильный PASCAL.OBJ для этой программы, вот отсюда: https://archive.pdp-11.org.ru/ukdwk_...omplekt/MY.DSK
Насколько я понимаю это версия PASFIS, для процессоров с поддержкой EIS и FIS. В ней подпрограммы умножения и деления используют команды EIS. Также отсутствует эмулятор FIS.

- - - Добавлено - - -


Я займусь доделкой основной процедуры и исправлением ошибок в ней.
Пока показывает ~140 различающихся байт - на всём файле.
Кстати для сравнения лучше использовать BINCON из RT-11. В эмуляторе RT-11 можно дать команду DIFF/BIN/OUT:файл файл1,файл2. Там все числа восьмеричные, всё прекрасно видно.

nzeemin
15.11.2022, 20:38
У меня свои способы 8-)
Собираю и линкую под эмулятором RT-11, сравниваю через WinMerge - очень наглядно всё видно за счёт подсветки, но числа 16-ричные.
Сейчас уже осталось 123 байта различий.

Alex_K
15.11.2022, 20:52
Сейчас уже осталось 123 байта различий.
А много различий в тех модулях, что делал я?

- - - Добавлено - - -


сравниваю через WinMerge - очень наглядно всё видно за счёт подсветки, но числа 16-ричные.
Т.к. проект с открытым кодом, то и восьмеричные можно сделать.

nzeemin
15.11.2022, 20:56
А много различий в тех модулях, что делал я?

Меньше чем в моих 8-) Ты гораздо аккуратнее.

nzeemin
16.11.2022, 00:54
Ну вот и всё.
Остался один байт различия, в заголовке - как мы уже давно знаем, это обусловлено различием в линковщике.

nzeemin
16.11.2022, 16:15
Alex_K, вопрос наверное - какие у тебя дальше планы по восстановленному исходнику? Будешь изучать детально что как работает?

Для себя я вижу, что можно это переписать в программу на FreePascal и/или на C++.

Alex_K
16.11.2022, 18:31
Alex_K, вопрос наверное - какие у тебя дальше планы по восстановленному исходнику? Будешь изучать детально что как работает?
Да собственно особо планов нет. Добить главный модуль, привести в порядок двоичным сравнением. Ну можно понять, какая процедура за что отвечает, понять структуру записей. Ну собственно и всё.
Сам я начал переводить в Паскаль только из интереса. Понял, что написана на Паскале, ну и захотелось понять, как они это на Паскале сделали.

- - - Добавлено - - -


Для себя я вижу, что можно это переписать в программу на FreePascal и/или на C++.
Вспомнил, что где-то год назад на гитхабе нашел ещё один DECOBJ - https://github.com/DimaRU/Decobj. Там же был ещё один проект DECSAV - https://github.com/DimaRU/Decsav. Программы написаны на MACRO-11, но снабжены прекрасными комментариями. Смотрел только DECOBJ. В нём есть ручное и декодирование и автоматическое. Но автоматическое не очень, всё-таки у Паскалевского DECOBJ "интеллект" чуточку получше. Сами файлы у меня перекачались в кодировке UTF-8, были некоторые проблемы с кириллицей в командах ассемблера. Всё это подчистил и перевёл в КОИ-8. В приложенном файле исходники и собранная программа.

Alex_K
16.11.2022, 21:45
Закончил комментарии в disasm.txt. Осталось сделать главный модуль на Паскале.
nzeemin, спасибо за тексты программы на гитхабе, тискал с неё методом копипастинга в комментарии в disasm.

nzeemin
16.11.2022, 22:03
Alex_K, пожалуйста. Тот паскалевский код что на гитхабе, уже собирается байт-в-байт в точности в тот же DECOBJ.SAV (за исключением одного байта в заголовке). В том коде что ты декодировал, я тоже исправил ошибки.

Alex_K
16.11.2022, 22:19
В том коде что ты декодировал, я тоже исправил ошибки.
Спасибо. Я уже посмотрел. Много ошибок. Как обычно в логических выражениях, когда переменная BOOLEAN через AND. Да и с выражением в L35532 тоже накосячил. Но надо посмотреть самому. Так что добью главный модуль, скомпилирую, слинкую и проверю BINCOM-ом.

Alex_K
17.11.2022, 22:38
А вот и мои ошибки:

BINCOM comparing/ DECOB1.SAV -- DECOBJ.SAV
000000 050/ 053346 053350 000016
000007 012/ 116300 116500 000600
014/ 001010 002426 003436
020/ 116501 116301 000600
022/ 002426 001010 003436
564/ 116504 105100 013404
566/ 002426 116504 114122
570/ 005104 002426 007522
572/ 140400 140004 000404
000010 472/ 005046 116600 113646
474/ 116616 000004 116612
476/ 000006 010046 010040
000011 166/ 000030 000006 000036
202/ 000030 000006 000036
206/ 000030 000006 000036
212/ 000030 000006 000036
522/ 103402 101402 002000
000012 442/ 062700 010601 072101
444/ 003712 062701 061013
446/ 010601 000004 010605
450/ 062701 062700 000001
452/ 000004 003712 003716
460/ 122021 122120 000101
000013 614/ 002402 003402 001000
770/ 103402 101402 002000
000014 104/ 000456 000340 000716
120/ 000324 000320 000004
000016 724/ 001724 002064 003740
000017 244/ 010200 010500 000700
250/ 000006 053402 053404
252/ 010501 010201 000700
256/ 053402 000006 053404
000025 060/ 000001 000006 000007
672/ 001002 001402 000400
000031 236/ 116601 105100 013701
240/ 000016 116601 116617
242/ 005101 000016 005117
244/ 140100 140001 000101
000032 744/ 000022 000014 000036
000033 120/ 000022 000014 000036
000037 010/ 010600 010500 000300
014/ 000004 053402 053406
016/ 010501 010601 000300
022/ 053402 000004 053406
106/ 010600 010500 000300
112/ 000004 053402 053406
114/ 010501 010601 000300
120/ 053402 000004 053406
246/ 010600 012700 002100
250/ 062700 012674 070174
252/ 000004 010601 010605
254/ 012701 062701 070000
256/ 012674 000004 012670
274/ 001002 001402 000400
000043 136/ 001402 001002 000400
000044 142/ 001402 001002 000400


- - - Добавлено - - -

Ну вот собственно всё и у меня. Переделал в процедуре L02020 аргумент VAL с char на integer, соответственно переделал её вызовы. А всё-таки с логическим выражением в L35532 я справился, ошибки там были в сравнении строк, аргументы надо было местами переставить.
Осталось что-то решить с ассемблерными вставками. Наверное придётся типы делать через RECORD CASE, другого пути не вижу.

DimaRU
18.11.2022, 13:18
Всем привет. Этот decobj на Паскале проходил через мои руки. Давно, в 80х, на кафедре М9 МВТУ им. Баумана. Куча кода и zero comments. После чего написал свой. Попробую отыскать исходники. У меня есть кучка заархивированных образов дисков RK05, нужно поднять эмулятор PDP-11 и посмотреть что там.

- - - Добавлено - - -

Да, есть вопрос - какая основная цель восстановления кода decobj?

nzeemin
18.11.2022, 13:40
Всем привет. Этот decobj на Паскале проходил через мои руки. Давно, в 80х, на кафедре М9 МВТУ им. Баумана. Куча кода и zero comments. После чего написал свой. Попробую отыскать исходники. У меня есть кучка заархивированных образов дисков RK05, нужно поднять эмулятор PDP-11 и посмотреть что там.

- - - Добавлено - - -

Да, есть вопрос - какая основная цель восстановления кода decobj?

Может выложить образы дисков сюда, а мы поможем найти? :)

Про цель выше уже обсуждалось - в основном разобрать и посмотреть как работает, в будущем, возможно - переписать на C++ под PC.

Oleg N. Cher
18.11.2022, 14:01
Зачем переписывать на C++? Разве не проще пересобрать при помощи Free Pascal?

Hunta
18.11.2022, 14:30
Разве не проще пересобрать при помощи Free Pascal?
А в чём проблема - исходники выложены, каждый может переписать под что хочет, хоть под (не к ночи будет помянут) Оберон

Alex_K
18.11.2022, 14:44
Да, есть вопрос - какая основная цель восстановления кода decobj?
Как я уже писал выше, мой интерес чисто спортивный. DECOBJ применяли для раскручивания библиотеки Паскаля. Декомпилировали с Паскаля обычно разные игрушки. Но заметил, что он тоже написан на Паскале, ну и решил посмотреть, как они это сделали.

nzeemin
18.11.2022, 14:56
Зачем переписывать на C++? Разве не проще пересобрать при помощи Free Pascal?

А разве похоже что мы тут ищем лёгких путей? 8-)

У меня в проекте pclink11 уже есть dumpobj - разбирает .OBJ и показывает все его составляющие в деталях.
Можно к нему добавить логику DECOBJ, плюс может ещё какие-то улучшения сделать.

DimaRU
18.11.2022, 15:08
Спортивный интерес - это здорово. Хотя я бы для реверс-инжиниринга использовал бы IDA. Проще написать плагин для неё (если ещё не написан). Интерактивный режим важен. Нужно только найти спецификации obj - файлов. Они точно есть, и причём универсальные для всех OS под PDP-11. Кроме конечно Unix.
Кстати, самое интересное для реверсинга - код, генерируемый компилятором Fortran-4. Фантастически гибкое использование команд PDP-11.
До кучи могу выложить реверснутые исходники K52 под RT-11. С добавленным режимом замены текста.

Hunta
18.11.2022, 15:21
реверснутые исходники K52 под RT-11
Исходники с комментариями есть для версий из 5.4-5.7

- - - Добавлено - - -


Нужно только найти спецификации obj - файлов
И это искать не требуется, давно известно, где есть

Alex_K
18.11.2022, 16:30
Кстати, самое интересное для реверсинга - код, генерируемый компилятором Fortran-4. Фантастически гибкое использование команд PDP-11.
К сожалению Фортран сразу делает OBJ-файл. Паскаль хоть делает файл на Макро-11 и там можно увидеть где напортачил при переводе на Паскаль. Да и к тому же у Фортрана очень большие SAV-файлы.

DimaRU
18.11.2022, 21:51
Исходники с комментариями есть для версий из 5.4-5.7



Подскажите, где можно посмотреть?

Hunta
19.11.2022, 00:31
Подскажите, где можно посмотреть?
bitsaver. Как и всё остальное

- - - Добавлено - - -

По дистрибутивам RT-11 ошибся, думал, на битсайвер их то же выложили
Можно взять отсюда
http://pdp-11.classiccmp.org/RT-11/dists/

Alex_K
20.11.2022, 11:57
По анализу текстов заметил, что переменные VAR2436, VAR2556 и VAR2626 относятся точно к одному типу записи. Это видно по взаимному присвоению в процедуре L10104. Также только эти переменные передаются в качестве параметров в процедуры и функции и с ними используется оператор with. А вот с переменной VAR2506 нигде with не используется и она нигде не передается в качестве параметров в процедуры и функции. Также присвоение значения этой переменной в процедуре L10104 осуществляется отдельно по полям. Это может говорить о том, что VAR2506 это не запись, а отдельные переменные, либо небольшое различие в описании полей RE10, RE12, RE36.
Так как в текстах ещё остались ассемблерные вставки, связанные с присвоением байтовых значений полям RE10, RE12, RE36, ввел через RECORD CASE новые типы, а также ввёл новый тип записи XRECE50, отличающийся от RECE50 только описанием полей RE10, RE12, RE36. Переменные VAR2436, VAR2556 и VAR2626 стали новым типом XRECE50. Переменную VAR2506 оставил типом RECE50.
Также ввёл новый тип для поля RG02 записи RECG1012. В итоге удалось избавится от ассемблерных вставок и сделать присвоение значений на Паскале.
Правильно это или нет, надеюсь узнаем, если DimaRU найдёт и выложит исходники DECOBJ на Паскале.

Результат в присоединённом файле.

DimaRU
23.11.2022, 00:56
Спасибо.

- - - Добавлено - - -

Здесь всё, что у меня есть на тему PDP11: https://drive.google.com/file/d/1cYcnFkFL_PxDl6zPmaH06daNB97aL-1h/view?usp=sharing

Может быть там есть исходники decobj, хотя не уверен. Так же там K52 под КОИ-8, для терминалов, на которых можно было переключать между КОИ-7 Н0 и Н1. Так же добавлен режим замены.
Ну ещё куча всякой всячины, не стал разбираться. Сейчас наверное уже всё есть, но для 80х это было ценность.

Hunta
23.11.2022, 09:02
Из интересного - некоторое количество дисков под Э-85, TSX (в том числе с исходниками PI драйвера)
Из крайне интересного - исходники компилятора с FORTRAN-а

DECOBJ, по ходу, какой-то другой - так как написан на MACRO, а не на Паскале. Ну и есть DECSAV

- - - Добавлено - - -

Версия компилятора с Fortran-а - V02.5. Не самый свежий (последняя версия, которая есть у меня - 2.8), но не такой уж и древний :)

Alex_K
23.11.2022, 09:23
Может быть там есть исходники decobj, хотя не уверен.
Посмотрел архив, быстрым взглядов исходников DECOBJ на Паскале не нашел. На Паскале есть там какая-то игрушка. Также видел исходники GARDEN и LAND, на как я понимаю дизассемблированные.

DimaRU
15.07.2023, 13:20
В разборках старого хлама нашел диск от аналога RK05 (ИЗОТ-1370) болгарского производства. На фотографии в сравнении с современным диском 3.5"
79195