//opens a driver device and gets the complete KiServiceTable public unsafe KiServiceTable GetKiServiceTable() { //the service table we will fill out and return later KiServiceTable kiServiceTable = new KiServiceTable(); int NumberOfServices; //open driver try { //our in and out buffer byte[] inBuffer = new byte[0]; byte[] outBuffer = new byte[0x1000]; //should be big enough // Interact(IOCTL_GET_SERVICE_TABLE(), inBuffer, outBuffer); //didn't found a byte[4] to int convertion method ... //First dword is NumberOfServices NumberOfServices = 0; fixed(byte *pOut = outBuffer) //unmanaged data { //first dword is cnt for number of services in this os NumberOfServices = ((int *)pOut)[0]; //and then the complete service table ... for (int cnt = 0; cnt < NumberOfServices; cnt++) { //get address uint address = ((uint *)pOut)[cnt + 1]; //create new entry KiServiceTableEntry entry = new KiServiceTableEntry(address); //resolve module name for that address entry.Module = GetModuleName(address); kiServiceTable.Add(entry); } } } catch (Exception e) { string msg = e.StackTrace + "\n\n" + e.Message + "\n\n" + e.HelpLink + "\n please contact the developer"; MessageBox.Show(msg); } return(kiServiceTable); }
//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"; }
//add one entry public void Add(KiServiceTableEntry kiServiceTableEntry) { kiServiceTable.Add(kiServiceTableEntry); }
//opens a driver device and gets the complete KiServiceTable public unsafe KiServiceTable GetKiServiceTable() { //the service table we will fill out and return later KiServiceTable kiServiceTable = new KiServiceTable(); int NumberOfServices; //open driver try { //our in and out buffer byte[] inBuffer = new byte[0]; byte[] outBuffer = new byte[0x1000]; //should be big enough // Interact(IOCTL_GET_SERVICE_TABLE(), inBuffer, outBuffer); //didn't found a byte[4] to int convertion method ... //First dword is NumberOfServices NumberOfServices = 0; fixed (byte* pOut = outBuffer) //unmanaged data { //first dword is cnt for number of services in this os NumberOfServices = ((int*)pOut)[0]; //and then the complete service table ... for (int cnt = 0; cnt < NumberOfServices; cnt++) { //get address uint address = ((uint*)pOut)[cnt + 1]; //create new entry KiServiceTableEntry entry = new KiServiceTableEntry(address); //resolve module name for that address entry.Module = GetModuleName(address); kiServiceTable.Add(entry); } } } catch (Exception e) { string msg = e.StackTrace + "\n\n" + e.Message + "\n\n" + e.HelpLink + "\n please contact the developer"; MessageBox.Show(msg); } return kiServiceTable; }
//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; } }