Guest User

Untitled

a guest
Nov 24th, 2014
322
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.29 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. if POC:
  31.     from Crypto.Cipher import AES
  32.     import hashlib
  33.  
  34.  
  35. usage = """\
  36. Usage: open_bump.py [-ha] "<image_file>" "<output_image>"
  37.  image_file        - <required> path to the image file to bump
  38.  output_image      - <optional> path to output the bumped file to (defaults to <image_file>_bumped.img
  39.  -a/--apend image_file  - <required> if in append mode, the <image_file> is appended rather than <output_file> being generated\
  40. """
  41.  
  42. lg_key = "b5e7fc2010c4a82d6d597ba040816da7832e0a5679c81475a0438447b711140f"
  43. lg_iv = "$ecure-W@|lp@per"
  44. lg_magic = "41a9e467744d1d1ba429f2ecea655279"
  45. lg_dec_magic = "696e6877612e77651000000047116667"
  46.  
  47.  
  48. def generate_signature(image_hash):
  49.     # the iv and key were extracted from the lg g2 aboot.img. I can explain how to find it on request.
  50.     iv = lg_iv
  51.     key = binascii.unhexlify(lg_key)
  52.     # this "magic" number was found after decrypting the bumped images
  53.     # Without codefire, this would not have been possible as I can find no reference in
  54.     # the images of the g2 or the g3
  55.     magic = binascii.unhexlify(lg_magic)
  56.     image_hash = binascii.unhexlify(image_hash)  # insert your hash here
  57.     # the structure of the signature in bump starts with a magic number, then seemingly random
  58.     # bytes. 2 zeros follow, then the hash of the image, then 6 zeros, then 512 bytes of random data again
  59.     data = magic + os.urandom(16) + '\x00'*2 + image_hash + '\x00'*6 + os.urandom(512)
  60.     # this is then padded to fill the needed 1024 bytes
  61.     padded_data = data + '\x00'*(1024-len(data))
  62.     # AES-256 is then used to encrypt the above data
  63.     cipher = AES.new(key, AES.MODE_CBC, iv)
  64.     return cipher.encrypt(padded_data)
  65.  
  66.  
  67. def bumped(image_data):
  68.     d = binascii.hexlify(image_data[-1024:])
  69.     return d.endswith(lg_magic) or d.startswith(lg_magic)
  70.  
  71.  
  72. def pair_reverse(s):
  73.     n = len(s) / 2
  74.     fmt = '%dh' % n
  75.     return struct.pack(fmt, *reversed(struct.unpack(fmt, s)))
  76.  
  77.  
  78. def get_page_size(image_name):
  79.     with open(image_name, 'rb') as f_img:
  80.         f_img.seek(36, 0)
  81.         return int(pair_reverse(binascii.hexlify(f_img.read(4))), 16)
  82.  
  83.  
  84. def get_size_from_kernel(f_image, page_size, seek_size):
  85.     f_image.seek(seek_size, 0)
  86.     return (int(pair_reverse(binascii.hexlify(f_image.read(4))), 16) / page_size) * page_size
  87.  
  88.  
  89. def pad_image(image_name):
  90.     page_size = get_page_size(image_name)
  91.     image_size = os.path.getsize(image_name)
  92.     num_pages = image_size / page_size
  93.  
  94.     f_image = open(image_name, 'a+b')
  95.  
  96.     paged_kernel_size = get_size_from_kernel(f_image, page_size, 8)
  97.     paged_ramdisk_size = get_size_from_kernel(f_image, page_size, 16)
  98.     paged_second_size = get_size_from_kernel(f_image, page_size, 24)
  99.     if paged_second_size <= 0:
  100.         paged_second_size = 0
  101.     paged_dt_size = get_size_from_kernel(f_image, page_size, 40)
  102.     if paged_dt_size <= 0:
  103.         paged_dt_size = 0
  104.     calculated_size = page_size + paged_kernel_size + paged_ramdisk_size + paged_second_size + paged_dt_size
  105.  
  106.     if calculated_size > image_size:
  107.         print("Invalid image: %s: calculated size greater than actual size" % image_name)
  108.         f_image.close()
  109.         sys.exit(1)
  110.     if image_size > calculated_size:
  111.         difference = image_size - calculated_size
  112.         if difference not in [page_size, page_size*2]:
  113.             if difference not in [1024, page_size + 1024, 2 * page_size + 1024]:
  114.                 print("Image already padded. Attempting to remove padding...")
  115.                 print("Beware: this may invalidate your image.")
  116.                 i = num_pages - 1
  117.                 f_image.seek(0, 0)
  118.                 while i >= 0:
  119.                     f_image.seek(page_size * i, 0)
  120.                     data = f_image.read(page_size)
  121.                     data = data.split('\x00')[0]
  122.                     if not data:
  123.                         f_image.truncate(page_size * i)
  124.                         i -= 1
  125.                     else:
  126.                         break
  127.             else:
  128.                 print("%s: Image already patched. Bailing out" % image_name)
  129.                 sys.exit(1)
  130.     f_image.close()
  131.  
  132.  
  133. def get_sha1(image_name):
  134.     return hashlib.sha1(open(image_name, 'rb').read()).hexdigest()
  135.    
  136.  
  137. def finish(out_image):
  138.     print("bumped image: %s" % out_image)
  139.     sys.exit(0)
  140.  
  141.  
  142. def main(in_image, out_image):
  143.     d_in_image = open(in_image, 'rb').read()
  144.     open(out_image, 'wb').write(d_in_image)
  145.     if bumped(d_in_image):
  146.         print("Image already bumped")
  147.         finish(out_image)
  148.     pad_image(out_image)
  149.     if POC:
  150.         sha1sum = get_sha1(out_image)
  151.         magic = generate_signature(sha1sum)
  152.     else:
  153.         magic = binascii.unhexlify(lg_magic)
  154.     with open(out_image, 'a+b') as f_out_image:
  155.         f_out_image.write(magic)
  156.     finish(out_image)
  157.  
  158.  
  159. def cli():
  160.     if len(sys.argv) < 2:
  161.         print(usage)
  162.         sys.exit(1)
  163.     if sys.argv[1] in ["-h", "--help"]:
  164.         print(usage)
  165.         sys.exit(0)
  166.     if sys.argv[1] in ["-a", "--append"]:
  167.         if len(sys.argv) < 3:
  168.             print(usage)
  169.             sys.exit(1)
  170.         image_name = out_image = sys.argv[2]
  171.     else:
  172.         image_name = sys.argv[1]
  173.         if len(sys.argv) >= 3:
  174.             out_image = sys.argv[2]
  175.         else:
  176.             out_split = os.path.splitext(image_name)
  177.             out_image = out_split[0] + "_bumped" + out_split[1]
  178.     if not os.path.isfile(image_name):
  179.         print("file not found: %s" % image_name)
  180.         sys.exit(1)
  181.     main(image_name, out_image)
  182.  
  183.  
  184. if __name__ == '__main__':
  185.     cli()
Advertisement
Add Comment
Please, Sign In to add comment