Land #12524, update most python code with python 3 compatibility
This commit is contained in:
Binary file not shown.
+95
-90
@@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#=============================================================================#
|
||||
# A simple python build script to build the singles/stages/stagers and
|
||||
# A simple python build script to build the singles/stages/stagers and
|
||||
# some usefull information such as offsets and a hex dump. The binary output
|
||||
# will be placed in the bin directory. A hex string and usefull comments will
|
||||
# be printed to screen.
|
||||
@@ -12,95 +14,98 @@
|
||||
#
|
||||
# Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
|
||||
#=============================================================================#
|
||||
import os, sys, time
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from subprocess import Popen
|
||||
from struct import pack
|
||||
#=============================================================================#
|
||||
def clean( dir="./bin/" ):
|
||||
for root, dirs, files in os.walk( dir ):
|
||||
for name in files:
|
||||
if name[-4:] == ".bin":
|
||||
os.remove( os.path.join( root, name ) )
|
||||
#=============================================================================#
|
||||
def locate( src_file, dir="./src/" ):
|
||||
for root, dirs, files in os.walk( dir ):
|
||||
for name in files:
|
||||
if src_file == name:
|
||||
return root
|
||||
return None
|
||||
#=============================================================================#
|
||||
def build( name ):
|
||||
location = locate( "%s.asm" % name )
|
||||
if location:
|
||||
input = os.path.normpath( os.path.join( location, name ) )
|
||||
output = os.path.normpath( os.path.join( "./bin/", name ) )
|
||||
p = Popen( ["nasm", "-f bin", "-O3", "-o %s.bin" % output, "%s.asm" % input ] )
|
||||
p.wait()
|
||||
xmit( name )
|
||||
else:
|
||||
print "[-] Unable to locate '%s.asm' in the src directory" % name
|
||||
#=============================================================================#
|
||||
def xmit_dump_ruby( data, length=16 ):
|
||||
dump = ""
|
||||
for i in xrange( 0, len( data ), length ):
|
||||
bytes = data[ i : i+length ]
|
||||
hex = "\"%s\"" % ( ''.join( [ "\\x%02X" % ord(x) for x in bytes ] ) )
|
||||
if i+length <= len(data):
|
||||
hex += " +"
|
||||
dump += "%s\n" % ( hex )
|
||||
print dump
|
||||
#=============================================================================#
|
||||
def xmit_offset( data, name, value ):
|
||||
offset = data.find( value );
|
||||
if offset != -1:
|
||||
print "# %s Offset: %d" % ( name, offset )
|
||||
#=============================================================================#
|
||||
def xmit( name, dump_ruby=True ):
|
||||
bin = os.path.normpath( os.path.join( "./bin/", "%s.bin" % name ) )
|
||||
f = open( bin, 'rb')
|
||||
data = f.read()
|
||||
print "# Name: %s\n# Length: %d bytes" % ( name, len( data ) )
|
||||
xmit_offset( data, "Port", pack( ">H", 4444 ) ) # 4444
|
||||
xmit_offset( data, "Host", pack( ">L", 0x7F000001 ) ) # 127.0.0.1
|
||||
xmit_offset( data, "ExitFunk", pack( "<L", 0x0A2A1DE0 ) ) # kernel32.dll!ExitThread
|
||||
xmit_offset( data, "ExitFunk", pack( "<L", 0x56A2B5F0 ) ) # kernel32.dll!ExitProcess
|
||||
xmit_offset( data, "ExitFunk", pack( "<L", 0xEA320EFE ) ) # kernel32.dll!SetUnhandledExceptionFilter
|
||||
xmit_offset( data, "ExitFunk", pack( "<L", 0xE035F044 ) ) # kernel32.dll!Sleep
|
||||
if dump_ruby:
|
||||
xmit_dump_ruby( data )
|
||||
#=============================================================================#
|
||||
def main( argv=None ):
|
||||
if not argv:
|
||||
argv = sys.argv
|
||||
try:
|
||||
if len( argv ) == 1:
|
||||
print "Usage: build.py [clean|all|<name>]"
|
||||
|
||||
def clean(dir='./bin/'):
|
||||
for root, dirs, files in os.walk(dir):
|
||||
for name in files:
|
||||
if name[-4:] == '.bin':
|
||||
os.remove(os.path.join(root, name))
|
||||
|
||||
def locate(src_file, dir='./src/'):
|
||||
for root, dirs, files in os.walk(dir):
|
||||
for name in files:
|
||||
if src_file == name:
|
||||
return root
|
||||
return None
|
||||
|
||||
def build(name):
|
||||
location = locate('%s.asm' % name)
|
||||
if location:
|
||||
input = os.path.normpath(os.path.join(location, name))
|
||||
output = os.path.normpath(os.path.join('./bin/', name))
|
||||
p = Popen(['nasm', '-f bin', '-O3', '-o %s.bin' %
|
||||
output, '%s.asm' % input])
|
||||
p.wait()
|
||||
xmit(name)
|
||||
else:
|
||||
print "# Built on %s\n" % ( time.asctime( time.localtime() ) )
|
||||
if argv[1] == "clean":
|
||||
clean()
|
||||
elif argv[1] == "all":
|
||||
for root, dirs, files in os.walk( "./src/migrate/" ):
|
||||
for name in files:
|
||||
if name[-4:] == ".asm":
|
||||
build( name[:-4] )
|
||||
for root, dirs, files in os.walk( "./src/single/" ):
|
||||
for name in files:
|
||||
if name[-4:] == ".asm":
|
||||
build( name[:-4] )
|
||||
for root, dirs, files in os.walk( "./src/stage/" ):
|
||||
for name in files:
|
||||
if name[-4:] == ".asm":
|
||||
build( name[:-4] )
|
||||
for root, dirs, files in os.walk( "./src/stager/" ):
|
||||
for name in files:
|
||||
if name[-4:] == ".asm":
|
||||
build( name[:-4] )
|
||||
else:
|
||||
build( argv[1] )
|
||||
except Exception, e:
|
||||
print "[-] ", e
|
||||
#=============================================================================#
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
#=============================================================================#
|
||||
print("[-] Unable to locate '%s.asm' in the src directory" % name)
|
||||
|
||||
def xmit_dump_ruby(data, length=16):
|
||||
dump = ''
|
||||
for i in range(0, len(data), length):
|
||||
bytes = data[i: i+length]
|
||||
hex = "\"%s\"" % (''.join(['\\x%02X' % x for x in bytes]))
|
||||
if i+length <= len(data):
|
||||
hex += ' +'
|
||||
dump += '%s\n' % (hex)
|
||||
print(dump)
|
||||
|
||||
def xmit_offset(data, name, value):
|
||||
offset = data.find(value)
|
||||
if offset != -1:
|
||||
print('# %s Offset: %d' % (name, offset))
|
||||
|
||||
def xmit(name, dump_ruby=True):
|
||||
bin = os.path.normpath(os.path.join('./bin/', '%s.bin' % name))
|
||||
f = open(bin, 'rb')
|
||||
data = f.read()
|
||||
print('# Name: %s\n# Length: %d bytes' % (name, len(data)))
|
||||
xmit_offset(data, 'Port', pack('>H', 4444)) # 4444
|
||||
xmit_offset(data, 'Host', pack('>L', 0x7F000001)) # 127.0.0.1
|
||||
# kernel32.dll!ExitThread
|
||||
xmit_offset(data, 'ExitFunk', pack('<L', 0x0A2A1DE0))
|
||||
# kernel32.dll!ExitProcess
|
||||
xmit_offset(data, 'ExitFunk', pack('<L', 0x56A2B5F0))
|
||||
# kernel32.dll!SetUnhandledExceptionFilter
|
||||
xmit_offset(data, 'ExitFunk', pack('<L', 0xEA320EFE))
|
||||
xmit_offset(data, 'ExitFunk', pack('<L', 0xE035F044)) # kernel32.dll!Sleep
|
||||
if dump_ruby:
|
||||
xmit_dump_ruby(data)
|
||||
|
||||
def main(argv=None):
|
||||
if not argv:
|
||||
argv = sys.argv
|
||||
if len(argv) == 1:
|
||||
print('Usage: build.py [clean|all|<name>]')
|
||||
else:
|
||||
print('# Built on %s\n' % (time.asctime(time.localtime())))
|
||||
if argv[1] == 'clean':
|
||||
clean()
|
||||
elif argv[1] == 'all':
|
||||
for root, dirs, files in os.walk('./src/migrate/'):
|
||||
for name in files:
|
||||
if name[-4:] == '.asm':
|
||||
build(name[:-4])
|
||||
for root, dirs, files in os.walk('./src/single/'):
|
||||
for name in files:
|
||||
if name[-4:] == '.asm':
|
||||
build(name[:-4])
|
||||
for root, dirs, files in os.walk('./src/stage/'):
|
||||
for name in files:
|
||||
if name[-4:] == '.asm':
|
||||
build(name[:-4])
|
||||
for root, dirs, files in os.walk('./src/stager/'):
|
||||
for name in files:
|
||||
if name[-4:] == '.asm':
|
||||
build(name[:-4])
|
||||
else:
|
||||
build(argv[1])
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -145,7 +145,7 @@ download_more:
|
||||
test eax,eax ; download failed? (optional?)
|
||||
jz failure
|
||||
|
||||
mov ax, word ptr [edi]
|
||||
mov ax, word [edi]
|
||||
add rbx, rax ; buffer += bytes_received
|
||||
|
||||
test rax,rax ; optional?
|
||||
|
||||
+110
-107
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
#=============================================================================#
|
||||
# A simple python build script to build the singles/stages/stagers and
|
||||
# some usefull information such as offsets and a hex dump. The binary output
|
||||
@@ -12,117 +13,119 @@
|
||||
#
|
||||
# Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
|
||||
#=============================================================================#
|
||||
import os, sys, time
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from subprocess import Popen
|
||||
from struct import pack
|
||||
#=============================================================================#
|
||||
def clean( dir="./bin/" ):
|
||||
for root, dirs, files in os.walk( dir ):
|
||||
for name in files:
|
||||
os.remove( os.path.join( root, name ) )
|
||||
#=============================================================================#
|
||||
def locate( src_file, dir="./src/" ):
|
||||
for root, dirs, files in os.walk( dir ):
|
||||
for name in files:
|
||||
if src_file == name:
|
||||
return root
|
||||
return None
|
||||
|
||||
#=============================================================================#
|
||||
def build( name ):
|
||||
location = locate( "%s.asm" % name )
|
||||
if location:
|
||||
input = os.path.normpath( os.path.join( location, name ) )
|
||||
output = os.path.normpath( os.path.join( "./bin/", name ) )
|
||||
p = Popen( ["nasm", "-f bin", "-O3", "-o %s.bin" % output, "%s.asm" % input ] )
|
||||
p.wait()
|
||||
xmit( name )
|
||||
else:
|
||||
print "[-] Unable to locate '%s.asm' in the src directory" % name
|
||||
def clean(dir='./bin/'):
|
||||
for root, dirs, files in os.walk(dir):
|
||||
for name in files:
|
||||
if name != '.keep':
|
||||
os.remove(os.path.join(root, name))
|
||||
|
||||
#=============================================================================#
|
||||
def xmit_dump_ruby( data, length=16 ):
|
||||
dump = ""
|
||||
for i in xrange( 0, len( data ), length ):
|
||||
bytes = data[ i : i+length ]
|
||||
hex = "\"%s\"" % ( ''.join( [ "\\x%02X" % ord(x) for x in bytes ] ) )
|
||||
if i+length <= len(data):
|
||||
hex += " +"
|
||||
dump += "%s\n" % ( hex )
|
||||
print dump
|
||||
def locate(src_file, dir='./src/'):
|
||||
for root, dirs, files in os.walk(dir):
|
||||
for name in files:
|
||||
if src_file == name:
|
||||
return root
|
||||
return None
|
||||
|
||||
#=============================================================================#
|
||||
def xmit_offset( data, name, value, match_offset=0 ):
|
||||
offset = data.find( value );
|
||||
if offset != -1:
|
||||
print "# %s Offset: %d" % ( name, offset + match_offset )
|
||||
def build(name):
|
||||
location = locate('%s.asm' % name)
|
||||
if location:
|
||||
input = os.path.normpath(os.path.join(location, name))
|
||||
output = os.path.normpath(os.path.join('./bin/', name))
|
||||
p = Popen(['nasm', '-f bin', '-O3', '-o %s.bin' %
|
||||
output, '%s.asm' % input])
|
||||
p.wait()
|
||||
xmit(name)
|
||||
else:
|
||||
print("[-] Unable to locate '%s.asm' in the src directory" % name)
|
||||
|
||||
#=============================================================================#
|
||||
def xmit( name, dump_ruby=True ):
|
||||
bin = os.path.normpath( os.path.join( "./bin/", "%s.bin" % name ) )
|
||||
f = open( bin, 'rb')
|
||||
data = f.read()
|
||||
print "# Name: %s\n# Length: %d bytes" % ( name, len( data ) )
|
||||
xmit_offset( data, "Port", pack( ">H", 4444 ) ) # 4444
|
||||
xmit_offset( data, "LEPort", pack( "<H", 4444 ) ) # 4444
|
||||
xmit_offset( data, "Host", pack( ">L", 0x7F000001 ) ) # 127.0.0.1
|
||||
xmit_offset( data, "IPv6Host", pack( "<Q", 0xBBBBBBBBBBBBBBB1 ) ) # An IPv6 Address
|
||||
xmit_offset( data, "IPv6ScopeId", pack( "<L", 0xAAAAAAA1 ) ) # An IPv6 Scope ID
|
||||
xmit_offset( data, "HostName", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\x00" ) # hostname filler
|
||||
xmit_offset( data, "RetryCounter", "\x6a\x05", 1 ) # socket retry
|
||||
xmit_offset( data, "CodeLen", pack( "<L", 0x12345678 ) ) # Filler
|
||||
xmit_offset( data, "Hostname", "https" )
|
||||
xmit_offset( data, "ExitFunk", pack( "<L", 0x0A2A1DE0 ) ) # kernel32.dll!ExitThread
|
||||
xmit_offset( data, "ExitFunk", pack( "<L", 0x56A2B5F0 ) ) # kernel32.dll!ExitProcess
|
||||
xmit_offset( data, "ExitFunk", pack( "<L", 0xEA320EFE ) ) # kernel32.dll!SetUnhandledExceptionFilter
|
||||
xmit_offset( data, "ExitFunk", pack( "<L", 0xE035F044 ) ) # kernel32.dll!Sleep
|
||||
xmit_offset( data, "EggTag1", pack( "<L", 0xDEADDEAD ) ) # Egg tag 1
|
||||
xmit_offset( data, "EggTag2", pack( "<L", 0xC0DEC0DE ) ) # Egg tag 2
|
||||
xmit_offset( data, "EggTagSize", pack( ">H", 0x1122 ) ) # Egg tag size
|
||||
xmit_offset( data, "RC4Key", "RC4KeyMetasploit") # RC4 key
|
||||
xmit_offset( data, "XORKey", "XORK") # XOR key
|
||||
if( name.find( "egghunter" ) >= 0 ):
|
||||
null_count = data.count( "\x00" )
|
||||
if( null_count > 0 ):
|
||||
print "# Note: %d NULL bytes found." % ( null_count )
|
||||
if dump_ruby:
|
||||
xmit_dump_ruby( data )
|
||||
def xmit_dump_ruby(data, length=16):
|
||||
dump = ''
|
||||
for i in range(0, len(data), length):
|
||||
bytes = data[i: i+length]
|
||||
hex = "\"%s\"" % (''.join(['\\x%02X' % x for x in bytes]))
|
||||
if i+length <= len(data):
|
||||
hex += ' +'
|
||||
dump += '%s\n' % (hex)
|
||||
print(dump)
|
||||
|
||||
#=============================================================================#
|
||||
def main( argv=None ):
|
||||
if not argv:
|
||||
argv = sys.argv
|
||||
try:
|
||||
if len( argv ) == 1:
|
||||
print "Usage: build.py [clean|all|<name>]"
|
||||
else:
|
||||
print "# Built on %s\n" % ( time.asctime( time.localtime() ) )
|
||||
if argv[1] == "clean":
|
||||
clean()
|
||||
elif argv[1] == "all":
|
||||
for root, dirs, files in os.walk( "./src/egghunter/" ):
|
||||
for name in files:
|
||||
build( name[:-4] )
|
||||
for root, dirs, files in os.walk( "./src/migrate/" ):
|
||||
for name in files:
|
||||
build( name[:-4] )
|
||||
for root, dirs, files in os.walk( "./src/single/" ):
|
||||
for name in files:
|
||||
build( name[:-4] )
|
||||
for root, dirs, files in os.walk( "./src/stage/" ):
|
||||
for name in files:
|
||||
build( name[:-4] )
|
||||
for root, dirs, files in os.walk( "./src/stager/" ):
|
||||
for name in files:
|
||||
build( name[:-4] )
|
||||
for root, dirs, files in os.walk( "./src/kernel/" ):
|
||||
for name in files:
|
||||
build( name[:-4] )
|
||||
else:
|
||||
build( argv[1] )
|
||||
except Exception, e:
|
||||
print "[-] ", e
|
||||
#=============================================================================#
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
#=============================================================================#
|
||||
def xmit_offset(data, name, value, match_offset=0):
|
||||
offset = data.find(value)
|
||||
if offset != -1:
|
||||
print('# %s Offset: %d' % (name, offset + match_offset))
|
||||
|
||||
def xmit(name, dump_ruby=True):
|
||||
bin = os.path.normpath(os.path.join('./bin/', '%s.bin' % name))
|
||||
f = open(bin, 'rb')
|
||||
data = bytearray(f.read())
|
||||
print('# Name: %s\n# Length: %d bytes' % (name, len(data)))
|
||||
xmit_offset(data, 'Port', pack('>H', 4444)) # 4444
|
||||
xmit_offset(data, 'LEPort', pack('<H', 4444)) # 4444
|
||||
xmit_offset(data, 'Host', pack('>L', 0x7F000001)) # 127.0.0.1
|
||||
xmit_offset(data, 'IPv6Host', pack(
|
||||
'<Q', 0xBBBBBBBBBBBBBBB1)) # An IPv6 Address
|
||||
xmit_offset(data, 'IPv6ScopeId', pack(
|
||||
'<L', 0xAAAAAAA1)) # An IPv6 Scope ID
|
||||
# hostname filler
|
||||
xmit_offset(data, 'HostName',
|
||||
b'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\x00')
|
||||
xmit_offset(data, 'RetryCounter', b'\x6a\x05', 1) # socket retry
|
||||
xmit_offset(data, 'CodeLen', pack('<L', 0x12345678)) # Filler
|
||||
xmit_offset(data, 'Hostname', b'https')
|
||||
# kernel32.dll!ExitThread
|
||||
xmit_offset(data, 'ExitFunk', pack('<L', 0x0A2A1DE0))
|
||||
# kernel32.dll!ExitProcess
|
||||
xmit_offset(data, 'ExitFunk', pack('<L', 0x56A2B5F0))
|
||||
# kernel32.dll!SetUnhandledExceptionFilter
|
||||
xmit_offset(data, 'ExitFunk', pack('<L', 0xEA320EFE))
|
||||
xmit_offset(data, 'ExitFunk', pack('<L', 0xE035F044)) # kernel32.dll!Sleep
|
||||
xmit_offset(data, 'EggTag1', pack('<L', 0xDEADDEAD)) # Egg tag 1
|
||||
xmit_offset(data, 'EggTag2', pack('<L', 0xC0DEC0DE)) # Egg tag 2
|
||||
xmit_offset(data, 'EggTagSize', pack('>H', 0x1122)) # Egg tag size
|
||||
xmit_offset(data, 'RC4Key', b'RC4KeyMetasploit') # RC4 key
|
||||
xmit_offset(data, 'XORKey', b'XORK') # XOR key
|
||||
if(name.find('egghunter') >= 0):
|
||||
null_count = data.count('\x00')
|
||||
if(null_count > 0):
|
||||
print('# Note: %d NULL bytes found.' % (null_count))
|
||||
if dump_ruby:
|
||||
xmit_dump_ruby(data)
|
||||
|
||||
def main(argv=None):
|
||||
if not argv:
|
||||
argv = sys.argv
|
||||
if len(argv) == 1:
|
||||
print('Usage: build.py [clean|all|<name>]')
|
||||
else:
|
||||
print('# Built on %s\n' % (time.asctime(time.localtime())))
|
||||
if argv[1] == 'clean':
|
||||
clean()
|
||||
elif argv[1] == 'all':
|
||||
for root, dirs, files in os.walk('./src/egghunter/'):
|
||||
for name in files:
|
||||
build(name[:-4])
|
||||
for root, dirs, files in os.walk('./src/migrate/'):
|
||||
for name in files:
|
||||
build(name[:-4])
|
||||
for root, dirs, files in os.walk('./src/single/'):
|
||||
for name in files:
|
||||
build(name[:-4])
|
||||
for root, dirs, files in os.walk('./src/stage/'):
|
||||
for name in files:
|
||||
build(name[:-4])
|
||||
for root, dirs, files in os.walk('./src/stager/'):
|
||||
for name in files:
|
||||
build(name[:-4])
|
||||
for root, dirs, files in os.walk('./src/kernel/'):
|
||||
for name in files:
|
||||
build(name[:-4])
|
||||
else:
|
||||
build(argv[1])
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
+152
-146
@@ -1,146 +1,152 @@
|
||||
#=============================================================================#
|
||||
# This script can detect hash collisions between exported API functions in
|
||||
# multiple modules by either scanning a directory tree or just a single module.
|
||||
# This script can also just output the correct hash value for any single API
|
||||
# function for use with the 'api_call' function in 'block_api.asm'.
|
||||
#
|
||||
# Example: Detect fatal collisions against all modules in the C drive:
|
||||
# >hash.py /dir c:\
|
||||
#
|
||||
# Example: List the hashes for all exports from kernel32.dll (As found in 'c:\windows\system32\')
|
||||
# >hash.py /mod c:\windows\system32\ kernel32.dll
|
||||
#
|
||||
# Example: Simply print the correct hash value for the function kernel32.dll!WinExec
|
||||
# >hash.py kernel32.dll WinExec
|
||||
#
|
||||
# Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
|
||||
#=============================================================================#
|
||||
from sys import path
|
||||
import os, time, sys
|
||||
|
||||
# Modify this path to pefile to suit your machine...
|
||||
pefile_path = "D:\\Development\\Frameworks\\pefile\\"
|
||||
|
||||
path.append( pefile_path )
|
||||
import pefile
|
||||
#=============================================================================#
|
||||
collisions = [ ( 0x006B8029, "ws2_32.dll!WSAStartup" ),
|
||||
( 0xE0DF0FEA, "ws2_32.dll!WSASocketA" ),
|
||||
( 0x6737DBC2, "ws2_32.dll!bind" ),
|
||||
( 0xFF38E9B7, "ws2_32.dll!listen" ),
|
||||
( 0xE13BEC74, "ws2_32.dll!accept" ),
|
||||
( 0x614D6E75, "ws2_32.dll!closesocket" ),
|
||||
( 0x6174A599, "ws2_32.dll!connect" ),
|
||||
( 0x5FC8D902, "ws2_32.dll!recv" ),
|
||||
( 0x5F38EBC2, "ws2_32.dll!send" ),
|
||||
|
||||
( 0x5BAE572D, "kernel32.dll!WriteFile" ),
|
||||
( 0x4FDAF6DA, "kernel32.dll!CreateFileA" ),
|
||||
( 0x13DD2ED7, "kernel32.dll!DeleteFileA" ),
|
||||
( 0xE449F330, "kernel32.dll!GetTempPathA" ),
|
||||
( 0x528796C6, "kernel32.dll!CloseHandle" ),
|
||||
( 0x863FCC79, "kernel32.dll!CreateProcessA" ),
|
||||
( 0xE553A458, "kernel32.dll!VirtualAlloc" ),
|
||||
( 0x300F2F0B, "kernel32.dll!VirtualFree" ),
|
||||
( 0x0726774C, "kernel32.dll!LoadLibraryA" ),
|
||||
( 0x7802F749, "kernel32.dll!GetProcAddress" ),
|
||||
( 0x601D8708, "kernel32.dll!WaitForSingleObject" ),
|
||||
( 0x876F8B31, "kernel32.dll!WinExec" ),
|
||||
( 0x9DBD95A6, "kernel32.dll!GetVersion" ),
|
||||
( 0xEA320EFE, "kernel32.dll!SetUnhandledExceptionFilter" ),
|
||||
( 0x56A2B5F0, "kernel32.dll!ExitProcess" ),
|
||||
( 0x0A2A1DE0, "kernel32.dll!ExitThread" ),
|
||||
|
||||
( 0x6F721347, "ntdll.dll!RtlExitUserThread" ),
|
||||
|
||||
( 0x23E38427, "advapi32.dll!RevertToSelf" )
|
||||
]
|
||||
|
||||
collisions_detected = {}
|
||||
modules_scanned = 0
|
||||
functions_scanned = 0
|
||||
#=============================================================================#
|
||||
def ror( dword, bits ):
|
||||
return ( dword >> bits | dword << ( 32 - bits ) ) & 0xFFFFFFFF
|
||||
#=============================================================================#
|
||||
def unicode( string, uppercase=True ):
|
||||
result = "";
|
||||
if uppercase:
|
||||
string = string.upper()
|
||||
for c in string:
|
||||
result += c + "\x00"
|
||||
return result
|
||||
#=============================================================================#
|
||||
def hash( module, function, bits=13, print_hash=True ):
|
||||
module_hash = 0
|
||||
function_hash = 0
|
||||
for c in unicode( module + "\x00" ):
|
||||
module_hash = ror( module_hash, bits )
|
||||
module_hash += ord( c )
|
||||
for c in str( function + "\x00" ):
|
||||
function_hash = ror( function_hash, bits )
|
||||
function_hash += ord( c )
|
||||
h = module_hash + function_hash & 0xFFFFFFFF
|
||||
if print_hash:
|
||||
print "[+] 0x%08X = %s!%s" % ( h, module.lower(), function )
|
||||
return h
|
||||
#=============================================================================#
|
||||
def scan( dll_path, dll_name, print_hashes=False, print_collisions=True ):
|
||||
global modules_scanned
|
||||
global functions_scanned
|
||||
try:
|
||||
dll_name = dll_name.lower()
|
||||
modules_scanned += 1
|
||||
pe = pefile.PE( os.path.join( dll_path, dll_name ) )
|
||||
for export in pe.DIRECTORY_ENTRY_EXPORT.symbols:
|
||||
if export.name is None:
|
||||
continue
|
||||
h = hash( dll_name, export.name, print_hash=print_hashes )
|
||||
for ( col_hash, col_name ) in collisions:
|
||||
if col_hash == h and col_name != "%s!%s" % (dll_name, export.name):
|
||||
if h not in collisions_detected.keys():
|
||||
collisions_detected[h] = []
|
||||
collisions_detected[h].append( (dll_path, dll_name, export.name) )
|
||||
break
|
||||
functions_scanned += 1
|
||||
except:
|
||||
pass
|
||||
#=============================================================================#
|
||||
def scan_directory( dir ):
|
||||
for dot, dirs, files in os.walk( dir ):
|
||||
for file_name in files:
|
||||
if file_name[-4:] == ".dll":# or file_name[-4:] == ".exe":
|
||||
scan( dot, file_name )
|
||||
print "\n[+] Found %d Collisions.\n" % ( len(collisions_detected) )
|
||||
for h in collisions_detected.keys():
|
||||
for (col_hash, col_name ) in collisions:
|
||||
if h == col_hash:
|
||||
detected_name = col_name
|
||||
break
|
||||
print "[!] Collision detected for 0x%08X (%s):" % ( h, detected_name )
|
||||
for (collided_dll_path, collided_dll_name, collided_export_name) in collisions_detected[h]:
|
||||
print "\t%s!%s (%s)" % ( collided_dll_name, collided_export_name, collided_dll_path )
|
||||
print "\n[+] Scanned %d exported functions via %d modules.\n" % ( functions_scanned, modules_scanned )
|
||||
#=============================================================================#
|
||||
def main( argv=None ):
|
||||
if not argv:
|
||||
argv = sys.argv
|
||||
try:
|
||||
if len( argv ) == 1:
|
||||
print "Usage: hash.py [/dir <path>] | [/mod <path> <module.dll>] | [<module.dll> <function>]"
|
||||
else:
|
||||
print "[+] Ran on %s\n" % ( time.asctime( time.localtime() ) )
|
||||
if argv[1] == "/dir":
|
||||
print "[+] Scanning directory '%s' for collisions..." % argv[2]
|
||||
scan_directory( argv[2] )
|
||||
elif argv[1] == "/mod":
|
||||
print "[+] Scanning module '%s' in directory '%s'..." % ( argv[3], argv[2] )
|
||||
scan( argv[2], argv[3], print_hashes=True )
|
||||
else:
|
||||
hash( argv[1], argv[2] )
|
||||
except Exception, e:
|
||||
print "[-] ", e
|
||||
#=============================================================================#
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
#=============================================================================#
|
||||
#!/usr/bin/env python3
|
||||
#=============================================================================#
|
||||
# This script can detect hash collisions between exported API functions in
|
||||
# multiple modules by either scanning a directory tree or just a single module.
|
||||
# This script can also just output the correct hash value for any single API
|
||||
# function for use with the 'api_call' function in 'block_api.asm'.
|
||||
#
|
||||
# Example: Detect fatal collisions against all modules in the C drive:
|
||||
# >hash.py /dir c:\
|
||||
#
|
||||
# Example: List the hashes for all exports from kernel32.dll (As found in 'c:\windows\system32\')
|
||||
# >hash.py /mod c:\windows\system32\ kernel32.dll
|
||||
#
|
||||
# Example: Simply print the correct hash value for the function kernel32.dll!WinExec
|
||||
# >hash.py kernel32.dll WinExec
|
||||
#
|
||||
# Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
|
||||
#=============================================================================#
|
||||
import pefile
|
||||
from sys import path
|
||||
import os
|
||||
import time
|
||||
import sys
|
||||
|
||||
# Modify this path to pefile to suit your machine...
|
||||
pefile_path = 'D:\\Development\\Frameworks\\pefile\\'
|
||||
|
||||
path.append(pefile_path)
|
||||
collisions = [(0x006B8029, 'ws2_32.dll!WSAStartup'),
|
||||
(0xE0DF0FEA, 'ws2_32.dll!WSASocketA'),
|
||||
(0x6737DBC2, 'ws2_32.dll!bind'),
|
||||
(0xFF38E9B7, 'ws2_32.dll!listen'),
|
||||
(0xE13BEC74, 'ws2_32.dll!accept'),
|
||||
(0x614D6E75, 'ws2_32.dll!closesocket'),
|
||||
(0x6174A599, 'ws2_32.dll!connect'),
|
||||
(0x5FC8D902, 'ws2_32.dll!recv'),
|
||||
(0x5F38EBC2, 'ws2_32.dll!send'),
|
||||
|
||||
(0x5BAE572D, 'kernel32.dll!WriteFile'),
|
||||
(0x4FDAF6DA, 'kernel32.dll!CreateFileA'),
|
||||
(0x13DD2ED7, 'kernel32.dll!DeleteFileA'),
|
||||
(0xE449F330, 'kernel32.dll!GetTempPathA'),
|
||||
(0x528796C6, 'kernel32.dll!CloseHandle'),
|
||||
(0x863FCC79, 'kernel32.dll!CreateProcessA'),
|
||||
(0xE553A458, 'kernel32.dll!VirtualAlloc'),
|
||||
(0x300F2F0B, 'kernel32.dll!VirtualFree'),
|
||||
(0x0726774C, 'kernel32.dll!LoadLibraryA'),
|
||||
(0x7802F749, 'kernel32.dll!GetProcAddress'),
|
||||
(0x601D8708, 'kernel32.dll!WaitForSingleObject'),
|
||||
(0x876F8B31, 'kernel32.dll!WinExec'),
|
||||
(0x9DBD95A6, 'kernel32.dll!GetVersion'),
|
||||
(0xEA320EFE, 'kernel32.dll!SetUnhandledExceptionFilter'),
|
||||
(0x56A2B5F0, 'kernel32.dll!ExitProcess'),
|
||||
(0x0A2A1DE0, 'kernel32.dll!ExitThread'),
|
||||
|
||||
(0x6F721347, 'ntdll.dll!RtlExitUserThread'),
|
||||
|
||||
(0x23E38427, 'advapi32.dll!RevertToSelf')
|
||||
]
|
||||
|
||||
collisions_detected = {}
|
||||
modules_scanned = 0
|
||||
functions_scanned = 0
|
||||
|
||||
def ror(dword, bits):
|
||||
return (dword >> bits | dword << (32 - bits)) & 0xFFFFFFFF
|
||||
|
||||
def unicode(string, uppercase=True):
|
||||
result = ''
|
||||
if uppercase:
|
||||
string = string.upper()
|
||||
for c in string:
|
||||
result += c + '\x00'
|
||||
return result
|
||||
|
||||
def hash(module, function, bits=13, print_hash=True):
|
||||
module_hash = 0
|
||||
function_hash = 0
|
||||
for c in unicode(module + '\x00'):
|
||||
module_hash = ror(module_hash, bits)
|
||||
module_hash += ord(c)
|
||||
for c in str(function + b'\x00'):
|
||||
function_hash = ror(function_hash, bits)
|
||||
function_hash += ord(c)
|
||||
h = module_hash + function_hash & 0xFFFFFFFF
|
||||
if print_hash:
|
||||
print('[+] 0x%08X = %s!%s' % (h, module.lower(), function))
|
||||
return h
|
||||
|
||||
def scan(dll_path, dll_name, print_hashes=False, print_collisions=True):
|
||||
global modules_scanned
|
||||
global functions_scanned
|
||||
dll_name = dll_name.lower()
|
||||
modules_scanned += 1
|
||||
pe = pefile.PE(os.path.join(dll_path, dll_name))
|
||||
for export in pe.DIRECTORY_ENTRY_EXPORT.symbols:
|
||||
if export.name is None:
|
||||
continue
|
||||
h = hash(dll_name, export.name, print_hash=print_hashes)
|
||||
for (col_hash, col_name) in collisions:
|
||||
if col_hash == h and col_name != '%s!%s' % (dll_name, export.name):
|
||||
if h not in collisions_detected.keys():
|
||||
collisions_detected[h] = []
|
||||
collisions_detected[h].append(
|
||||
(dll_path, dll_name, export.name))
|
||||
break
|
||||
functions_scanned += 1
|
||||
|
||||
def scan_directory(dir):
|
||||
for dot, dirs, files in os.walk(dir):
|
||||
for file_name in files:
|
||||
if file_name[-4:] == '.dll': # or file_name[-4:] == ".exe":
|
||||
scan(dot, file_name)
|
||||
print('\n[+] Found %d Collisions.\n' % (len(collisions_detected)))
|
||||
for h in collisions_detected.keys():
|
||||
for (col_hash, col_name) in collisions:
|
||||
if h == col_hash:
|
||||
detected_name = col_name
|
||||
break
|
||||
print('[!] Collision detected for 0x%08X (%s):' % (h, detected_name))
|
||||
for (collided_dll_path, collided_dll_name, collided_export_name) in collisions_detected[h]:
|
||||
print('\t%s!%s (%s)' %
|
||||
(collided_dll_name, collided_export_name, collided_dll_path))
|
||||
print('\n[+] Scanned %d exported functions via %d modules.\n' %
|
||||
(functions_scanned, modules_scanned))
|
||||
|
||||
def usage():
|
||||
print(
|
||||
'Usage: hash.py [/dir <path>] | [/mod <path> <module.dll>] | [<module.dll> <function>]')
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
if not argv:
|
||||
argv = sys.argv
|
||||
if len(argv) == 1:
|
||||
usage()
|
||||
else:
|
||||
print('[+] Ran on %s\n' % (time.asctime(time.localtime())))
|
||||
if argv[1] == '/dir':
|
||||
print("[+] Scanning directory '%s' for collisions..." % argv[2])
|
||||
scan_directory(argv[2])
|
||||
elif argv[1] == '/mod':
|
||||
print("[+] Scanning module '%s' in directory '%s'..." %
|
||||
(argv[3], argv[2]))
|
||||
scan(argv[2], argv[3], print_hashes=True)
|
||||
elif len(argv) < 3:
|
||||
usage()
|
||||
else:
|
||||
hash(argv[1], argv[2])
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
+1
-1
@@ -14,6 +14,6 @@
|
||||
%include "./src/block/block_api.asm"
|
||||
start: ;
|
||||
pop ebp ; pop off the address of 'api_call' for calling later.
|
||||
%include "./src/block/block_reverse_winhttp_http.asm"
|
||||
%include "./src/block/block_reverse_winhttp.asm"
|
||||
; By here we will have performed the reverse_tcp connection and EDI will be our socket.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user