//fill the listview with the information from kiServiceTable private void FillServiceTableList() { int hookCount = 0; //count hooked services for (int i = 0; i < kiServiceTable.NumberOfServices; i++) { //our current entry in the list KiServiceTableEntry entry = kiServiceTable.Get(i); //new item in list field ListViewItem item = new ListViewItem(String.Format("{0:000}", i), 0); //add function name item.SubItems.Add(entry.Name); //convert address into hex string string str = "0x" + Convert.ToString(entry.Address, 16); item.SubItems.Add(str); //add module name item.SubItems.Add(entry.Module.ToLower()); if (!((entry.Module == "ntoskrnl.exe") || (entry.Module == "ntkrnlmp.exe") || (entry.Module == "ntkrnlpa.exe") || (entry.Module == "ntkrpamp.exe"))) { //hooked item.BackColor = System.Drawing.Color.Salmon; hookCount++; } //add item into listview listViewKiService.Items.Add(item); } //change status text statusText.Text = hookCount.ToString() + " service calls are redirected from ntoskrnl.exe"; }
//searchs in the ntdll.dll export list for each service public unsafe void GetKiServiceNames(KiServiceTable kiServiceTable) { //base address from ntdll.dll //ntdll.dll is loaded in every process in nt automatically with kernel32.dll int ntdllBase = GetModuleHandle("ntdll.dll"); if (ntdllBase == 0) //should never happen return; int size = 0; //we need the address from the export table //export table is the first directory entry in the pe header int export = ImageDirectoryEntryToData(ntdllBase, true, 0, ref size); if (export == 0) //should never happen return; //+0x18 Number of names byte* ptr = (byte* )(export + 0x18); int numberOfNames = ((int *)ptr)[0]; //+0x20 Address of names ptr = (byte*)(export + 0x20); int addressOfNames = ((int*)ptr)[0]; //translate rva into va in memory //it is unsafe to do this way, need to correct it with the pe header addressOfNames += ntdllBase; for (int i = 0; i < numberOfNames; i++) { //get address from the name ptr = (byte*)(addressOfNames + i*4); int address = ((int*)ptr)[0]; address += ntdllBase; //copy string string name = ""; for (int i2 = 0; ((byte*)address)[i2] != 0; i2++) { name = name + (char)(((byte*)address)[i2]); } //get address from the method //getprocaddress helps us here address = GetProcAddress(ntdllBase, name); //check if it is service call //service calls always starts with //mov eax, code ptr = (byte*)(address); //mov eax has opocde 0xb8 if (((byte*)ptr)[0] != 0xb8 || ((byte*)ptr)[5] != 0xba) continue; ptr++; //reslove service code int serviceCode = ((int*)ptr)[0]; KiServiceTableEntry entry = kiServiceTable.Get(serviceCode); if (entry.Name.Length != 0) //already inserted continue; entry.Name = entry.Name + name; } }
//searchs in the ntdll.dll export list for each service public unsafe void GetKiServiceNames(KiServiceTable kiServiceTable) { //base address from ntdll.dll //ntdll.dll is loaded in every process in nt automatically with kernel32.dll int ntdllBase = GetModuleHandle("ntdll.dll"); if (ntdllBase == 0) //should never happen { return; } int size = 0; //we need the address from the export table //export table is the first directory entry in the pe header int export = ImageDirectoryEntryToData(ntdllBase, true, 0, ref size); if (export == 0) //should never happen { return; } //+0x18 Number of names byte *ptr = (byte * )(export + 0x18); int numberOfNames = ((int *)ptr)[0]; //+0x20 Address of names ptr = (byte *)(export + 0x20); int addressOfNames = ((int *)ptr)[0]; //translate rva into va in memory //it is unsafe to do this way, need to correct it with the pe header addressOfNames += ntdllBase; for (int i = 0; i < numberOfNames; i++) { //get address from the name ptr = (byte *)(addressOfNames + i * 4); int address = ((int *)ptr)[0]; address += ntdllBase; //copy string string name = ""; for (int i2 = 0; ((byte *)address)[i2] != 0; i2++) { name = name + (char)(((byte *)address)[i2]); } //get address from the method //getprocaddress helps us here address = GetProcAddress(ntdllBase, name); //check if it is service call //service calls always starts with //mov eax, code ptr = (byte *)(address); //mov eax has opocde 0xb8 if (((byte *)ptr)[0] != 0xb8 || ((byte *)ptr)[5] != 0xba) { continue; } ptr++; //reslove service code int serviceCode = ((int *)ptr)[0]; KiServiceTableEntry entry = kiServiceTable.Get(serviceCode); if (entry.Name.Length != 0) //already inserted { continue; } entry.Name = entry.Name + name; } }