macro import/export

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

  1. calidus

    calidus Member

    Публикаций:
    0
    Регистрация:
    27 дек 2005
    Сообщения:
    618
    Хочу сделать динамическое добавление строчек в секцию дата или в код , это 2 таблицы , одна с крк и вторая с адресами апи функций. Смысл в том что в проге используется слишком много апи и менять их нужно быстро , тоесть это придется перестраивать таблицы вручную. Удалять и добавлять нужное. Как можно макросом заменить эти действия когда код сам по себе вызывается колом в данные в дате.

    Я думал так например

    .code
    Callx MessageboxAx

    А макрос будет такой
    Call macro
    тут действия для инициализации двух структур типа в зависимости от данных в параметре

    MessageboxAx dd 0

    и MessageboxAxCRC dd 0

    хотелось бы разделить по библиотекам еще , например MessageboxAx пойдет в структуру ЮСЕР32
    а MessageboxAxCRC dd 0 пойдет в структуру Юсер32КРК.

    Как можно добавить динамическое определение библиотек и добавление в разные структуры данных для вызова ?

    Что то вроде такого , это быстрый набросок поэтому явно не рабочий но идея чтоб видна была
    Код (Text):
    1. macro    MessageVector        message1, message2:REST
    2.          IFNB    <user32>
    3. user32CrcApi struct
    4. MessageVectorCrcApi        dd 0
    5. dd 000000000h
    6. user32CrcApi ends
    7.  
    8. user32Api Struct
    9.                       MessageVectorApiStruct dd 0
    10. user32Api ends
    11.          ENDIF
    12. endm     MessageVector
     
  2. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.784
    calidus
    IMHO два противоречивых требования:
    1) добавление строчек в секцию import/export т.е. программа еще не компилирована
    2) в проге используется слишком много апи и менять их нужно быстро, т.е. программа уже скомпилирована, запущена, но вот вопрос -- секция импорта уже загружена, можно ли добавлять туда новые dll и функции? По второму вопросу, по-моему логично перед вызовом непрописанной в импорт функции проделать следующее
    Код (Text):
    1. invoke LoadLibrary,LIBR;загрузить библиотеку
    2.         mov [hLib],eax
    3. invoke GetProcAddress,[hLib],NameProc
    4. ;вызвать  процедуру с двумя параметрами
    5.     push dword[hLib]
    6.     push [hWnd]
    7.     CALL eax   
    8.  invoke FreeLibrary,[hLib];закрыть библиотеку
     
  3. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    link -debug YourProg.obj kernel32.lib user32.lib gdi32.lib wsock32.lib ...итд...
    Оно само определит заюзаные функи и прикрутит вам правильный импорт.

    А может я ничего не понял? Если вы хотите править импорт по самому себе, то учтите - статическое импортирование производится только при загрузке, переписать самого себя не просто, и exe-шник для таких целей вам придется линковать вручную сразу, или править под себя / писать свой линкер. Ну а у правильно слинкованого (таблицы импорта должны идти последними) можно править их на лету. Только зачем это вам?
     
  4. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.784
    _basmp_
    Может быть я чего-то не понял, но можно таблицы импорта писать вручную в бинарный файл и обходится без линкера, как это сделано в NASM и FASM
    Код (Text):
    1. ; nasm windows gui #
    2. ; nasmw hello.asm -o hello.exe
    3. %define exebase     0x400000
    4. %define MB_OK       0
    5. %macro invoke 1-*  ; macro to call Win32 API functions
    6.     %rep %0 - 1     ; repeat for each argument
    7.         %rotate -1  ; rotate right (last becomes %1)
    8.         push %1     ; push argument
    9.     %endrep
    10.     %rotate -1      ; %1 = function name
    11.     call  [%1]      ; call API function via IAT
    12. %endm
    13. [BITS 32]
    14. ORG exebase
    15. ;for WinXP - 335 bytes
    16. dd 'MZ','PE',1014Ch,0,0,0,10F0080h,10Bh,END_SECTION-start,0,0,start-exebase
    17. dd start-exebase,0,exebase,4,4,4,0,4,0,END_SECTION-exebase,start-exebase,0,2
    18. dd 100000h,1000h,100000h,1000h,0,4,0,0,import-exebase,end_import-import,0,0
    19. dd 0,0,'.text',0,start-exebase,END_SECTION-start,start-exebase,0,0,0
    20. dd 0E0000020h
    21. ;---------------------------------------------------------------------
    22. start:  invoke MessageBox,eax,Message,wTitle,eax;MB_OK
    23.         retn
    24. ;----------------------------------------------------------------------
    25. wTitle  db 'Iczelion Tutorial #2:MessageBox',0
    26. Message db 'Win32 Assembly with NASM is Great!'
    27. ;----------------------------------------------------------------------
    28. import:
    29. dd 0,0,0,user32_dll-exebase
    30. dd user32_table-exebase,0,0
    31. user32_table:
    32. MessageBox      dd _MessageBox-exebase
    33.                 dw 0
    34. _MessageBox db 0,0,'MessageBoxA',0      
    35. user32_dll  db 'user32'
    36. end_import:
    37. END_SECTION:
     
  5. calidus

    calidus Member

    Публикаций:
    0
    Регистрация:
    27 дек 2005
    Сообщения:
    618
    =) СПсб но вы меня не поняли , читайте еще раз. Обьяснил доступно ..

    Зачем мне в компилированном файле менять импорт и количество АПИ ? =) НЕТ это не то ! Речь идет об обыкновенных двух таблицах которые вы пишете для заполнения крк и адресов АПИ. Обычно их пишут в код или в дату сразу потом компилируют прогу и эти дворды заполняются данными.

    Смысл в том что Таблицы пустых двордов для крк и апи будут формироваться макросами во время компиляции. Что убирает работу ручного создания таблиц для крк и апи. Также по идее хотелось бы чтобы он сам определял с какой либы апи и делал дворд в таблицу юсер32 например.

    Разве мой макрос выше похож на за мену кода динамически в скомпиленной проге ? .. )))))))) Ну вот !
     
  6. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    а зачем крк? чтоб вручную искать в образе дллки?
    ну вот например сделать импорт как в фасме тольк вместо имен -крк...
     
  7. calidus

    calidus Member

    Публикаций:
    0
    Регистрация:
    27 дек 2005
    Сообщения:
    618
    GoldFinch ))))))) не надо отвлекаться , эти части уже сделаны и все оптимизировано и впорядке. что и надо было =) затруднения в макросе функциональность которого я описал =)
     
  8. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    calidus
    Абсолютно ничего не понятно. В чем вы затрудняетесь и что хотите сделать. В масм вы просто вызываете нужные функи, весь импорт будет построен и соптимизирован без всяких лишних телодвижений. В фасме макросы для импорта уже есть. В стандартную поставку входят.
     
  9. calidus

    calidus Member

    Публикаций:
    0
    Регистрация:
    27 дек 2005
    Сообщения:
    618
    Нету импорта , прога без импорта. Забей на импорт и если хочется помочь прочитай еще раз. Известные люди в асм сцене поняли меня , но не знают хорошего решения только предположения. Если не понятно ну значит не судьба )))
     
  10. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    Прочитал много раз. Чтобы юзать какието функции (или вообще имена), их надо до этого определить. Для этого составляется список всех известных функций, затем при втором проходе компилятора проверяется была ли эта функция использована (if used FuncName), если да - то производятся какие-то действия: добавление в импорт, или в твоем случае добавление в таблицу крк.
    Другой вариант - функция вызывается через макрос, который определяет где брать адрес для вызова. Для этого макрос добавляет каждую новую функцию в список, затем в конце файла (или при 2м прохоже компилятора) другой макрос из этого списка делает нужные таблицы. Но в этом случае надо задать длл в которой живет функция.
    И тот и другой способ реализуется на фасме минут за 5, про масм не скажу, т.к. уже забыл как им пользоваться.
     
  11. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    calidus
    Ну чтож. Дело ваше. Хотите доказать, что в чем-то нет решения - доказывайте. Не буду вам мешать.
     
  12. mz_

    mz_ New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2008
    Сообщения:
    9
    если несколько упростить и обобщить то что хочет ТС, то получим некий набор макросов, который при вызове например
    invoke kernel32.Sleep, 100
    во время компиляции сгенерирует код для загрузки kernel32, поиска там Sleep по ее хэшу и дальнейший вызов найденной функции с переданными параметрами
     
  13. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    чтобы не быть голословным - 1й вариант
    Код (Text):
    1. ...
    2. call MessageBoxA ;сам вызов
    3. ...
    4. ;списки всех апи
    5. kernel32_list equ AddAtomA, AddAtomW, AddConsoleAliasA, ...
    6. user32_list equ ...
    7. ....
    8. ;списки крк (можно заменить на вычисление средствами компилятора
    9. AddAtomA_crc = 12345
    10. AddAtomW_crc = 23456
    11. ...
    12. ;таблицы переходников
    13. kernel_thunk_table:
    14.    irp name,kernel32_list { if used name / make_import name / end if }
    15. user_thunk_table:  
    16.    irp name,user32_list { if used name / make_import name / end if }
    17. ;макрос объявления переходника
    18. macro make_import name {    
    19.      db 90,90,90 ;align
    20.      name db E9 ;здесь будет jmp
    21.      dd name#_crc;здесь брать крк и писать адрес
    22. }
    23. ....
    24. ;код заполнения переходника
    25. lea edi, [kernel_thunk_table+ecx*8+4]
    26. mov esi,[kernel_base]
    27. call crc2addr ;функция поиска апи в длл с базой esi по крк в [edi], результат в [edi]
     
  14. mz_

    mz_ New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2008
    Сообщения:
    9
    GoldFinch
    мне кажется надо больше автоматизации =)
     
  15. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    Можно и больше автоматизации... в фасме вообще можно во время компиляции разбирать таблицы экспорта системных длл и сразу прописывать адреса... ну или искать в какой длл находится функция. Однако чем городить килобайты текста макросов лучше написать отдельный препроцессор на чемнить типа пхп, строчек 20 будет наверное.
     
  16. mz_

    mz_ New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2008
    Сообщения:
    9
    GoldFinch
    препроцессор, пхп..) А на его отладку и доводку до кондиции сколько времени уйдет?) По своему опыту могу сказать что уж лучше убить день и написать 10кб аццких макросов которые потом с минимальными усилиями можно внедрить во все проекты, чем городить препроцессор вместо использования встроенного или ручками все править. Тут проблема то только в том, чтобы разобраться как правильно на макроязыке писать чтоб работало, и работало как надо =) Кстати судя по кодесу в первом посте, у нас масм
     
  17. calidus

    calidus Member

    Публикаций:
    0
    Регистрация:
    27 дек 2005
    Сообщения:
    618
    Спасибо =) .. Задача правильно ясна , в том то и дело что на ФАСМ это одно , но работа идет с МАСМ. Примеры тоже хорошие , но в каждом из вариантов примеров есть мелкие недочеты. Конечно их можно доработать и отладить все хорошо. Чтобы смена нужных апи и двордов проводилось 1 правкой или строкой. Над ПХП вариантом я тоже думал , да года 3 назад на нем писал да и прав mz_ в данном случае , мне это не очень подходит. Наверное цель всетаки выяснить вариаты реализации и собрать 1 рабочий классный пример. Поэтому можно не рассматривать каждый пример как конечный вариант =)
     
  18. mz_

    mz_ New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2008
    Сообщения:
    9
    вот тебе примерный кодес того что я описал выше - заменяет собой стандартный макрос invoke на собственный, который проверяет переданный параметр. Убрал всякие навороты, прокомментировал значимые и не очень места. Материала хватит для статьи =)

    Код (Text):
    1. ;invoke replacer
    2. ;kernel32.Sleep - use conversion
    3. ;Sleep - leave as usual import
    4. OPTION NOKEYWORD: <invoke> ;переопределяем стандартный макрос
    5. invoke MACRO LibNFunc:REQ, p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20
    6. LOCAL pos,counter
    7.     LOCAL LibNFuncLen ;имя функции (или длл.имя функции)
    8.     LOCAL iDotPos ;положение разделителя - точки - в строке
    9.    
    10.  
    11.    
    12.     LibNFuncLen SIZESTR <LibNFunc> ;вычисляем длину строки параметра LibNFunc
    13.     iDotPos INSTR <LibNFunc>, <.> ;получаем позицию точки в LibNFunc
    14.    
    15. %IF iDotPos
    16.     ;если обнаружена точка - значит разбиваем переданный параметр на имя длл и имя функции
    17.     sLib SUBSTR <LibNFunc>, 1, @CatStr(%iDotPos)-1
    18.     sFunc SUBSTR <LibNFunc>, @CatStr(%iDotPos)+1, @CatStr(%LibNFuncLen)-@CatStr(%iDotPos)
    19.    
    20.  
    21.     ;проверка не определена ли уже такая длл
    22.     sStr CATSTR <imf_>, sLib ;создаем имя флага по шаблону imf_имядлл
    23.     % IFNDEF sStr ;условная компиляция, если еще не определ флаг - определяем его
    24.         % echo sStr dll ;вывод отладочного сообщения
    25.         %sStr equ 1 ;определяем флаг imf_имядлл
    26.      ;а также определяем имя длл в текущей позиции кода
    27.         .code ;это уже идет в код
    28.             jmp @F   ;перепрыгиваем данные с именем длл до следующей инструкции
    29.      %  sz_&sLib& byte 0 ;определяем в коде имя метки по шаблону sz_имядлл чтобы впоследствии передавать ее в процедуру загрузки длл
    30.         %   $CR sLib ; здесь у меня свой макрос, шифрующий строку, но можно открытым текстом, код вроде будет таким %    byte 'sLib',0
    31.             @@:
    32.     ELSE
    33.         ;% echo sStr already def ;вывод отладочного сообщения
    34.     ENDIF
    35.  
    36.     ;проверяем, определен ли уже флаг imf_имядлл_имяфункции, нужно чтобы не допустить дубликатов при вызове одной и той же функции
    37.     sStr CATSTR <imf_>, sLib, <_>, sFunc
    38.     % IFNDEF sStr
    39.         % echo sStr import
    40.         %sStr equ 1
    41.      ; определяем значение хеша в текущей позиции кода
    42.         .code
    43.         jmp @F ;переходим на следующую инструкцию
    44.      %  dw_&sLib&_&sFunc& DWORD $HashString(%sFunc) ;определяем переменную вида dw_имядлл_имяфункции типа DWORD, макрос $HashString() нам подставляет значение хэша
    45.         @@:
    46.     ELSE
    47.         ;% echo sStr already def
    48.     ENDIF
    49.    
    50.    
    51. ELSE
    52.  ; здесь мы в случае если разделитель-точка не был найден в переданном имени функции, а значит перед нами вызов локальной функции (или обычной winapi),
    53. ; в данном случае мы не используем хеширование, но выводим предупреждение
    54.     IFNDEF DEBUG
    55.     %echo @FileCur(@CatStr(%@Line)) : [LibNFunc] invoked as usual import
    56.     ENDIF
    57. ENDIF
    58.  
    59.  
    60.  
    61.  
    62. ;тут скопипастеный у когото кусок по анализу и запихиванию параметров в стек
    63.     counter=0
    64.     FOR arg,<p20,p19,p18,p17,p16,p15,p14,p13,p12,p11,p10,p9,p8,p7,p6,p5,p4,p3,p2,p1>
    65.  
    66.         IFNB <arg>
    67.            
    68.  
    69.              counter=counter+4
    70.              pos=@InStr(1,arg,<ADDR >) OR @InStr(1,arg,<addr >) OR @InStr(1,arg,<Addr >)
    71.  
    72.              IF pos
    73.  
    74.                 IF (OPATTR(@SubStr(arg,%pos+5))) EQ 98
    75.                         lea eax,@SubStr(<arg>,%pos+5)
    76.                         push eax
    77.                 ELSE
    78.                         push OFFSET @SubStr(<arg>,%pos+5)
    79.                 ENDIF
    80.  
    81.              ELSE
    82.                         push arg
    83.              ENDIF
    84.         ENDIF
    85.     ENDM
    86.  
    87. ; подходим к вызову самой функции    
    88.  
    89. %IF iDotPos ; ##### тут у нас необычный вызов #####
    90.  
    91.     %   push dw_&sLib&_&sFunc&  
    92.     %   push offset sz_&sLib&
    93.     call find_api ;вызываем функцию поиска функции ;) Определена как find_api proc lpszLibName: DWORD, dwHashValue: DWORD
    94.  
    95.     call eax ; в eax мы получаем найденный адрес. Тут еще бы надо контроль на нулевой указатель и обработчик ошибок чтобы легче было искать проблему
    96.  
    97.        
    98. ELSE ; #### тут у нас обычный вызов #####
    99.    
    100.  
    101.     call LibNFunc
    102.  
    103.  
    104. ENDIF ;IFE iDotPos
    105.  
    106.     ;wsprintf fix - а это хрень чтобы подчистить стек для хитрых функций
    107.     IF ((OPATTR(funcname)) AND 11100000000y) EQ 00100000000y
    108.        IF counter NE 0
    109.           add esp,counter
    110.        ENDIF
    111.     ENDIF
    112.  
    113. ENDM
     
  19. calidus

    calidus Member

    Публикаций:
    0
    Регистрация:
    27 дек 2005
    Сообщения:
    618
    Спасибо =) Сильный макрос , ничего не скажешь.