Сейчас на форуме: rmn, ManHunter, _MBK_, tyns777, UniSoft (+10 невидимых)

 eXeL@B —› Программирование —› Ревёрс шаблонов с++
Посл.ответ Сообщение


Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 24 апреля 2012 12:44
· Личное сообщение · #1

Добрый день. Я вот помаленьку копаю движок сталкера Xray 1.6.0.2
Меня в нём заинтересовала скриптовая машина, а именно добавление туда функций и классов(прикручен туда luabind). Всё было бы хорошо, но luabind видоизменён(операции с памятью все делаются через специальный класс(видимо разработчики столкнулись с утечкой памяти и решили проблему перегрузкой всех new и delete))
Так вот. Меня интересует ревёрс шаблонов в С++. Там заменён стандартный std::auto_ptr на ихний. Впринципе ничего нового в реализации самой машины я не заметил. Только операции с памятью там изменены(выделение/освобождение).
Имел ли кто - нить опыт в ревёрсе шаблонов и знает ли кто-нить как глобально перегрузить оператор new(знаю можно чисто в классе перегрузить, но возможно ли совсем глобально это сделать?)
Сразу прошу меня извинить за возможные грамматические ошибки и написание "не по-русски".




Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 24 апреля 2012 13:14
· Личное сообщение · #2

Dart Sergius пишет:
знает ли кто-нить как глобально перегрузить оператор new

Шаблон + множественное наследование?

-----
Stuck to the plan, always think that we would stand up, never ran.





Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 24 апреля 2012 13:56
· Личное сообщение · #3

ARCHANGEL пишет:
множественное наследование

а структуру класса оно не сильно изменит? И не влияют ли "предки" на декодированное название функции потомка?




Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 24 апреля 2012 14:11
· Личное сообщение · #4

Dart Sergius пишет:
а структуру класса оно не сильно изменит?
Может сильно. Подабавляется в потомках то, чего не было в предках.

И не влияют ли "предки" на декодированное название функции потомка?
Хз.

-----
Stuck to the plan, always think that we would stand up, never ran.


| Сообщение посчитали полезным: Dart Sergius

Ранг: 481.4 (мудрец), 109thx
Активность: 0.180
Статус: Участник
Тот самый :)

Создано: 24 апреля 2012 14:41 · Поправил: Hexxx
· Личное сообщение · #5

Dart Sergius пишет:
знает ли кто-нить как глобально перегрузить оператор new

Мы для драйверов делали так:
Code:
  1. void* __cdecl operator new (size_t size)
  2. {
  3.     if (size == 0)
  4.         size = 4;
  5.  
  6.     return ExAllocatePoolWithTag(NonPagedPool, (ULONG)size, '++CL');
  7. }

и operator new[] аналогично

Не вьехал как это связано с реверсингом шаблонов. С шаблонами проблема в том что у тебя в коде 100500 классов, некоторые из которых похожи друг на друга как 2 капли воды и отличаются лишь каким-нить одним параметром. Т.е. инстансы для кучи типов, а код - копипаста.

-----
Реверсивная инженерия - написание кода идентичного натуральному


| Сообщение посчитали полезным: Dart Sergius

Ранг: 590.6 (!), 408thx
Активность: 0.360.18
Статус: Модератор

Создано: 24 апреля 2012 14:46 · Поправил: r_e
· Личное сообщение · #6

Dart Sergius
Если не ошибаюсь, new и delete можно переопределить глобально. Нужно просто объявить функции с определенным прототипом. Погугли.
Собсно, что касается шаблонов, то нужно понимать что все они инстанцируются с заданными типами. В итоге мы получаем кучу кода с одинаковой логикой и различными типами данных. По идее, для auto_ptr это некритично, потому как будет ли поле указателем на int или на CObject не играет никакой роли. Структура от этого не поменяется ни на байт.

Hexxx
Обошел на повороте

-----
старый пень


| Сообщение посчитали полезным: Dart Sergius


Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 24 апреля 2012 15:16 · Поправил: Dart Sergius
· Личное сообщение · #7

Спасибо буду пробовать.
Hexxx пишет:
Не вьехал как это связано с реверсингом шаблонов

разработчики заменили std::auto_ptr на свой шаблон
По идее, для auto_ptr это некритично, потому как будет ли поле указателем на int или на CObject не играет никакой роли
Спасибо, надеюсь это так.




Ранг: 331.1 (мудрец), 561thx
Активность: 0.190.06
Статус: Участник

Создано: 24 апреля 2012 16:42
· Личное сообщение · #8

Dart Sergius
Шаблоны реверсятся в С++ так же, как и всё остальное, но если ты в результате хочешь получить один шаблон, а не кучу "полуодинакового" кода на все инстанции, то анализируй одноименные функции по всем инстанциям и оформляй в шаблон, при некоторой сноровке ничего в этом сложного нет... В принципе, по желанию, ты можешь в любом std шаблоне заменить реализацию шаблонных параметров на свою, будь она внешней или внутренней, как Allocator, Hash, Comparator и другие.

-----
Everything is relative...




Ранг: 23.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 08 мая 2012 23:10
· Личное сообщение · #9

r_e
<<Собсно, что касается шаблонов, то нужно понимать что все они инстанцируются с заданными типами.

Забавную чушь Вы пишете О non-type параметрах не слышали видимо никогда?

Вообще то у шаблонов С++ существует 3 разновидности параметров: type parameter, non-type parameter и template parameter. Non-type параметры типами не инстанцируются -> Ваше высказывание ошибочно.

C++ Templates the Complete Guide by David Vandevoorde and Nicolai M. Josuttis.



Ранг: 23.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 08 мая 2012 23:32
· Личное сообщение · #10

Товарищи.
Я тут недавно класец для себя маленький сваял. А так как для себя писал, то соответственно нет ревизии кода и тому подобных вещей. Вообщем хотелось бы, чтобы Вы его покритиковали и высказали свои замечания. В первую очередь интересует оптимальность кода - может Вы лучше варианты увидите. (язык: C++) Если хотите взглянуть на творчество, то отпишите - покажу...



Ранг: 590.6 (!), 408thx
Активность: 0.360.18
Статус: Модератор

Создано: 09 мая 2012 01:17
· Личное сообщение · #11

TheNozza
Вы чисто потролить или с целью померяться?

Non-type template parameters must be of integral, enumeration, pointer, reference, or pointer to member type, and must be constant at compile time.

В RE вы не встретите compile-time calculations / MPL в бинаре, потому как вкомпиленно будет именно предрасчитанное компилятором значение. В остальных случаях будет таки либо создан тип / объект, либо сгенерирован код. Что и следовало понимать под странным словом инстанцирование.

Я даже близко не MVP в С++ и всегда открыт для плодотворной дискуссии. Вы можете просветить меня насчет non-type template parameters в реверсе и как они выражаются в скомпиленном коде. Открою для себя новый мир.

-----
старый пень




Ранг: 101.0 (ветеран), 344thx
Активность: 1.150
Статус: Участник

Создано: 09 мая 2012 01:34
· Личное сообщение · #12

r_e
Да не, это не троллинг. Он пытается самому себе доказать, что знает Си++.

TheNozza
Весеннее обострение? Я могу и вечный бан влепить, нет проблем. И таки да, Си++ Вы не знаете.



Ранг: 23.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 09 мая 2012 01:43
· Личное сообщение · #13

"В RE вы не встретите compile-time calculations / MPL в бинаре, потому как вкомпиленно будет именно предрасчитанное компилятором значение. В остальных случаях будет таки либо создан тип / объект, либо сгенерирован код. Что и следовало понимать под странным словом инстанцирование."

Зачем рассказывать то, о чём и так известно? Зачем слэш добавили(тип/объект) - чтобы съехать?

Читайте ещё раз внимательней свою первоначальную фразу, она была некорректной - вы её написали, а не я:
<<Собсно, что касается шаблонов, то нужно понимать что все они инстанцируются с заданными типами.
Про объекты(Instance of the class) там речи не было, только о типах.

For example:
template<int i> class C
{
public:
int k;
C() { k = i; }
};

class C<100>;

Пример, когда шаблон инстанцируется не типом, а конкретным значением 100. Это non-type параметр. Это не тип. Высказывание было некорректно. Но потом Вы поправились.



