//on load private void MainForm_Load(object sender, EventArgs e) { Driver LookupDriver = new Driver(); //load driver as a service LookupDriver.Load(); //open a device for the service if (!LookupDriver.Open("\\\\.\\Lookup")) { statusText.Text = "couldn't open lookup device"; LookupDriver.Unload(); return; } //create the kiServiceTable and get it from ring0 kiServiceTable = LookupDriver.GetKiServiceTable(); //reslove every service number into its name from ntdll.dll LookupDriver.GetKiServiceNames(kiServiceTable); //fill the table into the list field FillServiceTableList(); //same for the interrupt table interruptTable = LookupDriver.GetInterruptTable(); FillIntTableList(); //close device handle LookupDriver.Close(); //unload driver, we don't need it anymore LookupDriver.Unload(); }
//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; } }
//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; } }