Page 1 of 1

Windows List of running threads in running process

Posted: Fri Mar 09, 2018 6:57 pm
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

Re: Windows List of running threads in running process

Posted: Fri Mar 09, 2018 7:10 pm
by RSBasic
http://www.rsbasic.de/aktualisierung/wi ... mitteln.pb

Code: Select all

Debug "Thread - "+Str(te\th32ThreadID)

Re: Windows List of running threads in running process

Posted: Fri Mar 09, 2018 7:17 pm
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

Re: Windows List of running threads in running process

Posted: Wed Mar 14, 2018 11:46 pm
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!

Re: Windows List of running threads in running process

Posted: Wed Mar 14, 2018 11:47 pm
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.