Windows List of running threads in running process

Just starting out? Need help? Post your questions and find answers here.
Mike Yurgalavage
Enthusiast
Enthusiast
Posts: 118
Joined: Thu May 17, 2007 8:35 pm
Location: USA

Windows List of running threads in running process

Post by Mike Yurgalavage »

Is it possible to list the threads running in a program using windows api calls?

For instance, if we gathered the handle to our own program, can we list how many threads are running and where the threads originated (for instance if the thread is from a .dll or from the .exe, etc.) Maybe a list of thread IDs?

Also are there api commands to suspend the thread or resume a thread ID?

best,
Mike
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: Windows List of running threads in running process

Post by RSBasic »

http://www.rsbasic.de/aktualisierung/wi ... mitteln.pb

Code: Select all

Debug "Thread - "+Str(te\th32ThreadID)
Image
Image
User avatar
CELTIC88
Enthusiast
Enthusiast
Posts: 154
Joined: Thu Sep 17, 2015 3:39 pm

Re: Windows List of running threads in running process

Post by CELTIC88 »

origin post :
http://www.purebasic.fr/french/viewtopi ... =6&t=16811

... and you can also detect runpe and shellcode

Code: Select all

;By celtic88@ h (c) 2016 new up 2017 
;For other any use say my name :) !

EnableExplicit

Import "kernel32.lib"
  OpenThread.l(dwDesiredAccess.l,
               bInheritHandle.l,
               dwThreadId.l )
EndImport

Import ""
  GetSystemInfo(ps)
EndImport

OpenLibrary(0, "Psapi.dll")
Prototype.l GetModuleFileNameExW(hProcess,
                                 hModule,
                                 *lpFilename,
                                 nSize.l)
Global GetModuleFileNameEx.GetModuleFileNameExW=GetFunction(0,"GetModuleFileNameExW")

Structure Authorized_Address ;List Of authorized address created by process
  AddressStart.l
  AddressEnd.l
  Filename.s
EndStructure

Procedure Process_Adjust_Token_Privileges(); Adjust Token Privileges
  Protected priv.TOKEN_PRIVILEGES ,hToken .i,iReturn
  If( OpenProcessToken_( GetCurrentProcess_(), #TOKEN_ADJUST_PRIVILEGES | #TOKEN_QUERY, @hToken ) )
    priv\PrivilegeCount           = 1;
    priv\Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED;
    If( LookupPrivilegeValue_( #Null, #SE_DEBUG_NAME, @priv\Privileges[0]\Luid ) )
      iReturn=AdjustTokenPrivileges_( hToken, #False, @priv, 0, #Null, #Null );
      CloseHandle_( hToken )                                                  ;
    EndIf
  EndIf
  ProcedureReturn iReturn
EndProcedure

Procedure Get_All_authorized_address_ByProcess(Pid, List Address.Authorized_Address())
  ClearList(Address())
  Protected hProcess,tIMAGE_DOS_HEADER.IMAGE_DOS_HEADER,tIMAGE_NT_HEADERS.IMAGE_NT_HEADERS,
            hs, lpme.MODULEENTRY32,Nsize,i,lpImageBaseAddress,filename.s{#MAX_PATH}
  
  hProcess = OpenProcess_( #PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, #False, Pid );
  If hProcess
    GetModuleFileNameEx(hProcess,0, @filename, #MAX_PATH)
    CloseHandle_(hProcess)
  EndIf
  
  hs=CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE, Pid)
  If hs <> #INVALID_HANDLE_VALUE
    lpme.MODULEENTRY32\dwSize=SizeOf(MODULEENTRY32)
    If Module32First_(hs,@lpme)
      Repeat ; get all address created by loaded dll :)
        If UCase(PeekS(@lpme\szExePath))=UCase(filename)
          lpImageBaseAddress =lpme\modBaseAddr
        Else
          AddElement(Address())
          Address()\Filename = PeekS(@lpme\szExePath)
          Address()\AddressStart= (lpme\modBaseAddr)   
          Address()\AddressEnd =(lpme\modBaseAddr+lpme\modBaseSize)
        EndIf
      Until Module32Next_(hs,@lpme)=0
    EndIf
    CloseHandle_(hs)
  EndIf
  
  If ReadFile(0, FileName)
    ReadData(0,@tIMAGE_DOS_HEADER,SizeOf(IMAGE_DOS_HEADER))
    FileSeek(0,tIMAGE_DOS_HEADER\e_lfanew)
    ReadData(0,@tIMAGE_NT_HEADERS,SizeOf(IMAGE_NT_HEADERS))
    
    Protected tIMAGE_SECTION_HEADER.IMAGE_SECTION_HEADER
    #IMAGE_SCN_CNT_CODE=$00000020
    
    For i=0 To (tIMAGE_NT_HEADERS\FileHeader\NumberOfSections-1);get all pe sections
      FileSeek(0,tIMAGE_DOS_HEADER\e_lfanew+SizeOf(IMAGE_NT_HEADERS)+ (SizeOf(IMAGE_SECTION_HEADER)*i))
      If ReadData(0,@tIMAGE_SECTION_HEADER, SizeOf(IMAGE_SECTION_HEADER))
        With tIMAGE_SECTION_HEADER
          If \Characteristics & #IMAGE_SCN_CNT_CODE; Get original process work code address
            AddElement(Address())
            Address()\Filename = "<Pb Process>"
            Address()\AddressStart= (lpImageBaseAddress+\VirtualAddress)   
            Address()\AddressEnd= (lpImageBaseAddress+\VirtualAddress+\VirtualSize)
          EndIf
        EndWith
      EndIf
    Next    
    CloseFile(0)
  EndIf
  
EndProcedure

Procedure Scan_Process( Pid)
  
  If Pid=0
    Pid=GetCurrentProcessId_()
  EndIf
  
  NewList aAddress.Authorized_Address()
  Get_All_authorized_address_ByProcess(Pid, aAddress());Get authorized address
  
  #ThreadQuerySetWin32StartAddress=9
  Protected hs=CreateToolhelp32Snapshot_(#TH32CS_SNAPTHREAD,0);Get process all THREAD 
  If hs <> #INVALID_HANDLE_VALUE
    Protected lpte.THREADENTRY32\dwSize=SizeOf(THREADENTRY32)
    Protected Tsa.i
    If Thread32First_(hs,@lpte)
      Repeat 
        If lpte\th32OwnerProcessID = Pid
          Protected ht=OpenThread(#THREAD_ALL_ACCESS,0,lpte\th32ThreadID)
          If ht
            If NtQueryInformationThread_(ht,#ThreadQuerySetWin32StartAddress,@Tsa,SizeOf(integer),0)=0;Get thread Start address
              Protected Shellcodeinrun=1
              ForEach aAddress()
                If (Tsa) >= aAddress()\AddressStart And (Tsa) < aAddress()\AddressEnd ;If the thread start address is between authorised address => Ok is Clean
                  Debug "File name : " + aAddress()\Filename
                  Debug "ThreadID : " + lpte\th32ThreadID
                  Shellcodeinrun=0
                  Break
                EndIf
              Next
              If Shellcodeinrun=1  ;Else :)
                AddGadgetItem(4, -1,"..a suspect code is on running at address 0x"+ Hex(Tsa))
              EndIf
            EndIf
            CloseHandle_(ht)
          EndIf
        EndIf
      Until Thread32Next_(hs,@lpte)=0
    EndIf
    CloseHandle_(hs)
  EndIf
  
  Protected ps.SYSTEM_INFO
  GetSystemInfo(@ps)
  
  Protected hProcess = OpenProcess_( #PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, #False, Pid );Scan process memory
  If hProcess
    With ps
      Protected  lpMinimumApplicationAddress=\lpMinimumApplicationAddress
      Protected lpMaximumApplicationAddress=\lpMaximumApplicationAddress
      Protected mem_basic_info.MEMORY_BASIC_INFORMATION 
      While lpMinimumApplicationAddress < lpMaximumApplicationAddress
        If VirtualQueryEx_(hProcess, lpMinimumApplicationAddress, @mem_basic_info, SizeOf(MEMORY_BASIC_INFORMATION))
          If mem_basic_info\Protect = #PAGE_EXECUTE Or mem_basic_info\Protect = #PAGE_EXECUTE_READ Or mem_basic_info\Protect = #PAGE_EXECUTE_READWRITE Or mem_basic_info\Protect = #PAGE_EXECUTE_WRITECOPY
            Tsa=(mem_basic_info\BaseAddress)
            Shellcodeinrun=1
            ForEach aAddress()
              If (Tsa) >= aAddress()\AddressStart And (Tsa) < aAddress()\AddressEnd ;If the address of code is between authorised address => Ok is Clean
                Shellcodeinrun=0
                Break
              EndIf
            Next
            If Shellcodeinrun=1  ;Else :)
              AddGadgetItem(4, -1,"..a suspect executable code detected at address 0x"+ Hex(Tsa))
            EndIf
          EndIf
        EndIf
        lpMinimumApplicationAddress+mem_basic_info\RegionSize
      Wend
    EndWith
    CloseHandle_(hProcess)
  EndIf
EndProcedure

If Process_Adjust_Token_Privileges() <> 1
  Debug "Error set Process Privileges"
  End
EndIf

OpenWindow(0, 0, 0, 300, 190, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_WindowCentered)
ButtonGadget(1, 220, 10, 70, 25, "Scan")
StringGadget(2, 80, 10, 130, 25, "", #PB_String_Numeric)
TextGadget(3, 10, 10, 70, 25, "Process Pid")
EditorGadget(4, 0, 40, 300, 150, #PB_Editor_ReadOnly)

Define Event
Repeat
  Event = WaitWindowEvent()
  
  Select Event
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1 
          Scan_Process(Val(GetGadgetText(2)))
      EndSelect
      
  EndSelect
Until Event = #PB_Event_CloseWindow
interested in Cybersecurity..
Mike Yurgalavage
Enthusiast
Enthusiast
Posts: 118
Joined: Thu May 17, 2007 8:35 pm
Location: USA

Re: Windows List of running threads in running process

Post by Mike Yurgalavage »

RSBasic wrote:http://www.rsbasic.de/aktualisierung/wi ... mitteln.pb

Code: Select all

Debug "Thread - "+Str(te\th32ThreadID)
Thanks for the code tips. I'll check it out and see what I can do with it!
Mike Yurgalavage
Enthusiast
Enthusiast
Posts: 118
Joined: Thu May 17, 2007 8:35 pm
Location: USA

Re: Windows List of running threads in running process

Post by Mike Yurgalavage »

CELTIC88 wrote:origin post :
http://www.purebasic.fr/french/viewtopi ... =6&t=16811

... and you can also detect runpe and shellcode

Code: Select all

;By celtic88@ h (c) 2016 new up 2017 
;For other any use say my name :) !

EnableExplicit

Import "kernel32.lib"
  OpenThread.l(dwDesiredAccess.l,
               bInheritHandle.l,
               dwThreadId.l )
EndImport

Import ""
  GetSystemInfo(ps)
EndImport

OpenLibrary(0, "Psapi.dll")
Prototype.l GetModuleFileNameExW(hProcess,
                                 hModule,
                                 *lpFilename,
                                 nSize.l)
Global GetModuleFileNameEx.GetModuleFileNameExW=GetFunction(0,"GetModuleFileNameExW")

Structure Authorized_Address ;List Of authorized address created by process
  AddressStart.l
  AddressEnd.l
  Filename.s
EndStructure

Procedure Process_Adjust_Token_Privileges(); Adjust Token Privileges
  Protected priv.TOKEN_PRIVILEGES ,hToken .i,iReturn
  If( OpenProcessToken_( GetCurrentProcess_(), #TOKEN_ADJUST_PRIVILEGES | #TOKEN_QUERY, @hToken ) )
    priv\PrivilegeCount           = 1;
    priv\Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED;
    If( LookupPrivilegeValue_( #Null, #SE_DEBUG_NAME, @priv\Privileges[0]\Luid ) )
      iReturn=AdjustTokenPrivileges_( hToken, #False, @priv, 0, #Null, #Null );
      CloseHandle_( hToken )                                                  ;
    EndIf
  EndIf
  ProcedureReturn iReturn
EndProcedure

Procedure Get_All_authorized_address_ByProcess(Pid, List Address.Authorized_Address())
  ClearList(Address())
  Protected hProcess,tIMAGE_DOS_HEADER.IMAGE_DOS_HEADER,tIMAGE_NT_HEADERS.IMAGE_NT_HEADERS,
            hs, lpme.MODULEENTRY32,Nsize,i,lpImageBaseAddress,filename.s{#MAX_PATH}
  
  hProcess = OpenProcess_( #PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, #False, Pid );
  If hProcess
    GetModuleFileNameEx(hProcess,0, @filename, #MAX_PATH)
    CloseHandle_(hProcess)
  EndIf
  
  hs=CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE, Pid)
  If hs <> #INVALID_HANDLE_VALUE
    lpme.MODULEENTRY32\dwSize=SizeOf(MODULEENTRY32)
    If Module32First_(hs,@lpme)
      Repeat ; get all address created by loaded dll :)
        If UCase(PeekS(@lpme\szExePath))=UCase(filename)
          lpImageBaseAddress =lpme\modBaseAddr
        Else
          AddElement(Address())
          Address()\Filename = PeekS(@lpme\szExePath)
          Address()\AddressStart= (lpme\modBaseAddr)   
          Address()\AddressEnd =(lpme\modBaseAddr+lpme\modBaseSize)
        EndIf
      Until Module32Next_(hs,@lpme)=0
    EndIf
    CloseHandle_(hs)
  EndIf
  
  If ReadFile(0, FileName)
    ReadData(0,@tIMAGE_DOS_HEADER,SizeOf(IMAGE_DOS_HEADER))
    FileSeek(0,tIMAGE_DOS_HEADER\e_lfanew)
    ReadData(0,@tIMAGE_NT_HEADERS,SizeOf(IMAGE_NT_HEADERS))
    
    Protected tIMAGE_SECTION_HEADER.IMAGE_SECTION_HEADER
    #IMAGE_SCN_CNT_CODE=$00000020
    
    For i=0 To (tIMAGE_NT_HEADERS\FileHeader\NumberOfSections-1);get all pe sections
      FileSeek(0,tIMAGE_DOS_HEADER\e_lfanew+SizeOf(IMAGE_NT_HEADERS)+ (SizeOf(IMAGE_SECTION_HEADER)*i))
      If ReadData(0,@tIMAGE_SECTION_HEADER, SizeOf(IMAGE_SECTION_HEADER))
        With tIMAGE_SECTION_HEADER
          If \Characteristics & #IMAGE_SCN_CNT_CODE; Get original process work code address
            AddElement(Address())
            Address()\Filename = "<Pb Process>"
            Address()\AddressStart= (lpImageBaseAddress+\VirtualAddress)   
            Address()\AddressEnd= (lpImageBaseAddress+\VirtualAddress+\VirtualSize)
          EndIf
        EndWith
      EndIf
    Next    
    CloseFile(0)
  EndIf
  
EndProcedure

Procedure Scan_Process( Pid)
  
  If Pid=0
    Pid=GetCurrentProcessId_()
  EndIf
  
  NewList aAddress.Authorized_Address()
  Get_All_authorized_address_ByProcess(Pid, aAddress());Get authorized address
  
  #ThreadQuerySetWin32StartAddress=9
  Protected hs=CreateToolhelp32Snapshot_(#TH32CS_SNAPTHREAD,0);Get process all THREAD 
  If hs <> #INVALID_HANDLE_VALUE
    Protected lpte.THREADENTRY32\dwSize=SizeOf(THREADENTRY32)
    Protected Tsa.i
    If Thread32First_(hs,@lpte)
      Repeat 
        If lpte\th32OwnerProcessID = Pid
          Protected ht=OpenThread(#THREAD_ALL_ACCESS,0,lpte\th32ThreadID)
          If ht
            If NtQueryInformationThread_(ht,#ThreadQuerySetWin32StartAddress,@Tsa,SizeOf(integer),0)=0;Get thread Start address
              Protected Shellcodeinrun=1
              ForEach aAddress()
                If (Tsa) >= aAddress()\AddressStart And (Tsa) < aAddress()\AddressEnd ;If the thread start address is between authorised address => Ok is Clean
                  Debug "File name : " + aAddress()\Filename
                  Debug "ThreadID : " + lpte\th32ThreadID
                  Shellcodeinrun=0
                  Break
                EndIf
              Next
              If Shellcodeinrun=1  ;Else :)
                AddGadgetItem(4, -1,"..a suspect code is on running at address 0x"+ Hex(Tsa))
              EndIf
            EndIf
            CloseHandle_(ht)
          EndIf
        EndIf
      Until Thread32Next_(hs,@lpte)=0
    EndIf
    CloseHandle_(hs)
  EndIf
  
  Protected ps.SYSTEM_INFO
  GetSystemInfo(@ps)
  
  Protected hProcess = OpenProcess_( #PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, #False, Pid );Scan process memory
  If hProcess
    With ps
      Protected  lpMinimumApplicationAddress=\lpMinimumApplicationAddress
      Protected lpMaximumApplicationAddress=\lpMaximumApplicationAddress
      Protected mem_basic_info.MEMORY_BASIC_INFORMATION 
      While lpMinimumApplicationAddress < lpMaximumApplicationAddress
        If VirtualQueryEx_(hProcess, lpMinimumApplicationAddress, @mem_basic_info, SizeOf(MEMORY_BASIC_INFORMATION))
          If mem_basic_info\Protect = #PAGE_EXECUTE Or mem_basic_info\Protect = #PAGE_EXECUTE_READ Or mem_basic_info\Protect = #PAGE_EXECUTE_READWRITE Or mem_basic_info\Protect = #PAGE_EXECUTE_WRITECOPY
            Tsa=(mem_basic_info\BaseAddress)
            Shellcodeinrun=1
            ForEach aAddress()
              If (Tsa) >= aAddress()\AddressStart And (Tsa) < aAddress()\AddressEnd ;If the address of code is between authorised address => Ok is Clean
                Shellcodeinrun=0
                Break
              EndIf
            Next
            If Shellcodeinrun=1  ;Else :)
              AddGadgetItem(4, -1,"..a suspect executable code detected at address 0x"+ Hex(Tsa))
            EndIf
          EndIf
        EndIf
        lpMinimumApplicationAddress+mem_basic_info\RegionSize
      Wend
    EndWith
    CloseHandle_(hProcess)
  EndIf
EndProcedure

If Process_Adjust_Token_Privileges() <> 1
  Debug "Error set Process Privileges"
  End
EndIf

OpenWindow(0, 0, 0, 300, 190, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_WindowCentered)
ButtonGadget(1, 220, 10, 70, 25, "Scan")
StringGadget(2, 80, 10, 130, 25, "", #PB_String_Numeric)
TextGadget(3, 10, 10, 70, 25, "Process Pid")
EditorGadget(4, 0, 40, 300, 150, #PB_Editor_ReadOnly)

Define Event
Repeat
  Event = WaitWindowEvent()
  
  Select Event
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1 
          Scan_Process(Val(GetGadgetText(2)))
      EndSelect
      
  EndSelect
Until Event = #PB_Event_CloseWindow
Thanks I'll check it out! I sent you a PM.
Post Reply