Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Python Windows DLLs finding and calling
import pefile
import sys
import ctypes
import glob
import argparse
import itertools
def search_tables(thefile, pename, search = []):
if hasattr(thefile, "DIRECTORY_ENTRY_IMPORT"):
if args.verbose or args.dump:
print("Processing Import Table...")
for dllimport in thefile.DIRECTORY_ENTRY_IMPORT:
fname = dllimport.dll.decode()
for eachfunc in dllimport.imports:
if args.dump:
name = eachfunc.name if eachfunc.name else b"BLANK"
print("{0: >} in {1} at offset 0x{2:0>16X}".format(name.decode(),fname,eachfunc.address ))
continue
for eachterm in search:
if args.inexact:
if eachfunc.name and (eachterm in eachfunc.name.decode().lower()) or not search:
print("{} uses {} in dll {}".format(pename, eachfunc.name, fname))
else:
if eachfunc.name and eachterm == eachfunc.name.decode():
print("{} uses {} in dll {}".format(pename, eachfunc.name, fname))
#else:
# print("{} not in {}".format(eachterm, eachfunc.name)
if hasattr(thefile, "DIRECTORY_ENTRY_EXPORT"):
if args.verbose or args.dump:
print("Processing the Export Table...")
for symbol in thefile.DIRECTORY_ENTRY_EXPORT.symbols:
fname = thefile.DIRECTORY_ENTRY_EXPORT.name.decode()
if args.dump:
name = symbol.name if symbol.name else b"BLANK"
print("{0} in {1} at offset 0x{2:0>16X} in {}".format(name.decode(), fname, symbol.address_offset))
continue
for eachterm in search:
if symbol.name:
if args.inexact:
if symbol.name and (eachterm in symbol.name.decode().lower()) or not search:
print("{0} exports {1} at 0x{2:0>16X} ".format(pename, symbol.name, symbol.address_offset))
else:
if symbol.name and eachterm == symbol.name.decode():
print("{0} exports {1} at 0x{2:0>16X}".format(pename, symbol.name, symbol.address_offset))
def bits2flag(flags,byte_value):
bits_array = map(int, format(byte_value,"016b"))
return "|".join(itertools.compress(flags[::-1],bits_array))
search = ["printf", "gets", "lstrcpyW"]
dll_characteristics = ['reserved0', 'reserved1', 'reserved2', 'reserved3', 'undefined1', 'High_Entropy_VA', 'Dynamic_Base', 'Force_Integrity', 'NX_Compat', 'No_isolation', 'No_SEH', 'No_bind', 'App_Container', 'WDM_Driver', 'Guard_CF', 'Terminal_Server_Aware']
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--dump", action= "store_true", help = "Dump all information about the pe. No filters or search applied.")
parser.add_argument("-a","--add", nargs='*', help = "In addition to defaults also search for these functions being used by the exectuables. The function names are separated by spaces and terminated with two dashes. Example: -a modulea moduleb --")
parser.add_argument("-o","--only", nargs='*', help = "Only search for these functions being used by the executables. The function names are separated by spaces and terminated with two dashes. Example: -e modulea moduleb --")
parser.add_argument("-i","--inexact", action="store_true", help = "Ignore case sensitive and allow substring match of function names rather than exact names.")
parser.add_argument("-f","--flags", action="store_true", help = "Display the DLL Characteristic flags.")
parser.add_argument("-v","--verbose", action="store_true", help = "MAKE SOME NOISE UP IN HERE!!!")
parser.add_argument("-t", "--toggle", nargs="*", choices = dll_characteristics, help = "A list of Header Characteristics bit to toggle. Flags are spece separated and end with two dashes. Example --toggle NO_SEH Guard_CF --")
parser.add_argument("pefiles", help= "The name of an EXE or DLL is a required argument. Wildcards are supported.")
args = parser.parse_args()
pefiles = glob.glob(args.pefiles)
if len(pefiles)==0:
print("No files found.")
sys.exit(1)
if args.add:
search.extend(args.add)
if args.only:
search = args.only
for pe in pefiles:
try:
thefile = pefile.PE(pe)
except Exception as e:
print("Unable to open file {}".format(str(e)))
continue
if args.dump or args.flags:
file_options = thefile.OPTIONAL_HEADER.DllCharacteristics
print("{} flags : {}".format(pe, bits2flag(dll_characteristics, file_options)))
if args.toggle:
current_flags = thefile.OPTIONAL_HEADER.DllCharacteristics
bitsmask = 0
for eachflag in args.toggle:
bitsmask = bitsmask ^ (2**dll_characteristics.index(eachflag))
thefile.OPTIONAL_HEADER.DllCharacteristics = current_flags ^ bitsmask
thefile.write(filename = "{}.new".format(pe))
print("Flags Changes written to {}.new".format(pe))
if args.verbose:
print("Searching EXE {} for vulnerable functions {}".format(pe, str(search)))
search_tables(thefile,pe, search)
import pefile
import sys
import ctypes
import glob
import argparse
import itertools
def search_tables(thefile, pename, search = []):
if hasattr(thefile, "DIRECTORY_ENTRY_IMPORT"):
if args.verbose or args.dump:
print("Processing Import Table...")
for dllimport in thefile.DIRECTORY_ENTRY_IMPORT:
fname = dllimport.dll.decode()
for eachfunc in dllimport.imports:
if args.dump:
name = eachfunc.name if eachfunc.name else b"BLANK"
print("{0: >} in {1} at offset 0x{2:0>16X}".format(name.decode(),fname,eachfunc.address ))
continue
for eachterm in search:
if args.inexact:
if eachfunc.name and (eachterm in eachfunc.name.decode().lower()) or not search:
print("{} uses {} in dll {}".format(pename, eachfunc.name, fname))
else:
if eachfunc.name and eachterm == eachfunc.name.decode():
print("{} uses {} in dll {}".format(pename, eachfunc.name, fname))
#else:
# print("{} not in {}".format(eachterm, eachfunc.name)
if hasattr(thefile, "DIRECTORY_ENTRY_EXPORT"):
if args.verbose or args.dump:
print("Processing the Export Table...")
for symbol in thefile.DIRECTORY_ENTRY_EXPORT.symbols:
fname = thefile.DIRECTORY_ENTRY_EXPORT.name.decode()
if args.dump:
name = symbol.name if symbol.name else b"BLANK"
print("{0} in {1} at offset 0x{2:0>16X} in {}".format(name.decode(), fname, symbol.address_offset))
continue
for eachterm in search:
if symbol.name:
if args.inexact:
if symbol.name and (eachterm in symbol.name.decode().lower()) or not search:
print("{0} exports {1} at 0x{2:0>16X} ".format(pename, symbol.name, symbol.address_offset))
else:
if symbol.name and eachterm == symbol.name.decode():
print("{0} exports {1} at 0x{2:0>16X}".format(pename, symbol.name, symbol.address_offset))
def bits2flag(flags,byte_value):
bits_array = map(int, format(byte_value,"016b"))
return "|".join(itertools.compress(flags[::-1],bits_array))
search = ["printf", "gets", "lstrcpyW"]
dll_characteristics = ['reserved0', 'reserved1', 'reserved2', 'reserved3', 'undefined1', 'High_Entropy_VA', 'Dynamic_Base', 'Force_Integrity', 'NX_Compat', 'No_isolation', 'No_SEH', 'No_bind', 'App_Container', 'WDM_Driver', 'Guard_CF', 'Terminal_Server_Aware']
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--dump", action= "store_true", help = "Dump all information about the pe. No filters or search applied.")
parser.add_argument("-a","--add", nargs='*', help = "In addition to defaults also search for these functions being used by the exectuables. The function names are separated by spaces and terminated with two dashes. Example: -a modulea moduleb --")
parser.add_argument("-o","--only", nargs='*', help = "Only search for these functions being used by the executables. The function names are separated by spaces and terminated with two dashes. Example: -e modulea moduleb --")
parser.add_argument("-i","--inexact", action="store_true", help = "Ignore case sensitive and allow substring match of function names rather than exact names.")
parser.add_argument("-f","--flags", action="store_true", help = "Display the DLL Characteristic flags.")
parser.add_argument("-v","--verbose", action="store_true", help = "MAKE SOME NOISE UP IN HERE!!!")
parser.add_argument("-t", "--toggle", choices = dll_characteristics, help = "The name of a single PE DLL Characteristics bit to toggle.")
parser.add_argument("pefiles", help= "The name of an EXE or DLL is a required argument. Wildcards are supported.")
args = parser.parse_args()
pefiles = glob.glob(args.pefiles)
if len(pefiles)==0:
print("No files found.")
sys.exit(1)
if args.add:
search.extend(args.add)
if args.only:
search = args.only
for pe in pefiles:
try:
thefile = pefile.PE(pe)
except Exception as e:
print("Unable to open file {}".format(str(e)))
continue
if args.dump or args.flags:
file_options = thefile.OPTIONAL_HEADER.DllCharacteristics
print("{} flags : {}".format(pe, bits2flag(dll_characteristics, file_options)))
if args.toggle:
current_flags = thefile.OPTIONAL_HEADER.DllCharacteristics
bitsmask = 2**dll_characteristics.index(args.toggle)
thefile.OPTIONAL_HEADER.DllCharacteristics = current_flags ^ bitsmask
thefile.write(filename = "{}.new".format(pe))
print("Flags Changes written to {}.new".format(pe))
if args.verbose:
print("Searching EXE {} for vulnerable functions {}".format(pe, str(search)))
search_tables(thefile,pe, search)
import pefile
import sys
import ctypes
import glob
import argparse
import itertools
def search_tables(thefile, pename, search = []):
if hasattr(thefile, "DIRECTORY_ENTRY_IMPORT"):
if args.verbose or args.dump:
print("Processing Import Table...")
for dllimport in thefile.DIRECTORY_ENTRY_IMPORT:
fname = dllimport.dll.decode()
for eachfunc in dllimport.imports:
if args.dump:
name = eachfunc.name if eachfunc.name else b"BLANK"
print("{0: >} in {1} at offset 0x{2:0>16X}".format(name.decode(),fname,eachfunc.address ))
continue
for eachterm in search:
if args.inexact:
if eachfunc.name and (eachterm in eachfunc.name.decode().lower()) or not search:
print("{} uses {} in dll {}".format(pename, eachfunc.name, fname))
else:
if eachfunc.name and eachterm == eachfunc.name.decode():
print("{} uses {} in dll {}".format(pename, eachfunc.name, fname))
#else:
# print("{} not in {}".format(eachterm, eachfunc.name)
if hasattr(thefile, "DIRECTORY_ENTRY_EXPORT"):
if args.verbose or args.dump:
print("Processing the Export Table...")
for symbol in thefile.DIRECTORY_ENTRY_EXPORT.symbols:
fname = thefile.DIRECTORY_ENTRY_EXPORT.name.decode()
if args.dump:
name = symbol.name if symbol.name else b"BLANK"
print("{0} in {1} at offset 0x{2:0>16X} in {}".format(name.decode(), fname, symbol.address_offset))
continue
for eachterm in search:
if symbol.name:
if args.inexact:
if symbol.name and (eachterm in symbol.name.decode().lower()) or not search:
print("{0} exports {1} at 0x{2:0>16X} ".format(pename, symbol.name, symbol.address_offset))
else:
if symbol.name and eachterm == symbol.name.decode():
print("{0} exports {1} at 0x{2:0>16X}".format(pename, symbol.name, symbol.address_offset))
def bits2flag(flags,byte_value):
bits_array = map(int, format(byte_value,"016b"))
return "|".join(itertools.compress(flags[::-1],bits_array))
def togglebit(flags, toggle_flag, byte_value):
bits_mask = 2**flags.index(toggle_flag)
return byte_value ^ bits_mask
search = ["printf", "gets", "lstrcpyW"]
dll_characteristics = ['reserved0', 'reserved1', 'reserved2', 'reserved3', 'undefined1', 'High_Entropy_VA', 'Dynamic_Base', 'Force_Integrity', 'NX_Compat', 'No_isolation', 'No_SEH', 'No_bind', 'App_Container', 'WDM_Driver', 'Guard_CF', 'Terminal_Server_Aware']
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--dump", action= "store_true", help = "Dump all information about the pe. No filters or search applied.")
parser.add_argument("-a","--add", nargs='*', help = "In addition to defaults also search for these functions being used by the exectuables. The function names are separated by spaces and terminated with two dashes. Example: -a modulea moduleb --")
parser.add_argument("-o","--only", nargs='*', help = "Only search for these functions being used by the executables. The function names are separated by spaces and terminated with two dashes. Example: -e modulea moduleb --")
parser.add_argument("-i","--inexact", action="store_true", help = "Ignore case sensitive and allow substring match of function names rather than exact names.")
parser.add_argument("-f","--flags", action="store_true", help = "Display the DLL Characteristic flags.")
parser.add_argument("-v","--verbose", action="store_true", help = "MAKE SOME NOISE UP IN HERE!!!")
parser.add_argument("-t", "--toggle", choices = dll_characteristics, help = "The name of a single Header Characteristics bit to toggle.")
parser.add_argument("pefiles", help= "The name of an EXE or DLL is a required argument. Wildcards are supported.")
args = parser.parse_args()
pefiles = glob.glob(args.pefiles)
if len(pefiles)==0:
print("No files found.")
sys.exit(1)
if args.add:
search.extend(args.add)
if args.only:
search = args.only
for pe in pefiles:
try:
thefile = pefile.PE(pe)
except Exception as e:
print("Unable to open file {}".format(str(e)))
continue
if args.dump or args.flags:
file_options = thefile.OPTIONAL_HEADER.DllCharacteristics
print("{} flags : {}".format(pe, bits2flag(dll_characteristics, file_options)))
if args.toggle:
#LAB: Put your code here to toggle the PE flags here
#variable pe contains a string that is the file name you are processing
#variable thefile contains the pefile.PE data structure you need
#variable args.toggle contains what is passed after the -t or --toggle argument on the command line
print("Toggle is not currently supported.")
if args.verbose:
print("Searching EXE {} for vulnerable functions {}".format(pe, str(search)))
search_tables(thefile,pe, search)
import ctypes
x = ctypes.cdll.LoadLibrary(r'c:\windows\system32\crtdll.dll')
#
#Interestingly this will crash this program....
#C:\Users\mark\Desktop>python -c "print('A'*15685)"| python gets.py
#Type something for me!b'AAAAAAAAAAAAAAAAAAAA'
#But this will not
#C:\Users\mark\Desktop>python -c "print('A'*15684)"| python gets.py
#gets returns a pointer to value in memory and updates the buffer mystr
x.printf(b'Type something for me!')
mystr = ctypes.create_string_buffer(20)
respaddr = x.gets(mystr)
print(mystr.value)
#turn response address into a string
actualmem = ctypes.cast(respaddr, ctypes.c_char_p)
print(actualmem.value)
import pefile
import sys
import ctypes
import glob
import argparse
def dllinfo(dllpath, search=b""):
try:
thedll = pefile.PE(dllpath)
except Exception as e:
print("{} {}".format(dllpath,str(e)))
return
if hasattr(thedll, "DIRECTORY_ENTRY_EXPORT"):
for symbol in thedll.DIRECTORY_ENTRY_EXPORT.symbols:
if symbol.name:
if not search or (search.decode().lower() in symbol.name.decode().lower()):
print("Name {} is at offset {} in {}".format(symbol.name, symbol.address_offset,dllpath))
else:
print("{} has no exports.".format(dllpath))
def search_imports(infile, search = []):
try:
thefile = pefile.PE(infile)
except Exception as e:
print("Unable to open file {}",format(str(e)))
if hasattr(thefile, "DIRECTORY_ENTRY_IMPORT"):
for dllimport in thefile.DIRECTORY_ENTRY_IMPORT:
for eachfunc in dllimport.imports:
for eachterm in search:
if not args.exact:
if eachfunc.name and (eachterm in eachfunc.name.decode().lower()) or not search:
print("*"*100)
print("Name {} is using function {}".format(infile, eachfunc.name))
print("*"*100)
else:
if eachfunc.name and eachterm == eachfunc.name.decode():
print("*"*100)
print("Name {} is using function {}".format(infile, eachfunc.name))
print("*"*100)
#else:
# print("{} not in {}".format(eachterm, eachfunc.name)
search = ["printf", "gets", "lstrcpyw"]
parser = argparse.ArgumentParser()
parser.add_argument("-a","--add", nargs='*', help = "In addition to defaults also search for these functions being used by the exectuables.")
parser.add_argument("-o","--only", nargs='*', help = "Only search for these functions being used by the executables.")
parser.add_argument("-e","--exact", action="store_true", help = "Search for exact match of function names rather than as substrings.")
parser.add_argument("-v","--verbose", action="store_true", help = "MAKE SOME NOISE UP IN HERE!!!")
parser.add_argument("executable", help= "The name of an executable is a required argument.")
args = parser.parse_args()
exes = glob.glob(args.executable)
if len(exes)==0:
print("No Executables found.")
sys.exit(1)
if args.add:
search.extend(args.add)
if args.only:
search = args.only
for exe in exes:
if args.verbose:
print("Searching EXE {} for vulnerable functions {}".format(exe, str(search)))
search_imports(exe, search)
#x = ctypes.cdll.LoadLibrary(r'c:\windows\system32\crtdll.dll')
#x.printf("WHATS UP GOOD OLD PRINTF VULNERABILTIY!!! %x %x %x")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment