0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 13.09.11 17:27
Оценка:
Всем привет
алгоритм такой вызывается функция GetAddr и ей передается
уникальное число хеш посчитанный от имени функции которую надо вызвать
и чей адрес она должна вернуть когда в первый раз вызывается GetAddr
для конкретного хеша она парсит экспорт находит адрес запоминает
его по какой то схеме которую надо придумать и во время следующих
вызовов с этим же хешем быстро возращает адрес хеш из себя представляет
любое число от 0x00000000 — 0xfffffff надо максимально быстро отобразить
хеш на адрес функции и вернуть его тоесть по сути задача сводится
к маскимально быстрому отображению числа в диапазоне
0x00000000 — 0xfffffff на адрес функции

как тут можно реализовать есть идеи ?
скорость должна быть сравнимой с обычным вызовом функции
Re: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: Erop Россия  
Дата: 13.09.11 17:34
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>как тут можно реализовать есть идеи ?

J>скорость должна быть сравнимой с обычным вызовом функции

Хэш-таблици не интересуют?
Кстати, на момент компиляции этого хозяйства, все функции уже известны? А то есть много методик построения по известному набору образцов хэш-функции без коллизий, или с ограниченным сичлом коллизий...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: ononim  
Дата: 13.09.11 17:43
Оценка: +1
случайно не подойдет?
http://msdn.microsoft.com/en-us/library/bb432254(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/bb432242(v=VS.85).aspx
Как много веселых ребят, и все делают велосипед...
Re[2]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 13.09.11 17:57
Оценка:
Здравствуйте, Erop, Вы писали:

ну как бы есть некая адовая смесь которая при вызове обычной
winapi функции генерирует не то что ожидалось например
в исходнике мы видим например
SetWindowText(hWnd, szMsg);

разворачивается это в момент компиляции в следующее
push szMsg
push hWnd
push 0xYYYYYYYY ; это наш хеш от SetWindowText
call GetAddr ; на выхоже в eax адрес
call eax ; это наш SetWindowText

тоесть какую бы мы функцию не вызывали меняться будут только
хеши вся подстановка прозрачна для вызывающего кода он и не знает
что вызовы идут через хеши для этого специальной программой генерируется
.h файл с переопределенными макросами типа SetWindowText в реализации
которых много магии например учет сигнатуры вызываемой функции
подстановка хешей и прочее

вообщем механизм примерно такой смысл в том что хеш для каждой конкретной
функции передается всегда при каждом вызове этой функции и надо придумать
быструю систему отображения этих хешей на адреса время будет тратится только во воемя
первого вызова когда будет реальный поиск в таблице экспорта

хеши все известны ну вот представь .h файл со всеми определениями
функций нескольких системных библиотек какую я захочу оттуда функцию
вызвать одному богу известно
Re[3]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: Erop Россия  
Дата: 13.09.11 18:19
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>тоесть какую бы мы функцию не вызывали меняться будут только

J>хеши вся подстановка прозрачна для вызывающего кода он и не знает
J>что вызовы идут через хеши для этого специальной программой генерируется
J>.h файл с переопределенными макросами типа SetWindowText в реализации
J>которых много магии например учет сигнатуры вызываемой функции
J>подстановка хешей и прочее

J>хеши все известны ну вот представь .h файл со всеми определениями

J>функций нескольких системных библиотек какую я захочу оттуда функцию
J>вызвать одному богу известно

Что-то я не понял. Ну просто перенумеруй функции, дефайнами присвойим номера, и храни где-то статический массив, отображающий номера на адреса...

только не ясно, на кой это всё надо-то?

Смотри, шаг 1.
Вместо
call GetAddr
call eax
пишем просто call GoToAddr, а GoToAddr сама вычисляет адрес и переходит.
Но, если GoToAddr это просто
pop eax
jp MyTable[eax]
то можно просто call туда сделать без всякой GoToAddr, но, если, опять же, это просто вектор адресов, то можно просто сложить подряд jp туда и оз сюда, а call деать внутрь этого вектора. А сам вектро можно поручить линкеру прореживать, и оставлять там только нужные джампы.

Ну и, наконец, можно почитать доки к твоему линкеру, очень может быть, что он уже и сам всё это умеет...

Может расскажешь, зачем это всё надо? Тогда и совет получше получишь...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 13.09.11 18:53
Оценка:
Здравствуйте, Erop, Вы писали:

E>Что-то я не понял. Ну просто перенумеруй функции, дефайнами присвойим номера, и храни где-то статический массив, отображающий номера на адреса...


а можно немного кода набросать как все это будет не иогу понять ?
что значит пронумеровать по какому принципу пронумеровать
все функции из нескольких библиотек насколько большой делать массив
его что надо будет изменять для каждой программы а если нет то он просто
очень огромный будет что не подходит к тому же придется передавать хеш
и еще номер плюс аргументы или я Вас не понял

E>только не ясно, на кой это всё надо-то?

ну то что программы получаются без таблицы импорта это не надо объяснять
просто интересно сделать чтоб было хорошо и работало может пригодится
Re[2]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 13.09.11 18:59
Оценка:
Здравствуйте, ononim, Вы писали:

O>случайно не подойдет?

O>http://msdn.microsoft.com/en-us/library/bb432254(v=vs.85).aspx
O>http://msdn.microsoft.com/en-us/library/bb432242(v=VS.85).aspx
непонятно как его применить
Re[5]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 13.09.11 19:11
Оценка:
я грешным делом думал так сделать
получаем первый раз хеш парсим экспорт получаем адрес
вставляем в массив делаем qsort когда приходят новые хеши
делаем bsearch по этому массиву если нет то парсим и новый
адрес добавляем в массив делаем qsort для последующего быстрого
bsearch но во первых мы тут упираемся в фундаментальную проблему
синхронизации пока один поток ищет другой может сортировать
это не говоря уже про эффективность двочного поиска при
каждом вызове пусть в среднем 400 api в массиве
это при bsearch 8 сравнений впринципе очень быстро
но проблема синхронизации все портит
Re[6]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 13.09.11 19:32
Оценка:
хотя нет же можно сразу вставлять в нужную позицию если использовать
binary search tree для в среднем 400-х функций что вставка что
отображение хеша на адрес будут моментальными 8 сравнений
узел можно представить парой хеш <--> адрес
сортировать дерево по значению хеша
но вот от проблемы синхронизации мы никуда не ушли
Re[7]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 14.09.11 00:08
Оценка:
ну вот примерно так если в массиве 400 элементов что где то будет
соответствовать истине то если повторить поиск один миллиард раз
займет это менньше секунды вот для наглядности я сделалд 10
циклов по миллиарду поисков в каждом
time == 0.734000
time == 0.766000
time == 0.750000
time == 0.781000
time == 0.703000
time == 0.750000
time == 0.766000
time == 0.718000
time == 0.750000
time == 0.750000
Для продолжения нажмите любую клавишу . . .
отлично но ведь надо будет еще вставить синхронизацию
я вот о чем думаю множество потоков может искать одновремено
но когда кто то один или несколько потоков захотят вставить надо
дать им эксклюзивный доступ хорошо что операция вставки очень редкая
и время за нее можно не считать а в остальное время потоки параллельно
должны вести поиск тоесть не синхронизироватся надо придумать что то
типа модели много читающих один пишущий (много ищущих один вставляющий)
это мне кажется самое эффективное будет
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

struct CHashAddrTree
{
    static CHashAddrTree Tree;

    VOID Add(DWORD dwHash, PVOID pvAddr)
    {
        _Add(dwHash, pvAddr, &pRoot);
    }

    PVOID Find(DWORD dwHash)
    {
        return _Find(dwHash, pRoot);
    }

private:

    struct NODETREE;

    VOID _Add(DWORD dwHash, PVOID pvAddr, NODETREE** ppRoot)
    {
        if (!*ppRoot)
        {
            if (MaxNodes == dwCurFree)
                __asm int 3;

            NODETREE* pNode = &aNodes[dwCurFree];
            pNode->dwHash = dwHash;
            pNode->pvAddr = pvAddr;
            *ppRoot = pNode;
            dwCurFree++;
        }
        else if ((*ppRoot)->dwHash > dwHash)
            _Add(dwHash, pvAddr, &(*ppRoot)->pLeft);
        else if ((*ppRoot)->dwHash < dwHash)
            _Add(dwHash, pvAddr, &(*ppRoot)->pRight);
        else
            __asm int 3;
    }

    PVOID _Find(DWORD dwHash, NODETREE* pRoot)
    {
        if (!pRoot)
            return 0;
        if (pRoot->dwHash > dwHash)
            return _Find(dwHash, pRoot->pLeft);
        if (pRoot->dwHash < dwHash)
            return _Find(dwHash, pRoot->pRight);
        return pRoot->pvAddr;
    }

    struct NODETREE
    {
        DWORD dwHash;
        PVOID pvAddr;
        NODETREE* pLeft;
        NODETREE* pRight;
    };

    enum{MaxNodes = 400};
    NODETREE aNodes[MaxNodes];
    NODETREE* pRoot;
    DWORD dwCurFree;
};

CHashAddrTree CHashAddrTree::Tree;

#pragma message("enable -O2 -Ot for test")

#include <set>
#include <boost/timer.hpp>
int main()
{
    std::set<int> v;
    srand(GetTickCount());
    for (size_t i = 0; i < 400; i++)
    {
        int val = rand();
        std::pair<std::set<int>::iterator,bool> it = v.insert(val);
        if (it.second)
            CHashAddrTree::Tree.Add(val, 0);
        else
            i--;
    }
    for (int i = 0; i < 10; i++)
    {
        boost::timer tt;
        int volatile yu = 67;
        for (size_t ii = 0; ii < 1000000000; ii++)
            CHashAddrTree::Tree.Find(yu);
        printf("time == %f\n", tt.elapsed());
    }
}
Re[8]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 14.09.11 02:28
Оценка:
мои извинения на самом деле компилятор выкинул вызов функции Find
(я как чувствовал что то тут не то слишком быстро зря не посмотрел в ассемблер)
потому что я не использовал результат гад какой умный там же куча
вызовов рекурсивных и оставил такой
        for (size_t ii = 0; ii < 1000000000; ii++)
004011B7 83 E8 01         sub         eax,1 
            CHashAddrTree::Tree.Find(yu);
004011BA 8B 54 24 50      mov         edx,dword ptr [esp+50h] 
004011BE 75 F7            jne         main+107h (4011B7h)

вот данные исправленного теста 100.000.000 (сто миллионов)
поисков делает за 2 секунды
time == 2.140000
time == 2.063000
time == 2.031000
time == 2.031000
time == 2.031000
time == 2.032000
time == 2.047000
time == 2.015000
time == 2.031000
time == 2.047000
Для продолжения нажмите любую клавишу . . .
        for (size_t ii = 0; ii < 100000000; ii++)
        {
            gg = CHashAddrTree::Tree.Find(yu);
004011E1 8B 54 24 4C      mov         edx,dword ptr [esp+4Ch] 
004011E5 A1 C8 5C 40 00   mov         eax,dword ptr ds:[00405CC8h] 
004011EA 85 C0            test        eax,eax 
004011EC 74 1F            je          main+13Dh (40120Dh) 
004011EE 8B 08            mov         ecx,dword ptr [eax] 
004011F0 3B CA            cmp         ecx,edx 
004011F2 76 0A            jbe         main+12Eh (4011FEh) 
004011F4 8B 40 08         mov         eax,dword ptr [eax+8] 
004011F7 E8 54 FE FF FF   call        CHashAddrTree::_Find (401050h) 
004011FC EB 0F            jmp         main+13Dh (40120Dh) 
004011FE 73 0A            jae         main+13Ah (40120Ah) 
00401200 8B 40 0C         mov         eax,dword ptr [eax+0Ch] 
00401203 E8 48 FE FF FF   call        CHashAddrTree::_Find (401050h) 
00401208 EB 03            jmp         main+13Dh (40120Dh) 
0040120A 8B 40 04         mov         eax,dword ptr [eax+4] 
0040120D 83 EE 01         sub         esi,1 
00401210 89 44 24 50      mov         dword ptr [esp+50h],eax 
00401214 75 CB            jne         main+111h (4011E1h) 
        }

int main()
{
    std::set<int> v;
    srand(GetTickCount());
    for (size_t i = 0; i < 400; i++)
    {
        int val = rand();
        std::pair<std::set<int>::iterator,bool> it = v.insert(val);
        if (it.second)
            CHashAddrTree::Tree.Add(val, 0);
        else
            i--;
    }
    for (int i = 0; i < 10; i++)
    {
        boost::timer tt;
        int volatile yu = 67;
        PVOID volatile gg;
        for (size_t ii = 0; ii < 100000000; ii++)
        {
            gg = CHashAddrTree::Tree.Find(yu);
        }
        printf("time == %f\n", tt.elapsed());
    }
}

            PVOID _Find(DWORD dwHash, NODETREE* pRoot)
    {
        if (!pRoot)
00401050 85 C0            test        eax,eax 
00401052 74 14            je          CHashAddrTree::_Find+18h (401068h) 
            pNode->pvAddr = pvAddr;
            *ppRoot = pNode;
            dwCurFree++;
        }
        else if ((*ppRoot)->dwHash > dwHash)
            _Add(dwHash, pvAddr, &(*ppRoot)->pLeft);
        else if ((*ppRoot)->dwHash < dwHash)
            _Add(dwHash, pvAddr, &(*ppRoot)->pRight);
        else
            __asm int 3;
    }

    PVOID _Find(DWORD dwHash, NODETREE* pRoot)
    {
        if (!pRoot)
            return 0;
        if (pRoot->dwHash > dwHash)
00401054 8B 08            mov         ecx,dword ptr [eax] 
00401056 3B CA            cmp         ecx,edx 
00401058 76 05            jbe         CHashAddrTree::_Find+0Fh (40105Fh) 
            return _Find(dwHash, pRoot->pLeft);
0040105A 8B 40 08         mov         eax,dword ptr [eax+8] 
0040105D EB 05            jmp         CHashAddrTree::_Find+14h (401064h) 
        if (pRoot->dwHash < dwHash)
0040105F 73 0A            jae         CHashAddrTree::_Find+1Bh (40106Bh) 
            return _Find(dwHash, pRoot->pRight);
00401061 8B 40 0C         mov         eax,dword ptr [eax+0Ch] 

    PVOID _Find(DWORD dwHash, NODETREE* pRoot)
    {
        if (!pRoot)
00401064 85 C0            test        eax,eax 
00401066 75 EC            jne         CHashAddrTree::_Find+4 (401054h) 
            return 0;
00401068 33 C0            xor         eax,eax 
            _Add(dwHash, pvAddr, &(*ppRoot)->pLeft);
        else if ((*ppRoot)->dwHash < dwHash)
            _Add(dwHash, pvAddr, &(*ppRoot)->pRight);
        else
            __asm int 3;
    }

    PVOID _Find(DWORD dwHash, NODETREE* pRoot)
    {
        if (!pRoot)
            return 0;
        if (pRoot->dwHash > dwHash)
            return _Find(dwHash, pRoot->pLeft);
        if (pRoot->dwHash < dwHash)
            return _Find(dwHash, pRoot->pRight);
        return pRoot->pvAddr;
    }
0040106A C3               ret              
        return pRoot->pvAddr;
0040106B 8B 40 04         mov         eax,dword ptr [eax+4] 
    }
0040106E C3               ret

отлично надо сказать компилятор рекурсивную функцию
заменил циклом браво cl.exe
Re[9]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 14.09.11 02:57
Оценка:
величина    название    обозначение    величина    название    обозначение
101 с    декасекунда    дас    das    10−1 с    децисекунда    дс    ds
102 с    гектосекунда    гс    hs    10−2 с    сантисекунда    сс    cs
103 с    килосекунда    кс    ks    10−3 с    миллисекунда    мс    ms
106 с    мегасекунда    Мс    Ms    10−6 с    микросекунда    мкс    µs
109 с    гигасекунда    Гс    Gs    10−9 с    наносекунда    нс    ns
1012 с    терасекунда    Тс    Ts    10−12 с    пикосекунда    пс    ps
1015 с    петасекунда    Пс    Ps    10−15 с    фемтосекунда    фс    fs
1018 с    эксасекунда    Эс    Es    10−18 с    аттосекунда    ас    as
1021 с    зеттасекунда    Зс    Zs    10−21 с    зептосекунда    зс    zs
1024 с    йоттасекунда    Ис    Ys    10−24 с    йоктосекунда    ис    ys

если одна секунда это 1.000.000.000 миллиард наносекунд
у нас в секунду делается примерно 50.000.000 миллионов поисков
один поиск выходит занимает где то 20 наносекунд
Re[5]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: Erop Россия  
Дата: 14.09.11 03:12
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

E>>только не ясно, на кой это всё надо-то?

J>ну то что программы получаются без таблицы импорта это не надо объяснять
J>просто интересно сделать чтоб было хорошо и работало может пригодится

Почему, это, интересно, без таблицы импорта? А откуда, в конце концов, возьмутся адреса входов в системные DLL? Они на разных системах разные, вообще-то...
Если тебя устраивает работоспособность только на одной какой-то конкретной версии, то есть утилитка, которая умеет првязывать к нужной системе сразу, без хаков и глюков...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 14.09.11 03:14
Оценка:
плюс тут еще оверхед сам цикл дает его по идее
тоже надо вычесть из общего времени
Re[6]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 14.09.11 03:22
Оценка:
Здравствуйте, Erop, Вы писали:

E>Почему, это, интересно, без таблицы импорта? А откуда, в конце концов, возьмутся адреса входов в системные DLL? Они на разных системах разные, вообще-то...

E>Если тебя устраивает работоспособность только на одной какой-то конкретной версии, то есть утилитка, которая умеет првязывать к нужной системе сразу, без хаков и глюков...


как откуда а чьи хеша мы собтвенно на адреса отображать будем
именно этих системных api смотри первый раз пришедший хеш берем
берем таблицу экпорта системного модуля хешируем имя каждой
функции из экспорта сравниваем с нашим хешем если сошлись
запоминаем адрес опаределенной функции на следующие запросы
просто возвращаем адрес это может быть адрес той же
SetWindowText или какой то жругой определяется хешем а хеш
определяется в зависимости от того какую функцию мы вызываем
он неявно подставляется а сам файл с перепределенными макросами
и соответствующими хешами создается отдельной программой его потом
подключаеш и пишеш
Re: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: MasterZiv СССР  
Дата: 14.09.11 07:49
Оценка: +1
On 13.09.2011 21:27, jyuyjiyuijyu wrote:

> как тут можно реализовать есть идеи ?


map, hashtable.
Posted via RSDN NNTP Server 2.1 beta
Re[7]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: rising_edge  
Дата: 14.09.11 11:03
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>как откуда а чьи хеша мы собтвенно на адреса отображать будем

J>именно этих системных api смотри первый раз пришедший хеш берем
J>берем таблицу экпорта системного модуля хешируем имя каждой
J>функции из экспорта сравниваем с нашим хешем если сошлись
J>запоминаем адрес опаределенной функции на следующие запросы
J>просто возвращаем адрес это может быть адрес той же
J>SetWindowText или какой то жругой определяется хешем а хеш
J>определяется в зависимости от того какую функцию мы вызываем
J>он неявно подставляется а сам файл с перепределенными макросами
J>и соответствующими хешами создается отдельной программой его потом
J>подключаеш и пишеш

Я стечняюсь спросить: вы принципиально знаки препинания не употребляете?
Re[11]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: ononim  
Дата: 14.09.11 11:30
Оценка:
J>плюс тут еще оверхед сам цикл дает его по идее
J>тоже надо вычесть из общего времени
кстати, тут свои сообщения редактировать низзя, а вот удалять при помощи бомбочки справа сверху и писать новые, дополненные так сказать — можно
Как много веселых ребят, и все делают велосипед...
Re[8]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 14.09.11 14:45
Оценка:
получился макет так как некоторые функции еще не написаны
и так тут разрешается параллельный поиск нескольких потоков
тоесть никакой синхронизации нет и только когда будут
получать реальные адреса будет синхронизация с блокировкой остальных
но это во первых только в начале работы программы когда первые вызовы
api будут происходить во вторых очень мало
все ли корректно в этом макете в плане параллельных запросов ?
PVOID GetAddr(DWORD dwHash)
{
    PVOID pFunc = CHashAddrTree::Tree.Find(dwHash);
    if (!pFunc)
    {
        while (InterlockedExchange(&locked, TRUE) == TRUE)
            ;
        pFunc = CHashAddrTree::Tree.Find(dwHash);
        if (!pFunc)
        {
            pFunc = ParseExport(dwHash);  
            CHashAddrTree::Tree.Add(dwHash, pFunc);
        }
        InterlockedExchange(&locked, FALSE);
    }
    return pFunc;
}
Re[9]: 0x00000000 - 0xffffffff ---> 0xYYYYYYYY
От: jyuyjiyuijyu  
Дата: 14.09.11 14:53
Оценка:
или может добавить SwitchToThread в цикл а то если попадется
свирепствующий поток с высоким приоритетом он задавит
поток который получает адрес вот и деадлок
PVOID GetAddr(DWORD dwHash)
{
    PVOID pFunc = CHashAddrTree::Tree.Find(dwHash);
    if (!pFunc)
    {
        while (InterlockedExchange(&locked, TRUE) == TRUE) 
            SwitchToThread();
        pFunc = CHashAddrTree::Tree.Find(dwHash);
        if (!pFunc)
        {
            pFunc = ParseExport(dwHash);  
            CHashAddrTree::Tree.Add(dwHash, pFunc);
        }
        InterlockedExchange(&locked, FALSE);
    }
    return pFunc;
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.