int ODBG2_Pluginquery(int ollydbgversion,ulong *features, wchar_t pluginname[SHORTNAME],wchar_t pluginversion[SHORTNAME]) { if (ollydbgversion<201) return 0; StrcopyW(pluginname, SHORTNAME, PLUGIN_NAME); StrcopyW(pluginversion, SHORTNAME, VERSION); return PLUGIN_VERSION; }
// Menu function of main menu, displays About dialog. static int Mabout(t_table *pt,wchar_t *name,ulong index,int mode) { int n; wchar_t s[TEXTLEN]; if (mode==MENU_VERIFY) return MENU_NORMAL; // Always available else if (mode==MENU_EXECUTE) { // Debuggee should continue execution while message box is displayed. Resumeallthreads(); // In this case, Swprintf() would be as good as a sequence of StrcopyW(), // but secure copy makes buffer overflow impossible. n=StrcopyW(s,TEXTLEN,L"DiffSnake plugin v"); n+=StrcopyW(s+n,TEXTLEN-n,VERSION); // COPYRIGHT POLICY: This bookmark plugin is an open-source freeware. It's // just a sample. The copyright below is also just a sample and applies to // the unmodified sample code only. Replace or remove copyright message if // you make ANY changes to this code! n+=StrcopyW(s+n,TEXTLEN-n,L"\nCopyright none. This software is free as a bird"); // The conditionals below are here to verify that this plugin can be // compiled with all supported compilers. They are not necessary in the // final code. #if defined(__BORLANDC__) n+=StrcopyW(s+n,TEXTLEN-n,L"\n\nCompiled with Borland (R) "); #elif defined(_MSC_VER) n+=StrcopyW(s+n,TEXTLEN-n,L"\n\nCompiled with Microsoft (R) "); #elif defined(__MINGW32__) n+=StrcopyW(s+n,TEXTLEN-n,L"\n\nCompiled with MinGW32 "); #else n+=StrcopyW(s+n,TEXTLEN-n,L"\n\nCompiled with "); #endif #ifdef __cplusplus StrcopyW(s+n,TEXTLEN-n,L"C++ compiler"); #else StrcopyW(s+n,TEXTLEN-n,L"C compiler"); #endif MessageBox(hwollymain,s, L"DiffSnake plugin",MB_OK|MB_ICONINFORMATION); // Suspendallthreads() and Resumeallthreads() must be paired, even if they // are called in inverse order! Suspendallthreads(); return MENU_NOREDRAW; }; return MENU_ABSENT; };
int Hitlistdraw(wchar_t *s,uchar *mask,int *select, t_table *pt,t_drawheader *ph,int column,void *cache) { int n=0; t_hitlist * listitem; // For simple tables, t_drawheader is the pointer to the data element. It // can't be NULL, except in DF_CACHESIZE, DF_FILLCACHE and DF_FREECACHE. listitem=(t_hitlist *)ph; switch (column) { case DF_CACHESIZE: // Request for draw cache size // Columns 3 and 4 (disassembly and comment) both require calls to // Disasm(). To accelerate processing, I call disassembler once per line // and cache data between the calls. Here I inform the drawing routine // how large the cache must be. return 0;//sizeof(t_disasm); case DF_FILLCACHE: // Request to fill draw cache // We don't need to initialize cache when drawing begins. Note that cache // is initially zeroed. break; case DF_FREECACHE: // Request to free cached resources // We don't need to free cached resources when drawing ends. break; case DF_NEWROW: // Request to start new row in window // New row starts. Let us disassemble the command at the pointed address. // I assume that bookmarks can't be set on data. First of all, we need to // read the contents of memory. Length of 80x86 commands is limited to // MAXCMDSIZE bytes. case 0: // 0-based index n=Hexprint8W(s,listitem->index);//StrcopyW(s,TEXTLEN,L"%x",listitem->index); memset(mask,DRAW_GRAY,n); *select|=DRAW_MASK; break; case 1: n=StrcopyW(s,TEXTLEN,listitem->decodedinstruction); memset(mask,DRAW_GRAY,n); *select|=DRAW_MASK; break; default: break; }; return n; };
int ODBG2_Plugininit(void) { if(Createsorteddata(&handletable.sorted, sizeof(HANDLE_DATA), 1, NULL , NULL, SDM_NOSIZE) != 0) { Addtolist(0, DRAW_HILITE, L"[%s]: Unable to created sorted table data.", PLUGIN_NAME); return -1; } StrcopyW(handletable.name,SHORTNAME,PLUGIN_NAME); handletable.mode = TABLE_SAVEPOS | TABLE_AUTOUPD; handletable.bar.visible = 1; handletable.bar.name[0] = L"Handle"; handletable.bar.expl[0] = L""; handletable.bar.mode[0] = BAR_FLAT; handletable.bar.defdx[0] = 24; handletable.bar.name[1] = L"Type"; handletable.bar.expl[1] = L""; handletable.bar.mode[1] = BAR_FLAT; handletable.bar.defdx[1] = 30; handletable.bar.name[2] = L"Name"; handletable.bar.expl[2] = L""; handletable.bar.mode[2] = BAR_FLAT; handletable.bar.defdx[2] = 256; handletable.bar.nbar = 3; handletable.tabfunc = (TABFUNC*)handletable_proc; handletable.custommode = 0; handletable.customdata = NULL; handletable.updatefunc = NULL; handletable.drawfunc = (DRAWFUNC *)handletable_draw; handletable.tableselfunc = NULL; handletable.menu = (t_menu*)handlesmenu; return 0; }
// Copy row data from table .. // The code is from Copywholetable .. HGLOBAL CCmdLog::CopyRow(int row, int count) { void* pcache = nullptr; t_table *table = &m_Table; int offset = m_Table.offset; // Save current offset .. uchar cache[0x400]; uchar mask[TEXTLEN*2]; wchar wstr[TEXTLEN*2]; wchar *pbuf, *pstr; int width[NBAR]; int size,val,i,j,k,pos; HGLOBAL hMem; // Not support index at the end .. if (count <= 0) return nullptr; // Check parameters .. if (table->mode & TABLE_STDSCR) { size = static_cast<int>(table->sorted.n); if (row+count > size) return nullptr; } else { size = static_cast<int>(table->custommode); if (row+count > size) return nullptr; } // Calc the character width array .. for (size=i=0; i < table->bar.nbar && i < NBAR; ++i) { if ((val = table->bar.dx[i]) > 3) { width[i] = val / Getcharacterwidth(table, i); if (width[i] >= 0x100) width[i] = 0x0ff; size += val + 1; } else width[i] = 0; } if (size == 0) return nullptr; // Allocate the buffer .. size = (table->sorted.n+1) * (size+2) + 320; hMem = GlobalAlloc(0x2002u, 2 * size); pos = 0; if (hMem == nullptr) return nullptr; pbuf = reinterpret_cast<wchar*>(GlobalLock(hMem)); if (pbuf==nullptr) { GlobalFree(hMem); return nullptr; } // Get the window title .. if (table->hparent != nullptr) pos = GetWindowText(table->hparent, pbuf, 128); if (pos == 0) pos = StrcopyW(pbuf, TEXTLEN, table->name); if (pos == 0) pos = StrcopyW(pbuf, TEXTLEN, TEXT("Unnamed table")); pbuf[pos++] = TEXT('\r'); pbuf[pos++] = TEXT('\n'); // Require and allocate the cache ... val = table->drawfunc( wstr, mask, &val, table, reinterpret_cast<t_sorthdr*>(&i), DF_CACHESIZE, 0 ); if (val < 0x400) pcache = cache + 0; else pcache = Memalloc(val, SILENT); if (pcache == nullptr) { GlobalFree(hMem); return 0; } // Initialize the cache .. if (val > 0) { table->drawfunc( wstr, mask, &val, table, reinterpret_cast<t_sorthdr*>(&i), DF_FILLCACHE, pcache );} // Add bar title .. for (i = 0; i < table->bar.nbar && i < NBAR; ++i) { if (width[i] == 0) continue; pstr = table->bar.name[i]; for (j = 0; j < width[i]; ++j) { // The end char '$' or null .. if (pstr[j]==0 || pstr[j]==TEXT('$')) break; else pbuf[pos++] = pstr[j]; } // Not enough space to display the whole title .. // then end with '> ' if (j >= width[i] && pstr[j] && pstr[j] != TEXT('$')) { pbuf[pos++] = TEXT('>'); //pbuf[pos++] = TEXT(' '); // Append ' ' if we have too many space .. // It's not avaliable for the last column .. } else if (i < table->bar.nbar-1) { for ( ; j < width[i]+1; ++j) pbuf[pos++] = TEXT(' '); } } // The ending of title bar .. for( ; pos > 0; --pos) { if (pbuf[pos-1] != TEXT(' ')) { pbuf[pos++] = TEXT('\r'); pbuf[pos++] = TEXT('\n'); break; } } // Now get the logger data .. if (table->mode & TABLE_STDSCR) if (row+count > table->sorted.n) count = table->sorted.n - row; m_Table.offset = row; // We begin with row .. for (i = k = 0; i < count; ++i, k = i) { table->drawfunc( wstr, mask, &val, table, reinterpret_cast<t_sorthdr*>(&k), DF_NEWROW, pcache ); for (j = 0; j < table->bar.nbar && j < NBAR; ++j) { val = 0; if (width[j] == 0) continue; size = table->drawfunc ( pbuf+pos, mask, &val, table, reinterpret_cast<t_sorthdr*>(&k), j, pcache ); if ( val & DRAW_ULTEXT ) size = 0; else if (size >= 0) size = min(size, 255); else size = 0; // The width may large than the limit .. size = min(size, width[j]); // Translate the graph symbols .. Replacegraphs(ADDR_SYMMASK, pbuf+pos, mask, val, size); pos = pos + size; // The next position .. // Adjust the string .. if ( size < width[j] ) { if ( j < table->bar.nbar - 1 ) { for ( ; size < width[j] + 1; ++size) pbuf[pos++] = TEXT(' '); } } else { pbuf[pos++] = TEXT('>'); //pbuf[pos++] = TEXT(' '); } } // The ending of current line .. for( ; pos > 0; --pos) { if (pbuf[pos-1] != TEXT(' ')) { pbuf[pos++] = TEXT('\r'); pbuf[pos++] = TEXT('\n'); break; } } } // The ending of the whole content .. pbuf[pos] = 0; size = pos + 1; // Notify the draw function to free cache .. if (pcache != nullptr && pcache != cache+0) { table->drawfunc( wstr, mask, &val, table, reinterpret_cast<t_sorthdr*>(&i), DF_FREECACHE, pcache ); } // Cleanup and restore data ... table->offset = offset; GlobalUnlock(hMem); if (pcache && pcache != cache+0) Memfree(pcache); return GlobalReAlloc(hMem, size*2, GMEM_MOVEABLE); }
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; };