def assemble(data,arch): """ assembles a given block of data into bytecodes """ if arch=="X86": data=atandtparse.atandtpreprocess(data) tokens=atandtscan.scan(data) tree=atandtparse.parse(tokens) x=atandtparse.x86generate(tree) return x.value print "Unknown arch: %s"%arch return None
def assembleEx(data, arch): devlog("mosdef", "Assembling with arch %s" % arch) if data in ["", None]: devlog("mosdef", "assembling nothing!") return (None, None) if arch.upper() == "X86": #write out every assembled file... #file("mcode.s","w").write(data) if 1: devlog("mosdef", "Using new assembler") data = x86parse.assemble_x86(data) else: #old assembler is not compatible with #solaris x86 shellcode because we use CPUID #and a lot of other stuff it can't handle devlog("mosdef", "Using old assembler") data = atandtparse.atandtpreprocess(data) #print data tokens = atandtscan.scan(data) #print tokens #print "Getting tree" try: tree = atandtparse.parse(tokens) except: import traceback traceback.print_exc(file=sys.stdout) print "Syntax error in: %s" % data #change these numbers for sanity when you find #the line number... lines = data.split("\n")[68:75] print "Lines: %s" % ("\n".join(lines)) name = "parserbug_assembly.txt" print "Writing code that generated exception to %s" % name o = file(name, "wb") o.write(data) o.close() return (None, None) try: #print "Getting generation" x = atandtparse.x86generate(tree) except: import traceback traceback.print_exc() print "syntax error:" print data return (None, None) #print "Done assembling" return (x.value, x.metadata) return (data, None) elif arch.upper() in ["SPARC", "PPC", "ARM"]: procparse = __import__('%sparse' % arch.lower()) parser, yaccer = procparse.getparser() lexer = parser.lexer #print "pass 1" yaccer.parse(data, lexer=lexer, debug=0) #print "1: %s"%parser.labelinfo parser2, yaccer2 = procparse.getparser(runpass=2) parser2.labelinfo = parser.labelinfo #saved off from runpass 1 #print "2: %s %s"%(parser2.labelinfo,parser2.runpass) lexer2 = parser2.lexer #print "pass 2" yaccer2.parse(data, lexer=lexer2, debug=0) data = "".join(parser2.value) #print hexprint(data) return (data, None) #no metadata? print "Unknown arch: %s" % arch return (None, None)
def chunkize(shellc, wsize, jsize, arch="X86"): MAXINTELOPCODE = 9 if jsize > 127: print "Sorry, this chunksize version only support jmp rel8 (%d) " % jsize return "" data = atandtparse.atandtpreprocess(shellc) tokens = atandtscan.scan(data) tree = atandtparse.parse(tokens) x = atandtparse.x86generate(tree) #print x.metadata idx = 0 # memory index i = 0 # instruction labels = {} mark = {} result = "" chunk = "" ilength = 0 maxchunk = wsize - 2 # 2==sizeof("jmp jsize") # look for labels for a in range(0, len(x.metadata)): if x.metadata[a]["type"] == "label": labels[x.metadata[a]["label"]] = x.metadata[a] # NOTE FOR TOMORROW: # - Fijate que los marks[] se ponen por name, y en el caso de exit, se setea 2 veces, # pero una sola es la correcta, en cuanto a lo demas, parece que todo se ajusta :D # ya veremos maniana. for a in range(0, len(x.metadata)): if x.metadata[a].has_key("length"): ilength = x.metadata[a]["length"] # instruction size tmp = x.value[i:i + ilength] # intruction itself i += ilength elif x.metadata[a]["type"] == "label": name = x.metadata[a]["label"] # only for possitive "labeled" jmp if mark.has_key(name): for step in mark[name]: # ok... this is the NASTYest of the whole function (if nastyest exist on english dictionary) tmp2 = mosdef.assemble( "%s $%d" % (step[2], idx - step[0] - 2), arch) tmp2 = tmp2 + "\x90" * (step[1] - len(tmp2)) #print "\nset %s mark: %d to %d " % (name,step[3], step[3]+len(tmp2)) #for pt in range(0, len(result)): # print "[%d]" % pt + hex(ord(result[pt])), #tmp2="B" * len(tmp2) result = result[:step[3]] + tmp2 + result[step[3] + len(tmp2):] # for negative values, we update this x.metadata[a]["offset2"] = idx labels[x.metadata[a]["label"]] = x.metadata[a] continue else: print "Error: mnemonic without length: %s" % str(x.metadata[a]) if x.metadata[a].has_key("jumpto"): # is int ? where = x.metadata[a]["jumpto"] # USE LABELS :D (offset mucks everything up!) if type(where) == type(0): # make things work with integer pass elif labels.has_key(where): # Negative jmp with a label WORKING!!! if labels[where]["offset"] < x.metadata[a]["offset"]: noff = labels[where]["offset2"] - idx tmp = mosdef.assemble( "%s $%d" % (x.metadata[a]["type"], noff - ilength), arch) #if ilength+len(chunk) > maxchunk: if len(tmp) + len(chunk) > maxchunk: tmp = mosdef.assemble( "%s $%d" % (x.metadata[a]["type"], noff - len(tmp) - jsize - (wsize - len(chunk))), arch) # it might be possible that size change # jmp 127, so we will check that #if len(tmp) > ilength: # tmp= mosdef.assemble("%s $%d" % (x.metadata[a]["type"], noff - len(tmp)), arch) # print "(%d)" % (noff - len(tmp)) ilength = len(tmp) else: # POSITIVE jmp # We take the maximum possible size # jmp value # ORIGINAL psize = (x.metadata[a]["offset"] - labels[where]["offset"]) * (wsize + jsize) / wsize # and then, if its smaller, we will padd with \90 maxop = len( mosdef.assemble( "%s $%u" % (x.metadata[a]["type"], psize), arch)) ts = len(result) + len(chunk) ilength = maxop tmp = "@" * ilength bu = idx if ilength + len(chunk) > maxchunk: bu += (maxchunk - len(chunk)) + jsize ts += (wsize - len(chunk)) if mark.has_key(x.metadata[a]["jumpto"]): mark[x.metadata[a]["jumpto"]].append( (bu, maxop, x.metadata[a]["type"], ts)) else: mark[x.metadata[a]["jumpto"]] = [ (bu, maxop, x.metadata[a]["type"], ts) ] if ilength + len(chunk) > maxchunk: result+=chunk+ "\x90" * (maxchunk - len(chunk)) + \ mosdef.assemble("jmp $%d" % jsize, arch) #+ "A" * jsize # THIS IS FOR TEST POURPOSE ONLY idx += (maxchunk - len(chunk)) # padding idx += jsize # hole size idx += 2 # near jmp chunk = tmp idx += ilength else: chunk += tmp idx += ilength return result + chunk
def chunkize(shellc, wsize, jsize, arch="X86"): MAXINTELOPCODE = 9 if jsize > 127: print "Sorry, this chunksize version only support jmp rel8 (%d) " % jsize return "" data = atandtparse.atandtpreprocess(shellc) tokens = atandtscan.scan(data) tree = atandtparse.parse(tokens) x = atandtparse.x86generate(tree) #print x.metadata idx = 0 # memory index i = 0 # instruction labels = {} mark = {} result = "" chunk = "" ilength = 0 maxchunk = wsize - 2 # 2==sizeof("jmp jsize") # look for labels for a in range(0, len(x.metadata)): if x.metadata[a]["type"] == "label": labels[x.metadata[a]["label"]] = x.metadata[a] for a in range(0, len(x.metadata)): if x.metadata[a].has_key("length"): ilength = x.metadata[a]["length"] # instruction size tmp = x.value[i:i + ilength] # intruction itself i += ilength elif x.metadata[a]["type"] == "label": name = x.metadata[a]["label"] # only for possitive "labeled" jmp if mark.has_key(name): # ok... this is the NASTYest of the whole function (if nastyest exist on english dictionary) tmp2 = mosdef.assemble( "%s $%d" % (mark[name][2], idx - mark[name][0] - 2), arch) result = result[:mark[name][0]] + tmp2 + result[mark[name][0] + len(tmp2):] # for negative values, we update this x.metadata[a]["offset2"] = idx labels[x.metadata[a]["label"]] = x.metadata[a] continue else: print "Error: mnemonic without length: %s" % str(x.metadata[a]) if x.metadata[a].has_key("jumpto"): # is int ? where = x.metadata[a]["jumpto"] # USE LABELS :D (offset mucks everything up!) if type(where) == type(0): pass # make things work with integer elif labels.has_key(where): # Negative jmp with a label WORKING!!! if labels[where]["offset"] < x.metadata[a]["offset"]: noff = labels[where]["offset2"] - idx tmp = mosdef.assemble( "%s $%d" % (x.metadata[a]["type"], noff - ilength), arch) if ilength + len(chunk) > maxchunk: tmp = mosdef.assemble( "%s $%d" % (x.metadata[a]["type"], noff - len(tmp) - jsize - (maxchunk - len(chunk))), arch) # it might be possible that size change # jmp 127, so we will check that if len(tmp) > ilength: tmp = mosdef.assemble( "%s $%d" % (x.metadata[a]["type"], noff - len(tmp)), arch) ilength = len(tmp) else: # POSSITIVE jmp # We take the maximun possible size # jmp value psize = (x.metadata[a]["offset"] - labels[where]["offset"]) * (wsize + jsize) / wsize # and then, if its smaller, we will padd with \90 maxop = len( mosdef.assemble( "%s $%d" % (x.metadata[a]["type"], psize), arch)) tmp = "\x90" * maxop ilength = len(tmp) bu = idx if ilength + len(chunk) > maxchunk: # nops chunk bu += (maxchunk - len(chunk)) + jsize mark[x.metadata[a]["jumpto"]] = (bu, maxop, x.metadata[a]["type"]) if ilength + len(chunk) > maxchunk: result+=chunk+ "\x90" * (maxchunk - len(chunk)) + \ mosdef.assemble("jmp $%d" % jsize, arch) result += "A" * jsize # THIS IS FOR TEST POURPOSE ONLY idx += (maxchunk - len(chunk)) # padding idx += jsize # hole size idx += 2 # near jmp chunk = tmp idx += ilength else: chunk += tmp idx += ilength return result + chunk