Нарушение прав доступа при чтении буфера UNICODE_STRING - PullRequest
0 голосов
/ 07 сентября 2018

Я написал пользовательский поставщик учетных данных, который использует структуру KERB_CERTIFICATE_LOGON. Теперь, когда все работает нормально, я попытался написать несколько тестов модулей (я знаю, что тесты должны быть написаны до кодирования, но в этом случае мне пришлось выяснить, как все работает в первую очередь; -)).

Когда я пытаюсь утвердить содержимое структуры KERB_CERTIFICATE_LOGON, используя решение для этого SO-вопроса с wcsncmp следующим образом:

KERB_CERTIFICATE_LOGON* kerbCertificateLogon = reinterpret_cast<KERB_CERTIFICATE_LOGON*>(serializedCredentials->rgbSerialization);
wcsncmp(domainName, kerbCertificateLogon->DomainName.Buffer, kerbCertificateLogon->DomainName.Length / sizeof(wchar_t));

Я получаю нарушение прав доступа в wcsncmp на этом этапе:

    extern "C" int __cdecl wcsncmp(
    wchar_t const* a,
    wchar_t const* b,
    size_t         count
    )
{
    if (count == 0)
        return 0;

    while (--count != 0 && *a && *a == *b) // <== Here comes "read access violation b was 0x48"
    {
        ++a;
        ++b;
    }

    return static_cast<int>(*a - *b);
}

Кроме того, при отладке функции, заполняющей буфер, я могу видеть в представлении Visual Studio "Locals" непосредственно после заполнения буфера следующим кодом:

kerbCertificateLogon->DomainName.Buffer = reinterpret_cast<PWSTR>(domainBuffer - authInfo);

этот результат:

0x0000000000000048 <Ошибка чтения символов строки.>

ВТФ ??? Тот же код прекрасно работает при использовании LSA, поэтому я думаю, что все в порядке, но почему я не могу прочитать значение в простом юнит-тесте?

1 Ответ

0 голосов
/ 07 сентября 2018

ОК, как обычно, я нашел решение вскоре после того, как спросил. Вопреки одному из приведенных выше комментариев, ошибка связана со структурами сертификатов! Поэтому использование двух UNICODE_STRING не помогло бы воспроизвести проблему.

Внутри этих структур относительные указатели используются для хранения информации, как можно было видеть из ссылки на старый вопрос.

Я просто не видел дрова для деревьев.

Таким образом, решение довольно простое: вместо прямого использования указателя на буфер в UNICODE_STRING мне пришлось пересчитать абсолютный указатель. Я извлек это в метод, потому что мне нужно это сравнение довольно часто в моих тестах:

static void AssertRelativeUnicodeStringEquals(const wchar_t* expected, UNICODE_STRING actual, LPBYTE basePointer)
{
    const int result = wcscmp(expected, reinterpret_cast<PWSTR>(basePointer + reinterpret_cast<int>(actual.Buffer)));
    EXPECT_EQ(0, result);
}

Теперь я могу позвонить:

AssertRelativeUnicodeStringEquals(domainName, kerbCertificateLogon->DomainName, (LPBYTE)kerbCertificateLogon);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...