Ранг: 23.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 09 мая 2012 01:56
· Личное сообщение · #14

<<И таки да, Си++ Вы не знаете.

Конечно весь С++ от и до я не знаю. Не уверен, что есть такие люди, которые его знают полностью, если только авторы, т.к. язык очень сложный. Да и стандарты новые появляются...



Ранг: 23.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 09 мая 2012 02:35
· Личное сообщение · #15

Code:
  1. #include <vector>
  2. #include <string>
  3. #include <sstream>
  4.  
  5. class DigitalCounter
  6. {
  7. bool _OverflowFlag;
  8. unsigned int _Radix;
  9. unsigned int _Resolution;
  10. unsigned int * _pCurrentValue;
  11.  
  12. void MakeIncrement()
  13. {
  14.          static int Index = 0;
  15.  
  16.          if (++_pCurrentValue[Index] == _Radix)
  17.          {
  18.                  _pCurrentValue[Index] = 0;
  19.                  if (++Index == _Resolution)
  20.                  {
  21.                         _OverflowFlag = true;
  22.                         return;
  23.                  }
  24.                  MakeIncrement();
  25.                  Index = 0;
  26.          }
  27. }
  28.  
  29. public:
  30.  
  31. DigitalCounter(unsigned int Radix, unsigned int Resolution):
  32. _Radix(Radix), _Resolution(Resolution), _OverflowFlag(false)
  33.          _pCurrentValue = new unsigned int [_Resolution];
  34.          for (int i = 0; i < _Resolution; i++) _pCurrentValue[i] = 0;
  35. }
  36.  
  37. std::string asString()
  38. {
  39.          std::stringstream tmp;
  40.          for (int i = _Resolution - 1; i >= 0; i--) tmp << _pCurrentValue[i];
  41.          return tmp.str();
  42. }
  43.  
  44. void Reset()
  45. {
  46.          for (int i = 0; i < _Resolution; i++) _pCurrentValue[i]=0;
  47.          _OverflowFlag = false;
  48. }
  49.  
  50. bool Overflow() {return _OverflowFlag;}
  51. void operator++(){MakeIncrement();}
  52. unsigned int operator[] (unsigned int Index){return _pCurrentValue[Index];}
  53. unsigned int Resolution(){return _Resolution;}
  54. };


Предлагаю обсудить недостатки и преимущества кода данного класса. В нем я реализовал функционал счётчика с целью перебора произвольного алфавита(задаётся в рантайме) на любую глубину(задаётся в рантайме). В последний момент STL-евый vector был заменен на обычный массив с целью увеличения производительности, соответственно клиент класса берёт на себя ответственность при вызове operator[], т.к. выход за пределы массива более не контролируется. Вопрос: имеются ли более оптимальные пути?
Кому надо, те поймут, остальным не обязательно.



Ранг: 590.6 (!), 408thx
Активность: 0.360.18
Статус: Модератор

Создано: 09 мая 2012 11:00
· Личное сообщение · #16

TheNozza
И эти люди запрещают мне ковыряться в носу?
Тут тебе все, начиная с недочетов дизайна и заканчивая UB.

-----
старый пень





Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 09 мая 2012 11:46
· Личное сообщение · #17

хм, у меня проблема возникла ещё с ревёрсом самого оператора new.
Кароче есть такой код:
Code:
  1. luabindMemAlloc proc near
  2.  
  3. arg_0= dword ptr  4
  4. arg_4= dword ptr  8
  5.  
  6. mov     eax, [esp+arg_4]
  7. mov     ecx, [esp+arg_0]
  8. mov     edx, ds:?allocator_parameter@luabind@@3PAXA ; void * luabind::allocator_parameter
  9. push    eax
  10. mov     eax, [edx]
  11. push    ecx
  12. mov     ecx, ds:?allocator@luabind@@3P6APAXPAXPBXI@ZA ; void * (*luabind::allocator)(void *,void const *,uint)
  13. mov     edx, [ecx]
  14. push    eax
  15. call    edx
  16. add     esp, 0Ch
  17. retn
  18. luabindMemAlloc endp


в с++ он выглядит так насколько я понял:

