GetProcAddress и инициализация указателей на функции Kernel32

Тема в разделе "WASM.BEGINNERS", создана пользователем psu, 17 окт 2006.

  1. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    Стандартная процедура инициализации: найти GetProcAddress, в цикле найти указатели на все необходимые функции. Под ХР работает на ура, а вот под 98 и МЕ - облом. Некоторые функции их кернела находяться неправильно. Например, вместо GlobalAlloc получаю LocalAlloc, и это еще не самая страшная ошибка, большинство остальных фукнций вообще "не в тему"... Помогите!!!
     
  2. censored

    censored New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2005
    Сообщения:
    1.615
    Адрес:
    деревня "Анонимные Прокси"
    source?
     
  3. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    psu
    Может быть ты сравниваешь адреса, полученные под дебагером с реальными адресами экспортов кернела?
     
  4. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    зачем? стандартный пример, взят из этого же сайта
    масив имен функций, масив двордовских переменных им соответствующих
    цикл вызовов GetProcAddress
    Проганял через Олли, на вход GetProcAddress приходит "правильный" :) параметр, на выходе - туфта :dntknw:, при чем, повторяю, далеко не для всех функций!
     
  5. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    psu
    Бес кода, нет подсказки! Как можно судить где у тебя не верно, если мы не видим места в коде, где у тебя ошибка?
     
  6. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    kernel32_imp:
    db "GetModuleHandleA", 0
    db "LoadLibraryExA", 0
    db "CreateFileW", 0
    .................
    kernel32_imp_addr label DWORD
    _GetModuleHandleA dd ?
    _LoadLibraryExA dd ?
    _CreateFileW dd ?
    .................

    GetAPIs proc dwNumber, dwSource, dwTarget, dwKernelBase, dwGetProcAddress : DWORD

    pushad
    mov ecx, dwGetProcAddress
    mov esi, dwKernelBase
    mov ebx, dwTarget
    mov edi, dwSource

    mov eax, ecx
    mov ecx, dwNumber

    NextFunc:
    push eax
    push esi
    push edi
    push ebx
    push ecx

    push edi ;имя функции
    push esi ;база kernel32
    call eax ;вызов GetProcAddress

    pop ecx
    pop ebx
    pop edi
    pop esi

    .IF eax == 0
    pop eax
    mov eax, -1 ;error
    popad
    ret
    .ENDIF

    mov dword ptr [ ebx ], eax ;помещаем адрес функции в переменную
    pop eax
    add ebx, 4 ;следующая переменная

    push ecx ;сохраняем счетчик
    MOV_REG ecx, 30 ;для цепочечной команды
    push eax
    mov al, 0 ;ищем 0
    repne scasb
    pop eax
    pop ecx
    loop NextFunc

    popad
    xor eax, eax ;OK
    ret
    GetAPIs endp

    -------------------------------------
    Вызов функции:

    ...........
    push [ ebp + offset _GetProcAddress ]
    push [ ebp + offset dwKernel32Base ]
    lea eax, [ ebp + kernel32_imp_addr ]
    push eax
    lea eax, [ ebp + kernel32_imp ]
    push eax
    push KERNEL32_FUNCTIONS_COUNT
    lea eax, [ ebp + GetAPIs ]
    call eax
    ..........


    Код никак не оптимизирован, так что не пинайте...
    ПОВТОРЯЮ. На входе GetProcAddress правильная строка, на выходе - лажа
     
  7. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    psu
    На Win 98 адреса этих функций совпадают.

    Подробнее.
     
  8. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    psu

    В Win9x это не туфта, а ф-ции-заглушки, препятствующие трассировке дебагером расшаренного системного кода.
    Посмотри получаемые адреса, когда твоя прога работает не под отладчиком. (OutputDebugString/DebugView или в файл пиши).
     
  9. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    СreateFileW -> GetNamedPipeHandleStateW
    CloseHandle -> FindCloseChangeNotification
    FindFirstFileW -> HearSetFlags
    FindNextFileW -> lstrcmpiW
    GetTempPathW -> lstrcmpiW
    DeleteFileW -> TryEnterCriticalSection
    CopyFileW -> lstrcpynW
    GetModuleFileNameW -> lstrcpynW
    SetFileAttributesW -> lstrcmpiW
    Process32FirstW -> 0

    думал, проблема в юникоде, так ведь CloseHandle тоже лажа...
     
  10. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Очень зря используешь юникод в Win9x.
     
  11. censored

    censored New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2005
    Сообщения:
    1.615
    Адрес:
    деревня "Анонимные Прокси"
    проверил на w98 -- все ок, кроме Process32FirstW (её вроде нет, есть Process32First без A/W). если интересно, прожка в аттаче.
     
  12. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Или из за юникода или из-за рук, что скорее всего!
    ты точно уверен что полученные адреса соответствуют этим функциям?
     
  13. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    Вот скриншоты до и после вызова GetProcAddress для CreateFileW
     
  14. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    хмм.. вот что выяснилось: все лажовые функции имеют одинаковый адрес экпорта. Например, CloseHandle и FindCloseChangeNotification = 8C8B ( win98 ). Что делать? Как найти такую функцию по имени?
    З.Ы. Если прогу, которая слинкована с импортом CloseHandle , например, прогнать в олли под 98-й, то не получается зайти "внутрь" CloseHandle. Как же эта функция реализована ( она что, на уровне драйвера работает )?
     
  15. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    psu
    Тебе же green объяснил - в 9x под отладчиком таблица импорта и GetProcAddress выдают не реальные адреса функций kernel32, а адреса заглушек (ThunkToKernel).
    Даже тема такая была "IsDebuggerPresent по таблице импорта", но потерялась во время чистки форума. Вот нашел у себя заметки на эту тему:
    Код (Text):
    1. Еще одна хитрость работы под отладчиком уровня приложения под Win9x:
    2. можно сравнить адреса одной и той же функции API,
    3. полученные через GetProcAddress и по таблице импорта
    4.  
    5. Если посмотреть, что лежит по адресу импортируемой функции (@Func),
    6. то увидим:
    7.   FF 25 xx xx xx XX = JMP dword ptr [$XXxxxxxx]
    8.   ...
    9. [$XXxxxxxx]:
    10.   yy yy yy YY = $YYyyyyyy  
    11. т.е.перейти на адрес YYyyyyyy, который лежит по адресу XXxxxxxx таблицы импорта.
    12.  
    13. Так вот, если процесс запущен самостоятельно, то по адресу XXхххххх
    14. лежит адрес YYyyyyyy = ZZzzzzzz - реальный адрес функции, возвращаемый GetProcAddress.
    15. Причем величина адреса должна быть большой - больше базы модуля kernel32, возвращаемой
    16. GetModuleHandleA('kernel32'), - обычно это за пределами $B0.., т.к. ядро отображается в верхние адреса памяти. Другими словами загрузчик ОС подставляет в таблицу импорта
    17. реальные адреса вызываемых функций kernel32.
    18.  
    19. Если процесс запущен под отладчиком, то импорт усложняется - создаются
    20. промежуточные пересылки - санки (thunk to kernel). Загрузчик подставляет в таблицу не реальный адрес вызываемой функции, а адрес thunk
    21.   FF 25 xx xx xx XX = JMP dword ptr [$XXxxxxxx]
    22.   ...
    23. [$XXxxxxxx]:
    24.   yy yy yy YY = адрес thunk
    25.   ...
    26. [$YYyyyyyy]:
    27.  68 zz zz zz ZZ   = PUSH ZZzzzzzz, где ZZzzzzzz - адрес вызываемой функции
    28.  E9 rr rr rr RR   = JMP +$RRrrrrrr, где $RRrrrrrr относительное смещение
    29.  00 00 //какие-то выравнивающие байты, т.к. смещение задается отн.след.команды => +12
    30. Причем:
    31. 1) GetProcAddress возвращает не реальный адрес ZZ.., а такой же YY.. с пересылкой;
    32. 2) Разным объявлениям функции соответствуют разные адреса пересылок YY.., т.е.
    33.    если мы наряду с Windows.pas объявим свою аналогичную external функцию,
    34.    то и адреса XX.. у них будут разные (они всегда разные) и то, что по ним
    35.    лежит YY.. тоже разное и не равно ZZ.. и не равно адресу AA..,
    36.    возвращаемому GetProcAddress;
    37. 3) результирующий адрес относительного перехода, т.е. YY..+RR..+12 у всех
    38.    получается одинаковый, но куда он ведет "фиг его знает" - это не важно.
    39.  
    40. ВЫВОДЫ:
    41.   Для определения наличия отладчика достаточно извлечь адрес YY.. какой-либо
    42. безобидной популярной функции Win API (например GetLastError) и сравнить его
    43. 1) либо с базой модуля Kernel32 = GetModuleHandle (если <, то отладчик, т.к. обычно все санки отладчиков размещаются по адресам ~$8...),
    44. 2) либо с адресом, возвращаемым GetProcAddress (если <>, то отладчик),
    45. 3) либо с аналогичным адресом другого объявления той же функции (если <>, то отладчик).
    46.  
    47. ПРИМЕРЫ:
    48. ===========================================================
    49. БЕЗ ОТЛАДЧИКА:
    50. --------------
    51.  //1) вызов ф-ии GetFileInformationByHandle, объявленной в Windows.pas
    52.  FF 25 D0 82 50 00 = JMP dword ptr [$005082D025]
    53.  ...
    54.  [$005082D025]:
    55.  E2 C9 F9 BF = $BFF9C9E2 - настоящий адрес из kernel32.dll
    56.  
    57.  //2) дополнительно обяъвленная функция GetFileInformationByHandle
    58.  FF 25 B8 87 50 00 = = JMP dword ptr [$005087B8]
    59.  ...
    60.  [$005087B8]:
    61.  E2 C9 F9 BF = $BFF9C9E2 - настоящий адрес из kernel32.dll
    62.  
    63.  //3) адрес полученный через вызов GetProcAddress = $BFF9C9E2
    64.  ===> все совпадает
    65.  
    66. ПОД ОТЛАДЧИКОМ
    67. ---------------
    68.  //1) вызов ф-ии GetFileInformationByHandle, объявленной в Windows.pas
    69.  FF 25 D0 82 50 00 = JMP dword ptr [$005082D025] //эта строка не изменяется
    70.  ...
    71.  [$005082D025]:
    72.  98 EE E8 82 = $82E8EE98 //но здесь уже не реальный адрес, а санки
    73.  
    74.  //2) дополнительно обяъвленная функция GetFileInformationByHandle
    75.  FF 25  B8 87 50 00 = JMP dword ptr [$005087B8] //эта строка не изменяется
    76.  ...
    77.  [$005087B8]:
    78.  48 01 E9 82 = $82E90148 //тоже санки, но другое значение !
    79.  ...
    80.  [$82E90148]: //переходим на санки и видим настоящий адрес
    81.  68 E2 C9 F9 BF   = PUSH $BFF9C9E2 //вот настоящий адрес !!!
    82.  E9 78 56 10 3D   = JMP +$3D105678 => $82E90148+$3D105678 = $BFF957C0 + 12 = $BFF957CC
    83.  00 00 //выравнивающие байты, смещение задается отн.след.команды => +12
    84.  
    85.  //3) адрес полученный через вызов GetProcAddress = $82E90858
    86.  => тоже не настоящий и разница с нашим вариантом +$710
    87.  [$82E90858]: //смотрим и видим аналогичную пересылку
    88.  68 E2 C9 F9 BF = PUSH $BFF9C9E2 //вот настоящий адрес !!!
    89.  E9 68 4F 10 3D = JMP +$3D104F68 => $82E90858+$3D104F68 = $BFF957C0 + 12 = $BFF957CC
    90.  00 00 !!!!!!!!! => JMP на тоже место
    Зайти в режиме трассировки (исполнения) нельзя, а вот просто посмотреть реализацию можно по GoTo Exspression или Follow
     
  16. psu

    psu New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2006
    Сообщения:
    198
    я открываю kernel32 98-й винды с помощью PEviewer, и отладчик тут ни причем. Смотрим скриншоты