#!/usr/bin/python """ Computrace Option ROM Flash dumper Copyright (c) 2009 Core Security Technologies, Core SDI Inc. Developed by Anibal Sacco (Anibal.Sacco@coresecurity.com) and Alfredo Ortega (aortega@coresecurity.com) Implementation of the flash-dumping technique described in http://www.phrack.com/issues.html?issue=66&id=7 section 3.2.1 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """ import os,struct,sys # Computrace dumper tool # if you already know both tools path, please indicate below. # Will be autodetected otherwise flashRomPath="" upxPath="" dmidecodePath="" # BIOS file name BIOSFile="BIOSDUMP.bin" # Computrace Option rom filename OROMFile="computrace.rom" temporalFile="TMPdumpTmp.tmp" # Prints Option ROM Information def dumpOptionRomInfo(bios,pos): if struct.unpack("H",bios[pos:pos+2])[0] == 0xAA55: print "[INFO] Option Rom header found at position %x" % pos else: print "[ERROR] Option Rom header not found!" return -1 ORlen=ord(bios[pos+2:pos+3])*512 print "[INFO] Option Rom lenght: %s" % ORlen ORversion=bios[pos+5:pos+5+18] print "[INFO] Version: %s" % ORversion VID=struct.unpack("H",bios[pos+33:pos+35])[0] CID=struct.unpack("H",bios[pos+35:pos+37])[0] print "[INFO] PCI Vendor/CHIP ID: %x:%x" % (VID,CID) computrace=bios[pos:pos+ORlen] upxFound=0 if computrace.find("UPX!")>0: print "[INFO] UPX signature found -> Not a stub, complete agent found." upxFound=1 else: print "[INFO] Computrace found but no UPX signature -> this may be the Stub Agent" print "[INFO] Dumping to '%s' file..." % OROMFile dumpfile=open(OROMFile,"wb") dumpfile.write(computrace) dumpfile.close() return upxFound def dumpTheEasyWay(): print "[INFO] Triying to dump the BIOS, the easy way." cmd="flashrom -r %s > /dev/null" % BIOSFile print "[CMD] Executing '%s'" % cmd os.system(cmd) try: BIOS=open(BIOSFile,"rb").read() except: print "[INFO] That didn't work." return "" print "[INFO] FlashRom recognized and dumped the Flash Chip in %s" % BIOSFile if BIOS.find("CompuTrace")>0: print ("[SUCCESS] Computrace Found!") return BIOS return "" def dumpTheHardWay(): #finding list of flashrom supported chips print "[INFO] Triying to dump the BIOS, the hard way." cmd="flashrom -L > %s" % temporalFile print "[CMD] Executing '%s'" % cmd os.system(cmd) FR=open(temporalFile,"rb") chips=[] # parsing the chip list provided by FlashRom for line in FR.readlines(): if line.find("chipsets")>0: break line=line.split() if len(line)>0: if len(line[1])>0: chips.append(line[1]) print "[INFO] About %d flash models supported by Flashrom, triying all of them..." % len(chips) for chip in chips: cmd="flashrom -f -r -c %s %s > /dev/null" % (chip,BIOSFile) print "[CMD] Executing '%s'" % cmd os.system(cmd) try: f=open(BIOSFile,"rb") BIOS=f.read() f.close() if BIOS.find("CompuTrace")>0: print ("[SUCCESS] Computrace Found!") return BIOS except: pass return "" def unpackOptionRom(OROMFile): #The Option Rom inicialization is 1024 bytes in lenght. OROM=open(OROMFile,"rb").read() UPXOROMname="%s.unpacked" % OROMFile UPXOROM=open(UPXOROMname,"wb") pos=OROM.find("UPX!") if (pos==-1): print "[ERROR] UPX signature not found!" return "" UPXOROM.write(OROM[pos-4:]) UPXOROM.close() cmd="upx -d %s" % UPXOROMname print "[CMD] Executing '%s'" % cmd os.system(cmd) return UPXOROMname #---------------------------------------------------- # Usage if len(sys.argv)<2: print "Search and dumps computrace Agent in BIOS" print "Alfredo Ortega - Anibal Sacco - Core Security Technologies" print "If you really want to dump the bios, try '%s --dump' as root" % sys.argv[0] exit(0) # search for required tools #Flashrom if flashRomPath=="": os.system("which flashrom > %s" % temporalFile) flashRomPath=open(temporalFile,"rb").read() if len(flashRomPath)==0: print "[ERROR] FlashROM tool not found! Exiting..." print "[ERROR] Try: 'sudo apt-get install flashrom' in debian-based linux distros" exit(-1) #UPX if upxPath=="": os.system("which upx > %s" % temporalFile) upxPath=open(temporalFile,"rb").read() if len(upxPath)==0: print "[ERROR] UPX tool not found! continuing but will not uncompress Option ROM if found..." print "[ERROR] Try: 'sudo apt-get install upx' in debian-based linux distros" #DMIDecode if dmidecodePath=="": os.system("which dmidecode > %s" % temporalFile) dmidecodePath=open(temporalFile,"rb").read() if len(dmidecodePath)==0: print "[ERROR] dmidecode tool not found! continuing but will not report BIOS and computer make." print "[ERROR] Try: 'sudo apt-get install dmidecode' in debian-based linux distros" else: print "[INFO] System type:" os.system("dmidecode -t 1") #cleanup try: os.unlink(temporalFile) except: pass #Try the easy way, automatically recognize the Flash chip BIOS=dumpTheEasyWay() if len(BIOS)>0: if dumpOptionRomInfo(BIOS,BIOS.find("CompuTrace")-5) == 1: if upxPath!="": print "[INFO] We found UPX, triying to unpack Option ROM..." name = unpackOptionRom(OROMFile) print "[INFO] If upacking was successfull, the file %s can be run directly from DOS, is a .COM file" % name exit(0) print "[INFO] We found a UPX-compressed ROM, but no UPX present in path, couldn't decompress" exit(0) #Try the hard way, bruteforcing all known chips BIOS=dumpTheHardWay() if len(BIOS)>0: if dumpOptionRomInfo(BIOS,BIOS.find("CompuTrace")-5) == 1: if upxPath!="": print "We found UPX, triying to unpack Option ROM..." name=unpackOptionRom(OROMFile) print "[INFO] If upacking was successfull, the file %s can be run directly from DOS, is a .COM file" % name exit(0) print "[INFO] We found a UPX-compressed ROM, but no UPX present in path, couldn't decompress" exit(0)