Форум программистов, компьютерный форум, киберфорум
Наши страницы
tezaurismosis
Войти
Регистрация
Восстановить пароль
Рейтинг: 3.00. Голосов: 2.

Разбор PE-файла на C#

Запись от tezaurismosis размещена 08.07.2012 в 12:40
Метки c-sharp, pe-файлы

Решил написать программку для получения полей из PE-файлов (DOS, PE-заголовки, DataDir...). Я думаю, что на C++ это уже сто раз писали, а вот на шарпе... Может быть и нет, по крайней мере для общего развития.
Предлагаю ознакомиться и оценить небольшой участок кода. Я буду признателен, если вы мне предложите идеи по улучшению этого кода, чтобы я мог дописать оставшуюся часть в лучшем стиле.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* Считываем информацию о PE-файле
 * by tezaurismosis (www.cyberforum.ru). 2012
 */
 
using System;
using System.IO;
using System.Text;
 
namespace PEReader
{
    /// <summary>
    /// Данная структура содержит информацию о PE-файле (portable executable), 
    /// включая данные из заголовка DOS, PE и т.д.
    /// Описание полей PE-файла взято отсюда: http://mzc.narod.ru/Creating/Step008.htm
    /// и отсюда http://citforum.ru/programming/windows/machine_code/3.shtml
    /// </summary>
    public struct PEInfo
    {
        /// <summary>
        /// "Magic number" - магическое число в начале DOS-файла, содержит два символа - "MZ".
        /// Если файл содержит по данному адресу (0x00h) другие данные - то это не PE-файл.
        /// Размер - WORD, адрес - 0x00
        /// </summary>
        public short Magic;
        /// <summary>
        /// Количество байт на последней странице файла.
        /// Размер - WORD, адрес - 0x02
        /// </summary>
        public short LastByteCount;
        /// <summary>
        /// Количество страниц в файле.
        /// Размер - WORD, адрес - 0x04
        /// </summary>
        public short PageCount;
        /// <summary>
        /// Количество релокейшенов.
        /// Размер - WORD, адрес - 0x06
        /// </summary>
        public short RelocCount;
        /// <summary>
        /// Размер заголовка в параграфах.
        /// Размер - WORD, адрес - 0x08
        /// </summary>
        public short HeaderSize;
        
        public PEInfo(string path) {
            /* 
            -------------------------------------
                      ФОРМАТ PE-ФАЙЛА
            -------------------------------------
              | Заголовок DOS                 |
              |-------------------------------|
              | Программа-заглушка            |
              |-------------------------------|
              | Заголовок PE                  |
              |-------------------------------|
              | Доп. заголовок PE             |
              |-------------------------------|
              | Массив DataDir                |
              |-------------------------------|
              | Заголовки сегментов           |
              |-------------------------------|
              | Тела сегментов                |
              |-------------------------------|
              | Остальные области данных      |
              |_______________________________|
            */
            // Открываем PE-файл, используя BinaryReader в комбинации с FileStream
            using (FileStream file = new FileStream(path, FileMode.Open)) {
                using (BinaryReader reader = new BinaryReader(file)) {
                    // Поочерёдно считываем из потока нужное нам количество байт.
                    // Если требуется 1 байт (BYTE) используем ReadByte(),
                    // если 2 байта (WORD) используем ReadInt16(),
                    // если 4 байта (DWORD) используем ReadInt32(),
                    // если 8 байт (QWORD) используем ReadInt64()
                    // -------------
                    // Заголовок DOS
                    // --------------
                    // WORD 0x00
                    this.Magic = reader.ReadInt16();
                    // WORD 0x02
                    this.LastByteCount = reader.ReadInt16();
                    // WORD 0x04
                    this.PageCount = reader.ReadInt16();
                    // WORD 0x06
                    this.RelocCount = reader.ReadInt16();
                    // WORD 0x08
                    this.HeaderSize = reader.ReadInt16();
                }
            }
        }
    }
    
    class Program
    {    
        public static void Main(string[] args)
        {
            String path = @"C:\Program Files (x86)\Notepad++\notepad++.exe";
            PEInfo info = new PEInfo(path);
            Console.WriteLine("Magic: {0:x}\n" +
                              "LastByteCount: {1:x}\n" +
                              "PageCount: {2:x}\n" +
                              "RelocCount: {3:x}\n" +
                              "HeaderSize: {4:x}",
                              info.Magic,
                              info.LastByteCount,
                              info.PageCount,
                              info.RelocCount,
                              info.HeaderSize);
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
    }
}
Размещено в Без категории
Просмотров 32867 Комментарии 10
Всего комментариев 10
Комментарии
  1. Старый комментарий
    Аватар для NickoTin
    Посмотрите исходники Mono.Cecil (namespace Mono.Cecil.PE).

