WinBatch® Technical Support Forum

All Things WinBatch => WinBatch => Topic started by: pamsniffer on February 28, 2015, 01:05:33 PM

Title: check for runnning programs that are not signed
Post by: pamsniffer on February 28, 2015, 01:05:33 PM
Hi,

I want to make a winbatch script that is checking for running programs that are not signed.
maybe someone can help me.

pam
Title: Re: check for runnning programs that are not signed
Post by: td on March 02, 2015, 07:55:42 AM
Interesting problem.  I am not aware of any simple way to check all running programs for a digital signature.  You can use the WinVerifyTrust API function exported from Wintrust.dll via a DllCall to check the signature of the image file associated with each running process.  Of course, this entails getting the image file for each running process via the process extender or the dotNet "System.Diagnostics.Process" class.

MSFT's signtool command line tool can be used to verify the signature of an executable image.  The following article describes how to do this with the tool

https://msdn.microsoft.com/en-us/library/windows/desktop/aa388171%28v=vs.85%29.aspx (https://msdn.microsoft.com/en-us/library/windows/desktop/aa388171%28v=vs.85%29.aspx)

You would need to download the tool if you don't have it already and you would still need to get a list of all the running executable images.

There may be a pure FCL (dotNet) way to do this but that would require a little more research to establish its existence.
Title: Re: check for runnning programs that are not signed
Post by: td on March 02, 2015, 05:53:06 PM
Here's a mashup that more or less gets the image file names of running unsigned executables.  It needs a considerable amount of work including error handling and needs to be run as an elevated admin.

Code (winbatch) Select

; Handy constants
INVALID_HANDLE_VALUE=-1
WTD_UI_NONE=2
WTD_REVOKE_NONE=0
WTD_CHOICE_FILE=1
WTD_SAFER_FLAG=256
WTD_STATEACTION_VERIFY=1
WTD_STATEACTION_CLOSE=2

; Structures.
;WINTRUST_FILE_INFO structure
strWinTrustFileInfo = "DWORD:cbStruct;LPWSTR:pcwszFilePath;HANDLE:hFile;DWORD_PTR:pGUID"
hFileData  = DllStructAlloc(strWinTrustFileInfo)
DllStructPoke(hFileData, "cbStruct", IntControl(98, hFileData, 1,0,0)) ; Set the struct size.

; WINTRUST_DATA structure
strWinTrustData =  "DWORD:cbStruct;DWORD_PTR:pPolicyCallbackData;DWORD_PTR:pSIPClientData;DWORD:dwUIChoice;"
strWinTrustData := "DWORD:fdwRevocationChecks;DWORD:dwUnionChoice;DWORD_PTR:pFile;DWORD:dwStateAction;"
strWinTrustData := "HANDLE:hWVTStateData;LPWSTR:pwszURLReference;DWORD:dwProvFlags;DWORD:dwUIContext"
hTrustData = DllStructAlloc(strWinTrustData)
DllStructPoke(hTrustData, "cbStruct", IntControl(98, hTrustData, 1,0,0)) ; Set the struct size.
DllStructPoke(hTrustData, "dwUIChoice",WTD_UI_NONE)
DllStructPoke(hTrustData, "fdwRevocationChecks", WTD_REVOKE_NONE)
DllStructPoke(hTrustData, "dwUnionChoice", WTD_CHOICE_FILE)
DllStructPoke(hTrustData, "pFile", IntControl(98, hFileData, 2,0,0)) ; Set the file data pointer.
DllStructPoke(hTrustData, "dwProvFlags", WTD_SAFER_FLAG)

; Use the Authenticode policy provider for verification by filling a GUID structure
; with the guid that represents it.
strGuild = "unsigned long:Data1;unsigned short:Data2;unsigned short:Data3;unsigned char:Data4[8]"
strActionVerify = "{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}" ; String version of GUID
hGuid = DllStructAlloc(strGuild)
if !DllCall("Shell32.dll", long:"703",lpstr:strActionVerify, long:IntControl(98,hGuid, 2,0,0))
   Message("Signed Image Error", "GUID conversion failed")
   exit
endif

#DefineSubroutine IsImageSigned( _strImageFile)

   ; Set the file name.
   DllStructPoke(hFileData, "pcwszFilePath",_strImageFile)

   ; Do the deed.
   return  !DllCall("WINTRUST.DLL", long:"WinVerifyTrust",long:INVALID_HANDLE_VALUE, lpstruct:hGuid, lpstruct:hTrustData)
#EndSubroutine


; Use our handy dandy FCL system assembly's process related classes.
ObjectClrOption("use","System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
objProcess = ObjectClrNew("System.Diagnostics.Process")
aProcesses = objProcess.GetProcesses(".")

hName     = BinaryAlloc(512)
hSize     = BinaryAlloc(4)
lUnsigned = ""
nMax      =  ArrInfo(aProcesses, 1) - 1
nChecked  = 0
for  i = 0 to  nMax

   objProc = aProcesses[i]

   ; Trap CLR exception error.
   nErrorMode = ErrorMode(@off)
   hProcHandle = objProc.Handle
   nError = LastError()
   ErrorMode(nErrorMode)
   if nError then continue ; Skip if we can't get a handle.

   ; Can't use the dotNet MainModule class on 64-bit systems so use the Win32 API instead.
   BinaryPoke4(hSize, 0, 512)
   DllCall('Kernel32.dll',long:'QueryFullProcessImageNameA',long:hProcHandle,long:0,lpbinary:hName, lpbinary:hSize)
   BinaryEODSet(hName, 512)
   strFileName = BinaryPeekStr(hName,0,512)
   objProc.Dispose()
   
   ; Add unsigned apps to a list.
   if !IsImageSigned(strFileName) then lUnsigned = ItemInsert(strFileName, -1, lUnsigned,@Cr)
   nChecked += 1
next

; Cleanup
BinaryFree(hSize)
BinaryFree(hName)
DllStructFree(hGuid)
DllStructFree(hFileData)
dllStructFree(hTrustData)

; Display results.
Message("Checked ":nChecked:" of ":nMax+1:" Process Images", lUnsigned)
exit


Title: Re: check for runnning programs that are not signed
Post by: pamsniffer on March 03, 2015, 10:49:07 AM
thx