Почему дескриптор удалённого потока не отображается при перечислении потоков процеса?
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
LibPathLen: DWORD;
begin
LibPathLen := Length(NewDllPath)*2;
HProcess := OpenProcess(PROCESS_ALL_ACCESS, TRUE, PId);
RemotePMem := VirtualAllocEx(HProcess, 0, LibPathLen, MEM_COMMIT, PAGE_READWRITE);
StartAddress := GetProcAddress(GetModuleHandle('kernel32.dll'), PAnsiChar('LoadLibraryW'));
WriteProcessMemory(HProcess, RemotePMem, PWideChar(NewDllPath), LibPathLen, RealWrite);
HThread := CreateRemoteThread(HProcess, 0, 0, StartAddress, RemotePMem, 0, MyTId);
Edit4.Text := IntToStr(MyTId);
end;
var
LibPathLen: DWORD;
begin
LibPathLen := Length(NewDllPath)*2;
HProcess := OpenProcess(PROCESS_ALL_ACCESS, TRUE, PId);
RemotePMem := VirtualAllocEx(HProcess, 0, LibPathLen, MEM_COMMIT, PAGE_READWRITE);
StartAddress := GetProcAddress(GetModuleHandle('kernel32.dll'), PAnsiChar('LoadLibraryW'));
WriteProcessMemory(HProcess, RemotePMem, PWideChar(NewDllPath), LibPathLen, RealWrite);
HThread := CreateRemoteThread(HProcess, 0, 0, StartAddress, RemotePMem, 0, MyTId);
Edit4.Text := IntToStr(MyTId);
end;
Вижу только в поле редактирования куда вывожу его при создании удалённого потока
Вот так я перечисляю дескрипторы потоков в процессе:
Код:
procedure TForm1.Timer2Timer(Sender: TObject);
var
SnapHandle: CARDINAL;
ThreadEntry: ThreadEntry32;
NumThreads: BYTE;
NextProc: BOOL;
begin
Memo1.Clear;
NumThreads := 0;
SnapHandle := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, PId);
ThreadEntry.dwSize := SizeOf(ThreadEntry);
NextProc := Thread32First(SnapHandle, ThreadEntry);//получаем первый поток
while NextProc do
begin
if ThreadEntry.th32OwnerProcessID = PID then //проверка на принадлежность к процессу
begin
NumThreads := NumThreads + 1;
Memo1.Lines.Add(IntToStr(ThreadEntry.th32ThreadID));
end;
NextProc := Thread32Next(SnapHandle, ThreadEntry); //получаем следующий поток
end;
CloseHandle(SnapHandle); //освобождаем хендл
Edit3.Text := IntToStr(NumThreads);
end;
var
SnapHandle: CARDINAL;
ThreadEntry: ThreadEntry32;
NumThreads: BYTE;
NextProc: BOOL;
begin
Memo1.Clear;
NumThreads := 0;
SnapHandle := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, PId);
ThreadEntry.dwSize := SizeOf(ThreadEntry);
NextProc := Thread32First(SnapHandle, ThreadEntry);//получаем первый поток
while NextProc do
begin
if ThreadEntry.th32OwnerProcessID = PID then //проверка на принадлежность к процессу
begin
NumThreads := NumThreads + 1;
Memo1.Lines.Add(IntToStr(ThreadEntry.th32ThreadID));
end;
NextProc := Thread32Next(SnapHandle, ThreadEntry); //получаем следующий поток
end;
CloseHandle(SnapHandle); //освобождаем хендл
Edit3.Text := IntToStr(NumThreads);
end;
Длл которую я загружаю ничего не делает, т.е у неё пусто между бегин и енд.
Может ли быть такое что поток уничтожается, если ему нечего делать, а у меня остаются в переменных его дескриптор и хендл(уже никому не нужные)? Или поток должен быть завершён явно?
Количество потоков я получаю верное. проверенно всякими прогами которые способны выводить информацию о процессах, ну например: ArtMoney, Procmon, API Monitor ну и еще другие которые дают понять что происходит в процессе.
Когда срабатывыает мой код который создаёт удалённый поток то проги про которые я писал выше показывают что моя длл загруженна в адресное пространство "жертвы".
СreateToolhelp32Snapshot показывает потоки, кучу и загр. модули текущего процесса, но не чужого. (Takes a snapshot of the specified processes, as well as the heaps, modules, and threads used by these processes.)
Сорри ошибся в переводе. СreateToolhelp32Snapshot работает для указанного pID. Если не кажет может быть указаны разные pid`ы?
Цитата: drfaust
Сорри ошибся в переводе. СreateToolhelp32Snapshot работает для указанного pID. Если не кажет может быть указаны разные pid`ы?
Да читая эти мануалы при помощи переводчиков не сложно ошибиться. Иногда очень трудно уловить смысл описываемого параметра. Плюс ко всему описания не очень подробные И если не знаешь конкретно нормальное поведение функции то бывает очень сложно бороться с багами
Насчёт разных пидов очень сомневаюсь.
Во первых у меня во всей программе одна глобальная переменная PId.
Во вторых почему тот же самый код перечисляет остальные потоки кроме моего верно, и длл грузится куда надо
Цитата: QWERYTY
[..
Во первых у меня во всей программе одна глобальная переменная PId....
Во первых у меня во всей программе одна глобальная переменная PId....
И всё-таки стоит проверить (запись в stderr значений pid и просмотр отладчиком), и пусть они будут одинаковыми. Тогда легче искать траблу будет.
Изначально была задача перехватывать кое какие события в одной програмке. С начала я ставил хук на создание окна этой программой, но там был баг с которым не смог справиться. Когда дочернее окно порождало диалог с классом #32770 то прога "жертва" зависала.
Теперь пытаюсь перехватывать вызов CreateWindowExA из user32.dll.
Нижняя часть кода по сути не очень важна, это я хотел видеть(не залазя в разные проги) что после нажатия кнопки стало например не 7 потоков а 8
на С/С++ просто:
cerr<<"PID: "<<Pid;
или
fprintf(stderr,"PID: %li",PiD);
Просмотр - это в самой
З.Ы. Сорри, Ентер случайно нажал.
Дело в том что первое что пришло в голову поймать созданный мной поток. Для этого был модифицирован код в таймере:
NextProc := Thread32First(SnapHandle, ThreadEntry); //получаем первый поток
while NextProc do
begin
if ThreadEntry.th32OwnerProcessID = PID then //проверка на принадлежность к процессу
begin
if MyTId = ThreadEntry.th32ThreadID then ShowMessage('Попался поток, СУЧАРА!'); // MyTId тоже глобальная и после создания не меняется
NumThreads := NumThreads + 1;
Memo1.Lines.Add(IntToStr(ThreadEntry.th32ThreadID));
end;
И срабатывание таймера было установленно в 1/1000 секунды.
Начало появляться сообщение, но после нажатия ОК оно не появляется. Таймер продолжает работать, я вижу как мигает мемо.
Похоже что поток завершается, а вот по чему и нужно разобраться
Спасибо заранее..
когда завершается функция потока завершается и сам поток, если хочешь его поймать в теле функции напиши sleep или цикл какой то. не хочу много писать, так что скажу об очень хорошей книге, где это хорошо описывается "windows via c/c++", не смотри на то что написано си, там описывается сама система просто примеры на сях. там есть главы посвященные процессам и потокам. у меня сейчас на руках издание 2009 года, там на странице 176 раздел Завершение потока, где описывается как и почему. если не ясно что то конкретно, пиши суда.
И поток я уже поймал.
Я не писал ничего в функции потока, а просто применил сразу после создания потока функцию SuspendThread.
А потом по нажатию кнопки ResumeThread, и вот тогда он исчезал.
Всем спасибо кто отозвался.
Отвязка от CRT делается элементарно(если нет зависимости от неё).Я тоже читал и,на удивление,без проблем сделал ☺