Сейчас на форуме: zombi-vadim, zds (+4 невидимых)

 [email protected] —› Программирование —› Вопрос по GetProcAddress
Посл.ответ Сообщение

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

Создано: 14 сентября 2013 23:34 · Поправил: MisterSmile
· Личное сообщение · #1

Здравствуйте!
Дописываю PE-загрузчик. Думал уж, конец скоро, как столкнулся с непредвиденной проблемой, реализуя аналог GetProcAdress.

По спецификации она принимает первым параметром адрес загрузки DLL, вторым - указатель на строку, содержащую имя функции либо ординал.

Хочу сделать так, чтобы она могла работать, как с именами функций, так и ординалами.

И собственно вопрос: в случае, когда передается ординал, есть ли какие автоматизированные средства перевода, то бишь функции или макросы, из char* в DWORD? Например, если мне нужно преобразовать строку "07Е15A2C" в переменную DWORD со значением 07Е15A2C.
Или нужно всё собственными ручками писать?

Что-то я в интернете искал, но везде натыкался на вариант, когда строка переводится в последовательность значений, кодирующих каждый её символ.



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

Создано: 14 сентября 2013 23:40 · Поправил: Veliant
· Личное сообщение · #2

в delphi StrToInt('$'+val) или HexToInt
в С можно sscanf(.., "%08x"..) или atoi с добавленным 0x
Только смысл переводить в строку чтоб потом обратно в dword?

GetProcAddress(hModule, (char *)1);



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

Создано: 14 сентября 2013 23:55
· Личное сообщение · #3

Veliant, спасибо большое)

Не совсем понял последний вопрос. В одном и том же передаваемом параметре у нас может быть, как ординал, так и имя функции. Как иначе передать имя, если не строкой?




Ранг: 136.0 (ветеран), 360thx
Активность: 0.270.14
Статус: Участник
Qt Developer

Создано: 15 сентября 2013 00:08
· Личное сообщение · #4

MisterSmile пишет:
Хочу сделать так, чтобы она могла работать, как с именами функций, так и ординалами.


Нужно проверить переданный в функцию параметр. Если это указатель на строку. То старший Word не равен 0. Если это ординал, то старший Word равен 0.

-----
http://ntinfo.biz




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

Создано: 15 сентября 2013 00:16 · Поправил: MisterSmile
· Личное сообщение · #5

hors, это да. Только сначала нужно перевести в DWORD. Собственно поэтому и вопрос возник.




Ранг: 136.0 (ветеран), 360thx
Активность: 0.270.14
Статус: Участник
Qt Developer

Создано: 15 сентября 2013 00:21
· Личное сообщение · #6

MisterSmile пишет:
hors, это да. Только сначала нужно перевести в DWORD. Собственно поэтому и вопрос возник.


GetProcAdress принимает не строку. А указатель на строку. То есть адрес. Это и есть DWORD.

-----
http://ntinfo.biz




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

Создано: 15 сентября 2013 00:24 · Поправил: dosprog
· Личное сообщение · #7

Ключевой момент здесь - сравнение параметра с числом 10000h (старшее слово 0?).
Если параметр меньше, чем 10000h - то GetProcAddress считает, что нужно искать функцию по ординалу,
если параметр больше , чем 10000h - то GetProcAddress считает, что это указатель на строку-имя функции.
(Указатель в WIN32 PE-EXE всегда будет больше, чем 10000h).

- - - - - - - - - >8
mov eax, 3 ;; -it's ORDINAL < 10000h
.....
mov eax,402203h ;; -it's POINTER >10000h - адрес строки-имени функции
.....
push eax
push module_handle
call GetProcAddress
- - - - - - - - - >8



Ранг: 63.8 (постоянный), 2thx
Активность: 0.030
Статус: Участник

Создано: 15 сентября 2013 00:30 · Поправил: drin
· Личное сообщение · #8

MisterSmile
как то странно... с одной стороны вы пытаетесь реализовать совсем не тривиальную задачу, а с другой ваши познания спотыкаются на довольно простых вещах...
а) вы не знаете как перевести Hex строку в DWORD
б) переводить ничего не нужно, строка которая передается в GetProcAddress это PChar - 32битное число указатель на строку, если передается ordinal то это число и является тем порятковым номером ф-ии, а не указателем на имя... нужно просто рассматривать в таком случае этот PChar как DWORD и все, и как выше предложили если он ниже 0xFFFF это ординал,а если выше то ссылка на имя

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

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

Создано: 15 сентября 2013 00:37 · Поправил: dosprog
· Личное сообщение · #9

drin,
уточю - рассматривать будет WIN32 при выполнении GetProcAddress.
Если её что-то не устроит - вернёт ошибку, иначе вернёт адрес интересующей функции.

Если даётся ординал - он должен присутствовать в этом подуле,
если даётся указатель на строку-имя функции - то имя это должно присутствовать в числе экспортируемых имён.

В любом случае, самое страшное, что тут может произойти, - это GetProcAddress вернёт ошибку.



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

Создано: 15 сентября 2013 00:44 · Поправил: Veliant
· Личное сообщение · #10

Кстати, есть еще сквозной экспорт у библиотек. Когда вместо указателя на функцию будет указатель на имя функции в другой библиотеке. Например HeapAlloc kernel32 "сквозит" на ntdll.RtlAllocateHeap



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

Создано: 15 сентября 2013 00:50 · Поправил: dosprog
· Личное сообщение · #11

MisterSmile,
sscanf(...);
-- Экспортируется библиотекой msvcrt.dll.




Ранг: 72.3 (постоянный), 133thx
Активность: 0.380
Статус: Участник

Создано: 15 сентября 2013 00:59
· Личное сообщение · #12

Лучше чем LWE не запилите. Так что вопрос смысла не имеет.



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

Создано: 15 сентября 2013 01:00 · Поправил: dosprog
· Личное сообщение · #13

Veliant,

>>вместо указателя на функцию будет указатель на имя функции в другой библиотеке.

-- наверное, будет указатель на функцию в другой библиотеке ?...

Dr0p,
да тут речь идёт о простой маленькой утилитке, какую все или почти все когда-то для себя поделали.
Десяток строчек на Си. Чуть больше на асме.
...хотя ... нет, видимо, я не до конца понял суть проблемы.
Тут задумка, вроде, взрослая. Тогда я не понимаю, откуда проблема с конвертацией string->DWORD?..



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

Создано: 15 сентября 2013 01:04 · Поправил: dosprog
· Личное сообщение · #14

...Post removed...




Ранг: 72.3 (постоянный), 133thx
Активность: 0.380
Статус: Участник

Создано: 15 сентября 2013 01:06
· Личное сообщение · #15

dosprog

Загрузчик нужен для не многих целей. Это загрузка из памяти, либо осевой для каких нить буткитов. В любых иных случаях есть системный. Да и GPA() позволяет по ординалам искать. Не пойму в чём проблема.

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


Ранг: 72.3 (постоянный), 133thx
Активность: 0.380
Статус: Участник

Создано: 15 сентября 2013 01:30
· Личное сообщение · #16

> Тогда я не понимаю, откуда проблема с конвертацией string->DWORD?..

Строка это не массив символов загружаемый в стек в качестве аргументов. Строка в данном случае имеет фиксированный тип - PSTR. Префикс P" у типов означает Pointer". Это ссылка на строку, тоесть её адрес.

Ординал же есть число. Лень смореть как там у виньапишки, для нтлдр прото конкретное:

LdrGetProcedureAddress(
IN HANDLE ModuleHandle,
IN PANSI_STRING FunctionName OPTIONAL,
IN ULONG Ordinal OPTIONAL,
OUT PPOINTER ProcedureAddress
):NTSTATUS



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

Создано: 15 сентября 2013 01:37 · Поправил: dosprog
· Личное сообщение · #17

Dr0p
Всё. Я понял.
ТС просто грузит в память модуль, а потом хочет в памяти в этом модуле искать точки входа функций.
Так это проще сделать вызовом GetProcAddress, если только не замышляется дизассемблер для DLL'ей.
Как вы и написали в посте #15...

Вопрос был - как сконвертировать строку "123h" в DWORD 123h, видимо, "123h" это будет задаваемый от-руки ординал.
Вспомнилось, как это всё организовано было в WIN16 - там загрузка по ординалам делалась так:
принимается FAR указатель на строку. Эта строка - или имя функции, или строка-ординал в виде "#123",
где "123" - это WORD ординал 123dec.
Правда, был и третий способ - в стек запихивался ординал в двоичном виде как DWORD, но старшее слово у него должно было быть 0000 (вроде сегмента в FAR-указателе).
Ничего нового...




Ранг: 72.3 (постоянный), 133thx
Активность: 0.380
Статус: Участник

Создано: 15 сентября 2013 01:43
· Личное сообщение · #18

dosprog

GPA опенсурс. Но есно она не на дельфи.



Ранг: 72.1 (постоянный), 30thx
Активность: 0.050
Статус: Участник

Создано: 15 сентября 2013 02:41
· Личное сообщение · #19

У ординалов взведен старший бит адреса. т.е.
Code:
  1. if (XXX and $80000000)<>0
  2. then ... ординал
  3. else ... имя функции


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

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

Создано: 15 сентября 2013 04:42 · Поправил: dosprog
· Личное сообщение · #20

yagello,

>>У ординалов взведен старший бит адреса. т.е.

-- вы имеете в виду ординалы, находящиеся в таблице импорта PE-EXE файла.
Но такое практически не встречается нигде. Так не делают.
Можно, конечно, слинковать PE-EXE командой "C>TLINK32 /o ... ...",
но делать такое - это заведомо иметь проблемы с переносимостью на другую версию той же Windows.
ОРДИНАЛ ФУНКЦИИ НЕ ПОСТОЯНЕН В РАЗНЫХ ВЕРСИЯХ WIN32. Об этом и Микрософт предупреждала.
Импорт в WIN32 PE-EXE - практически всегда только по именам функций.
Конечно, импорт только из собственных библиотек можно реализовать и по ординалам.
Для затруднения анализа кода. Но зачем это делать, я не знаю... Только злить людей.
Что-то такое было в IDE.

Вот, кстати, старинная утилитка на тему загрузки DLL'лей с помошью системного загрузчика:
(LoadLibrary + GetProcAddress):


d5aa_15.09.2013_EXELAB.rU.tgz - PROCADDR.RAR




Ранг: 72.3 (постоянный), 133thx
Активность: 0.380
Статус: Участник

Создано: 15 сентября 2013 10:42 · Поправил: Dr0p
· Личное сообщение · #21

yagello

Code:
  1. FARPROC
  2. GetProcAddress(
  3.     HMODULE hModule,
  4.     LPCSTR lpProcName
  5.     )
  6.  
  7. /*++
  8.  
  9. Routine Description:
  10.  
  11.     This function retrieves the memory address of the function whose
  12.     name is pointed to by the lpProcName parameter.  The GetProcAddress
  13.     function searches for the function in the module specified by the
  14.     hModule parameter, or in the module associated with the current
  15.     process if hModule is NULL.  The function must be an exported
  16.     function; the module's definition file must contain an appropriate
  17.     EXPORTS line for the function.
  18.  
  19.     If the lpProcName parameter is an ordinal value and a function with
  20.     the specified ordinal does not exist in the module, GetProcAddress
  21.     can still return a non-NULL value.  In cases where the function may
  22.     not exist, specify the function by name rather than ordinal value.
  23.  
  24.     Only use GetProcAddress to retrieve addresses of exported functions
  25.     that belong to library modules.
  26.  
  27.     The spelling of the function name (pointed to by lpProcName) must be
  28.     identical to the spelling as it appears in the source library's
  29.     definition (.DEF) file.  The function can be renamed in the
  30.     definition file.  Case sensitive matching is used???
  31.  
  32. Arguments:
  33.  
  34.     hModule - Identifies the module whose executable file contains the
  35.         function.  A value of NULL references the module handle
  36.         associated with the image file that was used to create the
  37.         current process.
  38.  
  39.  
  40.     lpProcName - Points to the function name, or contains the ordinal
  41.         value of the function.  If it is an ordinal value, the value
  42.         must be in the low-order word and zero must be in the high-order
  43.         word.  The string must be a null-terminated character string.
  44.  
  45. Return Value:
  46.  
  47.     The return value points to the function's entry point if the
  48.     function is successful.  A return value of NULL indicates an error
  49.     and extended error status is available using the GetLastError function.
  50.  
  51.  
  52. --*/
  53.  
  54. {
  55.     NTSTATUS Status;
  56.     PVOID ProcedureAddress;
  57.     STRING ProcedureName;
  58.  
  59.     if ( (ULONG_PTR)lpProcName > 0xffff ) {
  60.         RtlInitString(&ProcedureName,lpProcName);
  61.         Status = LdrGetProcedureAddress(
  62.                         BasepMapModuleHandle( hModule, FALSE ),
  63.                         &ProcedureName,
  64.                         0L,
  65.                         &ProcedureAddress
  66.                         );
  67.         }
  68.     else {
  69.         Status = LdrGetProcedureAddress(
  70.                         BasepMapModuleHandle( hModule, FALSE ),
  71.                         NULL,
  72.                         PtrToUlong((PVOID)lpProcName),
  73.                         &ProcedureAddress
  74.                         );
  75.         }
  76.     if ( !NT_SUCCESS(Status) ) {
  77.         BaseSetLastNTError(Status);
  78.         return NULL;
  79.         }
  80.     else {
  81.         if ( ProcedureAddress == BasepMapModuleHandle( hModule, FALSE ) ) {
  82.             if ( (ULONG_PTR)lpProcName > 0xffff ) {
  83.                 Status = STATUS_ENTRYPOINT_NOT_FOUND;
  84.                 }
  85.             else {
  86.                 Status = STATUS_ORDINAL_NOT_FOUND;
  87.                 }
  88.             BaseSetLastNTError(Status);
  89.             return NULL;
  90.             }
  91.         else {
  92.             return (FARPROC)ProcedureAddress;
  93.             }
  94.         }
  95. }


- старшее слово обнулено.



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

Создано: 15 сентября 2013 13:55
· Личное сообщение · #22

Всех благодарю! Разобрался

Не знаю, почему своим ходом не дошёл до столь простого решения:

MyGetProcAddress (DynamicLoad("Dynamic.dll"), (char*)1); //если вызов по ординалу

MyGetProcAddress (DynamicLoad("Dynamic.dll"), "TestFunction"); //если вызов по имени функции

И всё работает)




Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 15 сентября 2013 14:20
· Личное сообщение · #23

Полагаю, можно закрыть, раз вопрос решён.


 [email protected] —› Программирование —› Вопрос по GetProcAddress
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати