#!/usr/bin/python # # The following Python code will take shellcode (buf variable) # and create SUB instructions that will generate shellcode four # bytes at a time and push them to the stack. # # The trick with this code is that EAX needs to be zeroed out before # each new set of SUB instructions. Also, the stack needs to be # aligned to be where you can execute the pushed instructions. All of # this is left to the reader. # # Author: Absane (blog.noobroot.comu) # Modified by: Alton Johnson (alton.jx@gmail.com) # # Last Updated: March 12, 2015 (by Alton Johnson) # import sys, os, getopt from random import choice from sys import argv total_length = 0 ### CHARACTERS THAT ARE ALLOWED ### code = '' goodchars = [] # Add all characters to the "good character" list. Replaced with -g for i in range(0, 256): goodchars.append(format(i, "#04x").replace("0x", "")) def compl(hexvalue): return int("FFFFFFFF",16) - int(hexvalue,16)+1 def findvalues(code, carry, last): total = 9999999999 wastetime = 99999 while (total != int(code,16)): a = choice(goodchars) b = choice(goodchars) c = choice(goodchars) total = int(a,16) + int(b,16) + int(c,16)+carry if (( total - 256 == int(code,16) ) and (last != 1) & wastetime < 1): return (a,b,c,1) wastetime += -1 return (a,b,c,0) def encode(x): global code, total_length y = x endian = (y[6] + y[7]) + (y[4] + y[5]) + (y[2] + y[3]) + (y[0] + y[1]) twocompl = compl(endian) k = str(hex(twocompl))[2:99].strip("L") k = "0" * ( 8 - len(k) ) + k first = k[0:2] second= k[2:4] third = k[4:6] fourth= k[6:8] a = findvalues(fourth,0,0) b = findvalues(third,a[3],0) c = findvalues(second,b[3],0) d = findvalues(first,c[3],1) output = '' final = '' plain = [] for i in range(0,3): for k in (a,b,c,d): output += "\\x" + k[i] plain.append(k[i]) final += '\n\"\\x2d' + output + "\"" total_length += (len(output)/4+1) final += "\t# SUB EAX," + plain[3] + plain[2] + plain[1] + plain[0] output = '' plain = [] code += "\n# Encoded: " + x code += "\n\"" + r"\x25\x41\x41\x41\x41" + "\"\t# SUB EAX,41414141" code += "\n\"" + r"\x25\x3E\x3E\x3E\x3E" + "\"\t# SUB EAX,3E3E3E3E" code += final code += "\n\"" + r"\x50" + "\"\t\t\t# PUSH EAX\n" total_length += 11 def encoden(x): global code, total_length y = x endian = (y[6] + y[7]) + (y[4] + y[5]) + (y[2] + y[3]) + (y[0] + y[1]) twocompl = compl(endian) k = str(hex(twocompl))[2:99].strip("L") k = "0" * ( 8 - len(k) ) + k first = k[0:2] second= k[2:4] third = k[4:6] fourth= k[6:8] a = findvalues(fourth,0,0) b = findvalues(third,a[3],0) c = findvalues(second,b[3],0) d = findvalues(first,c[3],1) output = '' final = '' plain = [] for i in range(0,3): for k in (a,b,c,d): output += "\\x" + k[i] plain.append(k[i]) final += '\\x2d' + output + "" total_length += (len(output)/4+1) output = '' plain = [] code += "\n# Encoded: " + x code += "\n\"" + r"\x25\x41\x41\x41\x41" code += r"\x25\x3E\x3E\x3E\x3E" code += final code += r"\x50" + "\"" + "\"" total_length += 11 def main(shell): global total_length k = shell while ( len(k)/2 % 4 != 0): k += '90' total_length += 1 z = '' line = '' rshell = [] for i in range(0, len(k), 8): for j in range(0,8): z += k[i + j] line = z + line rshell = [line] + rshell line = '' z = '' for i in rshell: encode(i) for i in rshell: encoden(i) def help(): print ("\n Usage: %s " % argv[0]) print ("\n -s \tEncode bytes from stdin (\\x00 format).") print (" -f \tEncodes shellcode from a file (\\x00 format).") print (" -g \tOptional parameter that restricts encoder to goodbytes. (\\x00 format).") print ("\n Usage example: %s -s \"\\x75\\xE7\\xFF\\xE7\"" % argv[0]) print (" Usage example: %s -f shellcode.txt -g good_chars.txt\n" % argv[0]) exit() def start(argv): buf = "" global code global goodchars if len(argv) < 1: help() try: opts, args = getopt.getopt(argv, "f:s:g:") except getopt.GetoptError as err: print ("\n Error: %s" % err) help() for opt, arg in opts: if opt == "-s": buf = arg buf = buf.replace("\\x","").replace("x","") elif opt == "-g": good_file = open(arg).read().replace("\n", "").replace("\\x", "").replace("\"", "") goodchars = [good_file[i:i+2] for i in range(0, len(good_file), 2)][:-1] elif opt == "-f": try: buf = open(arg).read().replace("\\x","").replace("\n","").replace("\"","") except Exception as err: print ("\n Error: %s" % err) exit() main(buf) code = code[:-1] print ("\nencoded_shellcode = (", code + "\n)") if __name__ == "__main__": try: start(argv[1:]) print ("\nTotal length in bytes: " + str(total_length) + "\n") except Exception as err: print ("\n Error: %s" % err) except KeyboardInterrupt: print ("\nExiting per user's request (ctrl-c)") exit()