ulong CCmdLog::setidle(ulong id) { LPLOGGER logger; ulong flag; if (id <= 0) return 0; EnterCriticalSection(&m_csShare); logger = reinterpret_cast<LPLOGGER>( Findsorteddata(&m_Table.sorted, id, 0) ); if (logger == nullptr) { flag = LOGGER_FLAG_NONE; Addtolist ( reinterpret_cast<ulong>(GetRetAddr()), DRAW_HILITE, text("Can't find the logger %d"), id ); } else { flag = logger->flag; logger->flag = LOGGER_FLAG_IDLE; Addtolist ( reinterpret_cast<ulong>(GetRetAddr()), DRAW_HILITE, text("Set idle for %d"), id ); } LeaveCriticalSection(&m_csShare); return flag; }
ulong CCmdLog::set(ulong id, int code, int type, ulong flag) { LPLOGGER logger = nullptr; if (id <= 0) return 0; EnterCriticalSection(&m_csShare); // Initialize the sorted data if it hasn't initialize yet .. if (Issortedinit(&m_Table.sorted) == 0) { if (Createsorteddata ( // Make sure it's already initialized. &m_Table.sorted, // Descriptor of sorted data sizeof(LOGGER), // Size of single data item 10, // Initial number of allocated items (SORTFUNC *)CCmdLog::SortProc, // Sorting function (DESTFUNC *)CCmdLog::DestProc, // Data destructor 0 ) != 0) { LeaveCriticalSection(&m_csShare); return 0; } } // Get the logger .. void *temp = Findsorteddata(&m_Table.sorted, id, 0); logger = reinterpret_cast<LPLOGGER>(temp); if (logger != nullptr) { logger->code = code; id = logger->addr; if (type) logger->type = type; if (flag) logger->flag = flag; } else id = 0; LeaveCriticalSection(&m_csShare); // Now redraw the window and return ... Updatetable(&m_Table, false); return id; }
// This function receives possible keyboard shortcuts from standard OllyDbg // windows. If it recognizes shortcut, it must process it and return 1, // otherwise it returns 0. extc int _export cdecl ODBG_Pluginshortcut( int origin, int ctrl, int alt, int shift, int key, void *item) { t_dump *pd; t_bookmark mark, *pm; // Plugin accepts shortcuts in form Alt+x or Shift+Alt+x, where x is a key // '0'..'9'. Shifted shortcut sets bookmark (only in Disassembler), // non-shifted jumps to bookmark from everywhere. if (ctrl == 0 && alt != 0 && key >= '0' && key <= '9') { if (shift != 0 && origin == PM_DISASM && item != NULL) { // Set new or replace existing bookmark. pd = (t_dump *)item; mark.index = key - '0'; mark.size = 1; mark.type = 0; mark.addr = pd->sel0; Addsorteddata(&(bookmark.data), &mark); if (bookmark.hw != NULL) InvalidateRect(bookmark.hw, NULL, FALSE); return 1; } // Shortcut recognized else if (shift == 0) { // Jump to existing bookmark (from any window). pm = Findsorteddata(&(bookmark.data), key - '0'); if (pm == NULL) Flash("Undefined bookmark"); else Setcpu(0, pm->addr, 0, 0, CPU_ASMHIST | CPU_ASMCENTER | CPU_ASMFOCUS); return 1; // Shortcut recognized }; }; return 0; // Shortcut not recognized };
ulong CCmdLog::erase(ulong id) { EnterCriticalSection(&m_csShare); void *temp = Findsorteddata(&m_Table.sorted, id, 0); LPLOGGER plog = reinterpret_cast<LPLOGGER>(temp); if (plog != nullptr) { Deletesorteddata(&m_Table.sorted, plog->addr, 0); Updatetable(&m_Table, false); } else id = 0; LeaveCriticalSection(&m_csShare); return id ; }
ulong CCmdLog::msg(ulong id, const std::wstring& msg, bool append) { std::wstring *pmsg; LPLOGGER plog; if (id <= 0) return 0; EnterCriticalSection(&m_csShare); // Initialize the sorted data if it hasn't initialize yet .. if (Issortedinit(&m_Table.sorted) == 0) { if (Createsorteddata ( // Make sure it's already initialized. &m_Table.sorted, // Descriptor of sorted data sizeof(LOGGER), // Size of single data item 10, // Initial number of allocated items (SORTFUNC *)CCmdLog::SortProc, // Sorting function (DESTFUNC *)CCmdLog::DestProc, // Data destructor 0 ) != 0) { LeaveCriticalSection(&m_csShare); return 0; } } // Get the logger .. void *temp = Findsorteddata(&m_Table.sorted, id, 0); if ((plog = reinterpret_cast<LPLOGGER>(temp)) != nullptr) { m_Table.custommode -= plog->rows; pmsg = reinterpret_cast<std::wstring*>(plog->msge); if (pmsg == nullptr) pmsg = new std::wstring(); if (append == false) { pmsg->clear(); plog->rows = 0; } else if (pmsg->back() != text('\n')) --plog->rows; // Extract the message ... std::wstring::const_iterator itr, eitr = msg.cend(); for (itr = msg.cbegin(); itr != eitr; ++itr) { // We don't support old mac format ... if (*itr == text('\t')) { pmsg->append(8, text(' ')); continue; } if (*itr == text('\r')) continue; if (*itr == text('\n')) ++ plog->rows; pmsg->push_back(*itr); } if (pmsg->back() != text('\n')) ++ plog->rows; plog->msge = pmsg; // Set the string ... m_Table.custommode += plog->rows; } else id = 0; // return 0 if the logger doesn't exist. LeaveCriticalSection(&m_csShare); // Redrawing the logger window and return .. if (m_Table.offset <= 0) Updatetable(&m_Table, false); else PostMessage(m_Table.hw,WM_VSCROLL,SB_PAGEDOWN,0); return id; }
// Dump windows display contents of memory or file as bytes, characters, // integers, floats or disassembled commands. Plugins have the option to modify // the contents of the dump windows. If ODBG2_Plugindump() is present and some // dump window is being redrawn, this function is called first with column= // DF_FILLCACHE, addr set to the address of the first visible element in the // dump window and n to the estimated total size of the data displayed in the // window (n may be significantly higher than real data size for disassembly). // If plugin returns 0, there are no elements that will be modified by plugin // and it will receive no other calls. If necessary, plugin may cache some data // necessary later. OllyDbg guarantees that there are no calls to // ODBG2_Plugindump() from other dump windows till the final call with // DF_FREECACHE. // When OllyDbg draws table, there is one call for each table cell (line/column // pair). Parameters s (UNICODE), mask (DRAW_xxx) and select (extended DRAW_xxx // set) contain description of the generated contents of length n. Plugin may // modify it and return corrected length, or just return the original length. // When table is completed, ODBG2_Plugindump() receives final call with // column=DF_FREECACHE. This is the time to free resources allocated on // DF_FILLCACHE. Returned value is ignored. // Use this feature only if absolutely necessary, because it may strongly // impair the responsiveness of the OllyDbg. Always make it switchable with // default set to OFF! extc int _export cdecl ODBG2_Plugindump(t_dump *pd, wchar_t *s,uchar *mask,int n,int *select,ulong addr,int column) { int i=0; wchar_t w[TEXTLEN]; void * result; if (column==DF_FILLCACHE) { // Check if there are any trace diffs to annotate at all if (hitlisttable.sorted.n==0) return 0; // empty diff means no annotations to do // Check whether it's Disassembler pane of the CPU window. if (pd==NULL || (pd->menutype & DMT_CPUMASK)!=DMT_CPUDASM) return 0; // Not a Disassembler // Just for the sake, assure that bookmarks apply: not a file dump, not a // backup display if (pd->filecopy!=NULL || (pd->dumptype & DU_TYPEMASK)!=DU_DISASM || (pd->dumptype & DU_BACKUP)!=0) return 0; // Invalid dump type // if we got to here return 1 to indicate that we want to annotate the second column return 1; } // No bookmarks to display else if (column==2) { // Check whether there is a bookmark. Note that there may be several marks // on the same address! result = Findsorteddata(&(hitlisttable.sorted),addr,0); if (result==0) return n; // No diff hits on address // Skip graphical symbols (loop brackets).(count number of graphical symbols at beginning of line for (i=0; i<n; i++) { if ((mask[i] & DRAW_GRAPH)==0) break; }; // Insert text. mask[0]=DRAW_GRAPH; s[0]=G_BIGPOINT; } else if (column==DF_FREECACHE) { // We have allocated no resources, so we have nothing to do here. }; return n; };
ulong CCmdLog::log(ulong id, int code, int type, const wchar *msg) { std::wstring *pmsg = nullptr; void *temp = nullptr; LPLOGGER plog = nullptr; ulong ulNewId = 0; EnterCriticalSection(&m_csShare); if (Issortedinit(&m_Table.sorted) == 0) { if (Createsorteddata ( // Initialize the sorted data &m_Table.sorted, // Descriptor of sorted data sizeof(LOGGER), // Size of single data item 10, // Initial number of allocated items (SORTFUNC *)CCmdLog::SortProc, // Sorting function (DESTFUNC *)CCmdLog::DestProc, // Data destructor 0 ) != 0) { LeaveCriticalSection(&m_csShare); return 0; } } if (id <= 0) { // Add new record .. // Can't add logger any more ... if (m_Table.custommode < MAXINT) { // Find a new id .. while (Findsorteddata(&m_Table.sorted,m_nNextId,0)) ++ m_nNextId; // Initialize a new item ... time_t timer; time(&timer); LOGGER logger = { m_nNextId, 1, type, 0, LOGGER_FLAG_IDLE, timer, code, nullptr }; // Initialize a new string.. (it's suck without c++11) std::wstring *pmsg = new std::wstring(); for (size_t npos = 0; msg[npos]; ++npos) { // We don't support old mac format ... if (msg[npos] == text('\r')) continue; if (msg[npos] == text('\n')) ++logger.rows; pmsg->push_back(msg[npos]); } if (pmsg->back() != text('\n')) { pmsg->push_back(text('\n')); ++logger.rows; } logger.msge = pmsg; // Set the string .... // Add a new item and return it's id .. temp = Addsorteddata(&m_Table.sorted, &logger); plog = reinterpret_cast<LPLOGGER>(temp); if (plog != nullptr) ulNewId = plog->addr; else { ulNewId = 0; delete logger.msge; } // Update the line count .. if (plog) m_Table.custommode += plog->rows; } } else { // Modify existed record . temp = Findsorteddata(&m_Table.sorted, id, 0); if ((plog = reinterpret_cast<LPLOGGER>(temp)) != nullptr) { m_Table.custommode -= plog->rows; // Update the logger .. plog->code = code; plog->type = type; plog->rows = 0; pmsg = reinterpret_cast<std::wstring*>(plog->msge); if (pmsg == nullptr) pmsg = new std::wstring(); else pmsg->clear(); // Clear the message first.. for (size_t npos = 0; msg[npos]; ++npos) { // We don't support old mac format ... if (msg[npos] == text('\r')) continue; if (msg[npos] == text('\n')) ++plog->rows; pmsg->push_back(msg[npos]); } if (pmsg->back() != text('\n')) { pmsg->push_back(text('\n')); ++plog->rows; } plog->msge = pmsg; // Set the string ........ m_Table.custommode += plog->rows; // Return this id . ulNewId = plog->addr; } } LeaveCriticalSection(&m_csShare); // Redrawing the logger window and return .. if (m_Table.offset <= 0) Updatetable(&m_Table, false); else PostMessage(m_Table.hw,WM_VSCROLL,SB_PAGEDOWN,0); return ulNewId; }
// This optional function receives commands from plugin menu in window of type // origin. Argument action is menu identifier from ODBG_Pluginmenu(). If user // activates automatically created entry in main menu, action is 0. extc void _export cdecl ODBG_Pluginaction(int origin, int action, void *item) { t_bookmark mark, *pb; t_dump *pd; if (origin == PM_MAIN) { switch (action) { case 0: // Menu item "Bookmarks", creates bookmark window. //Createbookmarkwindow(); // Make launcher { t_table *table; t_sorted *sorted; t_patch *patches; t_patch *elem; int i; FILE *f; table = Plugingetvalue(VAL_PATCHES); sorted = &table->data; patches = sorted->data; if(patches != NULL) { char *exe_name; char *launcher_name; int exe_name_len; // remove full path and keep exe name exe_name = Plugingetvalue(VAL_EXEFILENAME); exe_name += strlen(exe_name) - 1; while(*exe_name != '\\') --exe_name; ++exe_name; exe_name_len = strlen(exe_name); // create launcher file launcher_name = malloc(exe_name_len + 2); launcher_name[0] = '_'; strcpy(launcher_name + 1, exe_name); CopyFile("launcher.exe", launcher_name, 0); f = fopen(launcher_name, "a"); if(f != NULL) { //void *base_address = Plugingetvalue(VAL_MAINBASE); elem = patches; for(i = 0; i < sorted->n; i++) { fwrite(elem->orig, elem->size, 1, f); fwrite(elem->mod, elem->size, 1, f); fwrite(&elem->addr, sizeof(elem->addr) + sizeof(elem->size), 1, f); ++elem; } fwrite(exe_name, exe_name_len, 1, f); fwrite(&exe_name_len, sizeof(exe_name_len), 1, f); fwrite(&sorted->n, sizeof(sorted->n), 1, f); fwrite(SIG, sizeof(SIG) - 1, 1, f); fclose(f); } free(launcher_name); } } break; case 1: // Menu item "About", displays plugin info. If you write your own code, // please replace with own copyright! MessageBox(hwmain, "Bookmark plugin v1.10\n" "(demonstration of plugin capabilities)\n" "Copyright (C) 2001-2004 Oleh Yuschuk & Piérrot", "Bookmark plugin", MB_OK | MB_ICONINFORMATION); break; default: break; }; } else if (origin == PM_DISASM) { pd = (t_dump *)item; if (action >= 0 && action < 10) // Insert bookmark { mark.index = action; mark.size = 1; mark.type = 0; mark.addr = pd->sel0; Addsorteddata(&(bookmark.data), &mark); if (bookmark.hw != NULL) InvalidateRect(bookmark.hw, NULL, FALSE); } else if (action >= 10 && action < 20) // Delete bookmark { pb = (t_bookmark *)Findsorteddata(&(bookmark.data), action - 10); if (pb != NULL) { Deletesorteddata(&(bookmark.data), action - 10); if (bookmark.hw != NULL) InvalidateRect(bookmark.hw, NULL, FALSE); }; } else if (action >= 20 && action < 30) //Go to bookmark { pb = (t_bookmark *)Findsorteddata(&(bookmark.data), action - 20); if (pb != NULL) { Setcpu(0, pb->addr, 0, 0, CPU_ASMHIST | CPU_ASMCENTER | CPU_ASMFOCUS); }; }; }; };
static int MCompareTrace(t_table *pt,wchar_t *name,ulong index,int mode) { wchar_t buffer[100]; uchar * codeline; ulong codelinesize; if (mode==MENU_VERIFY) return MENU_NORMAL; // Always available else if (mode==MENU_EXECUTE) { ulong i,j,length, declength; uchar cmd[MAXCMDSIZE],*decode; t_disasm da; t_reg *reg; void * result; t_memory *pmem; t_hitlist hitlistitem; Deletesorteddatarange(&(hitlisttable.sorted),0,0xFFFFFFFF); for ( i=0; i<memory.sorted.n; i++) { pmem=(t_memory *)Getsortedbyindex(&memory.sorted,i); // Get next memory block. if ((pmem->type & MEM_GAP)!=0) continue; // Unallocated memory // Check whether it contains executable code. if ((pmem->type & (MEM_CODE|MEM_SFX))==0) continue; // Not a code // iterate through code for ( j=pmem->base; j<=pmem->base +pmem->size; j++) { codeline = Finddecode(j,&codelinesize); if (codeline) if (((*codeline)&DEC_TRACED)==DEC_TRACED){ result = Findsorteddata(&baselist,j,0); //Addtolist(result,DRAW_NORMAL,L"sorted"); if(!result){ length=Readmemory(cmd,j,MAXCMDSIZE,MM_SILENT|MM_PARTIAL); if (length==0) Addtolist(j,DRAW_NORMAL,L"Readmemory returned zero!"); decode=Finddecode(j,&declength); if (decode!=NULL && declength<length) decode=NULL; length=Disasm(cmd,length,j,decode,&da,DA_TEXT|DA_OPCOMM|DA_MEMORY,NULL,NULL); if (length==0) Addtolist(j,DRAW_NORMAL,L"Disasm returned zero!"); StrcopyW(hitlistitem.decodedinstruction,TEXTLEN,da.result); hitlistitem.index=j; hitlistitem.size=1; hitlistitem.type=0; Addsorteddata(&(hitlisttable.sorted),&hitlistitem); } } } } if (hitlisttable.hw==NULL){ // Create table window. Third parameter (ncolumn) is the number of // visible columns in the newly created window (ignored if appearance is // restored from the initialization file). If it's lower than the total // number of columns, remaining columns are initially invisible. Fourth // parameter is the name of icon - as OllyDbg resource. Createtablewindow(&hitlisttable,0,hitlisttable.bar.nbar,NULL, L"ICO_PLUGIN",PLUGINNAME); } else Activatetablewindow(&hitlisttable); return MENU_REDRAW; } return MENU_ABSENT; };