This is how 40D (and 400D) code decrypth the flasher code 1(2)

  • 11 Replies
  • 8765 Views
  • Publish
    Advertisements
    Hi,

    I have not much time lately but I figured out EXACTLY how the 40D and 400D calculates the decipher keys and how the flasher code is decrypted.
    This makes the it very simple to calculate these keys foe next FW updates.

    One of the first things the 40D does is to copy a block of data of 0x25530 bytes to the RAM area starting at 0x1900 (see sub on 0xFF8100DC)
    This data block contains the decipher keys.
    Key1 is stored on locations 0x7EC4 - 0x80C3    (512 bytes)  (copied form FFD902A4 - FFD904A3).
    Key2 is stored on locations 0x80C4 - 0x82C4    (513 bytes)  (copied form FFD904A4 - FFD906A4)

    Note to 400D users, the keys are located here
    Key1 = FFB6548 - FFB6747
    key2 = FFB6748 - FFB6948

    The keys are not used from byte on onwards but a starting point in the middle of the keys are calculated later in the sub  at 0xFFBC54C8
    For this two values are used
    - FF803FE1 is hard coded in the FW for both 40D and 400D.
    - 806ECB00 is located at address 0xBC in the header if the FIR File. This one is different for each firmware version.

    The offset is calculated in the following way. first multiply the two values.

    Temp1:= 0x806ECB00 * FF803FE1  = 802E.B3A6. A555.6B00
    Temp1 is split in a high and low dword

    Temp2 := 802E.B3A6

    The offset for Key1 is calulated by performing an AND operation on the value derived from the header 0x806ECB00
    Offset_Key1 := 806ECB00  AND 0x1FF
    Offset_Key1 := 0x100


    The offset for Key2 is calulated by
    Temp2 := Temp2 SLR 9 (= div by 0x200)
    Temp2 := Temp2 + Temp2 * SLL 9 (= mulltiply by 0x201)
    Offset_Key1 := 0x806ECB00  - Temp2 ( here agian 0x806ECB00 the the value loaded form the header is used)
    Offset_Key1 :=0x1A7

    The actual dectyprion uses the two Key values combined with an extra XOR with value 0x37 (same for both 40D and 400D).

    [Result] = [Input]  XOR  Key1  XOR  Key2  XOR  0x37

    Sadly the sub on location FFBC54C8 only decrypts the flasher code and not the FW paiload at the end. I am still figuring out where this is decrypted but I have not been able to find it. Does anyone have a clue?
    « Last Edit: 14 / January / 2009, 11:39:49 by emklap »

  • Publish
    This is how 40D (and 400D) code decrypth the flasher code 2(2)
    « Reply #1 on: 25 / July / 2008, 10:08:45 »

    I atteched a new explenation of the header data

    Code wise it looks like this

    Than the next happens
    FFBB6B18 : The sub "Execute_Ceres_Job" contains a switch statement which executes all kinds of actions on the CF card like file open, read write etc.

    FFBB7240 : This is case 29 "UPDATEFILEDATA_CERES_UPD_DecryptToFir" that opens the FIR file.
    ...
    ...
    FFBB72E8    BL   UPD_DecrypFlasher_FFBC4A5C
    ...
    ...
    FFBC4AA0    BL   "Check_FIR_and_read_and_decrypt_Flasher"
    R0 contains the a pointer to the start of the FIR code.
    here the size of the flasher code is loaded in R4 and on FFBC4DEC a call is made to "Goto_flasher_code_and_decrypt"

    _40D_ROM:FFBC4D9C Check_FIR_and_read_and_decrypt_Flasher  ; CODE XREF: UPD_DecrypFlasher_FFBC4A5C+44
    _40D_ROM:FFBC4D9C                 STMFD   SP!, {R4,LR}       ; Store Block to Memory
    _40D_ROM:FFBC4DA0                 MOV     R1, R0             ; R1 := R0 = Start of FIR file
    _40D_ROM:FFBC4DA4                 ADD     R2, R1, #0x24      ; R2 := Start FIR +0x24 ([Start+0x24] =0x000000B0)
    _40D_ROM:FFBC4DA8                 LDMIA   R2, {R2,R3}        ; Load multiple and increase after ==> R2:=0xB0; R3:=0x120
    _40D_ROM:FFBC4DAC                 CMP     R3, #0x120         ; Set cond. codes on Op1 - Op2
    _40D_ROM:FFBC4DB0                 MOV     R0, #0             ; R0;=0
    _40D_ROM:FFBC4DB4                 ADD     R4, R1, R2         ; R4:= start of FIR +0xB0 = [0x0019DB60] = addr of size of flasher code excluding header
    _40D_ROM:FFBC4DB8                 LDMCCFD SP!, {R4,PC}       ; return
    _40D_ROM:FFBC4DBC                 LDR     R3, [R1,#0x2C]     ; R3 := [Start of FIR + 0x2C] = 0xFFFFFFFF
    _40D_ROM:FFBC4DC0                 CMN     R3, #1             ; result := R3+1=0, only change flags, do not store
    _40D_ROM:FFBC4DC4                 ADD     R0, R1, R3         ; R0 := R1+R3 = start of FIR -1
    _40D_ROM:FFBC4DC8                 BEQ     loc_FFBC4DE8       ; jump if R3=-1
    _40D_ROM:FFBC4DCC                 LDR     R3, [R0,#0x24]     ; R3 := [Start FIR - 1 +0x24] = 0x120
    _40D_ROM:FFBC4DD0                 ADD     R0, R0, R3         ; R0 := Star FIR -1 + 120 = last byte of header
    _40D_ROM:FFBC4DD4                 BEQ     loc_FFBC4DE8       ; R0 := R4 =start of FIR +0xB0 = addr of Size of flasher code
    _40D_ROM:FFBC4DD8                 BL      Goto_flasher_code_and_decrypt       ; this is where XOR takes place
    _40D_ROM:FFBC4DDC                 CMN     R0, #1             ; Set cond. codes on Op1 + Op2
    _40D_ROM:FFBC4DE0                 MOVL    R0, 0xFFFFFFFF
    _40D_ROM:FFBC4DE4                 LDMEQFD SP!, {R4,PC}       ; Load Block from Memory
    _40D_ROM:FFBC4DE8
    _40D_ROM:FFBC4DE8 loc_FFBC4DE8                               ; CODE XREF: Check_FIR_and_read_and_decrypt_Flasher+2C
    _40D_ROM:FFBC4DE8                                            ; Check_FIR_and_read_and_decrypt_Flasher+38
    _40D_ROM:FFBC4DE8                 MOV     R0, R4             ; R0 := R4 =start of FIR +0xB0 = addr of Size of flasher code
    _40D_ROM:FFBC4DEC                 BL      Goto_flasher_code_and_decrypt       ; this is where XOR takes place


    Goto_flasher_code_and_decrypt
    In this sub the data "0x806ECB00" is loaded form the header of the FIR. This value is used in the next sub to calculate an offset that is used as starting point in the KEY data in the FIR.

    _40D_ROM:FFBC4E00 Goto_flasher_code_and_decrypt              ; CODE XREF: Check_FIR_and_read_and_decrypt_Flasher+3C
    _40D_ROM:FFBC4E00                                            ; Check_FIR_and_read_and_decrypt_Flasher+50
    _40D_ROM:FFBC4E00                 STMFD   SP!, {R4,R5,LR}    ; Store Block to Memory
    _40D_ROM:FFBC4E04                 MOV     R4, R0             ; R0 := R4 =start of FIR +0xB0 = addr of Size of flasher code
    _40D_ROM:FFBC4E08                 LDR     R3, [R4,#0xC]      ; R3 := [Start of FIR + 0xB0 + 0xC] = 0x806ECB00
    _40D_ROM:FFBC4E0C                 MOV     R5, #0             ; Rd = Op2
    _40D_ROM:FFBC4E10                 CMP     R3, R5             ; check if R3=0 ==> return
    _40D_ROM:FFBC4E14                 ADD     R0, R4, #0x70      ; R0 := Start of FIR + 0xB0 + 0x70 =[start + 0x120]
    _40D_ROM:FFBC4E18                 MOV     R2, R3             ; R2 := R3 = nr used to calc offset in XOR tables
    _40D_ROM:FFBC4E1C                 MOVEQ   R0, R3             ; Rd = Op2
    _40D_ROM:FFBC4E20                 LDMEQFD SP!, {R4,R5,PC}    ; return of R3=0
    _40D_ROM:FFBC4E24                 LDR     R1, [R4]           ; R1 = [R4] =  Size of flasher
    _40D_ROM:FFBC4E28                 BL      CipherBuffer_ROM_and_get_Key       ; R0 = start of flasher code


    And here the decryption takes place.
    On FFBC54C8 a second value is loaded in R12 that is combined with the value 0x806ECB00 to calculate the offset that is used as starting point in the KEY data in the FIR.
    This resulyt is an offset for Key1 of 100
    This resulyt is an offset for Key2 of 0x1A7
    The Keys themselves are loaded into the RAM data during start-up.
    An aditional XOR with the value 0x37 conclude the decryption on FFBC5540

    _40D_ROM:FFBC54C8 CipherBuffer_ROM_and_get_Key                  ; CODE XREF: Goto_flasher_code_and_decrypt+28
    _40D_ROM:FFBC54C8                 LDR     R12, =dword_FF803FE1    ; Load from Memory
    _40D_ROM:FFBC54CC                 STMFD   SP!, {R4-R8,LR}       ; Store Block to Memory
    _40D_ROM:FFBC54D0                 UMULL   LR, R3, R12, R2       ; RdHi,RdLo:=Rm*Rs ==> R3_hi,LR_lo := FF803FE1 * R2
    _40D_ROM:FFBC54D0                                               ; 802E.B3A6 : A555.6B00 <== FF80.3FE1 * 806E.CB00
    _40D_ROM:FFBC54D4                 LDR     R6, =End_of_Cipher_key1 ; = 80C3
    _40D_ROM:FFBC54D8                 MOV     R3, R3,LSR#9          ; div by 0x200 = clear lower 9 bits
    _40D_ROM:FFBC54DC                 LDR     R5, =End_of_Cipher_key2   ; = 82C4
    _40D_ROM:FFBC54E0                 ADD     R3, R3, R3,LSL#9       ; R3:=R3+(R3*0x200) ==> R3:=R3*0x201 ==> cleared lower bits
    _40D_ROM:FFBC54E4                 MOV     R12, R2,LSL#23       ; R12 := lower 9 bits of R2 (0x806ECB00) (shifted)
    _40D_ROM:FFBC54E8                 SUB     R7, R6, #0x1FC        ; calculate near start of cipher key1 (-508)
    _40D_ROM:FFBC54EC                 RSB     R2, R3, R2            ; =0x1A7 = R2 := R2 - R3
    _40D_ROM:FFBC54F0                 MOV     R12, R12,LSR#23       ; =0x100 = Shift lower 9 bits (of 0x806ECB00) back to original location
    _40D_ROM:FFBC54F4                 SUB     R7, R7, #3            ; 7EC4 start of cipher key1 (-508-503=-511) => 512 bytes
    _40D_ROM:FFBC54F8                 SUB     R3, R5, #0x200        ; 80C4 = start of cipher key2 (-512) => 513 bytes
    _40D_ROM:FFBC54FC                 SUBS    R4, R1, #0            ; R1 = R4:= flasher size
    _40D_ROM:FFBC5500                 ADD     R12, R12, R7          ; R12=R12+R7 = starting location in the middle of Key1
    _40D_ROM:FFBC5504                 ADD     LR, R2, R3            ; LR=R2+R3 = starting location in the middle of Key2
    _40D_ROM:FFBC5508                 LDMLEFD SP!, {R4-R8,PC}       ; Return when file size = 0
    _40D_ROM:FFBC550C                 MOV     R8, R7                ; R8 = Start of Key1
    _40D_ROM:FFBC5510                 MOV     R7, R3                ; R7 = Start of Key2
    _40D_ROM:FFBC5514
    _40D_ROM:FFBC5514 Cipher_Loop_ROM                              ; CODE XREF: CipherBuffer_ROM_and_get_Key+88
    _40D_ROM:FFBC5514                 LDRB    R3, [LR]              ; load next byte of key1
    _40D_ROM:FFBC5518                 LDRB    R2, [R12]             ; load next byte of key2
    _40D_ROM:FFBC551C                 LDRB    R1, [R0]             ; load next byte of Flasher code
    _40D_ROM:FFBC5520                 ADD     R12, R12, #1          ; Rd = Op1 + Op2
    _40D_ROM:FFBC5524                 ADD     LR, LR, #1            ; Rd = Op1 + Op2
    _40D_ROM:FFBC5528                 CMP     R12, R6               ; Set cond. codes on Op1 - Op2
    _40D_ROM:FFBC552C                 EOR     R3, R3, R2            ; key1 := Key1 XOR Key2
    _40D_ROM:FFBC5530                 EOR     R1, R1, R3            ; R1:= R1 xor (key1 XOR key2)
    _40D_ROM:FFBC5534                 SUB     R4, R4, #1            ; decrease bytes still to go
    _40D_ROM:FFBC5538                 MOVHI   R12, R8               ; if R12 > R6 (R6=End of Key) then R12:=R8 =start of key2
    _40D_ROM:FFBC553C                 CMP     LR, R5                ; Set cond. codes on Op1 - Op2
    _40D_ROM:FFBC5540                 EOR     R1, R1, #0x37         ; Rd = Op1 ^ Op2
    _40D_ROM:FFBC5544                 MOVHI   LR, R7                ; if LR > R5 (R5 = end of key) then LR:=R7 =start of key1
    _40D_ROM:FFBC5548                 CMP     R4, #0                ; compare bytes of file still to go >0
    _40D_ROM:FFBC554C                 STRB    R1, [R0],#1           ; store decrypted byte and goto next byte
    _40D_ROM:FFBC5550                 BGT     Cipher_Loop_ROM       ; load next byte of key1
    _40D_ROM:FFBC5554                 LDMFD   SP!, {R4-R8,PC}       ; Load Block from Memory
    _40D_ROM:FFBC5554 ; End of function CipherBuffer_ROM_and_get_Key

    =========================
    « Last Edit: 14 / January / 2009, 11:41:23 by emklap »

    *

    Offline mx3

    • ****
    • 372
  • Publish
    Re: This is how 40D (and 400D) code decrypth the flasher code 1(2)
    « Reply #2 on: 21 / November / 2008, 10:46:55 »
    Sadly the sub on location FFBC54C8 only decrypts the flasher code and not the FW paiload at the end. I am still figuring out where this is decrypted but I have not been able to find it. Does anyone have a clue?

    flasher decrypts payload :-)
    skype: max_dtc. ICQ: 125985663, email: win.drivers(at)gmail, eVB decompiler

    *

    Offline ditch

    • *
    • 22
  • Publish
    Re: This is how 40D (and 400D) code decrypth the flasher code 1(2)
    « Reply #3 on: 26 / November / 2008, 16:51:10 »
    being no developer, all i see is rocket science gibberish... BUT i am genuinely interested in anything that relates to firmware development. at this point, heck, i'd be glad to try out the beta firmware dataghost developed and used to shoot that video on his 40d.


  • Publish
    Re: This is how 40D (and 400D) code decrypth the flasher code 1(2)
    « Reply #4 on: 27 / November / 2008, 10:17:26 »
    Quote
    flasher decrypts payload :-)

    yes I know that  ;) but how can we do it ourselves? I have found 4 smaller keys and also the XOR statements where these are used but it takes a lot of time to try to figure out how these are used exactly and how to decrypt the payload ourselves

    See data head 2 and the 4 smaller keys at 0x19DC9C and later in the attached file.

    If we can figure out where these keys are located and how they are used automatic decryption of any 40D firmware must become possible.

    Unfortunalely I have very little time to work on this problem :(

  • Publish
    Excel macro for decrypting 40D FW (105, 108, 110, and 111)
    « Reply #5 on: 14 / January / 2009, 11:58:12 »
    Hi, because there are now several FW version out there (1.0.5, 1.0.8, 1.1.0 and 1.1.1) I made an excel macro to decrypt ALL these FW versions :D

    The offset of the keys for new FW version can be calculated as in the first post in this thread but most of them are already included in the macro.
    Attached is the file with the keys that is used by this Macro which is copied from the 40D FW itself. ::)
    Code: [Select]
    Sub Decrypt()
    Rootpath = "C:\40D Hack\Decrypt\"
    Dim HexArray1(512) As String
    Dim HexArray2(513) As String

    Dim DecArray1(512) As Byte
    Dim DecArray2(513) As Byte

    Open Rootpath + "Generic_40D_table.txt" For Input As #1


    For teller = 1 To 512
      Input #1, HexArray1(teller)
      DecArray1(teller) = CByte(HexArray1(teller))
    Next
    Line Input #1, Inline    ' Read empty line of data.
    For teller = 1 To 513
      Input #1, HexArray2(teller)
       DecArray2(teller) = CByte(HexArray2(teller))
    Next
    Close #1

    Dim MyChar As Byte
    Dim OutChar As Byte
    Dim XorVal As Byte

    Open Rootpath + "40d00111.fir" For Binary Access Read As #1     ' Open file for input.
    Open Rootpath + "40d00111.bin.txt" For Binary Access Write As #2    ' Open file for output.

    'FW 1.0.5
    ' Key1 offset = 0x92
    ' Key2 offset = 0x1B0
    '
    'FW 1.0.8
    ' Key1 offset = 0x100
    ' Key2 offset = 0x1A7
    '
    'FW 1.1.0
    ' Key1 offset = 0xAC
    ' Key2 offset = 0x1E8
    '
    'FW 1.1.1
    ' Key1 offset = 0x27
    ' Key2 offset = 0x191
    '
    Offset_Key1 = &H27
    Offset_Key2 = &H191

    ArrayTeller1 = 1 + Offset_Key1
    ArrayTeller2 = 1 + Offset_Key2


    current = 0
    Do While current < LOF(1)

      Get #1, , MyChar  ' Read 1 byte of data from input file
      If current >= &H120 Then
        XorVal = DecArray1(ArrayTeller1) Xor DecArray2(ArrayTeller2) Xor 55
        OutChar = MyChar Xor XorVal
        ArrayTeller1 = ArrayTeller1 + 1
        If ArrayTeller1 > 512 Then ArrayTeller1 = 1
        ArrayTeller2 = ArrayTeller2 + 1
        If ArrayTeller2 > 513 Then ArrayTeller2 = 1
      Else
        OutChar = MyChar
      End If
        Put #2, , OutChar  ' Write 1 byte to output file
    current = Loc(1)
    Loop

    Close #2    ' Close file.
    Close #1    ' Close file.
    Result = MsgBox("Ready", vbOKOnly, "Finished")
    End Sub

    Have fun with it.

    *

    Offline quietschi

    • ***
    • 116
    • Ixus70 102a
  • Publish
    Re: This is how 40D (and 400D) code decrypth the flasher code 1(2)
    « Reply #6 on: 14 / January / 2009, 13:26:06 »
    Hi emklap
    tried this exel macro and it works
    for you information theres a exe see
    http://chdk.setepontos.com/index.php/topic,111.msg27417.html#msg27417
    who can also decrypt every 40d 50d and 5d2 fir
    http://chdk.setepontos.com/index.php?action=dlattach;topic=111.0;attach=2700 dissect_fw3_2.rar

    Have you noticed that there are 256 similar bytes in every flasher see
    http://chdk.setepontos.com/index.php/topic,111.msg27642.html#msg27642
    maybe for decrypt payload?

    cheers quietschi


  • Publish
    Re: This is how 40D (and 400D) code decrypth the flasher code 1(2)
    « Reply #7 on: 14 / January / 2009, 14:49:01 »
    Hi quietschi,

    I had not seen the exe file, I have an older version of the tool dissect_fw.exe. Thanks for pointing me to the exe file.
    This exe file automtically calculates the off-set value's for the decryptipon tales which I still have to do by hand (a 1 minute job).

    I have read your other links and I could locate all the tables found for the 50D also in the 40D code.  :D

    Thanks,
    EMKLAP


  • Publish
    Re: This is how 40D (and 400D) code decrypth the flasher code 1(2)
    « Reply #8 on: 09 / February / 2009, 12:53:29 »
    Quote
    flasher decrypts payload :-)

    yes I know that  ;) but how can we do it ourselves? I have found 4 smaller keys and also the XOR statements where these are used but it takes a lot of time to try to figure out how these are used exactly and how to decrypt the payload ourselves

    See data head 2 and the 4 smaller keys at 0x19DC9C and later in the attached file.

    If we can figure out where these keys are located and how they are used automatic decryption of any 40D firmware must become possible.

    Unfortunalely I have very little time to work on this problem :(
    Excellent work, emklap - the 40D_1D.html file lays it out quite nicely.

    Since I do not have immediate access to IDA 5.2, I'll probably continue playing with brute force cracking mechanisms on the payload section, which implies that I'll need to know something about the contents.  A couple thoughts and questions for moving forward with this.

    - From what you know of the flasher decryption, does the flasher decryption only operate over the flasher code (and not the payload content)...  or maybe the payload is double encrypted?

    - Do you think the payload contains any text strings?  Also, why does the flasher code contain a ton of text strings that the camera would use (not specific to the flasher application)?  Could it be that all the text sections are delivered via the flasher code so-as to make decrypting the payload (firmware) more difficult?

    - Might the payload section have a similar header, or similar starting code as the flasher code?  Or is it possible the payload code is of a completely different architecture than the flasher code?  Perhaps a separate processor performs the flash operation?

    - I noticed some other threads mentioning that the Canon video recorder firmware implements encryption keys in interesting ways (forwards, backwards, cyclically, etc.)  Perhaps that's a clue as to how the small keys are used.

  • Publish
    Re: This is how 40D (and 400D) code decrypth the flasher code 1(2)
    « Reply #9 on: 09 / February / 2009, 13:52:50 »
    « Last Edit: 09 / February / 2009, 14:08:57 by emklap »

     

    Related Topics