diff --git a/laf_crypto.py b/laf_crypto.py
new file mode 100644
index 0000000..16d87eb
--- /dev/null
+++ b/laf_crypto.py
@@ -0,0 +1,33 @@
+from Crypto.Cipher import AES
+from lglaf import int_as_byte
+
+
+def key_transform(old_key):
+    new_key = b''
+    for x in range(32, 0, -1):
+        new_key += int_as_byte(old_key[x-1] - (x % 0x0C))
+    return new_key
+
+
+def xor_key(key, kilo_challenge):
+    # Reserve key
+    key_xor = b''
+    pos = 0
+    for i in range(8):
+        key_xor += int_as_byte(key[pos] ^ kilo_challenge[3])
+        key_xor += int_as_byte(key[pos + 1] ^ kilo_challenge[2])
+        key_xor += int_as_byte(key[pos + 2] ^ kilo_challenge[1])
+        key_xor += int_as_byte(key[pos + 3] ^ kilo_challenge[0])
+        pos += 4
+    return key_xor
+
+
+def encrypt_kilo_challenge(encryption_key, kilo_challenge):
+    plaintext = b''
+    for k in range(0, 16):
+        # Assemble 0x00 0x01 0x02 ... 0x1F byte-array
+        plaintext += int_as_byte(k)
+    encryption_key = key_transform(encryption_key)
+    xored_key = xor_key(encryption_key, kilo_challenge)
+    obj = AES.new(xored_key, AES.MODE_ECB)
+    return obj.encrypt(plaintext)
diff --git a/lglaf.py b/lglaf.py
index 4997c34..9e9e57f 100755
--- a/lglaf.py
+++ b/lglaf.py
@@ -7,7 +7,7 @@
 
 from __future__ import print_function
 from contextlib import closing
-import argparse, logging, re, struct, sys
+import argparse, logging, re, struct, sys, binascii
 
 # Enhanced prompt with history
 try: import readline
@@ -29,6 +29,15 @@ except: pass
 if '\0' == b'\0': int_as_byte = chr
 else: int_as_byte = lambda x: bytes([x])
 
+# laf crypto for KILO challenge/response
+try:
+    import laf_crypto
+except ImportError:
+    _logger.warning("LAF Crypto failed to import!")
+    pass
+
+# Use Manufacturer key for KILO challenge/response
+USE_MFG_KEY = False
 
 laf_error_codes = {
     0x80000000: "FAILED",
@@ -329,6 +338,24 @@ class USBCommunication(Communication):
     def close(self):
         usb.util.dispose_resources(self.usbdev)
 
+def challenge_response(comm, mode):
+    request_kilo = make_request(b'KILO', args=[b'CENT', b'\0\0\0\0', b'\0\0\0\0', b'\0\0\0\0'])
+    kilo_header, kilo_response = comm.call(request_kilo)
+    kilo_challenge = kilo_header[8:12]
+    _logger.debug("Challenge: %s" % binascii.hexlify(kilo_challenge))
+    if USE_MFG_KEY:
+        key = b'lgowvqnltpvtgogwswqn~n~mtjjjqxro'
+    else:
+        key = b'qndiakxxuiemdklseqid~a~niq,zjuxl'
+    kilo_response = laf_crypto.encrypt_kilo_challenge(key, kilo_challenge)
+    _logger.debug("Response: %s" % binascii.hexlify(kilo_response))
+    mode_bytes = struct.pack('<I', mode)
+    kilo_metr_request = make_request(b'KILO', args=[b'METR', b'\0\0\0\0', mode_bytes, b'\0\0\0\0'],
+                                     body=bytes(kilo_response))
+    metr_header, metr_response = comm.call(kilo_metr_request)
+    _logger.debug("KILO METR Response -> Header: %s, Body: %s" % (
+        binascii.hexlify(metr_header), binascii.hexlify(metr_response)))
+
 def try_hello(comm):
     """
     Tests whether the device speaks the expected protocol. If desynchronization
@@ -426,6 +453,8 @@ def command_to_payload(command, rawshell):
 parser = argparse.ArgumentParser(description='LG LAF Download Mode utility')
 parser.add_argument("--skip-hello", action="store_true",
         help="Immediately send commands, skip HELO message")
+parser.add_argument("--cr", action="store_true",
+        help="Do initial challenge response (KILO CENT/METR)")
 parser.add_argument('--rawshell', action="store_true",
         help="Execute shell commands as-is, needed on recent devices. "
              "CAUTION: stderr output is not redirected!")
@@ -449,6 +478,11 @@ def main():
         comm = autodetect_device()
 
     with closing(comm):
+        if args.cr:
+            # Mode 2 seems standard, will maybe
+            # change in other protocol versions
+            _logger.debug("Doing KILO challenge response")
+            challenge_response(comm, mode=2)
         if not args.skip_hello:
             try_hello(comm)
             _logger.debug("Hello done, proceeding with commands")