Created
April 23, 2012 01:06
-
-
Save ngbrown/2467960 to your computer and use it in GitHub Desktop.
Demonstrates Windows reading past the source string when using WideCharToMultiByte.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// WideCharToMultiByteTest.c : Demonstrates Windows reading past the source string | |
// when using WideCharToMultiByte. | |
// The source problem uses UNICODE_STRING, so it may not be null terminated. | |
// | |
#define _WIN32_WINNT 0x400 | |
#include <WinSDKVer.h> | |
#include <stdio.h> | |
#include <tchar.h> | |
#include <Windows.h> | |
void print_last_error_msg() | |
{ | |
DWORD lasterror; | |
LPWSTR errormessage = NULL; | |
lasterror = GetLastError(); | |
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, | |
NULL, lasterror, 0, (LPWSTR)&errormessage, 0x1024, 0); | |
wprintf(L"lasterror=%i: %s\r\n", lasterror, errormessage); | |
LocalFree(errormessage); | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
int len, newlen; | |
char *name = NULL; | |
WCHAR* tempBuffer; | |
SYSTEM_INFO systeminfo; | |
HANDLE memoryHndl; | |
LPVOID memoryPtr; | |
DWORD allocation_size; | |
LPVOID guardPtr; | |
const WCHAR* sourceBuffer = L"\\??\\C:\\Windows\\system32\\tzres.dll"; | |
int sourceLen = lstrlenW(sourceBuffer); /* characters */ | |
/* bytes, as passed by UNICODE_STRING.Length */ | |
int sourceBytes = sourceLen * 2; | |
printf("sourceBytes=%i\r\n", sourceBytes); | |
GetSystemInfo(&systeminfo); | |
allocation_size = systeminfo.dwAllocationGranularity; | |
printf("dwAllocationGranularity: %u\r\n", allocation_size); | |
memoryHndl = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, | |
0, allocation_size, L"Local\\Memblock"); | |
memoryPtr = MapViewOfFile( | |
memoryHndl, FILE_MAP_ALL_ACCESS, 0, 0, allocation_size); | |
if(memoryPtr == NULL) { | |
print_last_error_msg(); | |
} | |
/* Create a guard page next */ | |
guardPtr = VirtualAlloc((byte*)memoryPtr + allocation_size, | |
allocation_size, MEM_RESERVE, PAGE_NOACCESS); | |
if(guardPtr == NULL) { | |
print_last_error_msg(); | |
} | |
/* put our source string at the end of the memory page, before the guard page */ | |
tempBuffer = (WCHAR*)((byte*)memoryPtr + allocation_size - sourceBytes); | |
memcpy(tempBuffer, sourceBuffer, sourceBytes); | |
/* check the size */ | |
len = WideCharToMultiByte( | |
CP_ACP, 0, tempBuffer, sourceBytes, 0, 0, NULL, NULL); | |
printf("reported len=%i\r\n", len); | |
if(len > 0) { | |
/* Alter the way WideCharToMultiByte takes the cbMultiByte parameter, | |
* not per doc. WideCharToMultiByte reports an error. | |
*/ | |
name = (char*)malloc(len + 1); | |
newlen = WideCharToMultiByte( | |
CP_ACP, 0, tempBuffer, sourceBytes, name, len/2, NULL, NULL); | |
if (newlen <=0) { | |
print_last_error_msg(); | |
} | |
name[len/2] = 0; | |
printf("reported newlen=%i\r\n", newlen); | |
printf("converted string=%s\r\n", name); | |
free(name); | |
name = NULL; | |
} | |
if(len > 0) { | |
/* The normal way WideCharToMultiByte takes the cbMultiByte parameter, | |
* as returned from the size check. WideCharToMultiByte crashes into | |
* the next page when reading. This means that it is reading past the | |
* sourceBytes count. | |
*/ | |
name = (char*)malloc(len + 1); | |
newlen = WideCharToMultiByte( | |
CP_ACP, 0, tempBuffer, sourceBytes, name, len, NULL, NULL); | |
if (newlen <=0) { | |
print_last_error_msg(); | |
} | |
name[len] = 0; | |
printf("reported newlen=%i\r\n", newlen); | |
printf("converted string=%s\r\n", name); | |
free(name); | |
name = NULL; | |
} | |
CloseHandle(memoryHndl); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static char *unicode_to_ansi(PUNICODE_STRING uni) | |
{ | |
int len; | |
char *name = NULL; | |
USHORT *uniBufferTerminated; | |
if (uni->Buffer == NULL || uni->Length == 0) | |
return NULL; | |
uniBufferTerminated = malloc(uni->Length + 2); | |
memcpy(uniBufferTerminated, uni->Buffer, uni->Length); | |
*(WCHAR*)((char*)uniBufferTerminated + uni->Length) = 0x0000L; | |
len = WideCharToMultiByte(CP_ACP, 0, uniBufferTerminated, -1, 0, 0, NULL, NULL); | |
if(len > 0) { | |
name = malloc(len + 1); | |
WideCharToMultiByte(CP_ACP, 0, uniBufferTerminated, -1, name, len, NULL, NULL); | |
name[len] = 0; | |
} | |
free(uniBufferTerminated); | |
return name; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment