Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.68/25: Рейтинг темы: голосов - 25, средняя оценка - 4.68
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908

Функция поиска offset по hex значению в бинарном файле

03.03.2023, 20:41. Показов 7954. Ответов 77

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток.
По названию темы понятно, наверное, что надо сделать.
Начал своё дело с написания функции, которая конвертирует из hex в byte
C++
1
2
3
4
5
6
7
8
9
10
static vector<uint8_t> hex2byte(const char *hex) {
    char high, low;
    vector<uint8_t> buf(strlen(hex) / 2);
    for (int i = 0, length = strlen(hex); i < length; i += 2) {
        high = toupper(hex[i]) - '0';
        low = toupper(hex[i + 1]) - '0';
        buf[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low);
    }
    return buf;
}
Теперь осталось написать функцию поиска, которая бы возвращала бы найденный offset
Но для Windows и Linux нет одного метода.
Для Linux можно использовать mmap, а вот для Windows что?
Хотелось бы использовать один и тот же быстрый инструмент.
Так как работа связана с большими файлами и поиск надо будет делать, как с начала так и с конца файла, да ещё и на слабых машинах, где ОЗУ < размера обрабатываемого файла, то mmap на Linux вряд ли поможет.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.03.2023, 20:41
Ответы с готовыми решениями:

Замена hex данных в бинарном файле
Здравствуйте. Не особо этим интересовался. По факту хочу автоматизировать одну задачу. Но не знаю как в delphi работать с бинарными...

Функции поиска в бинарном файле
Задание: Есть структура с именем worker с полями: name - фамилия и инициалы; position - должность; year - год поступления на...

Функции поиска в бинарном файле по номеру записи
1) Считывание данных в массив структур из текстового файла structures.txt (он прикреплен). 2) Запись данных в бинарный файл. Структура...

77
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
04.03.2023, 14:33  [ТС]
Студворк — интернет-сервис помощи студентам
DrOffset, хде я писал про текст?!

Добавлено через 50 секунд
Verevkin, выходной - дело святое) удачно отдохнуть, возвращайся в понедельник
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
04.03.2023, 14:34
Цитата Сообщение от blackeangel Посмотреть сообщение
хде я писал про текст?!
Это действительно сейчас так важно?
но вообще вот:
Цитата Сообщение от blackeangel Посмотреть сообщение
C++
1
2
high = toupper(hex[i]) - '0';
 low = toupper(hex[i + 1]) - '0';
эти вот вычитания нулей ясно говорят о том, что у вас в hex - текст.
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
04.03.2023, 14:37  [ТС]
DrOffset, ну это как бы естественно и логично. Функции передаются hex значения в текстовом формате. И вы когда с Клавы вводите они тоже текстовые будут....
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
04.03.2023, 14:40
Цитата Сообщение от blackeangel Посмотреть сообщение
ну это как бы естественно и логично.
В разрезе того, что вы написали дальше:
Цитата Сообщение от blackeangel Посмотреть сообщение
файлы не текстовые, а по типу mkv, zstd, rar, img и т.д.
не естественно и не логично.
И никакого отношения к тому, что вы там можете ввести с клавиатуры это не имеет.

Цитата Сообщение от blackeangel Посмотреть сообщение
Функции передаются hex значения в текстовом формате.
Это еще почему? Если вы их из двоичного файла прочитали, то никакого "текстового формата" там не будет. Вам и Verevkin об этом написал.
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
04.03.2023, 14:46  [ТС]
DrOffset, Потому что консоль не текст не воспринимает.
Всё естественно и логично. На функцию подаются 2 параметра, текстовые: 1 - путь к файлу (не текстовому), 2 - hex значение для поиска. Возвращает offset первого совпадения. Поэтому в моих словах и телодвижениях нет ничего противоречащего друг другу.
0
04.03.2023, 14:51

Не по теме:

blackeangel, а, так hex - это то, что вводит юзер для поиска, а не то, что из файла считалось? А чего ж вы тогда, когда я написал

Цитата Сообщение от DrOffset Посмотреть сообщение
В смысле то, что надо найти, конвертировать в hex, а потом это искать в вашем файле сразу?
не сказали, что так и делаете? :) А вместо этого ответили:
Цитата Сообщение от blackeangel Посмотреть сообщение
может и лучше не конвертировать. Я не знаю просто.
? Это меня и запутало.
Ладно, понятно, разобрались.

0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
06.03.2023, 21:51  [ТС]
DrOffset, ну это хорошо. Есть советы ещё в этом направлении?
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
06.03.2023, 22:09
blackeangel, в посте #19.
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
08.03.2023, 18:47  [ТС]

Не по теме:

zayats80888, TheCalligrapher, а вы что остались в стороне? :D



Добавлено через 2 часа 27 минут
DrOffset, перечитал несколько раз этот пост и не понял, а как делать то поиск?
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
#include <iostream>
#include <fstream>
#include <string.h>
#include <vector>
 
using namespace std;
 
///standart block function  -->
std::string &replaceAll(string &str, const string &from, const string &to) {
    if (!from.empty()) {
        size_t start_pos = 0;
        while ((start_pos = str.find(from, start_pos)) != string::npos) {
            str.replace(start_pos, from.length(), to);
            start_pos += to.length();
        }
    }
    return str;
}
 
static vector<char> hex2byte(const char *hex) {
    char high, low;
    vector<char> buf(strlen(hex) / 2);
    for (int i = 0, length = strlen(hex); i < length; i += 2) {
        high = toupper(hex[i]) - '0';
        low = toupper(hex[i + 1]) - '0';
        buf[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low);
    }
    return buf;
}
///standart block function  <--
 
int find_offset(const char *file, const char *whatfind, const int course=0) {
    int block = 16777216; //16 Mb
    int offset_poz;
    vector<char> buff;
    buff.resize(block);
 
    string in(whatfind);
    if (in.find(" ") != string::npos) { //если есть пробелы - уберём
        in = replaceAll(in, " ", "");
    }
    whatfind = in.c_str();
    int len_whatfind = strlen(whatfind)/2; // размер того, что надо искать
    vector<char> data = hex2byte(whatfind);
    if (len_whatfind > block){ //ну мало ли
        block = len_whatfind;
        buff.resize(block);
    }
    fstream intput_file(file, ios::in | ios::binary);
    if (!intput_file.is_open()) {
        cerr << "File " << file << " not found" << endl;
        exit(2);
    }
    int size = intput_file.seekg(0,ios::end).tellg(); //размер файла
 
    if (course != 0 && size > block){ // напраление поиска: 0 - прямой, любое другое число - обратный
        intput_file.seekg(block,ios::end); //сразу идём в конец
    }else{
        intput_file.seekg(0,ios::beg);
    }
    while (!intput_file.eof()) {
        intput_file.read(buff.data(), block); //читаем кусок
 
        // чё тута?! как искать то?!
       // надо найти один вектор в другом
 
    }
    return offset_poz;
}
 
int main(int argc, char *argv[]) {
    int poz= find_offset("D:\\Old_system_MInt\\PycharmProjects\\untitled\\system-sign.img", "41 56 42 30");
    return 0;
}
ах да, забыл упамянуть - С++11 max, а в нём ::search отсутствует, вроде

Добавлено через 56 минут
или что или как? может не надо конвертить из hex в byte? тогда как читать файл в hex? или как? как вообще это сделать?!
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
09.03.2023, 17:05
Цитата Сообщение от blackeangel Посмотреть сообщение
как искать то?!
Я не стал повторять эти заморочки с направлением поиска, сами сделаете - у меня время дорогое и ограничено. Также для удобства использую С-функции чтения (потому что они сразу возвращают прочитанный размер, в отличие от read из <iostream>). Задача была проюллюстрировать описанный выше алгоритм.

Написано под Linux (мне так удобнее), поэтому, и для экономии времени, я использую готовую GNU-функцию memmem. Для Windows нужен будет ее аналог. Ниже привожу каноничную реализацию на C (думаю, можно переписать ее с использованием SSE, если скорость поиска будет неудовлетворительной).
Кликните здесь для просмотра всего текста

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
 void* memmem(const void* l, size_t l_len, const void* s, size_t s_len)
 {
     const char *cur, *last;
     const char* cl = (const char*)l;
     const char* cs = (const char*)s;
 
     /* we need something to compare */
     if(l_len == 0 || s_len == 0)
     {
         return NULL;
     }
 
     /* "s" must be smaller or equal to "l" */
     if(l_len < s_len)
     {
         return NULL;
     }
 
     /* special case where s_len == 1 */
     if(s_len == 1)
     {
         return memchr((void*)l, (unsigned char)*cs, l_len);
     }
 
     /* the last position where its possible to find "s" in "l" */
     last = cl + l_len - s_len;
 
     for(cur = cl; cur <= last; cur++)
     {
         if(cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
         {
             return (void*)cur;
         }
     }
 
     return NULL;
 }
Также в интернете можно найти множество реализаций этой функции, некоторые из них очень продвинутые.


Также отмечу, что я не делал тут пользовательский ввод в hex, и перевод пользовательского ввода в байты. У вас это сделано, прикрутите сами.
Вот основной код:
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
#include <iostream>
#include <cstdio>
#include <cstring>
#include <memory>
 
#include <string.h> // memmem: GNU SOURCE macro needed
 
std::size_t findOffsetInFile(std::FILE* file, std::size_t size, char const* bytes, std::size_t len)
{
    std::unique_ptr<char[]> buffer( new char[size * 2] );
 
    std::size_t tSize = 0; // Total read bytes
    std::size_t fSize = std::fread(&buffer[0], 1, size, file);
    if(fSize >= len)
    {
        char* pBuf = &buffer[0];
        if(char* pFnd = (char*)::memmem(pBuf, fSize, bytes, len))
        {
            return std::distance(pBuf, pFnd);
        }
        tSize += fSize;
        while(std::size_t sSize = std::fread(&buffer[fSize], 1, size, file))
        {
            char* pBuf = &buffer[fSize];
            // Also here is the processing of the buffer boundary
            if(char* pFnd = (char*)::memmem(pBuf - len, sSize + len, bytes, len)) 
            {
                return tSize + std::distance(pBuf, pFnd);
            }
            if(sSize < len)
            {
                break; // There's no point to continue lookup
            }
            tSize += sSize;
            fSize  = sSize;
 
            std::memcpy(&buffer[0], pBuf, fSize);
        }
    }
    return -1; // Not found or error
}
 
int main()
{
    std::FILE* fin = std::fopen("test.djvu", "rb");
    if(fin)
    {
        // Byte sequence: 73 B9 15 87
        const char bytes[] = {'\x73', '\xB9', '\x15', '\x87'};
 
        // 256 - buffer size
        std::size_t off = findOffsetInFile(fin, 256, bytes, sizeof bytes); 
        std::cout << "Offset: " << off << std::endl;
 
        std::fclose(fin);
    }
}
Код опубликован как есть. Код может содержать ошибки. Никакой технической поддержки я не осуществляю, претензии не принимаю. Также я не несу ответственности за несоответствие ожиданиям автора темы, за всевозможные "не работает" и т.п. При добавлении кода в боевой проект он нуждается в тестовом покрытии, которое также ложится на плечи автора темы.
0
31.03.2023, 13:22

Не по теме:

Цитата Сообщение от blackeangel Посмотреть сообщение
что тут ещё можно сказать?
Это текст лицензионного соглашения и отказа от претензий.
Мне надо как-то себя защитить от последующих претензий в стиле "Я тут вставил твой код в программу, которую я пишу для управления ядерным реактором, и у меня все взорвалось! Ты виноват в этом! Исправляй!".
Это немного утрировано, но мне довольно часто приходилось подобное выслушивать.

Это не отменяет того факта, что с вашей стороны было бы вежливо написать хотя бы о том, что именно вас не устраивает.
Это было бы уважением к тому времени, что я потратил на ответ вам.
На форумах не принято сбегать из темы без какого-то резюме, форум - это не QA support.

0
31.03.2023, 17:25  [ТС]

Не по теме:


Цитата Сообщение от DrOffset Посмотреть сообщение
Это текст лицензионного соглашения и отказа от претензий.
Мне надо как-то себя защитить от последующих претензий в стиле "Я тут вставил твой код в программу, которую я пишу для управления ядерным реактором, и у меня все взорвалось! Ты виноват в этом! Исправляй!".
Это немного утрировано, но мне довольно часто приходилось подобное выслушивать.
тут я вас не понял, судя по всему. Вообще считается, что на форуме код всегда представлен как есть и ответственность несёт тот кто его использует. Те кто хочет код, который работает как надо, у кого есть поддержка и т.п. - то это работа платная. Поправьте, если ошибаюсь.

Цитата Сообщение от DrOffset Посмотреть сообщение
Это не отменяет того факта, что с вашей стороны было бы вежливо написать хотя бы о том, что именно вас не устраивает.
не могу сказать, что меня не устраивает кроме того факта, что не могу опробовать данный код, т.к. он заточен под Linux, а у меня Windows. Хотя, вроде, писал
Цитата Сообщение от blackeangel Посмотреть сообщение
Но для Windows и Linux нет одного метода.
Для Linux можно использовать mmap, а вот для Windows что?
Хотелось бы использовать один и тот же быстрый инструмент.
Так что это не неуважение. Могу просто поверить вам на слово, что всё работает и всё хорошо, но проверить не могу.

0
737 / 704 / 110
Регистрация: 29.05.2015
Сообщений: 4,309
31.03.2023, 17:53
Цитата Сообщение от blackeangel Посмотреть сообщение
Только придется читать длину искомового выражения и проверять первое значение, если не совпало - двигаться на 1 позицию вперёд и снова проверять первую и так далее, пока не вопадет, как совпадет - проверять следующее кусок искомого. И так до тех пор, пока вся фраза не совпадёт. Но не кажется что это будет работать медленно?
читать первый байт искомового выражения и проверять первое значение
А есть другие варианты? Крикнуть АУ и ждать отклика?
0
31.03.2023, 18:00

Не по теме:

Цитата Сообщение от alexu_007 Посмотреть сообщение
А есть другие варианты?
Вообще то есть, и не один.
Алгоритмы поиска в строке
Поиск подстроки в строке
Это так, для общего развития.

0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
31.03.2023, 18:57
Лучший ответ Сообщение было отмечено blackeangel как решение

Решение

Цитата Сообщение от blackeangel Посмотреть сообщение
т.к. он заточен под Linux,
Я сказал, что он написан в линукс. А не что он заточен под Linux. Для Windows я привел функцию - она под спойлером. Вот:
Цитата Сообщение от DrOffset Посмотреть сообщение
Написано под Linux (мне так удобнее), поэтому, и для экономии времени, я использую готовую GNU-функцию memmem. Для Windows нужен будет ее аналог. Ниже привожу каноничную реализацию на C (думаю, можно переписать ее с использованием SSE, если скорость поиска будет неудовлетворительной).
Этот код работает под Windows без каких-либо изменений.

Добавлено через 2 минуты

Не по теме:

Цитата Сообщение от blackeangel Посмотреть сообщение
но проверить не могу.
Понимаете как для меня это звучит? Я буквально предоставил вам все, чтобы вы могли это проверить, специально приложил усилия, чтобы вы могли это проверить. А вы мне сейчас в глаза говорите, что не можете. Честно скажу - это возмутительно. :)


Добавлено через 3 минуты
Кроме того, заранее, если бы развитие дискуссии было в нужном ключе, у меня заготовлен был улучшенный с точки зрения производительности пример этой функции. Вот он:
Кликните здесь для просмотра всего текста
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
std::size_t findOffsetInFile(std::FILE* file, std::size_t size, char const* bytes, std::size_t len)
{
    std::unique_ptr<char[]> buffer( new char[size + len] );
 
    std::size_t tSize = 0; // Total read bytes
 
    char* sBuf = &buffer[0];
    std::size_t fSize = std::fread(sBuf, 1, size, file);
    if(fSize >= len)
    {
        if(char* pFnd = (char*)::memmem(sBuf, fSize, bytes, len))
        {
            return std::distance(sBuf, pFnd);
        }
        tSize += fSize;
        std::memcpy(sBuf, sBuf + fSize - len, len);
 
        char* pBuf = &buffer[len];
        while(std::size_t sSize = std::fread(pBuf, 1, size, file))
        {
            // Also here is the processing of the buffer boundary
            if(char* pFnd = (char*)::memmem(sBuf, sSize + len, bytes, len))
            {
                return tSize + std::distance(pBuf, pFnd);
            }
            if(sSize < len)
            {
                break; // There's no point to continue lookup
            }
            tSize += sSize;
            std::memcpy(sBuf, pBuf + sSize - len, len);
        }
    }
    return -1; // Not found or error
}
1
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
31.03.2023, 19:23  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Этот код работает под Windows без каких-либо изменений.
Если так, то это тогда то что нужно. Но меня смутило это
Цитата Сообщение от DrOffset Посмотреть сообщение
Написано под Linux (мне так удобнее), поэтому, и для экономии времени, я использую готовую GNU-функцию memmem.
видимо снова вас не так понял. Прошу прощения.
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
31.03.2023, 19:38
blackeangel, для проверки нужно просто добавить функцию memmem из кода под спойлером, чтобы остальной код ее увидел. И укажите какой-то реальный файл (для поиска), на котором будете проверять.

Если будете запускать в MSVC, то надо указать #define _CRT_SECURE_NO_WARNINGS в самом начале файла. Это единственное изменение, которое нужно сделать.
В MinGW работает как есть.
1
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
31.03.2023, 21:25  [ТС]
DrOffset, у меня CLion, поэтому добавил функцию memmem из кода под спойлером. Спасибо

Добавлено через 1 час 25 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
И укажите какой-то реальный файл (для поиска), на котором будете проверять.
проверил, работает. Вроде как надо. Только моя функция hex2byte не подходит теперь
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
31.03.2023, 23:40
Цитата Сообщение от blackeangel Посмотреть сообщение
Только моя функция hex2byte не подходит теперь
Почему? По-моему подходит.
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
31.03.2023, 23:48  [ТС]
DrOffset, ваша принимает char* array, а "моя" возвращает vector<uint8_t>... Нужно либо конвертировать как то, либо переписывать hex2byte
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.03.2023, 23:48

Функция поиска в бинарном дереве
Я понимаю как реализовать эту функцию если в бинарном дереве хранятся обычные числа(последовательно сравниваем и двигаемся по дереву в...

Создайте программу поиска вхождения строки в бинарном файле
Нужна помощь! 15. Создайте программу поиска вхождения строки в бинарном файле. Входит ли строку 'This program' в исполняемый файл...

Необычная функция в бинарном дереве поиска
Здравствуйте, уважаемые форумчане. Очень прошу Вашей помощи. Задание: Реализовать структуру данных двоичное дерево поиска,...

Методика поиска аналогичного кода бинарном файле нового релиза
Здравствуйте. Попала в руки такая задача. Есть две dll. Как мне объяснили второй файл (new.dll) это новый релиз первого файла (old.dll). ...

Функция, которая меняет строку в бинарном файле
Есть бинарный файл с информацией про олимпийские игры. И должна быть функция, изменения этой информации по желанию пользователя. все...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Процесс ориентированная диалектика (не новость - просто системное обновление, философия).
Hrethgir 20.06.2026
Однажды один участник в своём блоге, на этом форуме, сделал запись "О языках замолвите слово". Понимая, что язык - важная вещь, я решил хорошо подумать, прежде чем сказать, и сказал то, что вы видите. . .
Контроль уникальности строк в табличной части документа
Maks 18.06.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ПланированиеСпецтехники" с табличной частью "НаличиеОборудования", разработанного в КА2. Задача: контроль уникальности строк в. . .
Клиент
Uhbif79 18.06.2026
Здесь простой клиент для работы с сервером.
Сервер
Uhbif79 18.06.2026
Выкладываю простейший сервер.
Дефенестрация
kumehtar 18.06.2026
Узнал интересное слово. Дефенестрация. Это когда ты выбрасываешь кого-либо или что-либо из окна. Возьму на вооружение)))
Дихотомия добра и зла
kumehtar 18.06.2026
Как Дзен-буддисты говорят о добре и зле: не нужно воевать против зла, нужно воевать против невежества. Тогда добро станет ествественным, и поэтому вечным. Но дело в том, что невежество всё время. . .
Своя Интернет-Компания
iceja 18.06.2026
Я программист с экономическим образованием, пишу свой проект, это SaaS для бизнесов. Мне нужен co-founder с высшим экономическим образованием, и/ или инвестор. Сейчас проект в интенсивной разработке,. . .
24 Мат модель здравосохранения: функциональные требования к строительству пищеблока
anaschu 18.06.2026
СРесурсами1: финансовый SD-контур, калькулятор функциональных требований пищеблока Сегодня разделили затраты в агенте Экономика по образцу модели НАСОСЫ, добавили расчёт ROI и построили первый. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru