Перейти к содержанию
49406

Как я мучаюсь с фирмварью PSP


Haven

Рекомендуемые сообщения

Весьма интересное дело, этот реверс инжиниринг, столько всего интересного и недокументированного можно увидеть, с ума сойти!


Эта статья посвящена реверсу фирмвари (или прошивки) всеми любимой PSP и моей лени, тому, чем я занимаюсь вместо подготовки к экзаменам. Мной за основу была взята прошивка от PSP Go, версии 6.60 на официальном сайте. Я не очень опытен в реверсе, поэтому буду рад любым замечаниям. Ну что же, наверное не стоит медлить.

Первым делом конечно же стоит взять прошивку, опять же это можно сделать на официальном сайте Sony. Имя файла в принципе классическое для этой платформы - EBOOT.PBP. Со скачиванием проблем особых быть не должно, а вот что дальше...

Вообще есть несколько путей добычи декриптованной прошивки. Все выбирают классический: через PSARDumper и prxtool. К сожалению, этот способ мне не помог; PSARDumper не понимал как упакован файл, а при дальнейших махинациях (которые я опишу далее) prxtool не мог загрузить ELF-структуры:
 

e3939dcf7949.png


Существует еще одна тулза: prxdecrypter, но и она мне не смогла помочь, она тоже не понимала как упакован .prx файл.

Что ж, мне пришлось добираться до заветной цели на костылях, а я и не против. На каком-то сайте я нашел psptool некоего DaveeFTW, уже улучшенный другим человеком: zecoxao. Хорошо, что на github лежит этот репозиторий, иначе бы я перерыл бы всю историю браузера. Так получилось, что я сишник, да и оригинальную версию не видел, чтоб сравнить и проанализировать в каких местах оно стало лучше. Скорее всего вы на ОС Windows (на UNIX-like системах все +- так же), поэтому команда будет такова:

C:\Users\<user_name>\path\to\Python\Python38\python.exe pcard.py EBOOT.PBP EBOOT.PSAR

На самом деле можно и обойтись без EBOOT.PSAR, по крайней мере у меня это получилось.

И вот, наконец-то мы получили заветные разделы /flash0 и /flash1, я их уже перенес в отдельную папку проекта. Как раз таки на этом моменте и отказались работать prxtool и prxdecrypter. Скорее всего это связано с самим алгоритмом дешифровки, который видимо что-то либо пропускает, либо не дешифрует до конца.
 

67a0c0e58691.png


Декриптовав EBOOT.PBP встает следующий вопрос: "А как мне получить листинги, если и prxtool, и prxdecrypter отказываются работать?". Существует такой замечательный инструмент, как Ghidra - дизассемблер от NSA (стремно, не так ли?). Но теперь возникает и еще один вопрос: "А как мне резолвить psp-шные функции?". Я тоже задался этим вопросом и буквально через часа так 1.5 вспомнил, что я еще в марте рылся в pspsdk и пытался что-то написать под саму PSP. Зайдя на github проекта pspsdk я наткнулся на нужные скрипты, обнаруживающие psp-шные функции, они были как раз для Ghidra. Так что я незамедлительно сохранил скрипты на диск и пошел их пихать в Гидру.

Краткий гайд по Ghidra.
Думаю, вы разберетесь, как её запустить, по крайней мере на оф. сайте есть туториал, если вдрыг будут проблемы.
Давайте создадим новый проект: File -> New Project. Далее выбираем Non-Shared Project:
 

ba9b167c904c.png


Затем просто вводите имя своего проекта и укажите для него папку:
 

e4391ece3b88.png


Для того, чтоб установить скрипты для реверса psp-шных файлов нам нужно зайти в дизассемблер, это такой зеленый дракончик во вкладке Tool Chest. Нажимайте на него и вам откроется дизассемблер, перейдите в Script Manager:
 

6cd8469af96f.png


