DMv6 Patch
Nathan Hjelm <[email protected]>
| Newsgroups | gmane.comp.mobile.bitpim.devel |
|---|---|
| Message-ID | <[email protected]> |
After spending some time looking at challenges/responses and assembly code I can say I have DMv6 about 95% figured out. DMv6 phones respond to the 0xfe 0x00 command with a 0xfe 0x02 response (as opposed to 0xfe 0x01). The response is then a 0xfe 0x03 command containing an XOR of the DMv5 response mixed in with random numbers. The random numbers appear to have an effect on the locations of the key bytes (something I haven't had a chance to fully investigate) so for now I have hard- coded some "random" values for which the locations of the XOR bytes are known. Attached is the patch to enables DMv6 (which used on the VX-9100 and newer Verizon LG phones). I have verified that the changes do no interfere with the DMv5 code and that the code does indeed appear to work with the VX-9100. -Nathan ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ BitPim-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/bitpim-devel
DMv6.patch
(application/octet-stream, 27.5 KB)
Index: src/phones/p_lg.py
===================================================================
--- src/phones/p_lg.py (revision 4618)
+++ src/phones/p_lg.py (working copy)
@@ -2084,7 +2084,7 @@
self._bufferstartoffset=buf.getcurrentoffset()
try: self.__field_cmd
except:
- self.__field_cmd=UINT(**{'sizeinbytes': 1, 'default': 0xFE })
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'constant': 0xFE })
self.__field_cmd.writetobuffer(buf)
try: self.__field_unlock_code
except:
@@ -2103,7 +2103,7 @@
'Reads this packet from the supplied buffer'
self._bufferstartoffset=buf.getcurrentoffset()
if autolog and self._bufferstartoffset==0: self.autologread(buf, logtitle=logtitle)
- self.__field_cmd=UINT(**{'sizeinbytes': 1, 'default': 0xFE })
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'constant': 0xFE })
self.__field_cmd.readfrombuffer(buf)
self.__field_unlock_code=UINT(**{'sizeinbytes': 1, 'default': 0x00 })
self.__field_unlock_code.readfrombuffer(buf)
@@ -2117,14 +2117,14 @@
def __getfield_cmd(self):
try: self.__field_cmd
except:
- self.__field_cmd=UINT(**{'sizeinbytes': 1, 'default': 0xFE })
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'constant': 0xFE })
return self.__field_cmd.getvalue()
def __setfield_cmd(self, value):
if isinstance(value,UINT):
self.__field_cmd=value
else:
- self.__field_cmd=UINT(value,**{'sizeinbytes': 1, 'default': 0xFE })
+ self.__field_cmd=UINT(value,**{'sizeinbytes': 1, 'constant': 0xFE })
def __delfield_cmd(self): del self.__field_cmd
@@ -2309,6 +2309,614 @@
+class ULReqv6(BaseProtogenClass):
+ ""
+ __fields=['cmd', 'unlock_code', 'key0', 'zero', 'key1', 'key2', 'key3', 'key4']
+
+ def __init__(self, *args, **kwargs):
+ dict={}
+ # What was supplied to this function
+ dict.update(kwargs)
+ # Parent constructor
+ super(ULReqv6,self).__init__(**dict)
+ if self.__class__ is ULReqv6:
+ self._update(args,dict)
+
+
+ def getfields(self):
+ return self.__fields
+
+
+ def _update(self, args, kwargs):
+ super(ULReqv6,self)._update(args,kwargs)
+ keys=kwargs.keys()
+ for key in keys:
+ if key in self.__fields:
+ setattr(self, key, kwargs[key])
+ del kwargs[key]
+ # Were any unrecognized kwargs passed in?
+ if __debug__:
+ self._complainaboutunusedargs(ULReqv6,kwargs)
+ if len(args): raise TypeError('Unexpected arguments supplied: '+`args`)
+ # Make all P fields that haven't already been constructed
+
+
+ def writetobuffer(self,buf,autolog=True,logtitle="<written data>"):
+ 'Writes this packet to the supplied buffer'
+ self._bufferstartoffset=buf.getcurrentoffset()
+ try: self.__field_cmd
+ except:
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'constant': 0xFE })
+ self.__field_cmd.writetobuffer(buf)
+ try: self.__field_unlock_code
+ except:
+ self.__field_unlock_code=UINT(**{'sizeinbytes': 1, 'default': 0x03 })
+ self.__field_unlock_code.writetobuffer(buf)
+ self.__field_key0.writetobuffer(buf)
+ try: self.__field_zero
+ except:
+ self.__field_zero=UINT(**{'sizeinbytes': 2, 'default': 0x00 })
+ self.__field_zero.writetobuffer(buf)
+ self.__field_key1.writetobuffer(buf)
+ self.__field_key2.writetobuffer(buf)
+ self.__field_key3.writetobuffer(buf)
+ self.__field_key4.writetobuffer(buf)
+ self._bufferendoffset=buf.getcurrentoffset()
+ if autolog and self._bufferstartoffset==0: self.autologwrite(buf, logtitle=logtitle)
+
+
+ def readfrombuffer(self,buf,autolog=True,logtitle="<read data>"):
+ 'Reads this packet from the supplied buffer'
+ self._bufferstartoffset=buf.getcurrentoffset()
+ if autolog and self._bufferstartoffset==0: self.autologread(buf, logtitle=logtitle)
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'constant': 0xFE })
+ self.__field_cmd.readfrombuffer(buf)
+ self.__field_unlock_code=UINT(**{'sizeinbytes': 1, 'default': 0x03 })
+ self.__field_unlock_code.readfrombuffer(buf)
+ self.__field_key0=UINT(**{'sizeinbytes': 4})
+ self.__field_key0.readfrombuffer(buf)
+ self.__field_zero=UINT(**{'sizeinbytes': 2, 'default': 0x00 })
+ self.__field_zero.readfrombuffer(buf)
+ self.__field_key1=UINT(**{'sizeinbytes': 4})
+ self.__field_key1.readfrombuffer(buf)
+ self.__field_key2=UINT(**{'sizeinbytes': 4})
+ self.__field_key2.readfrombuffer(buf)
+ self.__field_key3=UINT(**{'sizeinbytes': 4})
+ self.__field_key3.readfrombuffer(buf)
+ self.__field_key4=UINT(**{'sizeinbytes': 4})
+ self.__field_key4.readfrombuffer(buf)
+ self._bufferendoffset=buf.getcurrentoffset()
+
+
+ def __getfield_cmd(self):
+ try: self.__field_cmd
+ except:
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'constant': 0xFE })
+ return self.__field_cmd.getvalue()
+
+ def __setfield_cmd(self, value):
+ if isinstance(value,UINT):
+ self.__field_cmd=value
+ else:
+ self.__field_cmd=UINT(value,**{'sizeinbytes': 1, 'constant': 0xFE })
+
+ def __delfield_cmd(self): del self.__field_cmd
+
+ cmd=property(__getfield_cmd, __setfield_cmd, __delfield_cmd, None)
+
+ def __getfield_unlock_code(self):
+ try: self.__field_unlock_code
+ except:
+ self.__field_unlock_code=UINT(**{'sizeinbytes': 1, 'default': 0x03 })
+ return self.__field_unlock_code.getvalue()
+
+ def __setfield_unlock_code(self, value):
+ if isinstance(value,UINT):
+ self.__field_unlock_code=value
+ else:
+ self.__field_unlock_code=UINT(value,**{'sizeinbytes': 1, 'default': 0x03 })
+
+ def __delfield_unlock_code(self): del self.__field_unlock_code
+
+ unlock_code=property(__getfield_unlock_code, __setfield_unlock_code, __delfield_unlock_code, None)
+
+ def __getfield_key0(self):
+ return self.__field_key0.getvalue()
+
+ def __setfield_key0(self, value):
+ if isinstance(value,UINT):
+ self.__field_key0=value
+ else:
+ self.__field_key0=UINT(value,**{'sizeinbytes': 4})
+
+ def __delfield_key0(self): del self.__field_key0
+
+ key0=property(__getfield_key0, __setfield_key0, __delfield_key0, None)
+
+ def __getfield_zero(self):
+ try: self.__field_zero
+ except:
+ self.__field_zero=UINT(**{'sizeinbytes': 2, 'default': 0x00 })
+ return self.__field_zero.getvalue()
+
+ def __setfield_zero(self, value):
+ if isinstance(value,UINT):
+ self.__field_zero=value
+ else:
+ self.__field_zero=UINT(value,**{'sizeinbytes': 2, 'default': 0x00 })
+
+ def __delfield_zero(self): del self.__field_zero
+
+ zero=property(__getfield_zero, __setfield_zero, __delfield_zero, None)
+
+ def __getfield_key1(self):
+ return self.__field_key1.getvalue()
+
+ def __setfield_key1(self, value):
+ if isinstance(value,UINT):
+ self.__field_key1=value
+ else:
+ self.__field_key1=UINT(value,**{'sizeinbytes': 4})
+
+ def __delfield_key1(self): del self.__field_key1
+
+ key1=property(__getfield_key1, __setfield_key1, __delfield_key1, None)
+
+ def __getfield_key2(self):
+ return self.__field_key2.getvalue()
+
+ def __setfield_key2(self, value):
+ if isinstance(value,UINT):
+ self.__field_key2=value
+ else:
+ self.__field_key2=UINT(value,**{'sizeinbytes': 4})
+
+ def __delfield_key2(self): del self.__field_key2
+
+ key2=property(__getfield_key2, __setfield_key2, __delfield_key2, None)
+
+ def __getfield_key3(self):
+ return self.__field_key3.getvalue()
+
+ def __setfield_key3(self, value):
+ if isinstance(value,UINT):
+ self.__field_key3=value
+ else:
+ self.__field_key3=UINT(value,**{'sizeinbytes': 4})
+
+ def __delfield_key3(self): del self.__field_key3
+
+ key3=property(__getfield_key3, __setfield_key3, __delfield_key3, None)
+
+ def __getfield_key4(self):
+ return self.__field_key4.getvalue()
+
+ def __setfield_key4(self, value):
+ if isinstance(value,UINT):
+ self.__field_key4=value
+ else:
+ self.__field_key4=UINT(value,**{'sizeinbytes': 4})
+
+ def __delfield_key4(self): del self.__field_key4
+
+ key4=property(__getfield_key4, __setfield_key4, __delfield_key4, None)
+
+ def iscontainer(self):
+ return True
+
+ def containerelements(self):
+ yield ('cmd', self.__field_cmd, None)
+ yield ('unlock_code', self.__field_unlock_code, None)
+ yield ('key0', self.__field_key0, None)
+ yield ('zero', self.__field_zero, None)
+ yield ('key1', self.__field_key1, None)
+ yield ('key2', self.__field_key2, None)
+ yield ('key3', self.__field_key3, None)
+ yield ('key4', self.__field_key4, None)
+
+
+
+
+class ULResv6(BaseProtogenClass):
+ ""
+ __fields=['cmd', 'unlock_code', 'unlock_key', 'unlock_ok', 'bytes']
+
+ def __init__(self, *args, **kwargs):
+ dict={}
+ # What was supplied to this function
+ dict.update(kwargs)
+ # Parent constructor
+ super(ULResv6,self).__init__(**dict)
+ if self.__class__ is ULResv6:
+ self._update(args,dict)
+
+
+ def getfields(self):
+ return self.__fields
+
+
+ def _update(self, args, kwargs):
+ super(ULResv6,self)._update(args,kwargs)
+ keys=kwargs.keys()
+ for key in keys:
+ if key in self.__fields:
+ setattr(self, key, kwargs[key])
+ del kwargs[key]
+ # Were any unrecognized kwargs passed in?
+ if __debug__:
+ self._complainaboutunusedargs(ULResv6,kwargs)
+ if len(args): raise TypeError('Unexpected arguments supplied: '+`args`)
+ # Make all P fields that haven't already been constructed
+
+
+ def writetobuffer(self,buf,autolog=True,logtitle="<written data>"):
+ 'Writes this packet to the supplied buffer'
+ self._bufferstartoffset=buf.getcurrentoffset()
+ self.__field_cmd.writetobuffer(buf)
+ self.__field_unlock_code.writetobuffer(buf)
+ self.__field_unlock_key.writetobuffer(buf)
+ self.__field_unlock_ok.writetobuffer(buf)
+ self.__field_bytes.writetobuffer(buf)
+ self._bufferendoffset=buf.getcurrentoffset()
+ if autolog and self._bufferstartoffset==0: self.autologwrite(buf, logtitle=logtitle)
+
+
+ def readfrombuffer(self,buf,autolog=True,logtitle="<read data>"):
+ 'Reads this packet from the supplied buffer'
+ self._bufferstartoffset=buf.getcurrentoffset()
+ if autolog and self._bufferstartoffset==0: self.autologread(buf, logtitle=logtitle)
+ self.__field_cmd=UINT(**{'sizeinbytes': 1})
+ self.__field_cmd.readfrombuffer(buf)
+ self.__field_unlock_code=UINT(**{'sizeinbytes': 1})
+ self.__field_unlock_code.readfrombuffer(buf)
+ self.__field_unlock_key=UINT(**{'sizeinbytes': 4})
+ self.__field_unlock_key.readfrombuffer(buf)
+ self.__field_unlock_ok=UINT(**{'sizeinbytes': 1})
+ self.__field_unlock_ok.readfrombuffer(buf)
+ self.__field_bytes=DATA()
+ self.__field_bytes.readfrombuffer(buf)
+ self._bufferendoffset=buf.getcurrentoffset()
+
+
+ def __getfield_cmd(self):
+ return self.__field_cmd.getvalue()
+
+ def __setfield_cmd(self, value):
+ if isinstance(value,UINT):
+ self.__field_cmd=value
+ else:
+ self.__field_cmd=UINT(value,**{'sizeinbytes': 1})
+
+ def __delfield_cmd(self): del self.__field_cmd
+
+ cmd=property(__getfield_cmd, __setfield_cmd, __delfield_cmd, None)
+
+ def __getfield_unlock_code(self):
+ return self.__field_unlock_code.getvalue()
+
+ def __setfield_unlock_code(self, value):
+ if isinstance(value,UINT):
+ self.__field_unlock_code=value
+ else:
+ self.__field_unlock_code=UINT(value,**{'sizeinbytes': 1})
+
+ def __delfield_unlock_code(self): del self.__field_unlock_code
+
+ unlock_code=property(__getfield_unlock_code, __setfield_unlock_code, __delfield_unlock_code, None)
+
+ def __getfield_unlock_key(self):
+ return self.__field_unlock_key.getvalue()
+
+ def __setfield_unlock_key(self, value):
+ if isinstance(value,UINT):
+ self.__field_unlock_key=value
+ else:
+ self.__field_unlock_key=UINT(value,**{'sizeinbytes': 4})
+
+ def __delfield_unlock_key(self): del self.__field_unlock_key
+
+ unlock_key=property(__getfield_unlock_key, __setfield_unlock_key, __delfield_unlock_key, None)
+
+ def __getfield_unlock_ok(self):
+ return self.__field_unlock_ok.getvalue()
+
+ def __setfield_unlock_ok(self, value):
+ if isinstance(value,UINT):
+ self.__field_unlock_ok=value
+ else:
+ self.__field_unlock_ok=UINT(value,**{'sizeinbytes': 1})
+
+ def __delfield_unlock_ok(self): del self.__field_unlock_ok
+
+ unlock_ok=property(__getfield_unlock_ok, __setfield_unlock_ok, __delfield_unlock_ok, None)
+
+ def __getfield_bytes(self):
+ return self.__field_bytes.getvalue()
+
+ def __setfield_bytes(self, value):
+ if isinstance(value,DATA):
+ self.__field_bytes=value
+ else:
+ self.__field_bytes=DATA(value,)
+
+ def __delfield_bytes(self): del self.__field_bytes
+
+ bytes=property(__getfield_bytes, __setfield_bytes, __delfield_bytes, None)
+
+ def iscontainer(self):
+ return True
+
+ def containerelements(self):
+ yield ('cmd', self.__field_cmd, None)
+ yield ('unlock_code', self.__field_unlock_code, None)
+ yield ('unlock_key', self.__field_unlock_key, None)
+ yield ('unlock_ok', self.__field_unlock_ok, None)
+ yield ('bytes', self.__field_bytes, None)
+
+
+
+
+class DM6Unlock2(BaseProtogenClass):
+ __fields=['cmd', 'data1', 'data2']
+
+ def __init__(self, *args, **kwargs):
+ dict={}
+ # What was supplied to this function
+ dict.update(kwargs)
+ # Parent constructor
+ super(DM6Unlock2,self).__init__(**dict)
+ if self.__class__ is DM6Unlock2:
+ self._update(args,dict)
+
+
+ def getfields(self):
+ return self.__fields
+
+
+ def _update(self, args, kwargs):
+ super(DM6Unlock2,self)._update(args,kwargs)
+ keys=kwargs.keys()
+ for key in keys:
+ if key in self.__fields:
+ setattr(self, key, kwargs[key])
+ del kwargs[key]
+ # Were any unrecognized kwargs passed in?
+ if __debug__:
+ self._complainaboutunusedargs(DM6Unlock2,kwargs)
+ if len(args): raise TypeError('Unexpected arguments supplied: '+`args`)
+ # Make all P fields that haven't already been constructed
+
+
+ def writetobuffer(self,buf,autolog=True,logtitle="<written data>"):
+ 'Writes this packet to the supplied buffer'
+ self._bufferstartoffset=buf.getcurrentoffset()
+ try: self.__field_cmd
+ except:
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'default': 0xFB })
+ self.__field_cmd.writetobuffer(buf)
+ try: self.__field_data1
+ except:
+ self.__field_data1=UINT(**{'sizeinbytes': 2, 'default': 0x06 })
+ self.__field_data1.writetobuffer(buf)
+ try: self.__field_data2
+ except:
+ self.__field_data2=UINT(**{'sizeinbytes': 1, 'default': 0x02 })
+ self.__field_data2.writetobuffer(buf)
+ self._bufferendoffset=buf.getcurrentoffset()
+ if autolog and self._bufferstartoffset==0: self.autologwrite(buf, logtitle=logtitle)
+
+
+ def readfrombuffer(self,buf,autolog=True,logtitle="<read data>"):
+ 'Reads this packet from the supplied buffer'
+ self._bufferstartoffset=buf.getcurrentoffset()
+ if autolog and self._bufferstartoffset==0: self.autologread(buf, logtitle=logtitle)
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'default': 0xFB })
+ self.__field_cmd.readfrombuffer(buf)
+ self.__field_data1=UINT(**{'sizeinbytes': 2, 'default': 0x06 })
+ self.__field_data1.readfrombuffer(buf)
+ self.__field_data2=UINT(**{'sizeinbytes': 1, 'default': 0x02 })
+ self.__field_data2.readfrombuffer(buf)
+ self._bufferendoffset=buf.getcurrentoffset()
+
+
+ def __getfield_cmd(self):
+ try: self.__field_cmd
+ except:
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'default': 0xFB })
+ return self.__field_cmd.getvalue()
+
+ def __setfield_cmd(self, value):
+ if isinstance(value,UINT):
+ self.__field_cmd=value
+ else:
+ self.__field_cmd=UINT(value,**{'sizeinbytes': 1, 'default': 0xFB })
+
+ def __delfield_cmd(self): del self.__field_cmd
+
+ cmd=property(__getfield_cmd, __setfield_cmd, __delfield_cmd, None)
+
+ def __getfield_data1(self):
+ try: self.__field_data1
+ except:
+ self.__field_data1=UINT(**{'sizeinbytes': 2, 'default': 0x06 })
+ return self.__field_data1.getvalue()
+
+ def __setfield_data1(self, value):
+ if isinstance(value,UINT):
+ self.__field_data1=value
+ else:
+ self.__field_data1=UINT(value,**{'sizeinbytes': 2, 'default': 0x06 })
+
+ def __delfield_data1(self): del self.__field_data1
+
+ data1=property(__getfield_data1, __setfield_data1, __delfield_data1, None)
+
+ def __getfield_data2(self):
+ try: self.__field_data2
+ except:
+ self.__field_data2=UINT(**{'sizeinbytes': 1, 'default': 0x02 })
+ return self.__field_data2.getvalue()
+
+ def __setfield_data2(self, value):
+ if isinstance(value,UINT):
+ self.__field_data2=value
+ else:
+ self.__field_data2=UINT(value,**{'sizeinbytes': 1, 'default': 0x02 })
+
+ def __delfield_data2(self): del self.__field_data2
+
+ data2=property(__getfield_data2, __setfield_data2, __delfield_data2, None)
+
+ def iscontainer(self):
+ return True
+
+ def containerelements(self):
+ yield ('cmd', self.__field_cmd, None)
+ yield ('data1', self.__field_data1, None)
+ yield ('data2', self.__field_data2, None)
+
+
+
+
+class DM6Unlock2Resp(BaseProtogenClass):
+ __fields=['cmd', 'data1', 'data2', 'unk']
+
+ def __init__(self, *args, **kwargs):
+ dict={}
+ # What was supplied to this function
+ dict.update(kwargs)
+ # Parent constructor
+ super(DM6Unlock2Resp,self).__init__(**dict)
+ if self.__class__ is DM6Unlock2Resp:
+ self._update(args,dict)
+
+
+ def getfields(self):
+ return self.__fields
+
+
+ def _update(self, args, kwargs):
+ super(DM6Unlock2Resp,self)._update(args,kwargs)
+ keys=kwargs.keys()
+ for key in keys:
+ if key in self.__fields:
+ setattr(self, key, kwargs[key])
+ del kwargs[key]
+ # Were any unrecognized kwargs passed in?
+ if __debug__:
+ self._complainaboutunusedargs(DM6Unlock2Resp,kwargs)
+ if len(args): raise TypeError('Unexpected arguments supplied: '+`args`)
+ # Make all P fields that haven't already been constructed
+
+
+ def writetobuffer(self,buf,autolog=True,logtitle="<written data>"):
+ 'Writes this packet to the supplied buffer'
+ self._bufferstartoffset=buf.getcurrentoffset()
+ try: self.__field_cmd
+ except:
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'default': 0xFB })
+ self.__field_cmd.writetobuffer(buf)
+ try: self.__field_data1
+ except:
+ self.__field_data1=UINT(**{'sizeinbytes': 2, 'default': 0x06 })
+ self.__field_data1.writetobuffer(buf)
+ try: self.__field_data2
+ except:
+ self.__field_data2=UINT(**{'sizeinbytes': 6, 'default': 0 })
+ self.__field_data2.writetobuffer(buf)
+ self.__field_unk.writetobuffer(buf)
+ self._bufferendoffset=buf.getcurrentoffset()
+ if autolog and self._bufferstartoffset==0: self.autologwrite(buf, logtitle=logtitle)
+
+
+ def readfrombuffer(self,buf,autolog=True,logtitle="<read data>"):
+ 'Reads this packet from the supplied buffer'
+ self._bufferstartoffset=buf.getcurrentoffset()
+ if autolog and self._bufferstartoffset==0: self.autologread(buf, logtitle=logtitle)
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'default': 0xFB })
+ self.__field_cmd.readfrombuffer(buf)
+ self.__field_data1=UINT(**{'sizeinbytes': 2, 'default': 0x06 })
+ self.__field_data1.readfrombuffer(buf)
+ self.__field_data2=UINT(**{'sizeinbytes': 6, 'default': 0 })
+ self.__field_data2.readfrombuffer(buf)
+ self.__field_unk=DATA()
+ self.__field_unk.readfrombuffer(buf)
+ self._bufferendoffset=buf.getcurrentoffset()
+
+
+ def __getfield_cmd(self):
+ try: self.__field_cmd
+ except:
+ self.__field_cmd=UINT(**{'sizeinbytes': 1, 'default': 0xFB })
+ return self.__field_cmd.getvalue()
+
+ def __setfield_cmd(self, value):
+ if isinstance(value,UINT):
+ self.__field_cmd=value
+ else:
+ self.__field_cmd=UINT(value,**{'sizeinbytes': 1, 'default': 0xFB })
+
+ def __delfield_cmd(self): del self.__field_cmd
+
+ cmd=property(__getfield_cmd, __setfield_cmd, __delfield_cmd, None)
+
+ def __getfield_data1(self):
+ try: self.__field_data1
+ except:
+ self.__field_data1=UINT(**{'sizeinbytes': 2, 'default': 0x06 })
+ return self.__field_data1.getvalue()
+
+ def __setfield_data1(self, value):
+ if isinstance(value,UINT):
+ self.__field_data1=value
+ else:
+ self.__field_data1=UINT(value,**{'sizeinbytes': 2, 'default': 0x06 })
+
+ def __delfield_data1(self): del self.__field_data1
+
+ data1=property(__getfield_data1, __setfield_data1, __delfield_data1, None)
+
+ def __getfield_data2(self):
+ try: self.__field_data2
+ except:
+ self.__field_data2=UINT(**{'sizeinbytes': 6, 'default': 0 })
+ return self.__field_data2.getvalue()
+
+ def __setfield_data2(self, value):
+ if isinstance(value,UINT):
+ self.__field_data2=value
+ else:
+ self.__field_data2=UINT(value,**{'sizeinbytes': 6, 'default': 0 })
+
+ def __delfield_data2(self): del self.__field_data2
+
+ data2=property(__getfield_data2, __setfield_data2, __delfield_data2, None)
+
+ def __getfield_unk(self):
+ return self.__field_unk.getvalue()
+
+ def __setfield_unk(self, value):
+ if isinstance(value,DATA):
+ self.__field_unk=value
+ else:
+ self.__field_unk=DATA(value,)
+
+ def __delfield_unk(self): del self.__field_unk
+
+ unk=property(__getfield_unk, __setfield_unk, __delfield_unk, None)
+
+ def iscontainer(self):
+ return True
+
+ def containerelements(self):
+ yield ('cmd', self.__field_cmd, None)
+ yield ('data1', self.__field_data1, None)
+ yield ('data2', self.__field_data2, None)
+ yield ('unk', self.__field_unk, None)
+
+
+
+
class data(BaseProtogenClass):
__fields=['bytes']
Index: src/phones/com_lg.py
===================================================================
--- src/phones/com_lg.py (revision 4618)
+++ src/phones/com_lg.py (working copy)
@@ -17,6 +17,7 @@
import p_lg
import prototypes
import common
+import random
class LGPhonebook:
@@ -1592,17 +1593,55 @@
_req=self.protocolclass.ULReq(unlock_key=0)
_resp=self.sendbrewcommand(_req, self.protocolclass.ULRes)
- # respond with the key
+ # generate the challenge-repsponse
_key=self.get_challenge_response(_resp.unlock_key)
if _key is None:
self.log('Failed to get the key.')
raise EnterDMError('Failed to get the key')
- _req=self.protocolclass.ULReq(unlock_code=1, unlock_key=_key)
- _resp=self.sendbrewcommand(_req, self.protocolclass.ULRes)
- if _resp.unlock_ok!=1:
+ if _resp.unlock_code == 0x02:
+ # DMv6 phones respond with "unlock code" 02
+ _resp = self._DMv6_unlock (_key ^ 0xffffffffL)
+ elif _resp.unlock_code == 0x00:
+ # DMv5 phones respond with "unlock code" 01
+ _resp = self._DMv5_unlock (_key)
+ else:
+ raise EnterDMError('Unknown unlock code from phone: %d'%_resp.unlock_code)
+
+ if _resp.unlock_ok != 1:
raise EnterDMError('Bad response - unlock_ok: %d'%_resp.unlock_ok)
+ def _DMv5_unlock(self, key):
+ _req=self.protocolclass.ULReq(unlock_code=1, unlock_key=key)
+ _resp=self.sendbrewcommand(_req, self.protocolclass.ULRes)
+ return _resp
+
+ def _DMv6_unlock(self, xorkey):
+ # key0 is entirely random
+ # key1-4 contain 3 random bytes and one xor key byte
+ # Note: the values of the random bytes seem to determine where the xor key byte is stored.
+ # Once we determine how the random bytes affect the key byte location the below values
+ # will be calculated randomly. For now hard-coding some values from a know response
+ # should work.
+ # -Nathan
+
+ key0 = 0x86b206a0L
+ key1 = 0x86b200a0L | ((xorkey & 0x000000ffL) << 8)
+ key2 = 0xb8200033L | (xorkey & 0x0000ff00L)
+ key3 = 0x57410069L | ((xorkey & 0x00ff0000L) >> 8)
+ key4 = 0x8da4007fL | ((xorkey & 0xff000000L) >> 16)
+
+ _req = self.protocolclass.ULReqv6(unlock_code=3, key0=key0, key1=key1, key2=key2, key3=key3, key4=key4)
+ _resp=self.sendbrewcommand(_req, self.protocolclass.ULResv6)
+
+ # the phone is most likely unlocked at this point
+
+ # TODO -- check if this command needs to be sent
+ _ul2 = self.protocolclass.DM6Unlock2()
+ _ul2_res = self.sendbrewcommand(_ul2, self.protocolclass.DM6Unlock2Resp)
+
+ return _resp
+
def enter_DM(self, e=None):
# do nothing if the phone failed to previously enter DM
if self._in_DM is False:
Index: src/phones/p_lg.p
===================================================================
--- src/phones/p_lg.p (revision 4618)
+++ src/phones/p_lg.p (working copy)
@@ -140,11 +140,11 @@
PACKET ULReq:
""
- 1 UINT { 'default': 0xFE } +cmd
+ 1 UINT { 'constant': 0xFE } +cmd
1 UINT { 'default': 0x00 } +unlock_code
4 UINT unlock_key
1 UINT { 'default': 0x00 } +zero
-
+
PACKET ULRes:
""
1 UINT cmd
@@ -152,6 +152,36 @@
4 UINT unlock_key
1 UINT unlock_ok
+PACKET ULReqv6:
+ ""
+ 1 UINT { 'constant': 0xFE } +cmd
+ 1 UINT { 'default': 0x03 } +unlock_code
+ 4 UINT key0
+ 2 UINT { 'default': 0x00 } +zero
+ 4 UINT key1
+ 4 UINT key2
+ 4 UINT key3
+ 4 UINT key4
+PACKET ULResv6:
+ ""
+ 1 UINT cmd
+ 1 UINT unlock_code
+ 4 UINT unlock_key
+ 1 UINT unlock_ok
+ * DATA bytes
+
+# it is unclear whether this command is meaningful
+PACKET DM6Unlock2:
+ 1 UINT { 'default': 0xFB } +cmd
+ 2 UINT { 'default': 0x06 } +data1
+ 1 UINT { 'default': 0x02 } +data2
+
+PACKET DM6Unlock2Resp:
+ 1 UINT { 'default': 0xFB } +cmd
+ 2 UINT { 'default': 0x06 } +data1
+ 6 UINT { 'default': 0 } +data2
+ * DATA unk
+
PACKET data:
* DATA bytes