Q&A

  • processid로 handle 얻는 방법 있나요?
아래 소스는 폴더공유취약성 팻치를 위한 것입니다.
하이퍼링크로 익스플로러가 뜨고, 다운로드창에서 '열기'를 누르면,
팻치작업이 진행되고(익스플로러process종료 및 subprocess생성)
팻치작업이 종료되었을 때(팻치완료여부를 registry를 읽어 판단)
팻치업데이트 버튼 숨기기 등을 할려 합니다.

문제는 아래 소스에서 익스플로러가 종료하고 나서 process list전체를 다시
가져와 for문으로 비교하여 익스플로서 PID와 익스플로러가 생성한 subprocess의 parentPID가 같은 것이 있으면, 없을 때까지 반복해서 process list를 다시 가져와 다시 비교하고 하는 순환처리를 할려고 하는데...

익스플로러의 subprocess가 생기기도 전에 다음 문장(processid가져오기, for순화 비교)이 실행되어 버리는 것 같습니다.

그래서 아래 RSUME: 레이블 위 위치에 타임딜레이를 둬야 하나요?
아니면, processid로 handle를 얻어 WaitForSingleObject함수로
subprocess가 종료되는 시점을 잡아야 할까요?

이것만 해결하면 코딩이 끝나는데, 미궁을 헤매는 기분입니다.
도움바랍니다.


procedure TFormMain.PanelPatchClick(Sender: TObject);
var
   reg       : TRegistry;
   PathCommd : String;
   StartInfo : TStartupInfo;
   ProcsInfo : TProcessInformation;
   CommdLine : String;
   Result    : Boolean;

   Process32 : TProcessEntry32;
   SHandle   : THandle;  // the handle of the Windows object
   isNext    : BOOLEAN;
   ProcessID : array of DWORD;
   ParentPID : array of DWORD;
   i, j, epi : Integer;

label RESUME;
begin
   FormMain.FormStyle := fsNormal;

   reg := Tregistry.Create;
   reg.RootKey := HKEY_LOCAL_MACHINE;
   if reg.openkey('SoftwareMicrosoftWindowsCurrentVersionApp PathsIExplore.exe', FALSE) then
      PathCommd := reg.readstring('');  // (기본값) 읽기
   reg.CloseKey;
   reg.Free;

   case GetOS of
      os98, os98SE :
         CommdLine := PathCommd + ' http://download.microsoft.com/download/win98SE/Update/11958/W98/EN-US/273991USA8.EXE';
      osME         :
         CommdLine := PathCommd + ' http://download.microsoft.com/download/winme/Update/11958/WinMe/EN-US/273991USAM.EXE';
   end;

   FillChar(StartInfo, SizeOf(StartInfo), #0);
   with StartInfo do
   begin
      cb          := SizeOf(StartInfo);
      dwFlags     := STARTF_USESHOWWINDOW;
      wShowWindow := SW_SHOW;
   end;
   // "IExplore.exe" process가 생성된다.
   Result := CreateProcess(nil, PChar(CommdLine), nil, nil, FALSE,
                          CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
                          nil, StartInfo, ProcsInfo);

   // 일단, "IExplore.exe" processID까지를 배열에 저장한다.
   Process32.dwSize := SizeOf(TProcessEntry32);
   SHandle          := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   SetLength(ProcessID, 100);
   SetLength(ParentPID, 100);
   if Process32First(SHandle, Process32) then
   begin
      i := 0;
      ProcessID[i] := Process32.th32ProcessID;
      repeat
         i      := i + 1;
         isNext := Process32Next(SHandle, Process32);
         if isNext then
            ProcessID[i] := Process32.th32ProcessID;
      until not isNext;
   end;
   epi := i - 1;  // Iexplore.exe processID의 배열 저장 위치index

   if Result then
      WaitForSingleObject(ProcsInfo.hProcess, INFINITE);  // "IExplore.exe" process가 종료할 때까지 기다린다.

   CloseHandle(ProcsInfo.hThread);  // hThread  핸들을 해제한다.
   CloseHandle(ProcsInfo.hProcess); // hProcess 핸들을 해제한다

//ShowMessage('ihfo;asj');

RESUME :
   // "IExplore.exe" subprocess를 만들었다면, 그 parentPID까지를 배열에 저장한다.
   if Process32First(SHandle, Process32) then
   begin
      j := 0;
      ParentPID[j] := Process32.th32ParentProcessID;
      repeat
         j      := j + 1;
         isNext := Process32Next(SHandle, Process32);
         if isNext then
            ParentPID[j] := Process32.th32ParentProcessID;
      until not isNext;
   end;

   // "IExplore.exe" process가 만든 subprocess가 있으면, 그 subprocess가 없어질 때가지 반복한다.
   for i := 0 to j do
      if ProcessID[epi] = ParentPID[i] then
         Goto RESUME;

/////// 위에서 팻치하는 subprocess가 없어질 때까지 미친듯이 순환해야 하는데, 왜 아래로 흘러가 버리죠???????????????????????????

   CloseHandle(SHandle);  // closes an open object handle

   FormMain.FormStyle := fsStayOnTop;

   // 이 부분에서 공유팻치가 성공적을 이루어 졌으면 다음 작업을 하고자 함
  
end;
0  COMMENTS