Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Разбор небольшого бага.

316
12 июля 2011 года
Alm3n
889 / / 29.05.2009
Доброго. Уж не знаю, в какой раздел это нужно было определить. Т.к. для меня это не критично да и просто решил поделиться наблюдениям, разместил тут.
Есть немного кода:
Код:
foo()
{
    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?

9
12 июля 2011 года
Lerkin
3.0K / / 25.03.2003
А GetLastError чего говорит?

[COLOR="gray"]P.S. С такими траблами, а бы функцию назвал не foo, а fffuuuu :)[/COLOR]
316
12 июля 2011 года
Alm3n
889 / / 29.05.2009
До GetLastError никогда не дойдет.
[ATTACH=CONFIG]5222[/ATTACH]
260
12 июля 2011 года
Ramon
1.1K / / 16.08.2003
На крайняк генерируем ассемблерный листинг и наслаждаемсо.
316
12 июля 2011 года
Alm3n
889 / / 29.05.2009
Цитата: Ramon
На крайняк генерируем ассемблерный листинг и наслаждаемсо.


Листинг чего? ZwReadVirtualMemory?

87
12 июля 2011 года
Kogrom
2.7K / / 02.02.2008
Цитата: Alm3n
Полез в отладчик, перед входом в функцию в стек кладутся валидные значения.



Может я неправильно читаю, но похоже, что указатель на Buffer содержит адрес параметра BytesToRead. Возможно, поэтому он заполняет мусором дальнейшую память. Правда, не понятно, как туда этот адрес попал.

Цитата: Alm3n
До GetLastError никогда не дойдет.



Поставь NULL вместо &dwBytesRead для эксперимента.

316
12 июля 2011 года
Alm3n
889 / / 29.05.2009
Цитата: Kogrom
Может я неправильно читаю, но похоже, что указатель на Buffer содержит адрес параметра BytesToRead. Возможно, поэтому он заполняет мусором дальнейшую память. Правда, не понятно, как туда этот адрес попал.


Точно, я как-то и не заметил, посмотрел беглым взглядом, что адрес указывает на стэк и забил. Следующий вызов ReadProcessMemory тоже затирает один ret чуть пониже в стэке.

Цитата:
Поставь NULL вместо &dwBytesRead для эксперимента.


Кладется 0, но все равно затирается.
Хоть данные считываются верные. Получается, ошибка компилятора?
UPD: как оказалось та же самая болезнь и у debug сборки. я-то все думал, почему некоторые строки после ReadProcessMemory с нечитабельными символами. Такого нет только в realease static.

14
12 июля 2011 года
Phodopus
3.3K / / 19.06.2008
NtQueryInformationProcess то как у нас объявлена?
316
12 июля 2011 года
Alm3n
889 / / 29.05.2009
Цитата: Phodopus
NtQueryInformationProcess то как у нас объявлена?


 
Код:
typedef LONG NtQueryInformationProcess (HANDLE ProcessHandle,PROCESSINFOCLASS ProcessInformationClass,
    PVOID ProcessInformation,ULONG ProcessInformationLength,PULONG ReturnLength);

Позвольте поинтересоваться, а это тут при чем?
87
12 июля 2011 года
Kogrom
2.7K / / 02.02.2008
Цитата: Alm3n
Получается, ошибка компилятора?



Возможно, ошибка в троеточиях. Тут куча указателей, поэтому возможно, что ты где-то с памятью неаккуратно поработал.

260
12 июля 2011 года
Ramon
1.1K / / 16.08.2003
Цитата: Alm3n
Листинг чего? ZwReadVirtualMemory?



Листинг вашего сишника.

PS: И почему мне кажется, что вся радость кроется в том под какую платформу вы это собираете и чем...

316
12 июля 2011 года
Alm3n
889 / / 29.05.2009
Полный листинг.
Код:
qint32 proc_list::cmdLine(proc_info *p)
{
    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;
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог