This is how 40D (and 400D) code decrypth the flasher code 1(2) - DSLR Hack development - CHDK Forum

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

  • 11 Replies
  • 17427 Views
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 »

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
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
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.


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 :(

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
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


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


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.

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


SimplePortal 2.3.6 © 2008-2014, SimplePortal