/// <summary> /// In some deployments Hyper-V was found to use a configuration as such /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool HV(long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; var shifted = (block[0x1fe] & 0xFFFFFFFFF000); var diff = offset - shifted; // detect mode 2, 2 seems good for most purposes and is more portable // maybe 0x3 is sufficient if (shifted != 0 && ((block[0] & 0xfff) == 0x063) && ((block[0x1fe] & 0xff) == 0x63 || (block[0x1fe] & 0xff) == 0x67) && block[0x1ff] == 0) { // we disqualify entries that have these bits configured // 111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000 0000 // if (((ulong)block[0x1fe] & 0xFFFF000000000480) == 0) { if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.HyperV }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) { dp.TopPageTablePage.Add(p, block[p]); } } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) { WriteLine(dp.ToString()); } Candidate = true; } } } return(Candidate); }
/// <summary> /// TODO: NetBSD needs some analysis /// Will add more later, this check is a bit noisy, consider it alpha /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool NetBSD(long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; var shifted = (block[255] & 0xFFFFFFFFF000); var diff = offset - shifted; if (((block[511] & 0xf3) == 0x63) && ((0x63 == (block[320] & 0xf3)) || (0x63 == (block[256] & 0xf3)))) { if (((block[255] & 0xf3) == 0x63) && (0 == (block[255] & 0x7FFF000000000000))) { if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.NetBSD }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) { dp.TopPageTablePage.Add(p, block[p]); } } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) { WriteLine(dp.ToString()); } Candidate = true; } } } return(Candidate); }
/// <summary> /// The FreeBSD check for process detection is good /// Consider it release quality ;) /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool FreeBSD(int bo, long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; var shifted = (block[bo + 0x100] & 0xFFFFFFFFF000); var diff = offset - shifted; if (((block[bo] & 0xff) == 0x67) && (0x67 == (block[bo + 0xff] & 0xff))) { if (((block[bo + 0x100] & 0xff) == 0x63) && (0 == (block[bo + 0x100] & 0x7FFF000000000000))) { if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.FreeBSD, TrueOffset = TrueOffset }; for (int p = 0; p < 0x200; p++) { if (block[bo + p] != 0) { dp.TopPageTablePage.Add(p, block[bo + p]); } } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) { WriteColor(ConsoleColor.Cyan, ConsoleColor.Black, dp.ToString()); } Candidate = true; } } } return(Candidate); }
/// <summary> /// This is the same check as the earlier process detection code from CSW and DefCon /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool Windows(long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; var shifted = (block[0x1ed] & 0xFFFFFFFFF000); var diff = offset - shifted; // detect mode 2, 2 seems good for most purposes and is more portable // maybe 0x3 is sufficient if (((block[0] & 0xfdf) == 0x847) && ((block[0x1ed] & 0xff) == 0x63 || (block[0x1ed] & 0xff) == 0x67)) { // we disqualify entries that have these bits configured //111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000 0000 if ((block[0x1ed] & 0x7FFF000000000480) == 0) { #if MODE_1 if (!SetDiff) { FirstDiff = diff; SetDiff = true; } #endif if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.Windows }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) { dp.TopPageTablePage.Add(p, block[p]); } } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) { WriteLine(dp.ToString()); } Candidate = true; } } } // mode 1 is implemented to hit on very few supported bits // developing a version close to this that will work for Linux #region MODE 1 IS PRETTY LOOSE #if MODE_1 else /// detect MODE 1, we can probably get away with even just testing & 1, the valid bit //if (((block[0] & 3) == 3) && (block[0x1ed] & 3) == 3) if ((block[0] & 1) == 1 && (block[0xf68 / 8] & 1) == 1) { // a possible kernel first PFN? should look somewhat valid... if (!SetDiff) { // I guess we could be attacked here too, the system kernel could be modified/hooked/bootkit enough // we'll see if we need to analyze this in the long run // the idea of mode 1 is a very low bit-scan, but we also do not want to mess up FirstDiff // these root entries are valid for all win64's for PTE/hyper/session space etc. if ((block[0xf78 / 8] & 1) == 1 && (block[0xf80 / 8] & 1) == 1 && (block[0xff8 / 8] & 1) == 1 && (block[0xff0 / 8] == 0)) { // W/O this we may see some false positives // however can remove if you feel aggressive if (diff < FileSize && (offset > shifted ? (diff + shifted == offset) : (diff + offset == shifted))) { FirstDiff = diff; SetDiff = true; } } } if (SetDiff && !(FirstDiff != diff) && (shifted < (FileSize + diff) //|| shifted != 0 )) { if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 1, PageTableType = PTType.Windows }; DetectedProcesses.TryAdd(offset, dp); WriteLine(dp); Candidate = true; } } } #endif #endregion return(Candidate); }
/// <summary> /// Naturally the Generic checker is fairly chatty but at least you can use it /// to find unknowns, we could use some more tuneables here to help select the /// best match, I currently use the value with the lowest diff, which can be correct /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool Generic(long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; long bestShift = long.MaxValue, bestDiff = long.MaxValue; var bestOffset = long.MaxValue; var i = 0x1ff; do { if (((block[0] & 0xff) == 0x63) && block[0x1ff] == 0) { if (((block[i] & 0xff) == 0x63 || (block[i] & 0xff) == 0x67)) { // we disqualify entries that have these bits configured // 111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000 0000 // if ((block[i] & 0x7FFF000000000480) == 0) { var shifted = (block[i] & 0xFFFFFFFFF000); if (shifted != 0 && shifted < FileSize) { var diff = offset - shifted; if (diff < bestDiff) { bestShift = shifted; bestDiff = diff; bestOffset = offset; } if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.GENERIC }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) { dp.TopPageTablePage.Add(p, block[p]); } } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) { WriteLine(dp.ToString()); } Candidate = true; } } } } } i--; // maybe some kernels keep more than 1/2 system memory // wouldn't that be a bit greedy though!? } while (i > 0xFF); return(Candidate); }
/// <summary> /// The LinuxS check is a single pass state preserving scanner /// /// This was created using kernel 3.19 as a baseline. More to follow. /// /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool LinuxS(long offset) { var Candidate = false; var group = -1; // The main observation on kern319 is the given set below of must-have offsets that are identical and 0x7f8 which is unique per process // Next is the behavior that uses entries in 2 directions from top down and bottom up // i.e. 0x7f0 0x0 are the next expected values. // All others would be unset in the top level / base page // // Kernel should have only the magnificent entries // memcmp 0 ranges 8-7f0, 800-880, 888-c88, c98-e88, e90-ea0, ea8-ff0 // after first (likely kernel) page table found, use it's lower 1/2 to validate other detected page tables // Linux was found (so far) to have a consistent kernel view. var kern319 = new Dictionary <int, bool> { [0x7f8] = false, [0x880] = true, [0xc90] = true, [0xe88] = true, [0xea0] = true, [0xff0] = true, [0xff8] = true }; var Profiles = new List <Dictionary <int, bool> >(); if (((block[0xFF] & 0xfff) == 0x067) && ((block[0x110] & 0xfff) == 0x067) && ((block[0x192] & 0xfff) == 0x067) && ((block[0x1d1] & 0xfff) == 0x067) && ((block[0x1d4] & 0xfff) == 0x067) && ((block[0x1fe] & 0xfff) == 0x067) && ((block[0x1ff] & 0xfff) == 0x067) && // this is the largest block of 0's // just do this one to qualify IsZero(block, 8, 0xe0) ) /* * if (IsZero(block, 8, 0xE0) && * IsZero(block, 0x100, 0x10) && * IsZero(block, 0x111, 0x80) && * IsZero(block, 0x193, 0x3e) && * IsZero(block, 0x1D2, 0x02) && * IsZero(block, 0x1D5, 0x29)) */ { // before we catalog this entry, check to see if we can put it in a group for (int i = 0; i < LinuxSFirstPages.Count(); i++) { if (EqualBytesLongUnrolled(block, LinuxSFirstPages[i], 0x100)) { group = i; } } // if we haven't found anything yet, setup first page if (LinuxSFirstPage == null) { LinuxSFirstPage = block; LinuxSFirstPages.Add(block); group = 0; } // load DP var dp = new DetectedProc { CR3Value = offset, FileOffset = offset, Diff = 0, Mode = 2, Group = group, PageTableType = PTType.LinuxS }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) { dp.TopPageTablePage.Add(p, block[p]); } } if (Vtero.VerboseOutput) { WriteLine(dp.ToString()); } DetectedProcesses.TryAdd(offset, dp); Candidate = true; } return(Candidate); }
/// <summary> /// This is the same check as the earlier process detection code from CSW and DefCon /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool Windows(long offset) { var Candidate = false; // pre randomized kernel 10.16 anniversario edition const int SELF_PTR = 0x1ed; //var offset = CurrWindowBase + CurrMapBase; var shifted = (block[SELF_PTR] & 0xFFFFFFFFF000); var diff = offset - shifted; // detect mode 2, 2 seems good for most purposes and is more portable // maybe 0x3 is sufficient if (((block[0] & 0xfdf) == 0x847) && ((block[SELF_PTR] & 0xff) == 0x63 || (block[SELF_PTR] & 0xff) == 0x67)) { // we disqualify entries that have these bits configured //111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000 0000 if ((block[0x1ed] & 0x7FFF000000000480) == 0) { #if MODE_1 if (!SetDiff) { FirstDiff = diff; SetDiff = true; } #endif if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.Windows, TrueOffset = TrueOffset }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) dp.TopPageTablePage.Add(p, block[p]); } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) WriteColor(ConsoleColor.Cyan, ConsoleColor.Black, dp.ToString()); Candidate = true; } } } // mode 1 is implemented to hit on very few supported bits // developing a version close to this that will work for Linux #region MODE 1 IS PRETTY LOOSE #if MODE_1 else /// detect MODE 1, we can probably get away with even just testing & 1, the valid bit //if (((block[0] & 3) == 3) && (block[0x1ed] & 3) == 3) if ((block[0] & 1) == 1 && (block[0xf68 / 8] & 1) == 1) { // a possible kernel first PFN? should look somewhat valid... if (!SetDiff) { // I guess we could be attacked here too, the system kernel could be modified/hooked/bootkit enough // we'll see if we need to analyze this in the long run // the idea of mode 1 is a very low bit-scan, but we also do not want to mess up FirstDiff // these root entries are valid for all win64's for PTE/hyper/session space etc. if ((block[0xf78 / 8] & 1) == 1 && (block[0xf80 / 8] & 1) == 1 && (block[0xff8 / 8] & 1) == 1 && (block[0xff0 / 8] == 0)) { // W/O this we may see some false positives // however can remove if you feel aggressive if (diff < FileSize && (offset > shifted ? (diff + shifted == offset) : (diff + offset == shifted))) { FirstDiff = diff; SetDiff = true; } } } if (SetDiff && !(FirstDiff != diff) && (shifted < (FileSize + diff) //|| shifted != 0 )) { if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 1, PageTableType = PTType.Windows }; DetectedProcesses.TryAdd(offset, dp); WriteColor(dp); Candidate = true; } } } #endif #endregion return Candidate; }
/// <summary> /// In some deployments Hyper-V was found to use a configuration as such /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool HV(long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; var shifted = (block[0x1fe] & 0xFFFFFFFFF000); var diff = offset - shifted; // detect mode 2, 2 seems good for most purposes and is more portable // maybe 0x3 is sufficient if (shifted != 0 && ((block[0] & 0xfff) == 0x063) && ((block[0x1fe] & 0xff) == 0x63 || (block[0x1fe] & 0xff) == 0x67) && block[0x1ff] == 0) { // we disqualify entries that have these bits configured // 111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000 0000 // if (((ulong)block[0x1fe] & 0xFFFF000000000480) == 0) { if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.HyperV, TrueOffset = TrueOffset }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) dp.TopPageTablePage.Add(p, block[p]); } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) WriteColor(ConsoleColor.Cyan, ConsoleColor.Black, dp.ToString()); Candidate = true; } } } return Candidate; }
/// <summary> /// Naturally the Generic checker is fairly chatty but at least you can use it /// to find unknowns, we could use some more tunable values here to help select the /// best match, I currently use the value with the lowest diff, which can be correct /// /// This will find a self pointer in the first memory run for a non-sparse memory dump. /// /// The calling code is expected to adjust offset around RUN gaps. /// /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool Generic(long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; //long bestShift = long.MaxValue, bestDiff = long.MaxValue; //var bestOffset = long.MaxValue; var i = 0x1ff; if (((block[0] & 0xff) == 0x63) || (block[0] & 0xfdf) == 0x847) { do { if (((block[i] & 0xff) == 0x63 || (block[i] & 0xff) == 0x67)) { // we disqualify entries that have these bits configured // 111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000 0000 // if ((block[i] & 0x7FFF000000000480) == 0) { var shifted = (block[i] & 0xFFFFFFFFF000); if (shifted == offset) { var diff = offset - shifted; // BUGBUG: Need to K-Means this or something cluster values to help detection of processes in sparse format // this could be better var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.GENERIC, TrueOffset = TrueOffset }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) dp.TopPageTablePage.Add(p, block[p]); } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) WriteColor(ConsoleColor.Cyan, ConsoleColor.Black, dp.ToString()); Candidate = true; } } } i--; } while (i > 0xFF); } // maybe some kernels keep more than 1/2 system memory // wouldn't that be a bit greedy though!? return Candidate; }
/// <summary> /// The FreeBSD check for process detection is good /// Consider it release quality ;) /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool FreeBSD(long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; var shifted = (block[0x100] & 0xFFFFFFFFF000); var diff = offset - shifted; if (((block[0] & 0xff) == 0x67) && (0x67 == (block[0xff] & 0xff))) { if (((block[0x100] & 0xff) == 0x63) && (0 == (block[0x100] & 0x7FFF000000000000))) { if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.FreeBSD, TrueOffset = TrueOffset }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) dp.TopPageTablePage.Add(p, block[p]); } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) WriteColor(ConsoleColor.Cyan, ConsoleColor.Black, dp.ToString()); Candidate = true; } } } return Candidate; }
/// <summary> /// The LinuxS check is a single pass state preserving scanner /// /// This was created using kernel 3.19 as a baseline. More to follow. /// /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool LinuxS(long offset) { var Candidate = false; var group = -1; // The main observation on kern319 is the given set below of must-have offsets that are identical and 0x7f8 which is unique per process // Next is the behavior that uses entries in 2 directions from top down and bottom up // i.e. 0x7f0 0x0 are the next expected values. // All others would be unset in the top level / base page // // Kernel should have only the magnificent entries // memcmp 0 ranges 8-7f0, 800-880, 888-c88, c98-e88, e90-ea0, ea8-ff0 // after first (likely kernel) page table found, use it's lower 1/2 to validate other detected page tables // Linux was found (so far) to have a consistent kernel view. var kern319 = new Dictionary<int, bool> { [0x7f8] = false, [0x880] = true, [0xc90] = true, [0xe88] = true, [0xea0] = true, [0xff0] = true, [0xff8] = true }; var Profiles = new List<Dictionary<int, bool>>(); if (((block[0xFF] & 0xfff) == 0x067) && ((block[0x110] & 0xfff) == 0x067) && ((block[0x192] & 0xfff) == 0x067) && ((block[0x1d1] & 0xfff) == 0x067) && ((block[0x1d4] & 0xfff) == 0x067) && ((block[0x1fe] & 0xfff) == 0x067) && ((block[0x1ff] & 0xfff) == 0x067) // this is the largest block of 0's // just do this one to qualify //IsZero(block, 8, 0xe0) ) if ( /*IsZero(block, 8, 0xE0) && IsZero(block, 0x100, 0x10) &&*/ IsZero(block, 0x111, 0x80) && IsZero(block, 0x193, 0x3e) && IsZero(block, 0x1D2, 0x02) && IsZero(block, 0x1D5, 0x29)) { // before we catalog this entry, check to see if we can put it in a group for (int i = 0; i < LinuxSFirstPages.Count(); i++) if (EqualBytesLongUnrolled(block, LinuxSFirstPages[i], 0x100)) group = i; // if we haven't found anything yet, setup first page if (LinuxSFirstPage == null) { LinuxSFirstPage = block; LinuxSFirstPages.Add(block); group = 0; } // load DP var dp = new DetectedProc { CR3Value = offset, FileOffset = offset, Diff = 0, Mode = 2, Group = group, PageTableType = PTType.LinuxS, TrueOffset = TrueOffset }; for (int p = 0; p < 0x200; p++) if (block[p] != 0) dp.TopPageTablePage.Add(p, block[p]); if (Vtero.VerboseOutput) WriteColor(ConsoleColor.Cyan, dp.ToString()); DetectedProcesses.TryAdd(offset, dp); Candidate = true; } return Candidate; }
/// <summary> /// Naturally the Generic checker is fairly chatty but at least you can use it /// to find unknowns, we could use some more tunable values here to help select the /// best match, I currently use the value with the lowest diff, which can be correct /// /// This will find a self pointer in the first memory run for a non-sparse memory dump. /// /// The calling code is expected to adjust offset around RUN gaps. /// /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool Generic(int x, long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; //long bestShift = long.MaxValue, bestDiff = long.MaxValue; //var bestOffset = long.MaxValue; var i = 0x1ff; if (((block[x] & 0xff) == 0x63) || (block[x] & 0xfdf) == 0x847) { do { if (((block[x + i] & 0xff) == 0x63 || (block[x + i] & 0xff) == 0x67)) { // we disqualify entries that have these bits configured // 111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000 0000 // if ((block[x + i] & 0x7FFF000000000480) == 0) { var shifted = (block[x + i] & 0xFFFFFFFFF000); if (shifted == offset) { var diff = offset - shifted; // BUGBUG: Need to K-Means this or something cluster values to help detection of processes in sparse format // this could be better var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.GENERIC, TrueOffset = TrueOffset }; for (int p = 0; p < 0x200; p++) { if (block[x + p] != 0) { dp.TopPageTablePage.Add(p, block[x + p]); } } DetectedProcesses.TryAdd(offset, dp); if (Vtero.DiagOutput) { WriteColor(ConsoleColor.Cyan, ConsoleColor.Black, dp.ToString()); } Candidate = true; } } } i--; } while (i > 0xFF); } // maybe some kernels keep more than 1/2 system memory // wouldn't that be a bit greedy though!? return(Candidate); }
/// <summary> /// Naturally the Generic checker is fairly chatty but at least you can use it /// to find unknowns, we could use some more tuneables here to help select the /// best match, I currently use the value with the lowest diff, which can be correct /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool Generic(long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; long bestShift = long.MaxValue, bestDiff = long.MaxValue; var bestOffset = long.MaxValue; var i = 0x1ff; do { if (((block[0] & 0xff) == 0x63) && block[0x1ff] == 0) { if (((block[i] & 0xff) == 0x63 || (block[i] & 0xff) == 0x67)) { // we disqualify entries that have these bits configured // 111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0100 1000 0000 // if ((block[i] & 0x7FFF000000000480) == 0) { var shifted = (block[i] & 0xFFFFFFFFF000); if (shifted != 0 && shifted < FileSize) { var diff = offset - shifted; if (diff < bestDiff) { bestShift = shifted; bestDiff = diff; bestOffset = offset; } if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.GENERIC }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) dp.TopPageTablePage.Add(p, block[p]); } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) WriteLine(dp.ToString()); Candidate = true; } } } } } i--; // maybe some kernels keep more than 1/2 system memory // wouldn't that be a bit greedy though!? } while (i > 0xFF); return Candidate; }
/* OpenBSD /src/sys/arch/amd64/include/pmap.h #define L4_SLOT_PTE 255 #define L4_SLOT_KERN 256 #define L4_SLOT_KERNBASE 511 #define L4_SLOT_DIRECT 510 */ /// <summary> /// Slightly better check then NetBSD so I guess consider it beta! /// </summary> /// <param name="offset"></param> /// <returns></returns> public bool OpenBSD(long offset) { var Candidate = false; //var offset = CurrWindowBase + CurrMapBase; var shifted = (block[255] & 0xFFFFFFFFF000); var diff = offset - shifted; if (((block[510] & 0xf3) == 0x63) && (0x63 == (block[256] & 0xf3)) && (0x63 == (block[254] & 0xf3))) { if (((block[255] & 0xf3) == 0x63) && (0 == (block[255] & 0x7FFF000000000000))) { if (!DetectedProcesses.ContainsKey(offset)) { var dp = new DetectedProc { CR3Value = shifted, FileOffset = offset, Diff = diff, Mode = 2, PageTableType = PTType.OpenBSD }; for (int p = 0; p < 0x200; p++) { if (block[p] != 0) dp.TopPageTablePage.Add(p, block[p]); } DetectedProcesses.TryAdd(offset, dp); if (Vtero.VerboseOutput) WriteLine(dp.ToString()); Candidate = true; } } } return Candidate; }