public static List <ServiceInfo> GetServicesByPID(int pid) { bool doUpdate = false; if (pid == -1) // -1 means get all and we always want a fresh list { doUpdate = true; } else { ServiceCacheLock.EnterReadLock(); doUpdate = ServiceCacheTime <= DateTime.FromFileTimeUtc(ProcFunc.GetProcessCreationTime(pid)).ToLocalTime(); ServiceCacheLock.ExitReadLock(); } if (doUpdate) { RefreshServices(); } ServiceCacheLock.EnterReadLock(); CloneableList <ServiceInfo> values; if (pid == -1) { values = ServiceCacheByPID.GetAllValues(); } else if (!ServiceCacheByPID.TryGetValue(pid, out values)) { values = null; } ServiceCacheLock.ExitReadLock(); return((values != null && values.Count == 0) ? null : values); }
public static List <ServiceInfo> GetServicesByPID(int pid) { bool doUpdate = false; if (pid == -1) // -1 means get all and we always want a fresh list { doUpdate = true; } else { long RawCreationTime; long RawExitTime; long RawKernelTime; long RawUserTime; try { IntPtr processHandle = System.Diagnostics.Process.GetProcessById(pid).Handle; GetProcessTimes(processHandle, out RawCreationTime, out RawExitTime, out RawKernelTime, out RawUserTime); } catch { return(null); } ServiceCacheLock.EnterReadLock(); doUpdate = ServiceCacheTime < DateTime.FromFileTimeUtc(RawCreationTime); ServiceCacheLock.ExitReadLock(); } if (doUpdate) { RefreshServices(); } ServiceCacheLock.EnterReadLock(); List <ServiceInfo> values; if (pid == -1) { values = ServiceCacheByPID.GetAllValues(); } else if (!ServiceCacheByPID.TryGetValue(pid, out values)) { values = null; } ServiceCacheLock.ExitReadLock(); return((values != null && values.Count == 0) ? null : values); }
public void UpdateSockets() { UInt64 curTick = MiscFunc.GetTickCount64(); UInt64 Interval = curTick - LastUpdate; LastUpdate = curTick; List <IPHelper.I_SOCKET_ROW> Sockets = new List <IPHelper.I_SOCKET_ROW>(); // enum all ockets IntPtr tcp4Table = IPHelper.GetTcpSockets(ref Sockets); IntPtr tcp6Table = IPHelper.GetTcp6Sockets(ref Sockets); IntPtr udp4Table = IPHelper.GetUdpSockets(ref Sockets); IntPtr udp6Table = IPHelper.GetUdp6Sockets(ref Sockets); MultiValueDictionary <UInt64, NetworkSocket> OldSocketList = SocketList.Clone(); for (int i = 0; i < Sockets.Count; i++) { IPHelper.I_SOCKET_ROW SocketRow = Sockets[i]; NetworkSocket Socket = FindSocket(OldSocketList, SocketRow.ProcessId, SocketRow.ProtocolType, SocketRow.LocalAddress, SocketRow.LocalPort, SocketRow.RemoteAddress, SocketRow.RemotePort, NetworkSocket.MatchMode.Strict); if (Socket != null) { //AppLog.Debug("Found Socket {0}:{1} {2}:{3}", Socket.LocalAddress, Socket.LocalPort, Socket.RemoteAddress, Socket.RemotePort); OldSocketList.Remove(Socket.HashID, Socket); } else { Socket = new NetworkSocket(SocketRow.ProcessId, SocketRow.ProtocolType, SocketRow.LocalAddress, SocketRow.LocalPort, SocketRow.RemoteAddress, SocketRow.RemotePort); //AppLog.Debug("Added Socket {0}:{1} {2}:{3}", Socket.LocalAddress, Socket.LocalPort, Socket.RemoteAddress, Socket.RemotePort); SocketList.Add(Socket.HashID, Socket); } // Note: sockets observed using ETW are not yet initialized as we are missing owner informations there if (Socket.ProgID == null) { Socket.CreationTime = SocketRow.CreationTime; if (App.engine.DnsInspector != null && Socket.RemoteAddress != null) { App.engine.DnsInspector.GetHostName(Socket.ProcessId, Socket.RemoteAddress, Socket, NetworkSocket.HostSetter); } var moduleInfo = SocketRow.Module; if (moduleInfo == null || moduleInfo.ModulePath.Equals("System", StringComparison.OrdinalIgnoreCase)) { Socket.ProgID = ProgramID.NewID(ProgramID.Types.System); } else { string fileName = moduleInfo.ModulePath; string serviceTag = moduleInfo.ModuleName; // Note: for services and system TCPIP_OWNER_MODULE_BASIC_INFO.pModuleName is the same TCPIP_OWNER_MODULE_BASIC_INFO.pModulePath // hence we don't have the actuall exe path and we will have to resolve it. if (serviceTag.Equals(fileName)) { fileName = null; // filename not valid } else { serviceTag = null; // service tag not valid } Socket.ProgID = App.engine.GetProgIDbyPID(Socket.ProcessId, serviceTag, fileName); } } Socket.Update(SocketRow, Interval); //IPHelper.ModuleInfo Info = SocketRow.Module; //AppLog.Debug("Socket {0}:{1} {2}:{3} {4}", Socket.LocalAddress, Socket.LocalPort, Socket.RemoteAddress, Socket.RemotePort, (Info != null ? (Info.ModulePath + " (" + Info.ModuleName + ")") : "") + " [PID: " + Socket.ProcessId + "]"); } foreach (NetworkSocket Socket in OldSocketList.GetAllValues()) { bool bIsUDPPseudoCon = (Socket.ProtocolType & (UInt32)IPHelper.AF_PROT.UDP) == (UInt32)IPHelper.AF_PROT.UDP && Socket.RemotePort != 0; // Note: sockets observed using ETW are not yet initialized as we are missing owner informations there if (Socket.ProgID == null) { Socket.CreationTime = DateTime.Now; if (App.engine.DnsInspector != null && Socket.RemoteAddress != null) { App.engine.DnsInspector.GetHostName(Socket.ProcessId, Socket.RemoteAddress, Socket, NetworkSocket.HostSetter); } // Note: etw captured connections does not handle services to well :/ Socket.ProgID = App.engine.GetProgIDbyPID(Socket.ProcessId, null, null); } Socket.Update(null, Interval); if (bIsUDPPseudoCon && (DateTime.Now - Socket.LastActivity).TotalMilliseconds < 5000) // 5 sec // todo: customize udp pseudo con time { OldSocketList.Remove(Socket.HashID, Socket); if (Socket.RemovedTimeStamp != 0) { Socket.RemovedTimeStamp = 0; } } else { Socket.State = (int)IPHelper.MIB_TCP_STATE.CLOSED; } } UInt64 CurTick = MiscFunc.GetCurTick(); foreach (NetworkSocket Socket in OldSocketList.GetAllValues()) { if (Socket.RemovedTimeStamp == 0) { Socket.RemovedTimeStamp = CurTick; } else if (Socket.RemovedTimeStamp < CurTick + 3000) // todo: customize retention time { SocketList.Remove(Socket.HashID, Socket); Socket.Program?.RemoveSocket(Socket); } //AppLog.Debug("Removed Socket {0}:{1} {2}:{3}", CurSocket.LocalAddress, CurSocket.LocalPort, CurSocket.RemoteAddress, CurSocket.RemotePort); } // cleanup if (tcp4Table != IntPtr.Zero) { Marshal.FreeHGlobal(tcp4Table); } if (tcp6Table != IntPtr.Zero) { Marshal.FreeHGlobal(tcp6Table); } if (udp4Table != IntPtr.Zero) { Marshal.FreeHGlobal(udp4Table); } if (udp6Table != IntPtr.Zero) { Marshal.FreeHGlobal(udp6Table); } }
public void SyncCache() { var dnsCacheDataTable = IntPtr.Zero; if (DnsGetCacheDataTable_I == null || !DnsGetCacheDataTable_I(out dnsCacheDataTable)) { return; } DateTime CurrentTime = DateTime.Now; // cache domains //var oldCache = new HashSet<string>(dnsCache.Keys); foreach (DnsCacheEntry cacheEntry in dnsCache.GetAllValues()) { if (cacheEntry.ExpirationTime > CurrentTime) { cacheEntry.ExpirationTime = CurrentTime; } // will be reset in the loop, efectivly timeouting all flushed entries imminetly } for (var tablePtr = dnsCacheDataTable; tablePtr != IntPtr.Zero;) { var entry = (DnsApi.DnsCacheEntry)Marshal.PtrToStructure(tablePtr, typeof(DnsApi.DnsCacheEntry)); tablePtr = entry.Next; // Note: DnsGetCacheDataTable_I should only return one result per domain name in cache mo mater how many entries there are // DnsQuery wil retrive all entries of any type for a given domain name thanks to DNS_QUERY_UN_DOCUMENTED var resultPtr = IntPtr.Zero; uint ret = DnsApi.DnsQuery(entry.Name, entry.Type, DnsApi.DnsQueryType.DNS_QUERY_NO_WIRE_QUERY | DnsApi.DnsQueryType.DNS_QUERY_UN_DOCUMENTED, IntPtr.Zero, ref resultPtr, IntPtr.Zero); if (ret != DnsApi.ERROR_SUCCESS) { continue; } //AppLog.Debug("DnsEntries: " + entry.Name); // get all entries for thisdomain name /*CloneableList<DnsCacheEntry> curEntries = null; * if (!dnsCache.TryGetValue(entry.Name, out curEntries)) * { * curEntries = new CloneableList<DnsCacheEntry>(); * dnsCache.Add(entry.Name, curEntries); * } * else * oldCache.Remove(entry.Name);*/ for (var recordIndexPtr = resultPtr; recordIndexPtr != IntPtr.Zero;) { var record = (DnsApi.DnsRecord)Marshal.PtrToStructure(recordIndexPtr, typeof(DnsApi.DnsRecord)); int offset = Marshal.OffsetOf(typeof(DnsApi.DnsRecord), "Data").ToInt32(); IntPtr data = recordIndexPtr + offset; recordIndexPtr = record.Next; string HostName = record.Name; IPAddress Address = null; string ResolvedString = null; CloneableList <DnsCacheEntry> curEntries = GetEntriesFor(HostName); DnsCacheEntry curEntry = null; if (record.Type == DnsApi.DnsRecordType.A || record.Type == DnsApi.DnsRecordType.AAAA) { switch (record.Type) { case DnsApi.DnsRecordType.A: { var ptr = (DnsApi.DnsARecord)Marshal.PtrToStructure(data, typeof(DnsApi.DnsARecord)); Address = new IPAddress((UInt32)ptr.IpAddress); break; } case DnsApi.DnsRecordType.AAAA: { var ptr = (DnsApi.DnsAAAARecord)Marshal.PtrToStructure(data, typeof(DnsApi.DnsAAAARecord)); Address = new IPAddress(ptr.IpAddress); break; } } if (Address.Equals(IPAddress.Any) || Address.Equals(IPAddress.IPv6Any)) // thats wht we get from a pi hole dns proxy if the domain is blocked { Address = null; } curEntry = curEntries.FirstOrDefault(e => { return(e.RecordType == record.Type && MiscFunc.IsEqual(e.Address, Address)); }); } else // CNAME, SRV, MX, DNAME { switch (record.Type) { //case DnsApi.DnsRecordType.PTR: // Address = RevDnsHost2Address(HostName); // goto case DnsApi.DnsRecordType.CNAME; //case DnsApi.DnsRecordType.DNAME: // entire zone case DnsApi.DnsRecordType.CNAME: // one host { var ptr = (DnsApi.DnsPTRRecord)Marshal.PtrToStructure(data, typeof(DnsApi.DnsPTRRecord)); ResolvedString = ptr.NameHost; break; } /*case DnsApi.DnsRecordType.SRV: * { * var ptr = (DnsApi.DnsSRVRecord)Marshal.PtrToStructure(data, typeof(DnsApi.DnsSRVRecord)); * ResolvedString = ptr.NameTarget + ":" + ptr.Port; * break; * } * case DnsApi.DnsRecordType.MX: * { * var ptr = (DnsApi.DnsMXRecord)Marshal.PtrToStructure(data, typeof(DnsApi.DnsMXRecord)); * ResolvedString = ptr.NameExchange; * break; * }*/ default: continue; } if (ResolvedString.Equals("null.arpa")) // I invented that or the DnsProxyServer so probably no one else uses it { ResolvedString = null; } curEntry = curEntries.FirstOrDefault(e => { return(e.RecordType == record.Type && MiscFunc.IsEqual(e.ResolvedString, ResolvedString)); }); } if (curEntry == null) { curEntry = new DnsCacheEntry() { HostName = HostName, RecordType = record.Type }; curEntry.ExpirationTime = CurrentTime.AddSeconds(record.Ttl); if (Address == null && ResolvedString == null) { curEntry.State = DnsCacheEntry.States.Blocked; } else { curEntry.State = DnsCacheEntry.States.Resolved; } curEntry.Address = Address; curEntry.ResolvedString = ResolvedString; AddCacheEntry(curEntries, curEntry); } else // just update { curEntry.ExpirationTime = CurrentTime.AddSeconds(record.Ttl); } } if (resultPtr != IntPtr.Zero) { DnsApi.DnsRecordListFree(resultPtr, DnsApi.DnsFreeType.DnsFreeRecordList); } } /*DateTime ExpirationLimit = CurrentTime.AddMinutes(App.GetConfigInt("DnsInspector", "CacheRetention", 15)); * // remove old entries * foreach (var Name in oldCache) * { * CloneableList<DnsCacheEntry> curEntries = dnsCache[Name]; * for (int i = 0; i < curEntries.Count; i++) * { * DnsCacheEntry curEntry = curEntries[i]; * if (curEntry.ExpirationTime < ExpirationLimit) * { * if (curEntry.RecordType == DnsApi.DnsRecordType.A || curEntry.RecordType == DnsApi.DnsRecordType.AAAA) * cacheByIP.Remove(curEntry.Address, curEntry); * else // CNAME, SRV, MX, DNAME * cacheByStr.Remove(curEntry.ResolvedString, curEntry); * * curEntries.RemoveAt(i--); * } * } * if (curEntries.Count == 0) * dnsCache.Remove(Name); * }*/ DnsApi.DnsRecordListFree(dnsCacheDataTable, DnsApi.DnsFreeType.DnsFreeRecordList); }
public void UpdateSockets() { UInt64 curTick = MiscFunc.GetTickCount64(); UInt64 Interval = curTick - LastUpdate; LastUpdate = curTick; List <IPHelper.I_SOCKET_ROW> Sockets = new List <IPHelper.I_SOCKET_ROW>(); // enum all ockets IntPtr tcp4Table = IPHelper.GetTcpSockets(ref Sockets); IntPtr tcp6Table = IPHelper.GetTcp6Sockets(ref Sockets); IntPtr udp4Table = IPHelper.GetUdpSockets(ref Sockets); IntPtr udp6Table = IPHelper.GetUdp6Sockets(ref Sockets); MultiValueDictionary <UInt64, NetworkSocket> OldSocketList = SocketList.Clone(); for (int i = 0; i < Sockets.Count; i++) { IPHelper.I_SOCKET_ROW SocketRow = Sockets[i]; NetworkSocket Socket = FindSocket(OldSocketList, SocketRow.ProcessId, SocketRow.ProtocolType, SocketRow.LocalAddress, SocketRow.LocalPort, SocketRow.RemoteAddress, SocketRow.RemotePort, NetworkSocket.MatchMode.Strict); if (Socket != null) { //AppLog.Debug("Found Socket {0}:{1} {2}:{3}", Socket.LocalAddress, Socket.LocalPort, Socket.RemoteAddress, Socket.RemotePort); OldSocketList.Remove(Socket.HashID, Socket); } else { Socket = new NetworkSocket(SocketRow.ProcessId, SocketRow.ProtocolType, SocketRow.LocalAddress, SocketRow.LocalPort, SocketRow.RemoteAddress, SocketRow.RemotePort); //AppLog.Debug("Added Socket {0}:{1} {2}:{3}", Socket.LocalAddress, Socket.LocalPort, Socket.RemoteAddress, Socket.RemotePort); SocketList.Add(Socket.HashID, Socket); } // Note: sockets observed using ETW are not yet initialized as we are missing owner informations there if (Socket.ProgID == null) { Socket.CreationTime = SocketRow.CreationTime; if (Socket.RemoteAddress != null) { App.engine.DnsInspector.GetHostName(Socket.ProcessId, Socket.RemoteAddress, Socket, NetworkSocket.HostSetter); } var moduleInfo = SocketRow.Module; if (moduleInfo == null || moduleInfo.ModulePath.Equals("System", StringComparison.OrdinalIgnoreCase)) { Socket.ProgID = ProgramID.NewID(ProgramID.Types.System); } else { string fileName = moduleInfo.ModulePath; string serviceTag = moduleInfo.ModuleName; // Note: for services and system TCPIP_OWNER_MODULE_BASIC_INFO.pModuleName is the same TCPIP_OWNER_MODULE_BASIC_INFO.pModulePath // hence we don't have the actuall exe path and we will have to resolve it. if (serviceTag.Equals(fileName)) { fileName = null; // filename not valid } else { serviceTag = null; // service tag not valid } Socket.ProgID = App.engine.GetProgIDbyPID(Socket.ProcessId, serviceTag, fileName); } } // a program may have been removed than the sockets get unasigned and has to be re asigned if (Socket.Assigned == false) { Program prog = Socket.ProgID == null ? null : App.engine.ProgramList.GetProgram(Socket.ProgID, true, ProgramList.FuzzyModes.Any); prog?.AddSocket(Socket); if (prog != null) { Socket.Access = prog.LookupRuleAccess(Socket); } } Socket.Update(SocketRow, Interval); //IPHelper.ModuleInfo Info = SocketRow.Module; //AppLog.Debug("Socket {0}:{1} {2}:{3} {4}", Socket.LocalAddress, Socket.LocalPort, Socket.RemoteAddress, Socket.RemotePort, (Info != null ? (Info.ModulePath + " (" + Info.ModuleName + ")") : "") + " [PID: " + Socket.ProcessId + "]"); } UInt64 CurTick = MiscFunc.GetCurTick(); foreach (NetworkSocket Socket in OldSocketList.GetAllValues()) { if (Socket.RemovedTimeStamp == 0) { Socket.RemovedTimeStamp = CurTick; } else if (Socket.RemovedTimeStamp < CurTick + 3000) // todo: customize retention time { SocketList.Remove(Socket.HashID, Socket); Program prog = Socket.ProgID == null ? null : App.engine.ProgramList.GetProgram(Socket.ProgID); prog?.RemoveSocket(Socket); } //AppLog.Debug("Removed Socket {0}:{1} {2}:{3}", CurSocket.LocalAddress, CurSocket.LocalPort, CurSocket.RemoteAddress, CurSocket.RemotePort); } // cleanup if (tcp4Table != IntPtr.Zero) { Marshal.FreeHGlobal(tcp4Table); } if (tcp6Table != IntPtr.Zero) { Marshal.FreeHGlobal(tcp6Table); } if (udp4Table != IntPtr.Zero) { Marshal.FreeHGlobal(udp4Table); } if (udp6Table != IntPtr.Zero) { Marshal.FreeHGlobal(udp6Table); } }