Guest User

Untitled

a guest
Nov 24th, 2014
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.19 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. #
  4. # Copyright (C) 2014  Anthony King
  5. # Copyright (C) 2014  CyboLabs
  6. #
  7. # Licensed under the Apache License, Version 2.0 (the "License");
  8. # you may not use this file except in compliance with the License.
  9. # You may obtain a copy of the License at
  10. #
  11. #     http://www.apache.org/licenses/LICENSE-2.0
  12. #
  13. # Unless required by applicable law or agreed to in writing, software
  14. # distributed under the License is distributed on an "AS IS" BASIS,
  15. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. # See the License for the specific language governing permissions and
  17. # limitations under the License.
  18. #
  19.  
  20. from __future__ import print_function
  21.  
  22. import binascii
  23. import os
  24. import struct
  25. import sys
  26.  
  27. # Proof of Concept
  28. POC = False
  29.  
  30.  
  31. usage = """\
  32. Usage: open_bump.py [-ha] "<image_file>" "<output_image>"
  33.  image_file        - <required> path to the image file to bump
  34.  output_image      - <optional> path to output the bumped file to (defaults to <image_file>_bumped.img
  35.  -a/--apend image_file  - <required> if in append mode, the <image_file> is appended rather than <output_file> being generated\
  36. """
  37.  
  38. lg_magic = "41a9e467744d1d1ba429f2ecea655279"
  39.  
  40.  
  41. def get_kernel_size(image_name):
  42.     page_size = get_page_size(image_name)
  43.     f_image = open(image_name, 'a+b')
  44.     paged_kernel_size = get_size_from_kernel(f_image, page_size, 8)
  45.     paged_ramdisk_size = get_size_from_kernel(f_image, page_size, 16)
  46.     paged_second_size = get_size_from_kernel(f_image, page_size, 24)
  47.     if paged_second_size <= 0:
  48.         paged_second_size = 0
  49.     paged_dt_size = get_size_from_kernel(f_image, page_size, 40)
  50.     if paged_dt_size <= 0:
  51.         paged_dt_size = 0
  52.     f_image.close()
  53.     return page_size + paged_kernel_size + paged_ramdisk_size + paged_second_size + paged_dt_size
  54.  
  55.  
  56. def bumped(image_data):
  57.     d = binascii.hexlify(image_data[-1024:])
  58.     return d.endswith(lg_magic) or d.startswith(lg_magic)
  59.  
  60.  
  61. def pair_reverse(s):
  62.     n = len(s) / 2
  63.     fmt = '%dh' % n
  64.     return struct.pack(fmt, *reversed(struct.unpack(fmt, s)))
  65.  
  66.  
  67. def get_page_size(image_name):
  68.     with open(image_name, 'rb') as f_img:
  69.         f_img.seek(36, 0)
  70.         return int(pair_reverse(binascii.hexlify(f_img.read(4))), 16)
  71.  
  72.  
  73. def get_size_from_kernel(f_image, page_size, seek_size):
  74.     f_image.seek(seek_size, 0)
  75.     return (int(pair_reverse(binascii.hexlify(f_image.read(4))), 16) / page_size) * page_size
  76.  
  77.  
  78. def pad_image(image_name):
  79.     page_size = get_page_size(image_name)
  80.     image_size = os.path.getsize(image_name)
  81.     num_pages = image_size / page_size
  82.  
  83.     calculated_size = get_kernel_size(image_name)
  84.  
  85.     f_image = open(image_name, 'a+b')
  86.  
  87.     if calculated_size > image_size:
  88.         print("Invalid image: %s: calculated size greater than actual size" % image_name)
  89.         f_image.close()
  90.         sys.exit(1)
  91.     if image_size > calculated_size:
  92.         difference = image_size - calculated_size
  93.         if difference not in [page_size, page_size*2]:
  94.             if difference not in [1024, page_size + 1024, 2 * page_size + 1024,
  95.                                   16, page_size + 16, 2 * page_size + 16]:
  96.                 print("Image already padded. Attempting to remove padding...")
  97.                 print("Beware: this may invalidate your image.")
  98.                 i = num_pages - 1
  99.                 f_image.seek(0, 0)
  100.                 while i >= 0:
  101.                     f_image.seek(page_size * i, 0)
  102.                     data = f_image.read(page_size)
  103.                     data = data.split('\x00')[0]
  104.                     if not data:
  105.                         f_image.truncate(page_size * i)
  106.                         i -= 1
  107.                     else:
  108.                         break
  109.             else:
  110.                 print("%s: Image already patched. Bailing out" % image_name)
  111.                 sys.exit(1)
  112.     f_image.close()
  113.  
  114.  
  115. def get_sha1(image_name):
  116.     return hashlib.sha1(open(image_name, 'rb').read()).hexdigest()
  117.    
  118.  
  119. def finish(out_image):
  120.     print("bumped image: %s" % out_image)
  121.     sys.exit(0)
  122.  
  123.  
  124. def main(in_image, out_image):
  125.     d_in_image = open(in_image, 'rb').read()
  126.     open(out_image, 'wb').write(d_in_image)
  127.     if bumped(d_in_image):
  128.         print("Image already bumped")
  129.         finish(out_image)
  130.     pad_image(out_image)
  131.     magic = binascii.unhexlify(lg_magic)
  132.     with open(out_image, 'a+b') as f_out_image:
  133.         f_out_image.write(magic)
  134.     finish(out_image)
  135.  
  136.  
  137. def cli():
  138.     if len(sys.argv) < 2:
  139.         print(usage)
  140.         sys.exit(1)
  141.     if sys.argv[1] in ["-h", "--help"]:
  142.         print(usage)
  143.         sys.exit(0)
  144.     if sys.argv[1] in ["-a", "--append"]:
  145.         if len(sys.argv) < 3:
  146.             print(usage)
  147.             sys.exit(1)
  148.         image_name = out_image = sys.argv[2]
  149.     else:
  150.         image_name = sys.argv[1]
  151.         if len(sys.argv) >= 3:
  152.             out_image = sys.argv[2]
  153.         else:
  154.             out_split = os.path.splitext(image_name)
  155.             out_image = out_split[0] + "_bumped" + out_split[1]
  156.     if not os.path.isfile(image_name):
  157.         print("file not found: %s" % image_name)
  158.         sys.exit(1)
  159.     main(image_name, out_image)
  160.  
  161.  
  162. if __name__ == '__main__':
  163.     cli()
Advertisement
Add Comment
Please, Sign In to add comment