    з.ы.
    C#
    1
    2
    
    using (FileStream file = ... ) {
                    using (BinaryReader reader = new BinaryReader(file) ) {
    Масло масленное, не находите?
    C#
    1
    
    using (var reader = new BinaryReader(File.Open( path, FileMode.Open ))) {
    Запись от NickoTin размещена 08.07.2012 в 13:48 NickoTin вне форума
    Обновил(-а) NickoTin 08.07.2012 в 14:19
  2. Старый комментарий
    Аватар для tezaurismosis
    Спасибо, SSTREGG, поправил. Mono.Cecil посмотрю
    Запись от tezaurismosis размещена 08.07.2012 в 14:52 tezaurismosis вне форума
  3. Старый комментарий
    Аватар для Pure
    интересно при чем вообще с++? для полнейшей и всестороннейшей работы с ПЕ файлом существует набор функций винапи, не зависящий от языка.
    Так что в принципе действо с ПЕ файлом можно произвести даже из макросов экселя, используя винапи.
    Запись от Pure размещена 08.07.2012 в 17:38 Pure вне форума
  4. Старый комментарий
    Аватар для tezaurismosis
    А функции WinAPI и заголовочные файлы написаны на C/C++, не?
    Запись от tezaurismosis размещена 08.07.2012 в 17:55 tezaurismosis вне форума
  5. Старый комментарий
    Аватар для NickoTin
    Pure, использовать готовое это конечно хорошо, время сокращает и т.п., но знать как оно там устроено внутри, иногда бывает очень полезно
    Запись от NickoTin размещена 08.07.2012 в 19:44 NickoTin вне форума
  6. Старый комментарий
    Аватар для Pure
    т.е. когда ты писал
    Цитата:
    Я думаю, что на C++ это уже сто раз писали, а вот на шарпе... Может быть и нет, по крайней мере для общего развития.
    ты конечно же имел ввиду что ос виндовс написана на С и асме)? Я вот подумал что ты несколько про иное
    Запись от Pure размещена 08.07.2012 в 22:35 Pure вне форума
  7. Старый комментарий
    Аватар для Pure
    SSTREGG, то что там написано выше от начала и до конца работает на винапи. ПЕ это как раз тот формат который на нижнем уровне обрабатывается винапишными функциями и хорошо разбивается теми же структурами. (имеется ввиду не уровень ручного ковыряния файла через хекс редактор, а через функции). Поэтому то что использовать готовое, как в случае выше - это хорошо конечно согласен ну и с тем что знать надо как оно устроено, нельзя не согласится. Однако каков смысл написания на шарпе того, что давно описано в функциях апи? Т.е. получается как ты любишь писать "масло маслянное". Хотя вероятно это равнозначно использованию стандартной библиотеки с++ для перемещению по файлу, какой нибудь fstream. Наверно это имел ввиду автор.



    А вообще подумалось раз такое инфо выложено то очень хорошо. Вот любопытно было бы увидеть добавление новой секции в бинарник через функции шарпа.Это и правда интересно и углубляет знания
    Запись от Pure размещена 08.07.2012 в 22:39 Pure вне форума
    Обновил(-а) Pure 08.07.2012 в 22:55
  8. Старый комментарий
    Аватар для tezaurismosis
    Цитата:
    Однако каков смысл написания на шарпе того, что давно описано в функциях апи?
    "Какой смысл придумывать новые языки и писать новые фреймворки, если всё можно сделать или уже сделано на C/C++?" - логика та же
    Запись от tezaurismosis размещена 09.07.2012 в 15:54 tezaurismosis вне форума
  9. Старый комментарий
    Аватар для Pure
    в шарпе оставлена возможность дергать функции апи. фреймворк не покрывает всего, да и глупо это - сидеть на винде и отрицать наличие удобных апи функций, заточенных для работы с ПЕ.

    было бы интересно увидеть твой ответ на вопрос ниже

    Цитата:
    "Какой смысл придумывать новые языки и писать новые фреймворки, если всё можно сделать или уже сделано на C/C++?"
    Запись от Pure размещена 09.07.2012 в 17:47 Pure вне форума
  10. Старый комментарий
    Аватар для tezaurismosis
    Цитата:
    удобных апи функций
    Я не считаю их удобными, и не считаю удобным использование языка C++ для программирования. Поэтому я и пользуюсь C#. Это мой ответ на вопрос
    Запись от tezaurismosis размещена 09.07.2012 в 18:29 tezaurismosis вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru