ODBG2_Pluginsaveudd
Optional plugin callback function, allows plugin to save module-related data to the .udd file.
In
the OllyDbg v1.xx plugin authors were forced (or at least expected) to
register unique .udd tags with the OllyDbg author (me). Version 2.xx
makes it differently. For each plugin, OllyDbg automatically creates
file-unique block of .udd record types. They are indexed by plugin
names (reported in ODBG2_Pluginquery(), not the name of DLL!). If there are two plugins with the same name, restored records
may be sent to the wrong plugin. Therefore it is very important that
plugin names are unique. A good (but of course insufficient) solution is to select random tags. For
example, if both plugins use tags 1, 2 and 3, the collision is unavoidable. If tags are 121, 122 and 123 in
one case and 9902, 9903 and 9904 in another, there will be no
collision.
Each plugin may define 65535
plugin-unique tags in the range 1 .. 65535. Tag 0 is reserved for the
future. For each data record plugin calls Pluginsaverecord() or Pluginpackedrecord().
If necessary, there may be several records with the same tag. Total
size of the data that plugin may save to the .udd file is limited
only by the disk capacity (although OllyDbg may experience some
problems if file size exceeds 2 GB).
Global,
process-oriented data must be saved to the main .udd file (named by
.exe). Module-related data must be saved in module files. Don't forget
to save all addresses relative to the module base, so that data will be
restored correctly even if module is relocated.
Note that this function is called not only when module unloads, but also when user selects Save data to .udd file... in the Modules window.
void
ODBG2_Pluginsaveudd(t_uddsave *psave,t_module *pmod,int ismainmodule);
Parameters:
psave
pmod
(in) Pointer to the structure of type t_module that describes the processed module
ismainmodule
(in) 1 if this is the main module (usually belonging to the file with extention .exe) and 0 otherwise
Return
values:
None
Example:
This simplified code is taken from the sample bookmark plugin:#define BOOKMARKTAG 0x0001 // Tag of bookmark recordtypedef struct t_uddmark { // Bookmark in .udd file
int
index;
// Bookmark index
ulong
offset;
// Offset from module base} t_uddmark;extc void _export cdecl ODBG2_Pluginsaveudd(const t_uddsave *psave, t_module *pmod,int ismainmodule) { int i; t_bookmark *pmark; t_uddmark um; for (i=0; i<bookmark.sorted.n; i++) { pmark=(t_bookmark *)Getsortedbyindex(&(bookmark.sorted),i); if (pmark->addr>=pmod->base && pmark->addr<pmod->base+pmod->size) { um.index=pmark->index; um.offset=pmark->addr-pmod->base; Pluginsaverecord(psave,BOOKMARKTAG,sizeof(um),&um); } }}
Plugin saves bookmarks that belong only to the specified module:
if (pmark->addr>=pmod->base && pmark->addr<pmod->base+pmod->size) ...
Each
record is a structure of type t_uddmark. Its size is fixed, but nothing
prevents you from saving records of variable size. Note that record
contains not the physical address of the bookmark, but its offset from
the module base:
um.offset=pmark->addr-pmod->base;
When
restoring bookmarks, plugin will add module base to the offset. If
module is loaded on a different base, bookmarks will get different
physical addresses, but will point to the same commands - and this is
what user expects.
But what will happen if bookmark is set
outside of any module? In our case it will be lost. Let's hope that
data pointed to by the bookmark will not be relocated. As there is no
associated module, we are going to save orphan bookmarks in the main
.udd file:
#define BOOKMARKTAG 0x0001 // Tag of bookmark record#define ORPHANTAG 0x0002 // Tag of orphan bookmark recordtypedef struct t_uddmark { // Bookmark in .udd file
int
index;
// Bookmark index
ulong
addroffs;
// Address or offset from module base} t_uddmark;extc void _export cdecl ODBG2_Pluginsaveudd(const t_uddsave *psave, t_module *pmod,int ismainmodule) { int i,j; t_bookmark *pmark; t_uddmark um; t_module *pm;
for (i=0; i<bookmark.sorted.n; i++) { pmark=(t_bookmark *)Getsortedbyindex(&(bookmark.sorted),i); if (pmark->addr>=pmod->base && pmark->addr<pmod->base+pmod->size) { um.index=pmark->index; um.addroffs=pmark->addr-pmod->base; Pluginsaverecord(psave,BOOKMARKTAG,sizeof(um),&um); }
else if (ismainmodule) {
for (j=0; j<module.sorted.n; j++) {
pm=(t_module *)Getsortedbyindex(&(module.sorted),j);
if (pm==NULL) continue; // Must not happen!
if (pmark->addr>=pm->base && pmark->addr<pm->base+pm->size)
break;
// Module found, not an orphan
;
};
if (j>=module.sorted.n) {
um.index=pmark->index; um.addroffs=pmark->addr; // This time direct address Pluginsaverecord(psave,ORPHANTAG,sizeof(um),&um);
}
}
}}
Here
I walk the list of all available modules. If main module is processed
and bookmark belongs to no defined module, it is saved with its
absolute address and tag ORPHANTAG.
See
also: