Введение в реверсинг с нуля используя IDA PRO. Часть 15.

Дата публикации 17 сен 2017 | Редактировалось 23 сен 2017
В предыдущей части, мы увидели несколько из многих методов, которые существуют для обнаружения и получения OEP в упакованном файле. Сейчас, вернёмся к двум пропущенными шагам: это ДАМП и ВОССТАНОВЛЕНИЕ IAT, стараясь объяснить их в этом туториале.

1.png

Мы снова попадаем в OEP программы и делаем её ПОВТОРНЫЙ АНАЛИЗ. Теперь у нас уже есть всё, чтобы сделать ДАМП.

Сейчас будем использовать IDC скрипт, а не PYTHON.

Код (C++):
  1. Static main()
  2. {
  3. auto fp, ea;
  4. fp = fopen("pepe.bin","wb");
  5. for(ea = 0x400000; ea < 0x40B200; ea++)
  6. fputc(Byte(ea), fp);
  7. }
  8.  
В скрипте введём IMAGEBASE(БАЗА_ОБРАЗА), адрес, которой равен 0x400000 и наибольший адрес последней секции исполняемого файла, который мы видим в IDA на вкладке SEGMENTS, который нужно СДАМПИТЬ. В этом случае секция OVERLAY, которая является последней секцией исполняемого файла, заканчивается по адресу 0x40B200.

2.png

3.png

Сохраним этот скрипт под каким-нибудь именем, например DUMPER.IDC

4.png

И запускаем его через FILE → SCRIPT FILE. Можно видеть, что IDA принимает скрипты как PYTHON так и свои родные IDC, поэтому тут с этим нет проблем.

5.png

Я делаю копию созданного файла и переименовываю его расширение в EXE. (Если Вы не видите расширения файлов, Вы должны изменить соответствующую опцию в НАСТРОЙКАХ ПРОВОДНИКА)

6.png

7.png

Видим, что у файла нет иконки, потому что некоторые шаги пропущены.

Во вложении приложен PE EDITOR 1.7, распакуем и запустим его.

8.png

Теперь идём в СЕКЦИИ.

9.png

Здесь делаем правый щелчок в каждой из секций и выбираем пункт DUMPFIXER.

10.png

11.png

Видим, что мы уже ближе к победе. По крайней мере, теперь, выводится иконка, хотя программа ещё не запускается, потому что необходимо отремонтировать IAT.

ЧТО ТАКОЕ IAT?

IAT или IMPORT ADDRESS TABLE - это таблица, находящаяся в исполняемом файле, она используется, когда запускается программа. В ней программа сохраняет адреса импортируемых функций, которые она использует, для того, чтобы программа смогла запуститься на любом компьютере.

Если IAT верная и если мы дадим исполняемый файл другому человеку, IAT будет заполнена значениями, соответствующими конкретному компьютеру, независимо от версии WINDOWS, который он имеет, и будет оставаться совместимым, и хорошо работать.

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

Мы помним из предыдущей части, что я хотел объяснить различие между верхним изображением, которое принадлежит упакованному файлу, когда он был в OEP перед ДАМПОМ и исходного файла.

12.png

Оба изображения показывают адрес 0x403238 и похоже, что они имеют одинаковое содержимое. Сейчас, давайте откроем оригинальный файл.

13.png

Здесь можно видеть ФАЙЛОВОЕ СМЕЩЕНИЕ, которое равно 0x1038, чтобы иметь возможность искать данные в HXD в исходном исполняемом файле.

Давайте откроем с помощью HXD оригинальный файл.

14.png

Видим, что содержимое памяти по смещению 0x1038 равно 0x355E.

Если я прибавлю значение 0x355E к IMAGEBASE, которое равно 0x400000, то получу результат 0x40355E. Что существует по этому адресу?

Чтобы увидеть что там находиться, нужно загрузить исходный файл с помощью опции MANUAL LOAD, для того, чтобы IDA загрузила все секции исполняемого файла.

15.png

Соглашаемся со всеми секциями для загрузки и когда файл загрузится, идём по адресу 0x40355E и видим в правой стороне имя API функции, оно равно GetModuleHandleA.

16.png

Итак, когда система загружает файл, программа начинает работать со всеми этими блоками. (1 блок — это одна API функция. Прим. Яши) Их можно увидеть ниже на изображении.

17.png

И каждый блок складывается с содержимым IMAGEBASE и ищет соответствующую функции строку. И из этой строки рассчитывается во время выполнения адрес для нашего компьютера. Как например в нашем случае ищется адрес API функции GetModuleHandleA на нашем компьютере и изменяется значение 5E 35 на адреса API.

Вот почему исполняемый файл работает на любом компьютере, потому что он всегда будет находить в каждой записи IAT имя соответcтвующей API функции и рассчитывать её адрес при загрузке программы. Таким образом всегда содержащийся в нём адрес будет действительным, хотя и будет отличаться от компьютера к компьютеру. Однако адрес блока GetModuleHandleA на всех компьютерах будет одинаковым во всех исполняемых файлах без рандомизации. Изменится только его содержимое.

