////////////////////////////////////////////////////////////////////////////////////////////////////////// // ps_base_address() // // search through all loaded modules for a string match and return it's base address. // bool ps_base_address (char *module, DWORD *address, DWORD *size) { map <DWORD,t_Debugger_memory*>::const_iterator it; dbg.ReBuildMemoryMap(); // determine the base address of the executable section for the loaded module. for (it = dbg.MemoryMap.begin(); it != dbg.MemoryMap.end(); ++it) { // match the module name. if (stricmp(it->second->Name.c_str(), module) != 0) continue; // ensure we found the correct section. if ((it->second->basics.Protect & PAGE_EXECUTE) || (it->second->basics.Protect & PAGE_EXECUTE_READ) || (it->second->basics.Protect & PAGE_EXECUTE_READWRITE) || (it->second->basics.Protect & PAGE_EXECUTE_WRITECOPY)) { // module executable section found. *address = it->second->address; *size = it->second->basics.RegionSize; return true; } } return false; }
int main (int argc, char **argv) { unsigned int cit; int option; char filename[MAX_PATH]; char command_line[MAX_PATH]; // win2k max = MAX_PATH, otherwise could be 32k. map <DWORD,t_Debugger_memory*>::const_iterator it; // init target char buf. memset(target, 0, sizeof(target)); // Set the debugger's log level. (disable logging) dbg.log.set(LOG_SHUTUP); dbg.SetGlobalLoglevel(LOG_SHUTUP); // // do the command line argument thing. // for (int i = 1; i < argc; i++) { // // attach to a pid. // if (stricmp(argv[i], "-a") == 0 && i + 1 < argc) { if (!dbg.attach(atoi(argv[i+1]))) { printf("[ERROR] No process with the ID %u\n", atoi(argv[i+1])); return 1; } // update the target name. strncpy(target, argv[i+1], sizeof(target) - 1); i++; } // // load a file. (no arguments) // else if (stricmp(argv[i], "-l") == 0 && i + 1 < argc) { if (!dbg.load(argv[i+1])) { printf("[ERROR] Could not load %s\n", argv[i+1]); return 1; } // update the target name. strncpy(target, argv[i+1], sizeof(target) - 1); // cut off the target name at the first dot. //char *dot = strchr(target, '.'); //*dot = 0; i++; } // // load a file with arguments. // else if (stricmp(argv[i], "-la") == 0 && i + 1 < argc) { _snprintf(command_line, sizeof(command_line), "%s %s", argv[i+1], argv[i+2]); if (!dbg.load(argv[i+1], command_line)) { printf("[ERROR] Could not load %s %s\n", argv[i+1], argv[i+2]); return 1; } // update the target name. _snprintf(target, sizeof(target), command_line); i += 2; } // // select a breakpoint list. // else if (stricmp(argv[i], "-b") == 0 && i + 1 < argc) { breakpoint_list = argv[i+1]; // we open the file now with a global file handle and set the breakpoints after all // the modules have been loaded and parsed in the initial breakpoint handler. if ((bpl = fopen(breakpoint_list, "r+")) == NULL) { printf("\n[ERROR] Failed opening breakpoing list: %s\n", breakpoint_list); return 1; } i++; } // // select a starting recorder mode. // else if (stricmp(argv[i], "-r") == 0 && *target != NULL && i + 1 < argc) { recorder_mode = atoi(argv[i+1]); // create / open recorder file. sprintf(filename, "%s.%d", target, recorder_mode); recorder = fopen(filename, "a+"); // create / open the register recorder file if register enumeration hasn't been disabled. if (reg_enum_flag) { sprintf(filename, "%s-regs.%d", target, recorder_mode); recorder_regs = fopen(filename, "a+"); } i++; } // // set "one-time" mode. ie: do not restore breakpoints. // else if (stricmp(argv[i], "--one-time") == 0) { dbg.one_time = true; } // // disable register enumeration / dereferencing. // else if (stricmp(argv[i], "--no-regs") == 0) { reg_enum_flag = false; } // // invalid option. // else ps_usage(); } // // command line sanity checking. // if (*target == NULL) ps_usage(); // // print banner and start working. // printf("\nprocess stalker\n" "pedram amini <*****@*****.**>\n" "compiled on "__DATE__"\n" "target: %s\n\n", target); // assign functions to handle breakpoints. dbg.set_inital_breakpoint_handler(&initial_break); dbg.set_breakpoint_handler(&normal_break); dbg.SetCloseRecordFunction(&closer); dbg.set_load_dll_handler(&ps_load_dll_callback); // assign a function to handle exit event. dbg.set_exit_handler(&itsdone); dbg.Analysis.StackDelta = true; dbg.Analysis.StackDeltaV = 2048; // // application main loop. // while (!main_terminate) { dbg.run(1000); for (cit = 0; cit < Children.size(); cit++) Children[cit]->run(1000); if (_kbhit()) { option = getch(); switch(option) { // activate a recorder. case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': // convert character option into integer option for recorder mode. option -= 48; // close any previously open recorder file. if (recorder_mode != NOT_RECORDING) { fclose(recorder); if (reg_enum_flag) fclose(recorder_regs); } printf("entering recorder mode %d, register enumeration is %s.\n", option, (reg_enum_flag ? "enabled" : "disabled")); recorder_mode = option; // create/open recorder file. sprintf(filename, "%s.%d", target, option); recorder = fopen(filename, "a+"); // create/open the register recording file if the register enumeration flag is raised. if (reg_enum_flag) { sprintf(filename, "%s-regs.%d", target, option); recorder_regs = fopen(filename, "a+"); } break; // detach from debuggee. case 'd': if (!dbg.pDebugActiveProcessStop || !dbg.pDebugSetProcessKillOnExit) { printf("\ndetaching is not possible on the current os ... request ignored.\n"); break; } main_terminate = true; printf("\nclosing any open recorder and detaching ...\n"); if (recorder_mode != NOT_RECORDING) { fclose(recorder); if (reg_enum_flag) fclose(recorder_regs); } dbg.detach(); break; // display available options. case 'h': ps_commands(); break; // display memory map for executable sections of each module. case 'm': dbg.ReBuildMemoryMap(); printf("\n---------- MODULE LIST ----------\n"); for (it = dbg.MemoryMap.begin(); it != dbg.MemoryMap.end(); ++it) { // determine the correct section) if ((it->second->basics.Protect & PAGE_EXECUTE) || (it->second->basics.Protect & PAGE_EXECUTE_READ) || (it->second->basics.Protect & PAGE_EXECUTE_READWRITE) || (it->second->basics.Protect & PAGE_EXECUTE_WRITECOPY)) { // module executable section found. printf("module %08x %s\n", it->second->address, it->second->Name.c_str()); } } printf("\nstalking:\n"); for (node *cursor = bp_modules; cursor != NULL; cursor = cursor->next) printf("%08x - %08x [%08x] %s\n", cursor->base, cursor->base + cursor->size, cursor->size, cursor->name); printf("---------- MODULE LIST ----------\n\n"); break; // quit program. case 'q': main_terminate = true; printf("\nclosing any open recorder and quiting ...\n"); if (recorder_mode != NOT_RECORDING) { fclose(recorder); if (reg_enum_flag) fclose(recorder_regs); } break; // toggle verbosity. ie: display per breakpoint disassembly. case 'v': disassemble_flag = !disassemble_flag; printf("turning breakpoint disassembly: %s\n", (disassemble_flag) ? "ON" : "OFF"); break; // close active recorder mode. case 'x': if (recorder_mode == NOT_RECORDING) break; fclose(recorder); if (reg_enum_flag) fclose(recorder_regs); printf("closing recorder mode %d\n", recorder_mode); recorder_mode = NOT_RECORDING; break; default: ps_commands(); } // switch } // _kbhit } // while // Debugger class will handle it's own cleanup. // XXX - we don't free the bp_module list. return 0; };