R0 CREW

IDA 6.8. Ошибка в скрипте MSP430.py. Часть 2

Приветствую всех. В предыдущей теме поднимался вопрос об ошибке в скрипте MSP430.py при дизассемблировании программного кода с 20-ти битной адресацией и уважаемым groke было предоставлено ее решение. В дальнейшем тема заполнилась информацией слабо относящейся к основному вопросу, поэтому было решено продолжить обсуждение здесь.
После исправления ошибки в скрипте MSP430.py была предпринята попытка декодирования программного кода с “обычной” 16-ти битной адресацией. К большому разочарованию обнаружилось, что инструкция вида br #1200h декодируется как mov #1200h, PC (чего не наблюдается при использовании оригинального MSP430.py). По сути, декодирование происходит правильно, только используется не эмулированное представление инструкции. Однако это ведет к тому, что IDA перестает автоматически декодировать тот код, к которому происходит переход по инструкции. Вопрос: можно ли это исправить, сохранив исправления для 20-ти битной адресации?

P.S. 20-ти битная инструкция, например такого вида bra #11200, декодируется правильно.

Приветствую!
Можете приложить байты неправильно декодируемой инструкции? Под рукой нет инструментов для транслирования в машинный код :frowning:

И, на всякий случай, и машинное представление правильно кодируемой инструкции.

Подозреваю что проблема в этом месте:

def is_movpc(self):
    # mov xxx, PC
    return self.cmd.itype == self.itype_mov and self.cmd.Op2.is_reg(self.ireg_PC) and self.cmd.auxpref == AUX_WORD

Из-за того что мы модифицируем auxpref (в правках оригинального скрипта из прошлой темы) у нас последнее условие не срабатывает и IDA не распознает что это инструкция меняющяя PC
Можно заменить на следующий код:

def is_movpc(self):
    # mov xxx, PC
    return self.cmd.itype == self.itype_mov and self.cmd.Op2.is_reg(self.ireg_PC) and ((self.cmd.auxpref & 0x7f) == AUX_WORD)

groke, Вы как всегда на высоте! Спасибо! Предложенное Вами изменение работает! Однако пока еще не все гладко…
Инструкция POPX эмулируемая, но она отображается “неэмулируемо”. Например, должно быть POPX &300h, а отображается как MOVX @SP+, &300h. Причем эта инструкция неправильно отображается не только с модифицированным MSP430.py, но и с оригинальным. Вот байты этой инструкции из окна Hex View 40 18 B2 41 00 03.

Попробуйте найти следующие строчки в скрипте

            self.itype_movx: [
                # movx #0, dst -> clrx dst
                [ lambda: is_imm_op(self.cmd.Op1, 0), self.itype_clrx, 2 ],
            ],

и заменить на следующий код:

            self.itype_movx: [
                # movx #0, dst -> clrx dst
                [ lambda: is_imm_op(self.cmd.Op1, 0), self.itype_clrx, 2 ],
                [ lambda: is_autoinc(self.cmd.Op1, self.ireg_SP), self.itype_popx, 2 ],
            ],

Я так понимаю в функции simpilfy словарь maptbl как раз определяет список замен инструкций на эмулируемые.

После этой правки у меня эти байты отображается как popx.w &300h

Исправил, все отображается как надо. Спасибо Вам! Буду изучать далее. Может еще будут недочеты…

Подскажите еще по такой теме. В msp430.py есть массив инструкций. Мне захотелось изменить регистр инструкций на верхний (чтобы в IDA было не mov, а MOV и т. д.). Однако если это сделать, то при открытии базы выходит куча ошибок (первая из них на скриншоте). Можно ли добиться отображения инструкций в верхнем регистре?

Надо заменить

def init_instructions(self):
        Instructions = []
        i = 0
        for x in self.instruc:
            if x['name'] != '':
                setattr(self, 'itype_' + x['name'], i)
            else:
                setattr(self, 'itype_null', i)
            i += 1

на

def init_instructions(self):
        Instructions = []
        i = 0
        for x in self.instruc:
            if x['name'] != '':
                setattr(self, 'itype_' + x['name'].lower(), i)
            else:
                setattr(self, 'itype_null', i)
            i += 1

Но это если мы в том самом массиве руками заменим имена.

Возможно, в функции out можно добавить где-нибудь приведение к верхнему регистру и тогда не придется заменять все в том самом массиве

Я, кстати, уже менял содержимое этой функции: закомментировал добавление суффикса .w к инструкциям, оперирующими словами, так как отсутствие суффикса подразумевает операцию со словом:

#       elif sz == AUX_WORD:
#           postfix = ".w"

А как выглядит операция приведения к верхнему регистру?

Прошу прощения - второй способ наверное все-таки будет потруднее, потому что код который надо будет править находится в стандартном классе Иды - processor_t

Все-таки придется в массиве instruc поменять имена и изменить код, как я написал выше :frowning:

  • в функции out поменять постфиксы “.a” … на “.A”

p.s - приведение к верхнему регистру функция .upper() в питоне

Вас понял. Спасибо огромное за помощь!
Сразу прошу прощения за назойливость, но у меня есть еще несколько вопросов. Один из них такой. В микроконтроллерах MSP есть периферийный устройства, регистры управления которыми расположены в RAM памяти. При декомпиляции я указываю, что необходимо создавать RAM память. Далее IDA при декодировании помечает обращения к регистрам управления из кода как byte_0 или word_140. Чтобы код был более понятным я вручную меняю эти наименования на правильные, то есть, указанные в даташите на соответствующий микроконтроллер. Подскажите, можно ли как-то автоматизировать этот процесс? То есть, один раз указать какой адрес как называется, а далее при декомпиляции любой прошивки от данного микроконтроллера “нажать кнопку” и проставить имена всех регистров управления.

Рад помочь:)
Сам когда-то пытался ковырять прошивку от фитнес браслета на msp430, но как-то со временем не вышло:(
Правильно ли я понял, что задача состоит в том, чтобы просто автоматически проименовать определенные адреса в базе?
Если да, то можно сделать простенький скрипт на питоне следующего вида:

MakeName(addr1, "name1")
MakeName(addr2, "name2")
...

Затем загрузить его по alt+f7

Чтобы выбирать между байтом, словом или двойным словом есть функции MakeByte(addr), MakeWord(addr), MakeDword(addr)

groke, у Вас что ни ответ, все в точку! Спасибо за Ваш труд!
Я писал о нескольких вопросах. Сейчас вспомнить не могу. Как вспомню, обязательно пристану снова. Спасибо Вам еще раз!

Вспомнил, что хотел спросить. При декодировании в тексте программы есть метки инструкций (например loc_118A:). Они не имеют отступа от края окна. Возможно ли сделать выравнивание меток по уровню основного кода?

Вот с этим подсказать не смогу:(
Ни разу не пытался, а в настройках вроде такого не нашел

Ну да ладно. Прошу прощения за беспокойство. Тем более, что это не необходимость, а моя прихоть.

groke, снова есть вопрос. Ранее Вы мне подсказали как создать скрипт для присвоения адресам имен (функция MakeName). Хочу расширить этот скрипт. Необходимо дать имена обработчикам прерываний. Как дать имя функции я знаю (опять же MakeName), как представить вектора в виде слов тоже (MakeWord). А как узнать значение слова, которое расположено по заданному адресу?

Word(addr), Byte(addr), Dword(addr)

Изучайте документацию по API:
https://www.hex-rays.com/products/ida/support/idapython_docs/

Подскажите еще, возможно ли скрипт на Питоне в IDA выполнить по шагам? А то напрограммирую сейчас, запущу, а он чего-нибудь не то сделает.

Надо использовать дебаггер. Есть стандартный pdb, но простое pdb.runcall(…) не работает из-за особенностей консоли в IDA, по идее, можно в классе pdb.Pdb задать пайпы на input и output, и посылать команды из другой консоли.
Ещё есть ссылки типа таких http://wingware.com/doc/howtos/idapython.