#ifndef __PROCESSCONTEXT_H__ #define __PROCESSCONTEXT_H__ #include #include #include class ProcessContext { public: void readmemory(uint32_t offset, uint32_t size, uint8_t* oiter) { while (size--) *oiter++ = readbyte(offset++); } void writememory(uint32_t offset, uint32_t size, const uint8_t* iter) { while (size--) writebyte(offset++, *iter++); } void readmemory(uint32_t offset, uint32_t size, uint32_t* oiter) { while (size--) *oiter++ = readdword(offset++); } void writememory(uint32_t offset, uint32_t size, const uint32_t* iter) { while (size--) writedword(offset++, *iter++); } virtual uint32_t readdword(uint32_t offset)=0; virtual void writedword(uint32_t offset, uint32_t value)=0; virtual uint8_t readbyte(uint32_t offset)=0; virtual void writebyte(uint32_t offset, uint8_t value)=0; virtual uint32_t alloc(uint32_t size)= 0; virtual void free(uint32_t ptr)= 0; virtual uint32_t pid() const= 0; virtual uint32_t canonicaladdress(uint32_t a)=0; }; typedef boost::shared_ptr ProcessContext_ptr; struct VirtualAddress { ProcessContext_ptr proc; uint32_t vaddr; VirtualAddress(ProcessContext_ptr proc, uint32_t vaddr) : proc(proc), vaddr(vaddr) { } }; inline bool operator==(const VirtualAddress& a, const VirtualAddress& b) { return a.proc->canonicaladdress(a.vaddr)==b.proc->canonicaladdress(b.vaddr); } inline bool operator<(const VirtualAddress& a, const VirtualAddress& b) { return a.proc->canonicaladdress(a.vaddr) < b.proc->canonicaladdress(b.vaddr); } class PatchManager { struct patchedbyte { patchedbyte() : original(0), patched(0) { } patchedbyte(uint8_t o, uint8_t p) : original(o), patched(p) { } uint8_t original; uint8_t patched; }; typedef std::map patchmap_t; patchmap_t _patches; ProcessContext_ptr _proc; public: PatchManager(ProcessContext_ptr proc) : _proc(proc) { } template void readoriginal(uint32_t offset, uint32_t size, T oiter) { patchmap_t::iterator i= _patches.lower_bound(offset); while (size--) { if (i==_patches.end() || offset < (*i).first) *oiter = _proc->readbyte(offset); else if (offset == (*i).first) { *oiter = (*i++).second.original; } else { throw "program error"; } ++oiter; ++offset; } } template void patchmemory(uint32_t offset, T first, T last) { patchmap_t::iterator i= _patches.lower_bound(offset); while (first!=last) { uint8_t patched= *first; if (i==_patches.end() || offset < (*i).first) { uint8_t original= _proc->readbyte(offset); if (original != patched) _patches[offset] = patchedbyte(original, patched); } else if (offset == (*i).first) { if ((*i).second.original!=patched) (*i++).second.patched= patched; else _patches.erase(i++); } else { throw "program error"; } _proc->writebyte(offset, patched); ++first; ++offset; } } void deletepatch(uint32_t offset, uint32_t size) { patchmap_t::iterator i= _patches.lower_bound(offset); while (i!=_patches.end() && (*i).firstwritebyte((*i).first, (*i).second.original); _patches.erase(i++); } } uint32_t originaldword(uint32_t offset) { uint8_t bytes[4]; readoriginal(offset, 4, bytes); return *(uint32_t*)bytes; } void patchdword(uint32_t offset, uint32_t value) { patchmemory(offset, (const uint8_t*)&value, (const uint8_t*)(&value+1)); } }; #endif