Вот почему на любом компьютере, если я сделаю:

CALL [0x403238]

Это всегда будет работать, потому что адрес 0x403238 - это запись IAT для функции GetModuleHandleA. Что будет меняться - это содержимое, которое система будет сохранять, изменив исходное значение 5E 35, которое указывает на строку, если мы сложим её с базой.

Не закрывая две других IDA с упакованным файлом, который остановлен в OEP и исходным файлом, в третьей IDA я открываю ДАМП, который мы только что сделали. Это файл PEPE - COPY.EXE.

В этом файле идём в IAT по адресу 0x403238.

18.png

Видим, что здесь смещение файла равно 0x3238 и оно не соответствует исходному файлу, потому что DUMPFIXER который исправлял RAWSIZE и VIRTUALSIZE, также изменил смещения, и запись IAT API GMHA(GMHA = GetModuleHandleA прим. Яши).

Если откроем этот файл в HXD и перейдём по адресу 0x3238.

19.png

То по этому адресу увидим:

20.png

Видим, что здесь у нас есть адрес API функции, а не смещение, которое нужно сложить с IMAGEBASE, чтобы получился адрес API.

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

21.png

Так в чём же проблема?

Когда программа запускается, она ищет в записи IAT значение, чтобы сложить его с IMAGEBASE и найти строку, чтобы рассчитать адрес, но сейчас значение поломано, потому что при дампинге был сохранен итоговый адрес, и программа будет “падать” при запуске, и будет неспособна правильно заполнить IAT.

Хорошо, чтобы закончить с этой темой, давайте подведём итог. Идея состоит в том, чтобы исправить IAT и восстановить все эти смещения, которые указывали на строки с именами API. Это не надо делать вручную, так как так будет очень долго. Чтобы сделать это быстрее, будем использовать утилиту под названием SCYLLA.

Забрать её можно здесь.

https://tuts4yoututs4you.com/download.php?view.3503

Пароль на архив RAR равен tuts4you

22.png

Я запускаю нашу распакованную SCYLLA.

23.png

В пункте ATTACH TO ACTIVE PROCESS из выпадающего меню я выбираю процесс упакованного файла, который остановлен в IDA на OEP.

24.png

Теперь меняем в программе OEP на значение 401000.

25.png

И нажимаем кнопку IAT AUTOSEARCH.

26.png

Программа говорит нам, что таблица IAT начинается по адресу 0x403184 и её размер равен 0x108.

После этого, давайте нажмём кнопку GET IMPORTS.

27.png

Видим, что SCYLLA нашла все адреса, за исключением трёх вхождений. Она показывает плохие записи после нажатия кнопки SHOW INVALID.

28.png

С другой стороны, видим, что смещение 3238 в упакованном файле принадлежало, соответственно, функции GetModuleHandleA и мы знали про это. Программа очень правильно рассчитало значение. Мы можем посмотреть в упакованном файле недействительные адреса записи 0x403248 в дальнейшем, чтобы увидеть, что они собой представляют.

29.png

Видим, что эта запись принадлежит библиотеке COMCTRL32.

И если я сделаю правый щелчок на неправильных записях в SCYLLA и выберу SCYLLA PLUGIN → PE COMPACT, она исправит эти ошибки.

30.png

Теперь записи совпадают с теми, которые мы только что видели.

31.png

Если нажмём кнопку SHOW SUSPECT, можем увидеть, верны ли эти два подозрительных вызова по адресам 0x403258 и 0x403278.

32.png

Да, они получаются правильными. Так что, теперь, можем нажать кнопку FIX DUMP.

33.png

SCYLLA сохранит записи в починенный файл PEPE-COPY_SCY.EXE, и теперь видно, что он работает.

34.png

Открыв этот распакованный файл в IDA, видим, что теперь OEP начинается по адресу 0x401000 и что имена похожи на имена API как в исходном файле, так что всё рассчитались правильно.

35.png

36.png

Таблица IAT выглядит также хорошо, как и у исходного файла.

Хорошо, мы распаковали наш первый и простой упаковщик. Позже мы увидим другие, более сложные упаковщики.

До встречи в 16-той части.


====================================================================
Автор текста: Рикардо Нарваха - Ricardo Narvaja (@ricnar456)
Перевод на английский: IvinsonCLS (@IvinsonCLS)
Перевод на русский с испанского+английского: Яша_Добрый_Хакер(Ростовский фанат Нарвахи).
Перевод специально для форума системного и низкоуровневого программирования - WASM.IN
22.09.2017
Версия 1.0

24 16.186
yashechka

yashechka
Ростовский фанат Нарвахи

Регистрация:
2 янв 2012
Публикаций:
90

Комментарии


      1. Kulagin 29 ноя 2021
        Решается добавлением #include <ida.idc> вначале скрипта:
        Код (Text):
        1. #include <ida.idc>
        2.  
        3. static main()
        4. {
        5. auto fp, ea;
        6. fp = fopen("pepe.bin", "wb");
        7. for ( ea=0x400000; ea < 0x40b200; ea++ )
        8. fputc(Byte(ea), fp);
        9. }
        10.  
        yashechka нравится это.
      2. кофейник 14 июн 2020
        SeveNT-f и yashechka нравится это.
      3. кофейник 11 июн 2020
        рабочий скрипт сохранения дампа памяти:

        auto fname = "C:\\My_dump.bin";
        auto address = 0x400000; //Start adress
        auto size = 0xb200; //Size
        auto file= fopen(fname, "wb");
        savefile(file, 0, address, size);
        fclose(file);

        Через Shift + F2
        Сохраняет в корень диска. Проверено при замене С на D.
        https://www.cyberforum.ru/low-level/thread2116605.html
        yashechka нравится это.
      4. CrawlUp 24 дек 2018
        Увы, вообще не понятно, что делать если scilla не работает, или исправляет но не все строки.
        yashechka нравится это.
      5. Sergey546 7 дек 2018
        спасибо
        yashechka нравится это.
      6. yashechka 7 дек 2018
        В блокноте, а как ещё?
      7. Sergey546 7 дек 2018
        Подскажите как создавать скрипт.
      8. yashechka 10 авг 2018
        Не скажу, сам я не пробовал. Ждем когда другие скажут.
      9. LastNoob 10 авг 2018
        Со скриптом действительно происходит беда,если импортировать из файла...
        Если я правильно понял Byte- дитя C# и последующих языков, а синтаксис больше походит на СИ, судя по методам, тут больше бы подошел тип переменных char,
        однако, с ним еще веселее, такой вот пустой дамп, знаю, тема себя уже изжила, но просто интересно, почему работает так, а не иначе)
        [​IMG]

        Благодарю за статью;)
        yashechka нравится это.
      10. yashechka 14 мар 2018
        Вы очень молодец :boast::boast::boast:
      11. CrawlUp 14 мар 2018
        Чтобы IDC скрипт заработал надо войти File->Script Command скопировать скрипт в появившееся окошко и запустить RUN[​IMG]
        hjujet и yashechka нравится это.
      12. yashechka 31 янв 2018
        Вручную никто ничего не делает.
      13. yashechka 31 янв 2018
        Смотрите курс Введение в отладку с нуля. Таблица чиниться с помощью программы ImportReconstructor
      14. Имя 30 янв 2018
        Разобрался вроде, но как в ручную сделать не особо понял)
        yashechka нравится это.
      15. Имя 30 янв 2018
        Я может что-то не догоняю, но с упакованным файлом обычно не идет неупакованный. А если так, то как восстановить таблицу IAT?
        Так-то понятно, но в жизни такого не бывает.
        yashechka нравится это.
      16. Sloneny 1 янв 2018
        У меня скрипт дампера матерился такими нехорошими словами:
        Код (Text):
        1. Function declaration is expected
        Оказалось что слово static в начале скрипта должно быть полностью строчным, а в примере оно начинается с заглавной.

        p.s. качайте архивы с файлами с сайта Рикардо, в них есть все файлы, и скрипты, и крякми, и даже дампы этих крякмей:)
        hjujet и yashechka нравится это.
      17. loonydev 9 ноя 2017
        У меня как раз десятка в виртуалке -_-

        Я не поленился и чекнул, он же вначале говорил что будет работать на последней версии 10-ки
        "В моем случае, я использую Windows 10 Anniversary Update x64 со всеми патчами, вплоть до 29 октября 2016."
        yashechka нравится это.
      18. yashechka 9 ноя 2017
        Я не знаю, но возможно.
        По прошлому курсу - Нарваха много не договаривает и делает ошибки :)
        Может быть потому что виртуалочка? В самом начале он вообще про Виндовс 10 зарекается
      19. loonydev 9 ноя 2017
        Блин, то ли я тупой, то ли здесь что-то не так с примерами.
        Скрипт дампа падает на функции Byte (Attempt to call undefined function 'Byte') , мол не такой... Может я что-то не установил? (Version 7.0.170914 Windows x64 (32-bit address size) на вируталочке)

        Вообщем вот мой скрипт через IPython, может у кого-то такой же геморой будет


        import idaapi
        file_out=open('C:\\Solution\\15\\my_bin_dump','wb')
        time_byte_s=[]
        for ea in range(0x400000,0x40B200):
        time_byte_s.append(Byte(ea))
        file_out.write(bytearray(time_byte_s))
        file_out.close()
        yashechka нравится это.
      20. jkmjkmjkm 29 сен 2017
        hjujet, DzenGURU и yashechka нравится это.
      21. yashechka 25 сен 2017
        Спасибо.
      22. jkmjkmjkm 24 сен 2017
        yashechka нравится это.
      23. yashechka 23 сен 2017
        Прошу оценить новый перевод. Учтены все предложения, комментарии, жалобы :boast::boast::boast:
        hjujet и DzenGURU нравится это.
      24. yashechka 23 сен 2017
        Готово :)
        DzenGURU нравится это.