Начало программирования.

Тема в разделе "WASM.BEGINNERS", создана пользователем Heineken, 22 ноя 2008.

  1. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    varnie
    одних асмов сколько

    кстати много ли Вы знаете языков, для которых сплайсинг это нормальная операция?
     
  2. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    GoldFinch
    мы говорим не про низкоуровневые ЯП, как ясно свидетельствует хотя бы даже начало данного топика. если бы ТС хотел учить асм, он бы не создавал эту тему.
    раз создал, значит его интересует не-асм, следовательно, предложение ему попробовать асм ему не подойдет;)

    сплайсинг - не имеет ничего общего с ЯП высокого уровня, а потому ваш вопрос применительно к ним некорректен. про асм не упоминаю, см абзац выше;)

    мы же не говорим, что С++ круче асма к примеру лишь потому, что поддерживает виртуальное наследование? :) вот и сплайсингом нам тоже тыкать не надо как дОвод :-|
    это не аргумент.

    ///////////
    кстати, на вышеупомянутом мною Лиспе можно налету сопоставить адрес встроенной функции с рассчитанным атомом значения. ну и подобные финты ушами;)
     
  3. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    думаю тут уже никого не волнует что хотел ТС...
     
  4. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    GoldFinch
    в таком случае вся тема переползет в ЯВУ vs asm.
    и непонятно кто кому чтО будет доказывать. в любом случае я пас.
     
  5. beginner

    beginner New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    233
    Ursus
    Код (Text):
    1. char *s = new char[5];
    2. s = (char*)(void*)&AAA::get;
    3. Ошибка    1   error C2440: приведение типов: невозможно преобразовать 'int (__thiscall AAA::* )(void)' в 'void *'  f:\work\wasm\wasm\bred.cpp  23  wasm
    код компилился на Visual Studio 2008
    Можешь проверять, может на другой версии компилятора заработает.
    Кстати студия на работе показала, что нужны другие смещения, можно в принципе автоматически вычислять их :)

    хы-хы русская студия жжет!!!!!!!
    Код (Text):
    1. wsprintf(buff, "%p", AAA::get);
    Ошибка 1 error C3867: AAA::get: в вызове функции отсутствует список аргументов;
    используйте "&AAA::get" для создания указателя на член f:\work\wasm\wasm\bred.cpp 22 wasm
    :)))) жесть!!!!!!

    Код (Text):
    1. wsprintf(buff, "%p", &AAA::get);
    Уж не знаю где подвох в вопросе, но попробую ответить как для новичка.
    Начнем с того, что данная функция подобна функции printf. Осуществляет форматированный вывод информации, согласно спецификаторам формата. Если printf осуществляет вывод в стандартный поток вывода, то wsprintf - осуществляет вывод в буфер. Кстати wsprintf довольно ограниченная функция, она не может выводить флоат и буфер ограничен 1024 байтами. Об этом можно почитать в мсдн.
    buff - буфер для приема результата
    "%p" - спецификатор вывода. МСДН: %p - Windows 2000/XP: Pointer. The address is printed using hexadecimal. Вывод указателя.
    &AAA::get - собственно сам указатель на метод, так, как того требует компилятор.
    В результате, в буфере мы получим значение указателя в тектовом виде.
    Далее преобразовываем его в HEX-число - это и есть искомый адрес функции.

    Если подытожить все вышесказанное, получаем следующее:
    Для сплайсинга функции, нужно знать ее адрес. Или адрес переходника.
    Указатель - это и есть начальный адрес этой функции, так как он содержит этот адрес. Немного сумбурно, но каждый для себя сам уясняет что такое указатель.
    Если нельзя получить адрес функции через "s = (char*)&AAA::get;" то применяем обходной маневр.

    И я не понимаю, почему в статьях Twister'a или Great'a, когда они получают адреса недокументированных структур, через асм-вставки, или еще как то - это нормальный подход, а когда я получаю указатель на метод класса - это подход через *опу.

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

    Ursus
    фишка с юнионом - тоже прикольно :)

    Ограничения-то ограничениям, но если есть задача, то ее нужно решать.
    При крекинге в лицензионном соглашении четко записано, что запрещается дизасмить программу, но не смотря на это ее реверсят, патчат и многое другое.
    Так и здесь - есть ограничения? значит попытаемся их обойти. Комп, к счастью, не сломается.
    Лично мне язык Си дает именно свободу в действиях, даже в таких, как обходить эти ограничения.
     
  6. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    разница в объеме генерируемого кода
    приведение типа это 0 (ноль) лишнего кода, вызов АПИ это много лишнего кода
     
  7. beginner

    beginner New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    233
    GoldFinch
    Прошу прощения, но реверсинг и взлом программ - это немножко не мой профиль. Это моя первая программа, которая вообще касается сплайсинга. Если б этим занимался профессиональный крекер или просто очень сильный кодер - думаю он бы нашел способ сплайсинга функции класса. И он был бы гораздо меньше, чем мой. Тут я не буду спорить.
    Я всего лишь показал, что возможности данного языка практически неограничены.
    Если автору темы нужны такие возможности - пусть изучает Си и С++
    Если автор темы хочет всего лишь заниматься кодописательством и не углубляться в кодокопательство - пусть учит паскаль.
     
  8. K10

    K10 New Member

    Публикаций:
    0
    Регистрация:
    3 окт 2008
    Сообщения:
    1.590
    У Паскаля не меньше возможностей...
     
  9. T800

    T800 Member

    Публикаций:
    0
    Регистрация:
    7 дек 2006
    Сообщения:
    293
    Адрес:
    Moscow
    beginner
    Код (Text):
    1. program Project2;
    2. {$APPTYPE CONSOLE}
    3. uses Windows, SysUtils;
    4.  
    5. type
    6.   TAAA = class
    7.   public
    8.     x: Integer;
    9.     procedure AAA1(i: Integer);
    10.     procedure AAA2;
    11.     function Get: Integer;
    12.   end;
    13.  
    14. procedure TAAA.AAA1(i: Integer); begin x := i; end;
    15. procedure TAAA.AAA2; begin end;
    16. function TAAA.Get: Integer;
    17. begin
    18.   Result := x;
    19.   asm nop; end;  // long jmp иначе не поместится =)
    20. end;
    21.  
    22. function myFunc(obj: TAAA): Integer; begin Result := 5; end;
    23.  
    24. var
    25.   obj: TAAA;
    26.   y, off: Integer;
    27.   p: PChar;
    28.   addrFunc: DWORD;
    29.   oldFlags: DWORD;
    30.  
    31. begin
    32.   obj := TAAA.Create;
    33.   obj.x := 1;
    34.   y := myFunc(nil);
    35.   y := obj.Get;
    36.   Writeln('Get = ', y);
    37.   p := @TAAA.Get;
    38.   if VirtualProtect(p, 5, PAGE_EXECUTE_READWRITE, @oldFlags) then begin
    39.     PByte(p)^ := $E9;
    40.     PInteger(p+1)^ := Integer(@myFunc) - Integer(p) - 5;
    41.   end;
    42.   y := obj.Get;
    43.   Writeln('Get = ', y);
    44.   obj.Free;
    45.   Readln;
    46. end.
     
  10. Ursus

    Ursus Member

    Публикаций:
    0
    Регистрация:
    15 мар 2006
    Сообщения:
    238
    Адрес:
    Russia
    Да разобрались с этим уже, я ж сказал, что по стандарту такое приведение недопустимо.


    Я знаю, как работает wsprintf(), и понимаю, что делает твой код. Вопрос был не в этом. Меня интересует, как ты понимаешь, почему в качестве параметра функции с переменным числом аргументов указатель на метод передается, причем передается без проблем, а присваивание с приведением к void* выполнить нельзя.

    На самом деле ответ (который я хотел услышать) - при передаче параметров в функцию с переменным числом аргументов компилятор не проверяет совпадение типов аргументов, а передает их почти "как есть".

    Да асм-вставки это почти нормально ("почти" - потому как платформозависимо). А преобразовывать указатель в строку (тем более с помощью wsprintf), для того, чтобы тут же преобразовать эту строку обратно в число - это действительно через ж%у :) Хотя бы потому, что wsprintf & strtol работают (по сравнению с прямым приведением типов) крайне медленно. И потому, что есть нормальные способы сделать то же самое - вот, хоть через юнионы.
     
  11. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    @AAA.get - нетипированный указатель на метод (аналог void*), можно привести к любому типу размером 4 байта

    Странная логика. Получаем указатель на метод через одно место, и тем самым доказываем, что возможности "неограничены" ?
    А насчет паскаля кстати не помню, чтобы хоть одно серьезное ограничение приводилось, кроме субъективных удобно\неудобно, да и то в сравнении с наворотами\приблудами С\С++. Еще раз повторю, что паскаль ближе к рукодельному асму и это как раз позволяет лучше понимать\чувствовать\контролировать работу программы.
    Поэтому правильнее говорить не о возможностях, а о скорости кодописания - если хочешь на 20% ускорить писанину и довериться компилятору, изучи стенографию С\С++ и пиши i++ и трехэтажные for, а если хочешь ручками - юзай тот же С\С++ без приблуд или паскаль с его асмоподобными inc(i) и простыми как валенок for :lol:
     
  12. Ursus

    Ursus Member

    Публикаций:
    0
    Регистрация:
    15 мар 2006
    Сообщения:
    238
    Адрес:
    Russia
    Слушай, докажы, да? А то повторять все умеют. Язык С как раз разрабатывался как сочетающий себе синтаксис высокого уровня с возможностью свободно отстреливать себе ноги...тьху... иметь доступ к низкоуровневым вещам типа арифметики указателей и т.п.
     
  13. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ursus
    Чего доказывать то ? Я ж говорю "юзай тот же С\С++ без приблуд", т.е. дело не в том, что С чего то не умеет, а в том, что в качестве его основных преимуществ выдвигаются всевозможные навороты типа 3-х этажных for, которых в паскале в принципе нет. При желании их можно было бы и в паскале накрутить и в ассемблере супермакросов замутить, но тогда они потеряют свое лицо и превратятся в тот же Ц. Об этом я и говорю - нет в паскале\дельфи приблудных фишек, и не надо, есть разумная достаточность и компромисс между высоким и низким уровнем, когда за лесом видны деревья :)
    PS: Кстати, в С\С++ есть (документированные) способы получения и подмены указателей на виртуальные методы классов ?
     
  14. T800

    T800 Member

    Публикаций:
    0
    Регистрация:
    7 дек 2006
    Сообщения:
    293
    Адрес:
    Moscow
    А разве паскаль не позволяет делать тоже самое?

    Когда я пишу на Делфи (с использованием функционала "приведение типов") я точно знаю во что компилятор "превратит" мой код. Т.е. фактически я понимаю типизацию как доп. информация для компилятора. А когда смотрю исходники на С (где разнотипные переменные смешиваются в одну кучу), мне очень сложно представить во что "это" преобразуется после компиляции.
     
  15. beginner

    beginner New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    233
    T800
    молодец с программой :)

    а насчет
    Для стандартных типов есть такое же стандартное приведение типов, которое не требует явного указания.
    Код (Text):
    1. char c = 'a';
    2. int x = 2*с;
    в данном случае содержимое переменной с приведется к типу int, выполнится умножение и результат занесется в x.
    Тебя смущает что можно умножать букву на число?

    Я тут почитал про типы данных делфи http://www.interface.ru/home.asp?artId=2561
    И что то не нашел, как можно организовать доступ к отдельному биту, как например на Си:
    Код (Text):
    1. struct имя_структуры {
    2.     тип имя1: длина_в_битах;
    3.     тип имя2: длина_в_битах;
    4.     ...
    5.     тип имяN: длина_в_битах;
    6. }
    Мож кто подскажет, как это делается то? :)

    Кстати, что такое вообще Delphi? Язык программирования или программный пакет?
     
  16. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    ск-ко учил и учу С/C++, не припомню чтобы сталкивалса со сложностями приведений типов. ума не приложу, чего вы так прицепились к этому ньюансу? что сложного? код в студию.
    из подобного рода ошибок могу заикнуться об арифметике, оперирующей unsigned int и int -ами. вот здесь грабли, согласен. если не знать какого типа результирующая переменная итд. почему про этот момент тогда уж ярые нелюбители С не упомянули? удивляюсь.
     
  17. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    beginner
    Никак, точнее ручками, как в асме ;) А нет видимо потому, что это довольно частная и редкая задача упаковки малоразрядных чисел. А для типовых задачек работы с битами как с флагами в паскале есть множества set of ...

    И то и другое. Дельфийский паскаль настолько ускакал от классического и турбо, что сами борманы его теперь называют delphi language

    varnie
    Насколько я понимаю, здесь ярых нелюбителей С нет, есть здравомыслящие люди, защищающие паскаль от необоснованных нападок. Не так уж он и плох, как его малюют :)
     
  18. bugaga

    bugaga New Member

    Публикаций:
    0
    Регистрация:
    1 июл 2007
    Сообщения:
    361
    фича bds2006 компиля - перегрузка операторов.
    Код (Text):
    1. {$apptype console}
    2. program test;
    3. type
    4.  myStr = record
    5.     str : string;
    6.     class [b]operator LeftShift[/b](a: myStr; b: integer): string;
    7. end;
    8.  
    9. class operator myStr.LeftShift(a:myStr; b: integer): string;
    10. begin
    11.   Result := pChar(integer(a) + b);
    12. end;
    13.  
    14. var
    15.     str : MyStr;
    16. begin
    17.  string(str) := 'Hello World!';
    18.  writeln ( [b]str shl 6[/b] );
    19. end.
    хм.. даже выводит сдвинутый результат :) Интересная тема для парсеров.
     
  19. beginner

    beginner New Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    233
    leo
    Код (Text):
    1. Q-156:  Как работать с битами?
    2. ------------------------------------------------------------
    3. Есть два способа.
    4. Низкоуровневый подход обеспечивается логическими операциями :
    5.  
    6. var
    7.   I : integer;
    8.   N : integer;                       // Номер бита в диапазоне от
    9. 0..SizeOf(TYPE)*8 - 1
    10.  
    11.   I := I or (1 shl N);               // установка бита
    12.   I := I and not (1 shl N);          // сброс бита
    13.   I := I xor (1 shl N);              // инверсия бита
    14.   if (i and (1 shl N)) <> 0 then...  // проверка установленного бита
    15.  
    16. Высокоуровневый подход опирается на представление числа в виде множества:
    17.  
    18. type
    19.   TIntegerSet = set of 0..SizeOf(Integer)*8 - 1;
    20. var
    21.   I : Integer;
    22.   N : Integer;
    23.  
    24.   Include(TIntegerSet(I), N);     // установили N-ный бит в 1
    25.   Exclude(TIntegerSet(I), N);     // сбросили N-ный бит в 0
    26.   if N in TIntegerSet(I) then...  // проверили N-ный бит
    Неудобно, особенно если поле содержит в себе не один бит, а 3 или 6 битов, и нужно сразу во все биты заносить информацию.
    Тогда нужно уточнить, о каких языках речь идет в данной теме. И какой будет тогда проще для начинающих? класический паскаль, делфи, Си или С++ ?
     
  20. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    Лисп однозначно.