import angrimport monkeyhex # this will format numerical results in hexadecimal#Load binaryproj = angr.Project('/bin/true')#BASIC BINARY DATAproj.arch #Get arch "<Arch AMD64 (LE)>"proj.arch.name #'AMD64'proj.arch.memory_endness #'Iend_LE'proj.entry #Get entrypoint "0x4023c0"proj.filename #Get filename "/bin/true"#There are specific options to load binaries#Usually you won't need to use them but you couldangr.Project('examples/fauxware/fauxware', main_opts={'backend': 'blob', 'arch': 'i386'}, lib_opts={'libc.so.6': {'backend': 'elf'}})
strcmp = proj.loader.find_symbol('strcmp')#<Symbol "strcmp" in libc.so.6 at 0x1089cd0>strcmp.name #'strcmp'strcmp.owne #<ELF Object libc-2.23.so, maps [0x1000000:0x13c999f]>strcmp.rebased_addr #0x1089cd0strcmp.linked_addr #0x89cd0strcmp.relative_addr #0x89cd0strcmp.is_export #True, as 'strcmp' is a function exported by libc#Get strcmp from the main objectmain_strcmp = proj.loader.main_object.get_symbol('strcmp')main_strcmp.is_export #Falsemain_strcmp.is_import #Truemain_strcmp.resolvedby #<Symbol "strcmp" in libc.so.6 at 0x1089cd0>
Μπλοκς
#Blocksblock = proj.factory.block(proj.entry)#Get the block of the entrypoint fo the binaryblock.pp()#Print disassembly of the blockblock.instructions #"0xb" Get number of instructionsblock.instruction_addrs #Get instructions addresses "[0x401670, 0x401672, 0x401675, 0x401676, 0x401679, 0x40167d, 0x40167e, 0x40167f, 0x401686, 0x40168d, 0x401694]"
Δυναμική Ανάλυση
Διαχειριστής Προσομοίωσης, Καταστάσεις
#Live States#This is useful to modify content in a live analysisstate = proj.factory.entry_state()state.regs.rip #Get the RIPstate.mem[proj.entry].int.resolved #Resolve as a C int (BV)state.mem[proj.entry].int.concreteved #Resolve as python intstate.regs.rsi = state.solver.BVV(3, 64)#Modify RIPstate.mem[0x1000].long =4#Modify mem#Other Statesproject.factory.entry_state()project.factory.blank_state()#Most of its data left uninitializedproject.factory.full_init_statetate() #Execute through any initializers that need to be run before the main binary's entry point
project.factory.call_state()#Ready to execute a given function.#Simulation manager#The simulation manager stores all the states across the execution of the binarysimgr = proj.factory.simulation_manager(state)#Startsimgr.step()#Execute one stepsimgr.active[0].regs.rip #Get RIP from the last state
Κλήση συναρτήσεων
Μπορείτε να περάσετε μια λίστα παραμέτρων μέσω args και ένα λεξικό μεταβλητών περιβάλλοντος μέσω env στο entry_state και full_init_state. Οι τιμές σε αυτές τις δομές μπορούν να είναι συμβολοσειρές ή bitvectors, και θα σειριοποιηθούν στην κατάσταση ως οι παράμετροι και το περιβάλλον για την προσομοιωμένη εκτέλεση. Η προεπιλεγμένη args είναι μια κενή λίστα, οπότε αν το πρόγραμμα που αναλύετε περιμένει να βρει τουλάχιστον ένα argv[0], θα πρέπει πάντα να το παρέχετε!
Αν θέλετε να έχετε το argc συμβολικό, μπορείτε να περάσετε ένα συμβολικό bitvector ως argc στους κατασκευαστές entry_state και full_init_state. Να είστε προσεκτικοί, όμως: αν το κάνετε αυτό, θα πρέπει επίσης να προσθέσετε έναν περιορισμό στην προκύπτουσα κατάσταση ότι η τιμή σας για το argc δεν μπορεί να είναι μεγαλύτερη από τον αριθμό των args που περάσατε στο args.
Για να χρησιμοποιήσετε την κατάσταση κλήσης, θα πρέπει να την καλέσετε με .call_state(addr, arg1, arg2, ...), όπου addr είναι η διεύθυνση της συνάρτησης που θέλετε να καλέσετε και argN είναι η Nη παράμετρος σε αυτή τη συνάρτηση, είτε ως ακέραιος αριθμός python, συμβολοσειρά ή πίνακας, είτε ως bitvector. Αν θέλετε να έχετε μνήμη κατανεμημένη και να περάσετε πραγματικά έναν δείκτη σε ένα αντικείμενο, θα πρέπει να το τυλίξετε σε ένα PointerWrapper, δηλαδή angr.PointerWrapper("point to me!"). Τα αποτελέσματα αυτού του API μπορεί να είναι λίγο απρόβλεπτα, αλλά εργαζόμαστε πάνω σε αυτό.
BitVectors
#BitVectorsstate = proj.factory.entry_state()bv = state.solver.BVV(0x1234, 32)#Create BV of 32bits with the value "0x1234"state.solver.eval(bv)#Convert BV to python intbv.zero_extend(30)#Will add 30 zeros on the left of the bitvectorbv.sign_extend(30)#Will add 30 zeros or ones on the left of the BV extending the sign
Συμβολικά BitVectors & Περιορισμοί
x = state.solver.BVS("x", 64)#Symbolic variable BV of length 64y = state.solver.BVS("y", 64)#Symbolic oprationstree = (x +1) / (y +2)tree #<BV64 (x_9_64 + 0x1) / (y_10_64 + 0x2)>tree.op #'__floordiv__' Access last operationtree.args #(<BV64 x_9_64 + 0x1>, <BV64 y_10_64 + 0x2>)tree.args[0].op #'__add__' Access of dirst argtree.args[0].args #(<BV64 x_9_64>, <BV64 0x1>)tree.args[0].args[1].op #'BVV'tree.args[0].args[1].args #(1, 64)#Symbolic constraints solverstate = proj.factory.entry_state()#Get a fresh state without constraintsinput= state.solver.BVS('input', 64)operation = (((input+4) *3) >>1) +inputoutput =200state.solver.add(operation == output)state.solver.eval(input)#0x3333333333333381state.solver.add(input<2**32)state.satisfiable()#False#Solver solutionssolver.eval(expression)#one possible solutionsolver.eval_one(expression)#solution to the given expression, or throw an error if more than one solution is possible.solver.eval_upto(expression, n) #n solutions to the given expression, returning fewer than n if fewer than n are possible.
solver.eval_atleast(expression, n) #n solutions to the given expression, throwing an error if fewer than n are possible.
solver.eval_exact(expression, n) #n solutions to the given expression, throwing an error if fewer or more than are possible.
solver.min(expression)#minimum possible solution to the given expression.solver.max(expression)#maximum possible solution to the given expression.
Hooking
>>> stub_func = angr.SIM_PROCEDURES['stubs']['ReturnUnconstrained'] # this is a CLASS>>> proj.hook(0x10000, stub_func())# hook with an instance of the class>>> proj.is_hooked(0x10000)# these functions should be pretty self-explanitoryTrue>>> proj.hooked_by(0x10000)<ReturnUnconstrained>>>> proj.unhook(0x10000)>>>@proj.hook(0x20000, length=5)... defmy_hook(state):... state.regs.rax =1>>> proj.is_hooked(0x20000)True
Επιπλέον, μπορείτε να χρησιμοποιήσετε proj.hook_symbol(name, hook), παρέχοντας το όνομα ενός συμβόλου ως το πρώτο επιχείρημα, για να συνδέσετε τη διεύθυνση όπου βρίσκεται το σύμβολο.