/* RPC Interface Enumerator IDC Script Copyright (C) 2005 Pedram Amini This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***** NOTES ***** This script will run over an IDA database and look for RPC_SERVER_INTERFACE structs. They are located by scanning for the length and magic fields at the known offset from another. The script will load and properly apply the RPC_SERVER_INTERFACE struct as well as the member struct MIDL_SERVER_INFO. The DispatchTable will then be followed and the dispatch routines will be enumerated. If the routine is not marked as function, a function will be created for it. */ #include static undefine_region (ea, length) { while(length--) MakeUnkn(ea + length, 0); } static main() { auto struc; auto loop_ea, ea; auto size, length, magic; auto count; auto func_name; auto addr; // load the microsoft sdk .til file into memory. if (!LoadTil("mssdk")) { Message("Failed loading mssdk.til\n"); return 1; } // load the structs we are interested in into the idb. Til2Idb(-1, "RPC_SERVER_INTERFACE"); Til2Idb(-1, "MIDL_SERVER_INFO"); // ensure our structs got loaded correctly. if (GetStrucIdByName("RPC_SERVER_INTERFACE") == -1) { Message("Failed loading RPC_SERVER_INTERFACE\n"); return 1; } if (GetStrucIdByName("MIDL_SERVER_INFO") == -1) { Message("Failed loading MIDL_SERVER_INFO\n"); return 1; } Message("\nRPC Enum - Pedram Amini \n\n"); // walk through the entire database. we don't just look at .text as .rdata // also been spotted to house RPC structs. for (loop_ea = MinEA(); loop_ea != BADADDR; loop_ea = NextAddr(loop_ea)) { ea = loop_ea; length = Byte(ea); magic = Dword(ea + 0x18); if (length == 0x44 && magic == 0x8A885D04) { Message("%08x: RPC_SERVER_INTERFACE\n", ea); // mark the RPC_SERVER_INTERFACE struct. size = GetStrucSize(GetStrucIdByName("RPC_SERVER_INTERFACE")); undefine_region(ea, size); if (!MakeStructEx(ea, size, "RPC_SERVER_INTERFACE")) { Message("*** Failed setting RPC_SERVER_INTERFACE struct @%08x\n\n", ea); continue; } // mark the MIDL_SERVER_INFO struct. ea = Dword(ea + 0x3C); Message("%08x: MIDL_SERVER_INFO\n", ea); size = GetStrucSize(GetStrucIdByName("MIDL_SERVER_INFO")); undefine_region(ea, size); if (!MakeStructEx(ea, size, "MIDL_SERVER_INFO")) { Message("*** Failed setting MIDL_SERVER_INFO struct @%08x\n\n", ea); continue; } // mark the DispatchTable. ea = Dword(ea + 0x4); Message("%08x: DispatchTable\n", ea); // enumerate the dispatch routines. for (count = 0; Dword(ea) != BADADDR; count++) { addr = Dword(ea); // mark the dispatch table offset as a dword offset. MakeDword(ea); // XXX - can't get this to work: OpOff(ea, 0, MinEA()); // ensure a function is defined at the target address. MakeFunction(addr, BADADDR); func_name = GetFunctionName(addr); // found a dispatch routine. if (strlen(func_name) != 0) { Message("%08x: dispatch routine 0x%02x %s\n", addr, count, func_name); } // if a dispatch routine can not be found we have reached the // end of the dispatch routine list. else { Message("done. Found %d RPC dispatch routines.\n\n", count); break; } ea = ea + 4; } } } }