void* hz(void*ptr,void*size){
return luabind::allocator(luabind::allocator_parameter, (const void*)ptr, size);
};
на что компилер мой генерит

Code:
  1. mov     eax, dword ptr ds:?allocator_parameter@luabind@@3PAXA_0 ; void * luabind::allocator_parameter
  2. push    0
  3. push    esi
  4. push    eax
  5. call    dword ptr ds:?allocator@luabind@@3P6APAXPAXPBXI@ZA_0 ; void * (*luabind::allocator)(void *,void const *,uint)
  6.  
  7. где 
  8. ?allocator_parameter@luabind@@3PAXA_0=
  9. jmp     ds:__imp_?allocator_parameter@luabind@@3PAXA 
  10. а ?allocator@luabind@@3P6APAXPAXPBXI@ZA_0
  11. jmp ds:__imp_?allocator@luabind@@3P6APAXPAXPBXI@ZA_0


Валится от того что void * (*luabind::allocator)(void *,void const *,uint) указывает на область памяти, которая недоступна для выполнения. Мб там указатели на функции, а я пытаюсь вызвать сами функции? Как мне лучше это написать?
Или во время инициализации dll своей прописать типо
luabind::allocator=(void __cdecl*(void*,void const*,uint))(*luabind::allocator)



Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 09 мая 2012 12:10
· Личное сообщение · #18

Dart Sergius
Может асм вставкой обойтись?



Ранг: 23.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 09 мая 2012 12:13
· Личное сообщение · #19

r_e
<<и заканчивая UB

UB возможно при вызове operator[].
Предположим идёт полный перебор 32-битного числа (Radix=2, Resolution=32). Если контролировать выход индекса за границы массива, то дополнительно будет сделано более, чем 2^32 степени ненужных сравнения, когда со стопроцентной вероятностью известно, что в клиентском коде индекс за границы не выходит. Тут выбирать приходится: либо безопасность, либо скорость.

Ну и конечно раз вместо вектора теперь динамический массив, то деструктор добавить нужно, иначе memory leak.




Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 09 мая 2012 12:14
· Личное сообщение · #20

ELF_7719116 символы как то надо нормально экспортнуть.
luabind::allocator_parameter и luabind::allocator экспортированы из другой dll.
есть вариант конечно попробовать посмотреть исходные значения в olly(ida тяжко перебазирует 7-ми метровый dll), и сравнить с значениями, которые получаются у меня в программе.



Ранг: 23.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 09 мая 2012 12:44
· Личное сообщение · #21

r_e

На Core 2 Duo полный перебор 32-битного числа с максимальным приоритетом процесса (nice -n -20 ./Counter) занимает 2 минуты 35.11 секунд. Что - то медленно.




Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 09 мая 2012 13:22
· Личное сообщение · #22

хм, я кажется понял что у меня неверно было.
у меня на extern он генерит странный код.
Как я понимаю, загрузчик просто заполнит мою переменню, и всё. Но компилер делает по другому. Он досоздаёт переменную
__imp_?allocator@luabind@@3P6APAXPAXPBXI@ZA_0
которую и заполняет как я понял загрузчик Windows.
и в адрес моей переменной пихает указатель на jmp. Появляются 2 лишних байта(jmp). Как это бы обойти?



Ранг: 590.6 (!), 408thx
Активность: 0.360.18
Статус: Модератор

Создано: 09 мая 2012 13:41
· Личное сообщение · #23

TheNozza
hint: UB из-за этого if (++Index == _Resolution)
Я user-case'ы даже не рассматривал.

А также в студии:
- Отсутствие деструкора - утечка памяти. Неиспользование smart pointers.
- Непроверка критических участков с бросанием эксепшнов.
- Неконстантные функции, возвращающие константы.
- Неоптимальная упаковка данных. Чо уж тогда тип элемента счетчика не сделать параметром шаблона?
- Постфиксные инкременты
- Нестандартное поведение перегруженного инкремента
- Дизайн нерасширяем
- Для данного кода в конструкторе достаточно было вызвать Reset
- Множественные perfomance issues, например:
>> for (int i = 0; i < _Resolution; i++) _pCurrentValue[i]=0;
memset() для линейного непрерывного пространства, for_each для итераторов
>> std::string asString()
Передача объекта через стек.

