def kernel_stack(vm): sp0 = vm.mem.read_dword(vm.cpu.sr.tr_base + 4) ss3 = vm.mem.read_dword(sp0 - 4) sp3 = vm.mem.read_dword(sp0 - 8) cs3 = vm.mem.read_dword(sp0 - 16) off = vm.cpu.sr.gdtr_base + (cs3 & (~3)) dsc = SegmentDescriptor(vm.mem.vread(off, 8)) if dsc.dpl != 3: return False off = vm.cpu.sr.gdtr_base + (ss3 & (~3)) dsc = SegmentDescriptor(vm.mem.vread(off, 8)) sp3 = vm.cpu.linear(dsc.base, sp3) nm_sz = 100 stack = (sp3 & PgMsk.addr) + 4096 while True: try: vm.mem.translate(stack) except: break stack += 4096 nm_addr = stack - nm_sz name = vm.mem.vread(nm_addr, nm_sz).strip('\x00').split('\x00')[-1] log("info", "[%s]" % (repr(name))) return False
def __init__(self, vm, cr3): if vm.cpu.mode.pg != CPUMode.pg32: log("error", "paging mode not supported: %s" % vm.cpu.mode) raise ValueError self.pgd = PageDirectory(vm, cr3) self.map = Mapping(self.pgd)
def kernel_stack(vm): sp0 = vm.mem.read_dword(vm.cpu.sr.tr_base + 4) ss3 = vm.mem.read_dword(sp0 - 4) sp3 = vm.mem.read_dword(sp0 - 8) cs3 = vm.mem.read_dword(sp0 - 16) off = vm.cpu.sr.gdtr_base + (cs3 & (~3)) dsc = SegmentDescriptor(vm.mem.vread(off, 8)) if dsc.dpl != 3: return False off = vm.cpu.sr.gdtr_base + (ss3 & (~3)) dsc = SegmentDescriptor(vm.mem.vread(off, 8)) sp3 = vm.cpu.linear(dsc.base, sp3) nm_sz = 100 stack = (sp3 & PgMsk.addr) + 4096 while True: try: vm.mem.translate(stack) except: break stack += 4096 nm_addr = stack - nm_sz name = vm.mem.vread(nm_addr, nm_sz).strip("\x00").split("\x00")[-1] log("info", "[%s]" % (repr(name))) return False
def on_write_cr3(vm): cr3 = vm.cpu.sr.cr3 & PgMsk.addr if not vm.ads.has_key(cr3): vm.ads[cr3] = AddrSpace(vm, cr3) log("info", "added new cr3 0x%x to ads (#%d)" % (cr3, len(vm.ads))) #return True return False
def search_page(page, data): blob = vm.mem.pread(page.paddr, 4<<10) idx = blob.find(data) if idx == -1: return None log("info", "found data @ paddr 0x%x" % (page.paddr+idx)) return page.paddr+idx
def __init__(self, val): self.raw = val self.p = val & PgMsk.present self.w = val & PgMsk.write self.u = val & PgMsk.user self.addr = val & PgMsk.addr log("paging", str(self))
def search_page(page, data): blob = vm.mem.pread(page.paddr, 4 << 10) idx = blob.find(data) if idx == -1: return None log("info", "found data @ paddr 0x%x" % (page.paddr + idx)) return page.paddr + idx
def OSFactory(affinity, settings=None): if affinity == OSAffinity.Linux26: return Linux26(settings) elif affinity == OSAffinity.WinXP: return WinXP(settings) elif affinity == OSAffinity.Win7: return Win7(settings) log("error", "Unknown OS affinity") raise ValueError
def __init__(self, vm, vaddr, paddr): self.addr = paddr log("paging", "PageTable reading physical page @ 0x%x" % paddr) self.raw = struct.unpack("<1024L", vm.mem.pread(paddr, 4<<10)) self.pte = [] for i in xrange(1024): self.pte.append(Pte(vaddr, self.raw[i])) vaddr += 4<<10
def find_kmem(vm): log("fkm", "Looking for kernel pages into user mappings") #check if they have another mapping with user privilege fmt = "U ads 0x%x match K ads 0x%x:\n (user) %s\n (krnl) %s" for klst in vm.kppg.itervalues(): for ka, kp in klst: for a in vm.ads: ulst = vm.ads[a].search_paddr(kp.paddr, user=True) if len(ulst) != 0: for p in ulst: log("fkm", fmt % (a, ka, p, kp))
def find_kmem(vm): log("fkm", "Looking for kernel pages into user mappings") #check if they have another mapping with user privilege fmt = "U ads 0x%x match K ads 0x%x:\n (user) %s\n (krnl) %s" for klst in vm.kppg.itervalues(): for ka,kp in klst: for a in vm.ads: ulst = vm.ads[a].search_paddr(kp.paddr,user=True) if len(ulst) != 0: for p in ulst: log("fkm", fmt % (a,ka,p,kp))
def wcr3(vm): cr3 = vm.cpu.sr.cr3 & PgMsk.addr if not cr3: return False if not vm.ads.has_key(cr3): ads = AddrSpace(vm, cr3) vm.ads[cr3] = ads log("info", "added new cr3 0x%x to ads (%d)" % (cr3, len(vm.ads))) search_ads(ads) return False
def __init__(self, vm, cr3): self.addr = cr3 & PgMsk.addr log("paging", "PageDirectory reading physical page @ 0x%x" % self.addr) self.raw = struct.unpack("<1024L", vm.mem.pread(self.addr, 4<<10)) self.pde = [] vaddr = 0 for i in xrange(1024): self.pde.append(Pde(vm, vaddr, self.raw[i])) vaddr += 4<<20
def wcr3(vm): cr3 = vm.cpu.sr.cr3 & PgMsk.addr if not cr3: return False if not vm.ads.has_key(cr3): ads = AddrSpace(vm, cr3) vm.ads[cr3] = ads for p in ads.iter_pages(user=False): vm.kppg[p.paddr].append((cr3,p)) log("info", "added new cr3 0x%x to ads (%d)" % (cr3, len(vm.ads))) return False
def wcr3(vm): cr3 = vm.cpu.sr.cr3 & PgMsk.addr if not cr3: return False if not vm.ads.has_key(cr3): ads = AddrSpace(vm, cr3) vm.ads[cr3] = ads for p in ads.iter_pages(user=False): vm.kppg[p.paddr].append((cr3, p)) log("info", "added new cr3 0x%x to ads (%d)" % (cr3, len(vm.ads))) return False
def wcr3(vm): cr3 = vm.cpu.sr.cr3 & PgMsk.addr if not cr3: return False if not vm.ads.has_key(cr3): ads = AddrSpace(vm, cr3) vm.ads[cr3] = ads log("info", "added new cr3 0x%x to ads (%d)" % (cr3, len(vm.ads))) elif len(vm.ads) >= vm.nr_cr3: return find_shared(vm) return False
def __find_process(self, vm): kprcb = vm.mem.read_dword(vm.cpu.sr.fs_base+self.__settings["kprcb"]) kthread = vm.mem.read_dword(kprcb+self.__settings["kthread"]) eprocess = vm.mem.read_dword(kthread+self.__settings["eprocess"]) while eprocess != 0: name = vm.mem.vread(eprocess+self.__settings["name"],16) log("os", "process %s" % name[:name.index('\x00')]) if self.__pname in name: self.__pcr3 = vm.mem.read_dword(eprocess+self.__settings["cr3"]) log("os", "cr3 %#x" % self.__pcr3) return True elif "Idle" in name: return False eprocess = vm.mem.read_dword(eprocess+self.__settings["next"]) eprocess -= self.__settings["next"] return False
def __finish(self): if len(self.__symbols) == 1: return None log("symbols", "sorting symbols") self.__symbols.sort() log("symbols", "recompute size") for i in range(0,len(self.__symbols)): s = self.__symbols[i] s.prev = self.__symbols[(i-1)%len(self.__symbols)] s.next = self.__symbols[(i+1)%len(self.__symbols)] if s.size == 0: n = s.next s.size = n.addr - s.addr return self.__symbols
def __finish(self): if len(self.__symbols) == 1: return None log("symbols", "sorting symbols") self.__symbols.sort() log("symbols", "recompute size") for i in range(0, len(self.__symbols)): s = self.__symbols[i] s.prev = self.__symbols[(i - 1) % len(self.__symbols)] s.next = self.__symbols[(i + 1) % len(self.__symbols)] if s.size == 0: n = s.next s.size = n.addr - s.addr return self.__symbols
def __walk_process(self, vm, task): head = task while True: mm = vm.mem.read_dword(task+self.__settings["mm"]) if mm != 0: comm = task+self.__settings["comm"] name = vm.mem.vread(comm, 15) pgd = vm.mem.read_dword(mm+self.__settings["pgd"]) log("os", "task %s" % name) if self.__pname in name: self.__task = task self.__pcr3 = pgd - 0xc0000000 log("os", "cr3 %#x" % self.__pcr3) return True task = self.__next_task(vm, task) if task == head: return False
def search_ads(ads): log("sads", "Searching PGD/PTs mapping into address space 0x%x" % ads.pgd.addr) ptb_addrs = [ads.pgd.addr] for p in ads.iter_pagetables(): ptb_addrs.append(p.addr) log("sads", "PGD/PTs : %s" % " ".join([hex(i) for i in ptb_addrs])) for a in ptb_addrs: plst = ads.search_paddr(a) if len(plst) != 0: log("sads", "match for 0x%x" % a) for p in plst: log("sads", "%s" % p)
def find_shared(vm): log("fsm", "Find shared pages accross address spaces") vm.all_pages = defaultdict(list) for a in vm.ads: for p in vm.ads[a].iter_pages(user=True): vm.all_pages[p.paddr].append((a,p)) for addr,pages in vm.all_pages.iteritems(): if len(pages) > 1: log("fsm", "match for 0x%x" % addr) for ads,pg in pages: log("fsm", "ads 0x%x: %s" % (ads,pg)) return True
def find_shared(vm): log("fsm", "Find shared pages accross address spaces") vm.all_pages = defaultdict(list) for a in vm.ads: for p in vm.ads[a].iter_pages(user=True): vm.all_pages[p.paddr].append((a, p)) for addr, pages in vm.all_pages.iteritems(): if len(pages) > 1: log("fsm", "match for 0x%x" % addr) for ads, pg in pages: log("fsm", "ads 0x%x: %s" % (ads, pg)) return True
from amoco.arch.x86 import cpu_x86 as am from ramooflax.core import VM, CPUFamily, log from ramooflax.utils import disassemble def disasm_wrapper(addr, data): return am.disassemble(data, address=addr) def sstep_disasm(vm): insns = disassemble(vm, disasm_wrapper, vm.cpu.code_location()) print insns.split('\n')[0] return True ## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer) log.setup(info=True, fail=True, gdb=False) vm.attach() vm.stop() vm.cpu.filter_singlestep(sstep_disasm) log("info", "\n####\n#### type: vm.singlestep()\n####\n") vm.interact(dict(globals(), **locals())) vm.detach()
#!/usr/bin/env python # # Filter on CPUID=4 # from ramooflax.core import VM, CPUFamily, log def cpuid_hook(vm): log("info", "cpuid(1) = 0x%x 0x%x 0x%x 0x%x" % (vm.cpu.gpr.eax, vm.cpu.gpr.ebx, vm.cpu.gpr.ecx, vm.cpu.gpr.edx)) return False ## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer) log.setup(info=True, fail=True) vm.attach() vm.stop() vm.cpu.filter_cpuid(cpuid_hook, 1) log("info", "ramooflax ready!") vm.interact2(dict(globals(), **locals()))
def hypercall(vm): log("info", "hypercall") return True
def sstep(vm): log("info", "sstep") print disasm(vm) return False
def cpuid_hook(vm): log("info", "cpuid(1) = 0x%x 0x%x 0x%x 0x%x" % (vm.cpu.gpr.eax, vm.cpu.gpr.ebx, vm.cpu.gpr.ecx, vm.cpu.gpr.edx)) return False
def pf_hook(vm): log("info", "Page Fault @ %#x" % vm.cpu.gpr.pc) return True
def __start(self): log("symbols", "loading symbols")
#!/usr/bin/env python # # read msr 0x1b = APIC_BASE # from ramooflax.core import VM, CPUFamily, log ## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer) log.setup(info=True, fail=True) vm.attach() vm.stop() vm.cpu.msr.read(0x1b) log("info", "MSR(APIC_BASE) = 0x%x 0x%x" % (vm.cpu.msr.eax, vm.cpu.msr.edx)) vm.detach()
def show_page(ads, vaddr): pg = get_page(ads, vaddr) log("info", "%s" % pg)
# # We are looking for "argv[1]" running under debian # # We install the Linux26.find_process_filter on cr3 writes # The framework will call our filter Before each write # import sys from ramooflax.core import VM, CPUFamily, log from ramooflax.utils import OSFactory, OSAffinity # create logging for this script log.setup(info=True, fail=True) if len(sys.argv) < 2: log("fail", "gimme prog name") sys.exit(-1) # Target process process_name = sys.argv[1] # Some offsets for debian 2.6.32-5-486 kernel settings = {"thread_size":8192, "comm":540, "next":240, "mm":268, "pgd":36} os = OSFactory(OSAffinity.Linux26, settings) hook = os.find_process_filter(process_name) ## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer)
for ads, pg in pages: log("fsm", "ads 0x%x: %s" % (ads, pg)) return True ## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer) vm.nr_cr3 = 5 vm.ads = {} log.setup(info=True, fail=True, gdb=False, vm=True, brk=True, evt=False, fsm=(True, log.blue)) vm.attach() vm.stop() vm.cpu.filter_write_cr(3, wcr3) log("info", "ready!") vm.interact2(dict(globals(), **locals()))
# # This script uses amoco engine (https://github.com/bdcht/amoco) # from amoco.arch.x86 import cpu_x86 as am from ramooflax.core import VM, CPUFamily, log from ramooflax.utils import disassemble def disasm_wrapper(addr, data): return am.disassemble(data, address=addr) def sstep_disasm(vm): insns = disassemble(vm, disasm_wrapper, vm.cpu.code_location()) print insns.split('\n')[0] return True ## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer) log.setup(info=True, fail=True, gdb=False) vm.attach() vm.stop() vm.cpu.filter_singlestep(sstep_disasm) log("info", "\n####\n#### type: vm.singlestep()\n####\n") vm.interact(dict(globals(), **locals())) vm.detach()
# Print eip on raised page fault def pf_hook(vm): log("info", "Page Fault @ %#x" % vm.cpu.gpr.pc) return True ## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer) vm.attach() vm.stop() vm.cpu.filter_write_cr(3, hook) while not vm.resume(): continue vm.cpu.release_write_cr(3) vm.cpu.set_active_cr3(os.get_process_cr3(), True, OSAffinity.Linux26) vm.cpu.filter_exception(CPUException.page_fault, pf_hook) vm.cpu.lbr.enable() vm.resume() log("info", vm.cpu.gpr) log("info", vm.cpu.lbr) vm.detach()
# # We are looking for "argv[1]" running under debian # # We install the Linux26.find_process_filter on cr3 writes # The framework will call our filter Before each write # import sys from ramooflax.core import VM, CPUFamily, log from ramooflax.utils import OSFactory, OSAffinity # create logging for this script log.setup(info=True, fail=True) if len(sys.argv) < 2: log("fail", "gimme prog name") sys.exit(-1) # Target process process_name = sys.argv[1] # Some offsets for debian 2.6.32-5-486 kernel settings = { "thread_size": 8192, "comm": 540, "next": 240, "mm": 268, "pgd": 36 } os = OSFactory(OSAffinity.Linux26, settings) hook = os.find_process_filter(process_name)
#!/usr/bin/env python # # Filter on CPUID=4 # from ramooflax.core import VM, CPUFamily, log def cpuid_hook(vm): log("info", "cpuid(1) = 0x%x 0x%x 0x%x 0x%x" % \ (vm.cpu.gpr.eax,vm.cpu.gpr.ebx,vm.cpu.gpr.ecx,vm.cpu.gpr.edx)) return False ## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer) log.setup(info=True, fail=True) vm.attach() vm.stop() vm.cpu.filter_cpuid(cpuid_hook, 1) log("info", "ramooflax ready!") vm.interact2(dict(globals(), **locals()))
def cpuid_hook(vm): log("info", "cpuid(1) = 0x%x 0x%x 0x%x 0x%x" % \ (vm.cpu.gpr.eax,vm.cpu.gpr.ebx,vm.cpu.gpr.ecx,vm.cpu.gpr.edx)) return False
# We are looking for "argv[1]" running under windows 7 # # We install a filter on cr3 writes # On each write, the vmm gives us control # before the write operation # import sys from ramooflax.core import VM, CPUFamily, log from ramooflax.utils import OSFactory, OSAffinity # create logging for this script log.setup(info=True, fail=True) if len(sys.argv) < 2: log("fail", "gimme prog name") sys.exit(-1) # Target process process_name = sys.argv[1] # Some offsets for Windows 7 Premium FR 32 bits settings = {"kprcb":0x20, "kthread":4, "eprocess":0x150, "name":0x16c, "cr3":0x18, "next":0xb8} os = OSFactory(OSAffinity.Win7, settings) hook = os.find_process_filter(process_name) ## ## Main
for p in ulst: log("fkm", fmt % (a,ka,p,kp)) ## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer) vm.nr_cr3 = 1 vm.ads = {} #keep track of every kernel physical pages vm.kppg = defaultdict(list) log.setup(info=True, fail=True, gdb=False, vm=True, brk=True, evt=False, fkm=(True,log.blue)) vm.attach() vm.stop() vm.cpu.filter_write_cr(3, wcr3) log("info", "ready!") while len(vm.ads) < vm.nr_cr3: vm.resume() vm.detach() find_kmem(vm)
## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer) vm.attach() vm.stop() vm.cpu.breakpoints.add_data_w(vm.cpu.sr.tr_base+4, 4, hook) while not vm.resume(): continue vm.cpu.breakpoints.remove(1) vm.cpu.set_active_cr3(os.get_process_cr3(), affinity=OSAffinity.Linux26) log("info", "found break process") # # Breakpoints handling # #1 vm.cpu.breakpoints.remove() vm.cpu.breakpoints.add_insn(0x804844b) vm.cpu.breakpoints.add_insn(0x804846b, lambda x:False) while vm.resume(): continue if vm.cpu.gpr.pc != 0x804846b: log("fail", "failure 1") vm.detach(leave=True)
## ## Main ## peer = "172.16.131.128:1337" vm = VM(CPUFamily.Intel, peer) vm.attach() vm.stop() vm.cpu.breakpoints.add_data_w(vm.cpu.sr.tr_base + 4, 4, hook) while not vm.resume(): continue vm.cpu.breakpoints.remove(1) vm.cpu.set_active_cr3(os.get_process_cr3(), affinity=OSAffinity.Linux26) log("info", "found break process") # # Breakpoints handling # #1 vm.cpu.breakpoints.remove() vm.cpu.breakpoints.add_insn(0x804844b) vm.cpu.breakpoints.add_insn(0x804846b, lambda x: False) while vm.resume(): continue if vm.cpu.gpr.pc != 0x804846b: log("fail", "failure 1") vm.detach(leave=True)