Выберите нужную директорию в Script Directories (там будет зелененький +, нажмите на него) с скриптами для psp-функций и сохраните (не нажимайте dismiss), они нам пригодятся. Выходим из дизассемблера.
 

12912fc54b34.png


Далее нам в проект нужно импортировать файл, это делается через File -> Import File, затем выбрать нужный файл. Если вы собрались реверсить .prx, то рекомендую вам в следующем контекстном меню выбрать "Batch", после просто нажмите "OK". Я импортировал avcodec.prx (остальным файлам по 3-4 дня):
 

e87d8fcca711.png


Откройте нужную папку с расширением .prx и кликните 2 раза по "gzip_decompressed", снова откроется дизассемблер. Теперь нам предложат проанализировать файл:
 

7aefd833ec7c.png


Выбираем да. В следующем окне оставляем все как есть:
 

90a4d4090cd5.png


Вуаля, у нас теперь есть листинг. Перед вами MIPS архитектура, используемая Sony, как раз для PSP и некоторых других приставок и вещей. Предварительно пройдитесь установленным плагином, чтоб было понятнее где какие функции. Я это как раз забыл сделать, так что пришлось мне частично переписывать полученный С-псевдокод кое-какого модуля.

Для понимания архитектуры MIPS я оставлю вам вот этот документик + вы можете руководствоваться этим и вот этим, а так же эмулятором самой архитектуры. Я же пройдусь по самому интересному без углубления во что, да как, почему и зачем, иначе статья получится очень большой, поэтому все интересное будет разобрано на псевдокоде.

Я начал с анализа sircs.prx. Правда анализ на данный момент все равно не полный, так что будут некоторые неточности.

Боль и хардварь.
Первым делом мне нужно дать вам расшифровку SIRCS - Sony Integrated Remote Control System.
Протокол существует в 3-х версиях: 12, 15 и 20 битная. К сожалению, я не могу сказать какая версия у PSP Go, для этого мне нужна сама плата, которой я сейчас не обладаю. Но думаю, что либо 15, либо 20 битная. Вот как оно выглядит:
 

b12d151fdea4.png

Полную информацию о протоколе можно найти здесь.
Как и говорил ранее - я упомяну здесь самые интересные и главные на мой взгляд куски.

main функция, понятно сразу, что она делает:

uint entry(void) {
  int iVar1;
  iVar1 = FUN_00000000();

  return (uint)(iVar1 < 0);
}

Следом за ней идет некая функция FUN_00000000(), предполагаю, что она инициализирует сам модуль:

int FUN_00000000(void) {
  int iVar1;

  /* 0x00000094 - 0x000000BO, 0x000000BC & 0x000000B4 - 0x000000B8 are R/0 addresses and uses RAM */
  uRam00000094 = 0;
  uRam00000098 = 0;
  uRam0000009c = 0;
  uRam000000a0 = 0;
  uRam000000a4 = 0;
  uRam000000a8 = 0;
  uRam000000ac = 0;
  uRam000000b0 = 0;
  iRam000000b4 = 0;
  iRam000000b8 = 0;
  uRam000000bc = 0;

  iVar1 = FUN_00002440();
  if (iVar1 < 0x500000) {
    uRam00000094 = 1;
    FUN_000023e0(2,0);
  }
  iVar1 = FUN_00002310(0xe,2,0x140,0);
  if (-1 < iVar1) {
    iVar1 = FUN_000023b8("SceSIRCS",1,1,1);
    if (-1 < iVar1) {
      iRam000000b4 = iVar1;
      iVar1 = FUN_00002378("SceSIRCS",1,0,0);
      if (-1 < iVar1) {
        uRam000000bc = 0;
        uRam00000098 = 0;
        iRam000000b8 = iVar1;
        iVar1 = FUN_00001b34();
        if (-1 < iVar1) {
          FUN_00001b28(0xa8c);
          return 0;
        }
        FUN_000023c8(0xc0008de);
      }
      FUN_00002350(0x3821);
    }
    FUN_00002328(0xe);
  }

  return iVar1;
}

SceSIRC скорее всего принадлежит include-файлу аля pspsirc.h, который я попробую в скором времени вытащить.
Дальше тут идут два больших куска, они реально большие и наверное отвечают за логику таймера, поэтому вы сможете найти их на github, ссылка будет в конце статьи.
Вот это задает портам какие-то базовые значения:

undefined4 FUN_000016b8(void) {
  int iVar1;
  
  iVar1 = sceSysregGetTachyonVersion();
  if (iVar1 < 0x500000) {
    sceGpioPortClear(4);
  }
  sceSysregUartIoEnable(5);
  sceSysregUartClkEnable(5);
  _DAT_be540004 = 0xffff;
  _DAT_be54001c = 0x280;
  _DAT_be540020 = 0xd;
  _DAT_be540024 = 0;
  _DAT_be540028 = 0;
  _DAT_be54002c = 0x70;
  _DAT_be540030 = 0x307;
  _DAT_be540034 = 0;
  _DAT_be540038 = 0x50;
  
  return 0;
}

Примечателен undefined4, скорее всего это какой-то пользовательский тип данных.
Здесь примечателен некий SceIrdaDriver, сложно сказать, есть ли у PSP ИК-порт или это просто моя ошибочная ассоциация:

undefined4 FUN_00001828(void) {
  int iVar1;
  undefined4 uVar2;

  /* R/O address */
  /* SceIrdaDrive - InfraRed Data Association Driver? */
  iRam00000078 = sceKernelCreateFpl("SceIrdaDriver",1,1,0x3c070000);

  uVar2 = 0x802a0006;

  if (-1 < iRam00000078) {
    iVar1 = sceKernelTryAllocateFpl(iRam00000078,0x88);
    uVar2 = 0x802a0006;
    if (-1 < iVar1) {
      iVar1 = sceKernelTryAllocateFpl(0x4021,0x84);
      uVar2 = 0x802a0006;
      if (-1 < iVar1) {
        sceKernelRegisterIntrHandler(0x25,2,FUN_000020e8,0x40);
        sceKernelEnableIntr(0x25);
        /* R/O address */
        iRam0000008c = sceKernelEnableIntr("SceIrdaDriver",0x201,0,0);
        uVar2 = 0x802a0006;
        if (-1 < iRam0000008c) {
          uVar2 = 0;
        }
      }
    }
  }

  return uVar2;
}

Еще несколько интересных, но жирнючих функций в конце файла, не уверен, но возможно они отвечают за "Bit Counter" и так же таймер.

end-point:

undefined4 module_stop(void) {
  FUN_00001b54();
  sceGpioPortSet(4);
  sceSysregSircsClkDisable();
  sceSysregSircsIoDisable();
  sceKernelReleaseIntrHandler(0xe);
  sceKernelDeleteSema(0x3821);
  sceKernelDeleteEventFlag(0xc0008de);
  FUN_00001b54();
  FUN_00000a4c();
  return 0;
}

====================================
Конечно, дело это долгое и муторное, но все же интересное. Не знаю, смогу ли я закончить или я брошу это. В любом случае вы можете следить за моим прогрессом на github. Надеюсь, вам было интересно скроллить это чтиво.

SHELLSHOCK: тык
Буду так же рад, если вы будете помогать мне, это конечно только при особом желании.
Если у вас возникли вопросы, то можете обратиться ко мне в теме, лс или в телеге. В телеге я немножечко активнее.
tg: @kreophagia
 

Ссылка на комментарий
Поделиться на другие сайты

Конечно, дело это долгое и муторное, но все же интересное. Не знаю, смогу ли я закончить или я брошу это. В любом случае вы можете следить за моим прогрессом на github. Надеюсь, вам было интересно скроллить это чтиво.

Продолжай!

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
×
×
  • Создать...