Привет всем!
Я запустила mirror driver из примеров DDK.Меня интересует перехват текста,который выводиться на экран.В примере выводиться адрес строки,которая выводиться на экран.
DISPDBG((0,"Mirror Driver DrvTextOut:pwstr=%08x\n",pstro ?pstro->pwszOrg : (WCHAR*)-1));
Где pstro->pwszOrg-адрес нужной мне строчки.
Как получить по этому адресу сам текст?
Я делала так.
PCSZ s;
PANSI_STRING str=NULL;
RtlInitAnsiString(str,s);
PUNICODE_STRING unstr;
RtlInitUnicodeString(unstr,pstro->pwszOrg);
RtlUnicodeStringToAnsiString(str,unstr,TRUE);
DISPDBG((0,"Test:pwstr=%s\n",str->Buffer));
RtlFreeAnsiString(str);
Как только добавляешь эти Rtl-функции,вообще ничего на экран не выводиться(всмысле в дебагер)
В чём может быть причина?Это мой первый драйвер,поэтому я ума не приложу,в чём проблема.
Спасибо.
Re: DDK,mirror driver,unicod to ansi
От:
Аноним
Дата:
08.05.07 06:32
Оценка:
L>Как только добавляешь эти Rtl-функции,вообще ничего на экран не выводиться(всмысле в дебагер) L>В чём может быть причина?
Не знаю, в чём причина — я обычно не утруждаю себя разбором кода, если он элементарно неудобочитаем (aka некрасив).
Предлагаю воспользоваться примитивами, которые я когда-то написал для своих драйверов и пользуюсь уже года два, работают прекрасно.
Вот они:
//
// converts string to Unicode string
//
PUNICODE_STRING atou (char* string)
{
PUNICODE_STRING pus;
ANSI_STRING as;
ULONG len;
if (string == NULL) return NULL;
len = slen (string);
RtlInitAnsiString (&as, string);
pus = sallocu (NULL, (USHORT) len * sizeof (WCHAR));
if (! pus) return NULL;
if (! NT_SUCCESS (RtlAnsiStringToUnicodeString (pus, &as, FALSE)))
{
sfreeu (pus, TRUE);
return NULL;
}
pus -> Buffer [len] = 0;
return pus;
}
//
// converts WCHAR array to string;
// 'length' in bytes
//char* wtoa (PWCHAR string, ULONG length)
{
UNICODE_STRING us;
char* r = NULL;
if (string == NULL) return NULL;
us.Buffer = NULL;
if (! sallocu (&us, (USHORT) length)) return NULL;
if (! scopyu (&us, string, (USHORT) length)) goto END;
r = utoa (&us);
END:
sfreeu (&us, FALSE);
return r;
}
//
// allocates Unicode string ('length' in bytes)
//
PUNICODE_STRING sallocu (PUNICODE_STRING pustr, USHORT length)
{
BOOL bfull = FALSE;
if (length == 0) return NULL;
if (length % sizeof (WCHAR) != 0) length ++;
if (pustr == NULL)
{
bfull = TRUE;
pustr = npalloc (sizeof (UNICODE_STRING));
if (! pustr) return NULL;
}
else
{
if (! MmIsAddressValid (pustr)) return NULL;
}
pustr -> MaximumLength = length + sizeof (WCHAR);
pustr -> Length = 0;
pustr -> Buffer = npalloc (pustr -> MaximumLength);
if (! pustr -> Buffer)
{
pustr -> MaximumLength = 0;
if (bfull) sfreeu (pustr, TRUE);
return NULL;
}
return pustr;
}
//
// frees Unicode string
//void sfreeu (PUNICODE_STRING pustr, BOOL bFreeAll)
{
if (pustr == NULL) return;
if (pustr -> Buffer) pfree (&pustr -> Buffer);
if (bFreeAll)
{
pfree (&pustr);
}
else
{
pustr -> Length = 0;
pustr -> MaximumLength = pustr -> Length;
}
}
//
// copies specified string and
// returns pointer to new string
//char* scopy (char* string)
{
char* newstr = NULL;
ULONG len;
ULONG i;
if (string == NULL) return NULL;
len = slen (string);
newstr = npalloc (len + 1);
if (! newstr) return NULL;
for (i = 0; i < len; i ++)
{
newstr [i] = string [i];
}
newstr [len] = 0;
return newstr;
}
//
// allocates buffer (length = length(string) + alength + 1)
// and initializes it with 'string'; returns buffer
//char* sinit (char* string, ULONG alength)
{
ULONG len = slen (string);
char* ps = npalloc (len + alength + 1);
if (! ps) return NULL;
mcopy (ps, string, len);
ps [len] = 0;
return ps;
}
//
// replaces one char 'cold' to another 'cnew'
//char* sreplace (char* string, char cold, char cnew)
{
ULONG len = slen (string);
ULONG i;
if (string == NULL) return NULL;
for (i = 0; i < len; i ++)
{
if (string [i] == cold)
{
string [i] = cnew;
}
}
return string;
}
//
// compares specified number of bytes
// of two strings
//
BOOL scmpn (char* string1,
char* string2,
BOOL ignoreCase,
ULONG length)
{
ULONG i;
ULONG len, t;
char c1, c2;
if (string1 == string2) return TRUE;
len = slen (string1);
t = slen (string2);
if (len == t && len == 0) return TRUE;
if (t < len) len = t;
if (length < len) len = length;
else if (length > len) return FALSE;
for (i = 0; i < len; i ++)
{
c1 = string1 [i];
c2 = string2 [i];
if (ignoreCase)
{
c1 = RtlUpperChar (c1);
c2 = RtlUpperChar (c2);
}
if (c1 != c2)
{
return FALSE;
}
}
return TRUE;
}
//
// compares two strings (length will be calculated)
//
BOOL scmp (
char* string1,
char* string2,
BOOL ignoreCase)
{
ULONG i = 0;
ULONG len = 0, t = 0;
char c1 = 0, c2 = 0;
BOOL r = FALSE;
if (string1 == string2)
{
r = TRUE;
goto END;
}
if (! MmIsAddressValid (string1) ||
! MmIsAddressValid (string2))
{
goto END;
}
len = slen (string1);
t = slen (string2);
if (t != len) return FALSE;
if (len == 0) return TRUE;
for (i = 0; i < len; i ++)
{
c1 = string1 [i];
c2 = string2 [i];
if (ignoreCase)
{
c1 = RtlUpperChar (c1);
c2 = RtlUpperChar (c2);
}
if (c1 != c2)
{
goto END;
}
}
r = TRUE;
END:
return r;
}
//
// compares two chars
//
BOOL scmpc (char char1,
char char2,
BOOL ignoreCase)
{
if (ignoreCase)
{
char1 = RtlUpperChar (char1);
char2 = RtlUpperChar (char2);
}
return (char1 == char2);
}
//
// searches for substring in specified string
//char* sfind (
char* string,
char* substr,
BOOL ignoreCase)
{
ULONG sslen = slen (substr);
ULONG sl = slen (string);
ULONG i = 0;
if (sslen == 0 || sl == 0) return NULL;
if (sl < sslen) return NULL;
while (i + sslen <= sl)
{
if (scmpn (string + i, substr, ignoreCase, sslen))
{
return (string + i);
}
i ++;
}
return NULL;
}
//
// searches for substring in specified string
// from end of string
//char* sfindr (
char* string,
char* substr,
BOOL ignoreCase)
{
ULONG sslen = slen (substr);
ULONG sl = slen (string);
char* pos;
if (sslen == 0 || sl == 0) return NULL;
if (sl < sslen) return NULL;
pos = string + sl - sslen - 1;
while (pos != string)
{
if (scmpn (pos, substr, ignoreCase, sslen))
{
return pos;
}
pos --;
}
return NULL;
}
//
// allocates specified number of bytes
// in non-paged memory, and optionally,
// fills this block with zeros
//
PVOID _npalloc (SIZE_T size, BOOL bZero)
{
PVOID r = NULL;
size = _getsize (size);
r = ExAllocatePool (NonPagedPool, size);
if (r && bZero) RtlZeroMemory (r, size);
return r;
}
//
// allocates specified number of bytes
// in non-paged memory
//
PVOID npalloc (SIZE_T size)
{
return _npalloc (size, FALSE);
}
//
// allocates specified number of bytes
// in non-paged memory and fill it
// with zeros
//
PVOID npallocz (SIZE_T size)
{
return _npalloc (size, TRUE);
}
//
// frees specified memory block
//void pfree (PVOID* ppointer)
{
PVOID p = NULL;
//
// check argument
//if (ppointer == NULL) return;
if (*ppointer == NULL) return;
//
// save pointer to memory block
//
p = *ppointer;
//
// indicate buffer is unusable
//
InterlockedExchange (
(PLONG) ppointer,
(LONG) NULL);
//
// free memory block
//
ExFreePool (p);
}
//
// copies specified number of bytes
// (destination buffer must be allocated)
//void mcopy (BYTE* dest, BYTE* src, ULONG length)
{
ULONG i = 0;
PMDL pmdlsrc = NULL;
PMDL pmdldst = NULL;
BOOL bdst = FALSE, bsrc = FALSE;
BYTE* psrc = NULL;
BYTE* pdest = NULL;
if (length == 0) return;
if (! dest) return;
if (! src) return;
//
// lock buffers in memory (make them resident)
// (numbers from DDK for Windows 2003 SP1)
//if (length < PAGE_SIZE * (65535 - sizeof (MDL)) / sizeof (ULONG_PTR) &&
KeGetCurrentIrql () <= APC_LEVEL)
{
//
// lock source buffer
//
pmdlsrc = IoAllocateMdl (src, length, FALSE, FALSE, NULL);
if (pmdlsrc)
{
MmBuildMdlForNonPagedPool (pmdlsrc);
__try { MmProbeAndLockPages (pmdlsrc, KernelMode, IoReadAccess); }
__except (EXCEPTION_CONTINUE_EXECUTION) { goto PERFORM_OPERATION; }
bsrc = TRUE;
}
//
// lock destination buffer
//
pmdldst = IoAllocateMdl (dest, length, FALSE, FALSE, NULL);
if (pmdldst)
{
MmBuildMdlForNonPagedPool (pmdldst);
__try { MmProbeAndLockPages (pmdldst, KernelMode, IoWriteAccess); }
__except (EXCEPTION_CONTINUE_EXECUTION) { goto PERFORM_OPERATION; }
bdst = TRUE;
}
psrc = (BYTE*) MmGetSystemAddressForMdlSafe (pmdlsrc, NormalPagePriority);
pdest = (BYTE*) MmGetSystemAddressForMdlSafe (pmdldst, NormalPagePriority);
}
PERFORM_OPERATION:
__try
{
//
// just copy bytes
//if (pdest && psrc)
{
for (i = 0; i < length; i ++)
{
pdest [i] = psrc [i];
}
}
else
{
for (i = 0; i < length; i ++)
{
dest [i] = src [i];
}
}
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
//
// do nothing
//
}
//
// unlock pages
//if (bsrc) MmUnlockPages (pmdlsrc);
if (bdst) MmUnlockPages (pmdldst);
//
// free resources
//if (pmdlsrc) IoFreeMdl (pmdlsrc);
if (pmdldst) IoFreeMdl (pmdldst);
}
//
// converts Unicode string to string
//char* utoa (PUNICODE_STRING string)
{
ANSI_STRING as;
char* result = NULL;
ULONG len;
if (! string) goto END;
if (! string -> Buffer) goto END;
len = slenu (string) / sizeof (WCHAR);
as.Length = 0;
as.MaximumLength = (USHORT) len + 1;
as.Buffer = npalloc (as.MaximumLength);
if (! as.Buffer) goto END;
if (! NT_SUCCESS (RtlUnicodeStringToAnsiString (&as, string, FALSE)))
{
pfree (&as.Buffer);
goto END;
}
result = as.Buffer;
result [len] = 0;
END:
return result;
}
L>Это мой первый драйвер,поэтому я ума не приложу,в чём проблема.
Бывает.
Re[2]: DDK,mirror driver,unicod to ansi
От:
Аноним
Дата:
08.05.07 06:38
Оценка:
А>Предлагаю воспользоваться примитивами, которые я когда-то написал для своих драйверов и пользуюсь уже года два, работают прекрасно.
Вот ещё:
//
// reads string value data from registry
//char*
rgets (char* path, char* name)
{
HANDLE hkey = NULL;
NTSTATUS status = STATUS_ACCESS_DENIED;
char* result = NULL;
PUNICODE_STRING pus = NULL;
OBJECT_ATTRIBUTES oa;
PUNICODE_STRING keypath = NULL;
PUNICODE_STRING valuename = NULL;
BYTE* data = NULL;
ULONG rlen = 0;
KEY_VALUE_PARTIAL_INFORMATION* buff = NULL;
if (path == NULL) goto END;
if (name == NULL) goto END;
// init buffers
keypath = atou (path);
if (! keypath) goto END;
valuename = atou (name);
if (! valuename) goto END;
data = npalloc (MAX_BUFFER_LENGTH + sizeof (KEY_VALUE_PARTIAL_INFORMATION));
if (! data) goto END;
// init attributes
InitializeObjectAttributes (
&oa,
keypath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
//
// open registry key
//
status = ZwOpenKey (
&hkey,
KEY_READ,
&oa);
if (! NT_SUCCESS (status)) goto END;
//
// query value data
//
status = ZwQueryValueKey (
hkey,
valuename,
KeyValuePartialInformation,
data,
MAX_BUFFER_LENGTH + sizeof (KEY_VALUE_PARTIAL_INFORMATION),
&rlen);
if (! NT_SUCCESS (status)) goto END;
buff = (KEY_VALUE_PARTIAL_INFORMATION*) data;
if (buff -> Type != REG_SZ &&
buff -> Type != REG_EXPAND_SZ &&
buff -> Type != REG_MULTI_SZ) goto END;
// extract data from the end of the buffer
pus = sallocu (NULL, (USHORT) buff -> DataLength);
if (! pus) goto END;
if (! scopyu (pus, (PWCHAR) buff -> Data, (USHORT) buff -> DataLength)) goto END;
// convert Unicode to ANSI
result = utoa (pus);
END:
// close keyif (hkey) ZwClose (hkey);
// cleanupif (keypath) sfreeu (keypath, TRUE);
if (valuename) sfreeu (valuename, TRUE);
if (data) pfree (&data);
if (pus) sfreeu (pus, TRUE);
return result;
}
//
// reads DWORD value data from registry
//
DWORD
rgetdw (char* path, char* name)
{
HANDLE hkey = NULL;
NTSTATUS status = STATUS_ACCESS_DENIED;
DWORD result = 6;
OBJECT_ATTRIBUTES oa;
PUNICODE_STRING keypath = NULL;
PUNICODE_STRING valuename = NULL;
BYTE* data = NULL;
ULONG rlen = 0;
KEY_VALUE_PARTIAL_INFORMATION* buff = NULL;
if (path == NULL) goto END;
if (name == NULL) goto END;
// init buffers
keypath = atou (path);
if (! keypath) goto END;
valuename = atou (name);
if (! valuename) goto END;
data = npalloc (MAX_BUFFER_LENGTH + sizeof (KEY_VALUE_PARTIAL_INFORMATION));
if (! data) goto END;
// init attributes
InitializeObjectAttributes (
&oa,
keypath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
//
// open registry key
//
status = ZwOpenKey (
&hkey,
KEY_READ,
&oa);
if (! NT_SUCCESS (status)) goto END;
//
// query value data
//
status = ZwQueryValueKey (
hkey,
valuename,
KeyValuePartialInformation,
data,
MAX_BUFFER_LENGTH + sizeof (KEY_VALUE_PARTIAL_INFORMATION),
&rlen);
if (! NT_SUCCESS (status)) goto END;
buff = (KEY_VALUE_PARTIAL_INFORMATION*) data;
if (buff -> Type != REG_DWORD) goto END;
if (buff -> DataLength < sizeof (DWORD)) goto END;
// save result value
result = *((DWORD*) buff -> Data);
END:
// close keyif (hkey) ZwClose (hkey);
// cleanupif (keypath) sfreeu (keypath, TRUE);
if (valuename) sfreeu (valuename, TRUE);
if (data) pfree (&data);
return result;
}
//
// returns length in bytes of Unicode string
//
USHORT slenu (PUNICODE_STRING pustr)
{
if (pustr == NULL) return 0;
return pustr -> Length;
}
//
// returns length in bytes of string
//
ULONG slen (char* string)
{
ULONG ul = 0;
if (! string) return 0;
while (string [ul ++] != 0);
return (-- ul);
}
ULONG stoi (char* pString, ULONG base)
{
PUNICODE_STRING pus = NULL;
ULONG r = 0;
NTSTATUS status = STATUS_UNSUCCESSFUL;
pus = atou (pString);
if (! pus) goto END;
status = RtlUnicodeStringToInteger (pus, base, &r);
if (! NT_SUCCESS (status)) r = 0;
END:
if (pus) sfreeu (pus, TRUE);
return r;
}
//
// returns string equivalent of
// specified ULONG with specified base
//char* itos (ULONG ul, ULONG base)
{
WCHAR ubuff [50];
UNICODE_STRING ustr;
NTSTATUS status = STATUS_UNSUCCESSFUL;
char* r = NULL;
ustr.Length = 0;
ustr.MaximumLength = 49;
ustr.Buffer = ubuff;
status = RtlIntegerToUnicodeString (ul, base, &ustr);
if (NT_SUCCESS (status))
{
r = utoa (&ustr);
}
return r;
}
//
// initializes Unicode string with specified Unicode buffer
// and sets specified length for Unicode string
//
PUNICODE_STRING sinitu (PUNICODE_STRING pustr, PWCHAR string, USHORT length)
{
if (pustr == NULL) return NULL;
if (string == NULL) return NULL;
__try
{
pustr -> Buffer = string;
pustr -> Length = length;
pustr -> MaximumLength = pustr -> Length;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return NULL;
}
return pustr;
}
//
// copies all WCHARs from Unicode buffer
// to buffer of Unicode string (destination
// buffer must be allocated before call of
// this function);
// 'length' in bytes
//
PUNICODE_STRING scopyu (PUNICODE_STRING pustr, PWCHAR string, USHORT length)
{
if (pustr == NULL) return NULL;
if (pustr -> Buffer == NULL) return NULL;
if (string == NULL) return NULL;
if (length % sizeof (WCHAR) != 0) length --;
if (length == 0) return NULL;
__try
{
mcopy ((BYTE *) pustr -> Buffer, (BYTE*) string, length);
pustr -> Length = length;
pustr -> MaximumLength = pustr -> Length;
pustr -> Buffer [length / sizeof (WCHAR)] = 0;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return NULL;
}
return pustr;
}
pstro->pwszOrg — это я понимаю указатель на строку WCHAR, оканчивающуюся null-ом?
и вероятно вы хотите вывести эту строку в окно дебагера?
попробуйте выводить так:
if ((pstro!=NULL)&&(pstro->pwszOrg!=NULL))
DbgPrint("string=%S\n",pstro->pwszOrg);
кроме того вы неправильно пытались инициализировать строку ANSI: L> PCSZ s; L> PANSI_STRING str=NULL; L> RtlInitAnsiString(str,s);
у вас "s" — должен быть указателем на реальную строку, а у вас эта переменная даже не инициализирована!
Бывает.
Мне кстати тут недавно кто-то сказал о том, что мы, обладающие знаниями люди, должны быть внимательны, когда даём кому-то советы или вообще пишем ответ, ибо так можно надолго ввести спрашивающего в заблуждение. И правильно сказал. Присоединяйся!
Вынужден вас (всех) огорчить, ни один из приведенных тут вариантов (пожалуй, кроме форматирования с S) ни к чему не приведет. Причина банальна — драйвер экрана может экспортировать напрямую (не через прокси библиотеку) только функции из win32k.sys. Надо использовать EngUnicodeToMultiByteN. И всего то... А вообще, зачем преобразовывать именно в драйвере, мне немного непонятно. Ну да это проблемы автора...
L>Как только добавляешь эти Rtl-функции,вообще ничего на экран не выводиться(всмысле в дебагер)
Правильно, ведь драйвер не загружается. Причину я описал в сообщении ниже по ветке.
L>В чём может быть причина?Это мой первый драйвер,поэтому я ума не приложу,в чём проблема.
Проблема в том, что надо читать внимательно документацию, там описано, какие функции и где можно использовать...
В общем, удачи. Она точно понадобится
AS>Вынужден вас (всех) огорчить, ни один из приведенных тут вариантов (пожалуй, кроме форматирования с S) ни к чему не приведет. Причина банальна — драйвер экрана может экспортировать напрямую (не через прокси библиотеку) только функции из win32k.sys. Надо использовать EngUnicodeToMultiByteN. И всего то... А вообще, зачем преобразовывать именно в драйвере, мне немного непонятно. Ну да это проблемы автора...
во первых: не экспортировать , а импортировать наверно
а потом чем этот драйвер такой особенный, что не сможет вызвать другие фукнции ядра???
ну если и не напрямую, адрес можно легко узнать, прототип функции известен... проблемы не вижу...
AS>>Вынужден вас (всех) огорчить, ни один из приведенных тут вариантов (пожалуй, кроме форматирования с S) ни к чему не приведет. Причина банальна — драйвер экрана может экспортировать напрямую (не через прокси библиотеку) только функции из win32k.sys. Надо использовать EngUnicodeToMultiByteN. И всего то... А вообще, зачем преобразовывать именно в драйвере, мне немного непонятно. Ну да это проблемы автора...
_>во первых: не экспортировать , а импортировать наверно
Да, импортировать. Впрочем, и экспортировать тоже, раз не может импортировать. В общем, в PE дисплей драйвера (но не модулей, которые он использует, и многие этим пользуются для удобного общения с экзекутивом, а зря) не должно быть никаких референсов на модули, отличные от win32k.sys.
_>а потом чем этот драйвер такой особенный, что не сможет вызвать другие фукнции ядра???
Читайте DDK. Там все сказано, что, почему и как. Можно начать с http://msdn2.microsoft.com/en-us/library/ms801048.aspx (или поискать в группо-гугле display driver import ntoskrnl — там сразу первые ссылки ровно то, что вас интересует). А в ДДК там как раз картинка, где показано, что с чем может взаимодействовать. Конечно, как обычно, явно выудить из ДДК что-либо сложно, там все больше намеками, но если прочитать все и несколько раз... В общем, удачи Хотя, откровенно говоря, я бы сейчас уже не стал — в виста все перевернуто с ног на голову. В смысле, драйвера экрана опять стали жить там, где им и дОлжно быть — в юзер моде. Вернулись к архитектуре вин95
_>ну если и не напрямую, адрес можно легко узнать, прототип функции известен... проблемы не вижу...
А я вижу. Основная проблема в том, что дисплей драйвер _не_ должен вызывать эти функции ввиду своей ахитектуры. С экзекутивом общается минипорт.
А адрес узнать не совсем легко. Ну и еще остаются вопросы, связанны с тем, что дисплей драйвер, как и win32k.sys живут в отдельном пространстве сессии и выделяют память из нее же... Хотя, конечно, простейшие функции типа установки события вызывать можно (если посмотреть их реализацию в win32k.sys часто это просто переходники к KeXxxx). В общем, драйверы экрана это совсем не WDM и лезть в них "своими грязными руками" прямо вот так с налета не надо
имхо, вообще начинать изучение устройство ядра Windows сразу с драйвера экрана — не совсем правильно... надо изучить какие-то основы... и хотя бы для начала пользоваться правильно функциями RtlXXX для работы со строками...
вот.
Re[6]: DDK,mirror driver,unicod to ansi
От:
Аноним
Дата:
10.05.07 05:53
Оценка:
TC>Не пора ли выйти из сумрака?
LOL TarasCo, я вас обожаю!
А серьёзно — пока рановато, поверьте на слово. Но когда это произойдёт, вы — первым узнаете об этом