Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- """htl_extract.py, Extracts the embedded source code from Cisco Security Agent Management Console.
- Gerry Eisenhaur <gerry@hiredhacker.com>
- """
- import os
- import sys
- import struct
- import pefile
- from itertools import takewhile
- _KEY = 'Copyright material protected by a technological protection measure!'
- _KEY_LEN = len(_KEY)
- def get_section_by_name(pe, name):
- try:
- section = filter(lambda s: s.Name == name, pe.sections)[0]
- except IndexError, e:
- return None
- return section
- def not_null(c):
- return c != '\0'
- def decrypt_data(data):
- decrypted_data = []
- for idx, val in enumerate(data):
- decrypted_data.append(chr(ord(val) - ord(_KEY[idx % _KEY_LEN])))
- return ''.join(decrypted_data)
- def main(output_path="./extracted", filename="webadmin.exe", section_name="htlconst"):
- pe = pefile.PE(filename, fast_load=True)
- # Create the output path is needed, then chdir to it
- output_path = os.path.abspath(output_path)
- if not os.path.isdir(output_path):
- os.makedirs(output_path)
- os.chdir(output_path)
- # Filename to search for when locating the file table
- search_string = "login.htl"
- # The htlconst section contains all the data we need
- htlconst = get_section_by_name(pe, section_name)
- assert htlconst is not None, "Could not find section: %s" % section_name
- image_base = pe.OPTIONAL_HEADER.ImageBase
- try:
- # Get index of known filename in htlconst section data
- filename_offset = htlconst.data.index(search_string)
- except ValueError:
- sys.exit("Could not find search string: %s" % search_string)
- # Get address of known filename in htlconst section
- filename_rva = filename_offset + htlconst.VirtualAddress + image_base
- # Search for a pointer to the filename
- filename_ptr = struct.pack("I", filename_rva)
- assert filename_ptr in htlconst.data, "Could not find pointer to filename"
- # Search back for 0x00000000 and add 4 to get the start of the struct
- table_offset = None
- filename_ptr_idx = htlconst.data.index(filename_ptr)
- # Is there a better way todo this?
- for idx in reversed(xrange(0, filename_ptr_idx, 4)):
- if htlconst.data[idx:idx+4] == "\x00\x00\x00\x00":
- table_offset = idx + 4
- break
- assert table_offset is not None, "Could not find start of file table"
- cur_offset = table_offset
- while True:
- # unpack pointers to the filename and its 'encrypted' contents
- (ptr_filename, ptr_data) = struct.unpack('II', htlconst.data[cur_offset:cur_offset + 8])
- # Check for the end of the structure
- if not htlconst.contains_rva(ptr_data - image_base):
- break
- filename = pe.get_string_at_rva(ptr_filename - image_base)
- print '[+] Extracting: %s' % filename
- data_offset = (ptr_data - image_base - htlconst.VirtualAddress)
- encrypted_data = takewhile(not_null, htlconst.data[data_offset:])
- decrypted_data = decrypt_data(encrypted_data)
- f = open(filename, 'w')
- f.write(decrypted_data)
- f.close()
- cur_offset += 8
- print "[+] Done extracting %d files." % ((cur_offset - table_offset)/8)
- if __name__ == "__main__":
- main()
Add Comment
Please, Sign In to add comment