Разбор небольшого бага.
Есть немного кода:
{
HANDLE hProcess=NULL;
PROCESS_BASIC_INFORMATION pbi;
PEB peb;
DWORD dwBytesRead;
NtQueryInformationProcess* NtQ=NULL;
...
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ,false,p->id);
if(!hProcess) ret=1;
else
{
HMODULE hLibrary = GetModuleHandle(L"ntdll.dll");
if(!hLibrary) ret=1;
else
{
NtQ=(NtQueryInformationProcess*)GetProcAddress(hLibrary,"NtQueryInformationProcess");
if (!NtQ) ret=1;
else
{
(*NtQ)(hProcess,ProcessBasicInformation, &pbi, sizeof(pbi), &dwBytesRead);
FreeLibrary(hLibrary);
}
if(pbi.PebBaseAddress)
{
ret=1;
if(ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), &dwBytesRead))
...
Вот в ReadProcessMemory как раз трабл. Все переменные передаются валидные, но после его вызова получаю ошибку невозможности записи по адресу FFFFFFFF. Такая ошибка была только в релиз шаред версии, ни в статик релиз, ни в дебаг ее не было.
Полез в отладчик, перед входом в функцию в стек кладутся валидные значения.
0022C9F4 0000049C |hProcess = 0000049C
0022C9F8 7FFDE000 |pBaseAddress = 7FFDE000
0022C9FC 0022CA00 |Buffer = 0022CA00
0022CA00 000001D8 |BytesToRead = 1D8 (472.)
[COLOR="plum"]0022CA04 0022CC3C \pBytesRead = 0022CC3C[/COLOR]
Дальше - глубже. А это стэк после вызова ZwReadVirtualMemory:
0022C9F4 |0000049C
0022C9F8 |7FFDE000
0022C9FC |0022CA00
0022CA00 |000001D8
[COLOR="plum"]0022CA04 |FFFFFFFF[/COLOR]
Последний адрес - это ни что иное, как &dwBytesRead. Поменял в отладчике значение адреса после переноса в регистр и все заработало. Потом в этой функции ReadProcessMemory вызывается еще несколько раз, но адрес в стэке уже не меняется. Как лечить такие штуковины и чья это ошибка - компилятора или библиотеки Windows?
[COLOR="gray"]P.S. С такими траблами, а бы функцию назвал не foo, а fffuuuu :)[/COLOR]
[ATTACH=CONFIG]5222[/ATTACH]
Листинг чего? ZwReadVirtualMemory?
Может я неправильно читаю, но похоже, что указатель на Buffer содержит адрес параметра BytesToRead. Возможно, поэтому он заполняет мусором дальнейшую память. Правда, не понятно, как туда этот адрес попал.
Поставь NULL вместо &dwBytesRead для эксперимента.
Точно, я как-то и не заметил, посмотрел беглым взглядом, что адрес указывает на стэк и забил. Следующий вызов ReadProcessMemory тоже затирает один ret чуть пониже в стэке.
Кладется 0, но все равно затирается.
Хоть данные считываются верные. Получается, ошибка компилятора?
UPD: как оказалось та же самая болезнь и у debug сборки. я-то все думал, почему некоторые строки после ReadProcessMemory с нечитабельными символами. Такого нет только в realease static.
PVOID ProcessInformation,ULONG ProcessInformationLength,PULONG ReturnLength);
Позвольте поинтересоваться, а это тут при чем?
Возможно, ошибка в троеточиях. Тут куча указателей, поэтому возможно, что ты где-то с памятью неаккуратно поработал.
Листинг вашего сишника.
PS: И почему мне кажется, что вся радость кроется в том под какую платформу вы это собираете и чем...
{
HANDLE hProcess=NULL;
WCHAR* cmdLine=NULL;
HANDLE hHeap=NULL;
PROCESS_BASIC_INFORMATION pbi;
PEB peb;
RTL_USER_PROCESS_PARAMETERS peb_upp;
DWORD dwBytesRead;
int ret;
NtQueryInformationProcess* NtQ=NULL;
int e;
hHeap = GetProcessHeap();
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |PROCESS_VM_READ,false,p->id);
if(!hProcess) ret=1;
else
{
HMODULE hLibrary = GetModuleHandle(L"ntdll.dll");
if(!hLibrary) ret=1;
else
{
NtQ=(NtQueryInformationProcess*)GetProcAddress(hLibrary,"NtQueryInformationProcess");
if (!NtQ) ret=1;
else
{
(*NtQ)(hProcess,ProcessBasicInformation, &pbi, sizeof(pbi), &dwBytesRead);
FreeLibrary(hLibrary);
}
if(pbi.PebBaseAddress)
{
ret=1;
if(ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), NULL))
{
e=GetLastError();
dwBytesRead = 0;
if(ReadProcessMemory(hProcess,peb.ProcessParameters,&peb_upp,sizeof(RTL_USER_PROCESS_PARAMETERS),
&dwBytesRead))
{
if(peb_upp.CommandLine.Length > 0)
{
cmdLine = (WCHAR *)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,peb_upp.CommandLine.Length+10);
if(cmdLine)
{
if(ReadProcessMemory(hProcess,peb_upp.CommandLine.Buffer,cmdLine,
peb_upp.CommandLine.Length,&dwBytesRead));
ret=0;
}}}}
if(!ret)
{
p->commandLine.append(QString::fromWCharArray(cmdLine));
}}}}
HeapFree(hHeap,0,cmdLine);
return ret;
}