Вывод: наколенная школьная поделка.

-----
старый пень


| Сообщение посчитали полезным: redlord

Ранг: 33.4 (посетитель), 24thx
Активность: 0.020
Статус: Участник

Создано: 09 мая 2012 14:28
· Личное сообщение · #24

TheNozza


в многопоточном приложении не юзабелен



Ранг: 23.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 09 мая 2012 15:08
· Личное сообщение · #25

r_e

<<UB из-за этого if (++Index == _Resolution)
При каком сценарии здесь возникнет UB? (последовательность вызова интерфейсных методов)


<<Отсутствие деструкора - утечка памяти.
Да, это косяк.

<<Неконстантные функции, возвращающие константы.
Не критично. Хотя можно поправить.

<<Неоптимальная упаковка данных.
А вот это непростой вопрос. Думал над ним. Упаковка данных действительно неоптимальная.

Концепция была следующая: есть алфавит, например из трёх букв 'a','b','c'. Нужно перебрать все варианты слов из пяти букв данного алфавита. Задаём счётчику: Radix = 3; Resolution = 5; После каждого инкремента счётчика пока !Overflow() через operator[] запрашиваем все цифры и отображаем их на символы алфавита.
То есть:
00000 -> aaaaa
00001 -> aaaab
.........................
22222 -> cccccc

У Вас есть другие варианты?

<<Чо уж тогда тип элемента счетчика не сделать параметром шаблона?
С какой целью? Элементы счётчика всегда цифры.

<<Постфиксные инкременты
Его можно реализовать на базе префексного. Главное добиться оптимальности кода префексного оператора.

<< std::string asString()
<<Передача объекта через стек.
Так возвращается из метода временная переменная.

Вообщем обсуждать надо...



Ранг: 590.6 (!), 408thx
Активность: 0.360.18
Статус: Модератор

Создано: 09 мая 2012 15:21
· Личное сообщение · #26

TheNozza
UB> DigitalCounter l(1, 1);
for (int i = 0; i < 0xffffffff; ++i) ++l;

> С какой целью? Элементы счётчика всегда цифры.
Это могут быть ну очень большие цифры. И тогда вашего int просто не хватит.

> Его можно реализовать на базе префеиксного.
Не только можно, но так и реализуется. Это классика. Соответственно, постфиксный используется только там где неприменим префиксный.

> Так возвращается из метода временная переменная.
Чего уж тогда не перегрузить оператор вывода в поток? Было бы вполне в с++ стиле.

Собсно, чо тут обсуждать? Поумерь ЧСВ и неси в мир доброе и светлое нормальным тоном.

-----
старый пень




Ранг: 23.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 09 мая 2012 16:36
· Личное сообщение · #27

r_e

Давайте взглянем на более глобальные вещи: а именно на применённый алгоритм.
Возможно, такой счётчик (со свойственной ему рекурсией) для брутфорса вариант неподходящий. Вам знакомы другие алгоритмы?

Может на базе дерева существует шанс выполнить тот же перебор в более короткий срок? А может и нет.
Что думаете?



Ранг: 23.4 (новичок)
Активность: 0.010
Статус: Участник

Создано: 09 мая 2012 16:44
· Личное сообщение · #28

На этом форуме многие занимаются не созданием ПО, а анализом уже существующего.
Никто случайно не в курсе у ломалок забытых паролей от архивов(много таких программ), ядрышко на счётчике базируется или иным образом устроено? Интересно их внутреннее устройство.




Ранг: 105.6 (ветеран), 36thx
Активность: 0.10
Статус: Участник

Создано: 09 мая 2012 17:19 · Поправил: Dart Sergius
· Личное сообщение · #29

TheNozza, ща придёт Archer и скажет про кнопку "правка".
где-то в сети пробегало решение вашей задачи, но где я уже не помню.
И вы не знаете как решить мою проблему? Как мне импортировать нормально без jmp, который вставляет компилятор?

Проблема решилась
return allocator(&allocator_parameter, (const void*)ptr, size);
тупо передал адрес нашего jmp =)


 eXeL@B —› Программирование —› Ревёрс шаблонов с++
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати