Skip to content

Instantly share code, notes, and snippets.

@en4rab
Last active December 14, 2024 23:04
Show Gist options
  • Save en4rab/550880c099b5194fbbf3039e3c8ab6fd to your computer and use it in GitHub Desktop.
Save en4rab/550880c099b5194fbbf3039e3c8ab6fd to your computer and use it in GitHub Desktop.
Recovering the BIOS password from a Panasonic CF-U1 mk2 (AMI Aptio UEFI)

Recovering the BIOS password from a Panasonic CF-U1 mk2 (AMI Aptio UEFI)

A mess of my own making

While messing with a CF-U1 handheld PC that I bought off ebay I managed to mess up the BIOS and it seems it reverted to previous settings which included an unknown BIOS password, it would however still boot into windows. Since I could still boot windows I was able to dump the bios flash using AFUWINGUI.EXE the version I used was 3.09.03.1462 which is available here:
https://www.ami.com/support-other/ Click on Aptio 4 AMI Firmware Update Utility

There may be a more appropriate version to use as this seemed to have trouble checking the bios version when flashing but did work if you selected "Do Not Check ROM ID" but flashing isnt needed to get the password.

Dumping the flash

alt text
Run AFUWINGUI.EXE and at the bottom of the "Information" tab click the save button to make a backup of your bios, the default name is afuwin.rom Now open this saved image with UEFITool_NE available here:
https://github.com/LongSoft/UEFITool/releases

I used UEFITool_NE_A51_win32.zip later versions should work fine. The new engine (NE) verson seems to deal with AMI's odd nvram format better.

alt text

Expand the first EfiFirmwareFilesystemGuid >> NVRAM dropdown tree and look for the GUID
C811FA38-42C8-4579-A9BB-60E94EDDFB34 (AMITSESetup)
with subtype Data there will be others with subtype Link which are older no longer valid entrys because of the odd way AMI nvram works, if you find one of these right click on it and select "Go to data" and it will take you to the actual data entry.
Now right click and select "Body hex view" and you should see something like:

0000  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0040  7B 13 94 A6 07 3A 29 CD D2 60 1A F4 5C 87 ED 1A  {.”¦.:)ÍÒ`.ô\‡í.
0050  07 AE AE 41 DC D4 0A 68 AB FB FA 0E 55 A2 B0 35  .®®AÜÔ.h«ûú.U¢°5
0060  0B C9 66 5C C1 EF 1C 83 77 16 D2 A9 2D 3D 88 D0  .Éf\Áï.ƒw.Ò©-=ˆÐ
0070  E3 63 3E F7 99 8A F4 1D 4F B1 AA 44 05 D8 60 6B  ãc>÷™Šô.O±ªD.Ø`k
0080  01

In this the bytes from 0x00 to 0x3F are the currently unset user password, 0x40 to 0x7F are the obfuscated administrator password and 0x80 is the quiet boot flag.

1337 encryption

The password is obfuscated using super secure xor

VOID PasswordEncode( CHAR16 *Password, UINTN MaxSize)
{
    UINTN	ii;
    unsigned int key = 0x935b;

#if SETUP_PASSWORD_NON_CASE_SENSITIVE
    for ( ii = 0; ii < MaxSize; ii++ )
        Password[ii] = ((Password[ii]>=L'a')&&(Password[ii]<=L'z'))?(Password[ii]+L'A'-L'a'):Password[ii];
#endif

    // Encode the password..
    for ( ii = 1; ii <= MaxSize/2; ii++ )
        Password[ii-1] = (CHAR16)(Password[ii-1] ^ (key*ii));
}

So Xoring the above encoded password:

7B 13 94 A6 07 3A 29 CD D2 60 1A F4 5C 87 ED 1A 07 AE AE 41 DC D4 0A 68 AB FB FA 0E 55 A2 B0 35 
0B C9 66 5C C1 EF 1C 83 77 16 D2 A9 2D 3D 88 D0 E3 63 3E F7 99 8A F4 1D 4F B1 AA 44 05 D8 60 6B

with

5B 93 B6 26 11 BA 6C 4D C7 E0 22 74 7D 07 D8 9A 33 2E 8E C1 E9 54 44 E8 9F 7B FA 0E 55 A2 B0 35 
0B C9 66 5C C1 EF 1C 83 77 16 D2 A9 2D 3D 88 D0 E3 63 3E F7 99 8A F4 1D 4F B1 AA 44 05 D8 60 6B

gives

20 80 22 80 16 80 45 80 15 80 38 80 21 80 35 80 34 80 20 80 35 80 4e 80 34 80 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Each character of the password is stored as 2 bytes, and as x86 is wrong endian im guessing should be read as 0x8020 0x8022 I have no idea where the 0x80 comes from possibly its something to do with the EFI_SHIFT_STATE_VALID in this case the password was lower case, possibly uppercase status is encoded in this byte too I have no idea I havent tested uppercase passwords.

WTF scancodes how does this map to keys

From the unobfuscated data you can see the password is 13 characters long, im going to ignore the 0x80 bytes as i dont understand them :P and just look at the others:
20 22 16 45 15 38 21 35 34 20 35 4e 34
They appear to be some sort of scancodes, although while googleing this I found some AMI bioses seem to use ascii here so you can read it out directly as text, but not on this machine.
When this CF-U1 arrived from ebay it had a password which i sucessfully guessed as "toughbook" my second guess would have been "panasonic" since using text written on the front of the PC as a password saves writing it under the battery cover :P
Looking through the older link entrys for the AMITSESetup nvram I found what I thought was the data for this password which deobfuscating as above gave (ignoring the 0x80):

35 39 37 24 25 14 39 39 27
t  o  u  g  h  b  o  o  k

This seemed promising repeated characters have the same value and gives a bit of a key to the mapping Some googeling later about UEFI scancodes and i found this page:
http://wiki.phoenix.com/wiki/index.php/EFI_KEY
From this it seems the value is the offset into this enum so in the toughbook example 35 translates to EfiKeyD5 a second page I found gave the mapping from EfiKey to ascii:
https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Bus/Usb/UsbKbDxe/KeyBoard.c#L36

So i made up a list of byte to ascii using these, below are just 0x10 to 0x4E to cover most values but not be too stupidly long.

Hex Char EFIkey Hex Char EFIkey
10 z EfiKeyB1 30 Tab EfiKeyTab
11 x EfiKeyB2 31 q EfiKeyD1
12 c EfiKeyB3 32 w EfiKeyD2
13 v EfiKeyB4 33 e EfiKeyD3
14 b EfiKeyB5 34 r EfiKeyD4
15 n EfiKeyB6 35 t EfiKeyD5
16 m EfiKeyB7 36 y EfiKeyD6
17 , EfiKeyB8 37 u EfiKeyD7
18 . EfiKeyB9 38 i EfiKeyD8
19 / EfiKeyB10 39 o EfiKeyD9
1A EfiKeyRShift 3A p EfiKeyD10
1B EfiKeyUpArrow 3B [ EfiKeyD11
1C 1 EfiKeyOne 3C ] EfiKeyD12
1D 2 EfiKeyTwo 3D \ EfiKeyD13
1E 3 EfiKeyThree 3E EfiKeyDel
1F EfiKeyCapsLock 3F EfiKeyEnd
20 a EfiKeyC1 40 EfiKeyPgDn
21 s EfiKeyC2 41 7 EfiKeySeven
22 d EfiKeyC3 42 8 EfiKeyEight
23 f EfiKeyC4 43 9 EfiKeyNine
24 g EfiKeyC5 44 ` EfiKeyE0
25 h EfiKeyC6 45 1 EfiKeyE1
26 j EfiKeyC7 46 2 EfiKeyE2
27 k EfiKeyC8 47 3 EfiKeyE3
28 l EfiKeyC9 48 4 EfiKeyE4
29 ; EfiKeyC10 49 5 EfiKeyE5
2A ' EfiKeyC11 4A 6 EfiKeyE6
2B | EfiKeyC12 4B 7 EfiKeyE7
2C 4 EfiKeyFour 4C 8 EfiKeyE8
2D 5 EfiKeyFive 4D 9 EfiKeyE9
2E 6 EfiKeySix 4E 0 EfiKeyE10
2F + EfiKeyPlus

So what was the password?

Using the above list and the recovered scancodes gave:

20 22 16 45 15 38 21 35 34 20 35 4e 34
a  d  m  1  n  i  s  t  r  a  t  0  r

and when i tried adm1nistrat0r it worked!
This is not complete as there are still questions about the 0x80 bytes but my guess is they encode the shift alt etc modifier keys but im back into my handheld so i'm not sure ill look further into it. This may also apply to other Aptio bioses as well as the Panasonic CF-U1, and if the machine isnt bootable you may be able to use a cheap spi adapter to dump the bios, in the case of the CF-U1 it uses an LPC flash which I don't think you can get cheap clips and readers for and its buried in the machine so a nuisance to get to.

@kevingrout
Copy link

Yes noticed that so im presuming the user password '1111' is 20 bytes 26F7EF0F129A96B45A2BC3921B60A5F371C7B9B7

@userx14
Copy link

userx14 commented Jul 13, 2022

Yes noticed that so im presuming the user password '1111' is 20 bytes 26F7EF0F129A96B45A2BC3921B60A5F371C7B9B7

Yeah, but if they have done their job well it is salted with something before putting it into the hash function.

You cound check if one of them changes if you are able to alter the user password.

@kevingrout
Copy link

kevingrout commented Jul 13, 2022

Brain now hurts :) more dump info
Note 4 x 1 different from before as was looking at wrong C811FA38-42C8-4579-A9BB-60E94EDDFB34
user =20 x 0's

8B36AB9EB46EE70ADF40E18A9E037E46
6FE4C665000000000000000000000000
000000000000000080691481CCAD07F6
89E882E202FD951DC2576E5200000000
00000000000000000000000000000000
00

user =4 x 1's
8B84FE6B155A7C2CEA39C6E9A02539BC
1A9F30DE000000000000000000000000
000000000000000080691481CCAD07F6
89E882E202FD951DC2576E5200000000
00000000000000000000000000000000
00

@kevingrout
Copy link

Update, cleared user password and first 20 bytes changed to 00 so read/edited and reflashed now have admin access and no passwords set. would have been nice to work out what password was.
Many thanks for your help userx14

@cbbeerman
Copy link

I'm working on a Toughbook CF-31 and was able to find the password in the .rom as described.
From the file it appears to only have a supervisor password
I also don't understand where XOR value comes from
I'd appreciate any help
Thank you

0000 00000000000000000000000000000000
0010 00000000000000000000000000000000
0020 00000000000000000000000000000000
0030 00000000000000000000000000000000
0040 5B42B64D110C6CF3C782227A7D66D89A
0050 33DB8E92E9E844B19F18FA45552AB0E1
0060 0B626693C1F81C3B7736D2742D1A8887
0070 E3F73EF99901F4C34FF7AA1605A46028
0080 01

5B42B64D110C6CF3C782227A7D66D89A33DB8E92E9E844B19F18FA45552AB0E10B626693C1F81C3B7736D2742D1A8887E3F73EF99901F4C34FF7AA1605A46028

@userx14
Copy link

userx14 commented Jul 14, 2022

When calculating the xor of the bytes of your dump with the key from en4rab I get:
d1006b00b600be0062000e0061000000f5005300bc00590063004b008800d400ab00cf001700b8002000dd002700570094000e008b00de00460052007c0043
padding removed:
d16bb6be620e6100f553bc59634b88d4abcf17b820dd2757940e8bde46527c43
First time I've seen a hashed result that is 32bytes long, if you ignore the zero padding. Maybe hashed with sha256?
Best
Benjamin

@cbbeerman
Copy link

Maybe or could it be that the unsigned int key = 0x935b is wrong for this Toughbook model. Guess I'll have to figure out how the key changes the XOR value

@userx14
Copy link

userx14 commented Jul 14, 2022

Well I think you found the right sequence.
At least the sequence was definitifeley xored with the en4rab key, since otherwise you would not get those 0x00 as padding.

@cbbeerman
Copy link

Very good point. Maybe it has something to do with possible uppercase characters in the password.
I'll play with some of my ideas and will post the results if I discover anything.
Thank you userx14 for all of your help and thank you en4rab for posting this.

@corty8
Copy link

corty8 commented Jul 26, 2022

Hi All
I was just wondering if anyone has looked into the location where the Accumulative Hours are stored on the Toughbooks?
I can find references to it but not much than that
Cheers

@Wasmachineman-NL
Copy link

Hi All I was just wondering if anyone has looked into the location where the Accumulative Hours are stored on the Toughbooks? I can find references to it but not much than that Cheers

why, so you can fuck over the used market by selling CF-19's with 15k+ hours as 500h? No thanks.

@maxtheobald
Copy link

Hello,
I have a FZ-G1 MK4 in front of me which has a bios password. I followed the instructions and the video on Youtube, but made a dump via CH341a and neoprogrammer. However, I can't find a password in AMITSESetup.

HEX:
0000 4E5641521901FFFFFF8327414D495453
0010 455365747570000000000000000000000
0020 00000000000000000000000000000000
0030 00000000000000000000000000000000
0040 00000000000000000000000000000000
0050 00000000000000000000000000000000
0060 00000000000000000000000000000000
0070 00000000000000000000000000000000
0080 00000000000000000000000000000000
0090 00000000000000010000000000000000
00A0 00000000000000000000000000000000
00B0 00000000000000000000000000000000
00C0 00000000000000000000000000000000
00D0 00000000000000000000000000000000
00E0 00000000000000000000000000000000
00F0 00000000000000000000000000000000
0100 00000000000000000000000000000000
0110 000000000000000000

HEX Body:
0010 00000000000000000000000000000000
0020 00000000000000000000000000000000
0030 00000000000000000000000000000000
0040 00000000000000000000000000000000
0050 00000000000000000000000000000000
0060 00000000000000000000000000000000
0070 00000000000000000000000000000000
0080 01000000000000000000000000000000
0090 00000000000000000000000000000000
00A0 00000000000000000000000000000000
00B0 00000000000000000000000000000000
00C0 00000000000000000000000000000000
00D0 00000000000000000000000000000000
00E0 00000000000000000000000000000000
00F0 00000000000000000000000000000000
0100 0000

I hope for a bad or wrong dump and next time I will unsolder the IC and re-read it.

@userx14
Copy link

userx14 commented Sep 6, 2022

I hope for a bad or wrong dump and next time I will unsolder the IC and re-read it.

Hi max,

i would guess that a bad dump is unlikely, since you were able to find AMITSESetup.

Maybe the following issues apply:

  • UEFI tool sometimes does not show the content of the variables, if you are using the current version. Use the older "a51" release and see if the content changes.
  • If this does not help you can try search for the last few hex characters of the key "B1 AA 44 05 D8 60 6B" by opening the bios with a raw hex editor. For short passwords or the 20 bytes hash these should stay the same. But there are potentially multiple matches.
  • Panasonic might have changed the way that the password is stored.

Best,
Benjamin

@corty8
Copy link

corty8 commented Sep 7, 2022

Hello, I have a FZ-G1 MK4 in front of me which has a bios password. I followed the instructions and the video on Youtube, but made a dump via CH341a and neoprogrammer. However, I can't find a password in AMITSESetup.

HEX: 0000 4E5641521901FFFFFF8327414D495453 0010 455365747570000000000000000000000 0020 00000000000000000000000000000000 0030 00000000000000000000000000000000 0040 00000000000000000000000000000000 0050 00000000000000000000000000000000 0060 00000000000000000000000000000000 0070 00000000000000000000000000000000 0080 00000000000000000000000000000000 0090 00000000000000010000000000000000 00A0 00000000000000000000000000000000 00B0 00000000000000000000000000000000 00C0 00000000000000000000000000000000 00D0 00000000000000000000000000000000 00E0 00000000000000000000000000000000 00F0 00000000000000000000000000000000 0100 00000000000000000000000000000000 0110 000000000000000000

HEX Body: 0010 00000000000000000000000000000000 0020 00000000000000000000000000000000 0030 00000000000000000000000000000000 0040 00000000000000000000000000000000 0050 00000000000000000000000000000000 0060 00000000000000000000000000000000 0070 00000000000000000000000000000000 0080 01000000000000000000000000000000 0090 00000000000000000000000000000000 00A0 00000000000000000000000000000000 00B0 00000000000000000000000000000000 00C0 00000000000000000000000000000000 00D0 00000000000000000000000000000000 00E0 00000000000000000000000000000000 00F0 00000000000000000000000000000000 0100 0000

I hope for a bad or wrong dump and next time I will unsolder the IC and re-read it.

I have never had any success trying to do these on the board and for what it is worth they are by far one of the easiest chips to remove and re-install once you have reprogrammed them

@mikrovr
Copy link

mikrovr commented Sep 7, 2022

@corty8
It will not be possible to find the corresponding password for your model. Just clear the NVRAM.

@corty8
Copy link

corty8 commented Sep 7, 2022

@corty8 It will not be possible to find the corresponding password for your model. Just clear the NVRAM.

oh yes that is what I have do, I have done dozens of the FZ-G1 units, but someone above mentions that they have tried to do it while the BIOS chips is still soldered to the board and said I have not had any success in trying to do it that way, I always remove the chip to clear it

@maxtheobald
Copy link

Hello, I have a FZ-G1 MK4 in front of me which has a bios password. I followed the instructions and the video on Youtube, but made a dump via CH341a and neoprogrammer. However, I can't find a password in AMITSESetup.
HEX: 0000 4E5641521901FFFFFF8327414D495453 0010 455365747570000000000000000000000 0020 00000000000000000000000000000000 0030 00000000000000000000000000000000 0040 00000000000000000000000000000000 0050 00000000000000000000000000000000 0060 00000000000000000000000000000000 0070 00000000000000000000000000000000 0080 00000000000000000000000000000000 0090 00000000000000010000000000000000 00A0 00000000000000000000000000000000 00B0 00000000000000000000000000000000 00C0 00000000000000000000000000000000 00D0 00000000000000000000000000000000 00E0 00000000000000000000000000000000 00F0 00000000000000000000000000000000 0100 00000000000000000000000000000000 0110 000000000000000000
HEX Body: 0010 00000000000000000000000000000000 0020 00000000000000000000000000000000 0030 00000000000000000000000000000000 0040 00000000000000000000000000000000 0050 00000000000000000000000000000000 0060 00000000000000000000000000000000 0070 00000000000000000000000000000000 0080 01000000000000000000000000000000 0090 00000000000000000000000000000000 00A0 00000000000000000000000000000000 00B0 00000000000000000000000000000000 00C0 00000000000000000000000000000000 00D0 00000000000000000000000000000000 00E0 00000000000000000000000000000000 00F0 00000000000000000000000000000000 0100 0000
I hope for a bad or wrong dump and next time I will unsolder the IC and re-read it.

I have never had any success trying to do these on the board and for what it is worth they are by far one of the easiest chips to remove and re-install once you have reprogrammed them

Okay, no problem, I'll desolder the chip and read it in again.

@corty8 It will not be possible to find the corresponding password for your model. Just clear the NVRAM.

Okay and now clearing the NVRAM means what exactly? What do I have to watch out for?

I hope for a bad or wrong dump and next time I will unsolder the IC and re-read it.

Hi max,

i would guess that a bad dump is unlikely, since you were able to find AMITSESetup.

Maybe the following issues apply:

  • UEFI tool sometimes does not show the content of the variables, if you are using the current version. Use the older "a51" release and see if the content changes.
  • If this does not help you can try search for the last few hex characters of the key "B1 AA 44 05 D8 60 6B" by opening the bios with a raw hex editor. For short passwords or the 20 bytes hash these should stay the same. But there are potentially multiple matches.
  • Panasonic might have changed the way that the password is stored.

Best, Benjamin

I will search in Hex Editor for these Hex characters, maybe i will have success.

Thank you guys for your help.

best wishes

@corty8
Copy link

corty8 commented Sep 7, 2022

maxtheobald are you doing a search for the GUID or are you actually scrolling through and trying to find it?

@warst
Copy link

warst commented Sep 7, 2022

Hello, I have a FZ-G1 MK4 in front of me which has a bios password. I followed the instructions and the video on Youtube, but made a dump via CH341a and neoprogrammer. However, I can't find a password in AMITSESetup.
HEX: 0000 4E5641521901FFFFFF8327414D495453 0010 455365747570000000000000000000000 0020 00000000000000000000000000000000 0030 00000000000000000000000000000000 0040 00000000000000000000000000000000 0050 00000000000000000000000000000000 0060 00000000000000000000000000000000 0070 00000000000000000000000000000000 0080 00000000000000000000000000000000 0090 00000000000000010000000000000000 00A0 00000000000000000000000000000000 00B0 00000000000000000000000000000000 00C0 00000000000000000000000000000000 00D0 00000000000000000000000000000000 00E0 00000000000000000000000000000000 00F0 00000000000000000000000000000000 0100 00000000000000000000000000000000 0110 000000000000000000
HEX Body: 0010 00000000000000000000000000000000 0020 00000000000000000000000000000000 0030 00000000000000000000000000000000 0040 00000000000000000000000000000000 0050 00000000000000000000000000000000 0060 00000000000000000000000000000000 0070 00000000000000000000000000000000 0080 01000000000000000000000000000000 0090 00000000000000000000000000000000 00A0 00000000000000000000000000000000 00B0 00000000000000000000000000000000 00C0 00000000000000000000000000000000 00D0 00000000000000000000000000000000 00E0 00000000000000000000000000000000 00F0 00000000000000000000000000000000 0100 0000
I hope for a bad or wrong dump and next time I will unsolder the IC and re-read it.

I have never had any success trying to do these on the board and for what it is worth they are by far one of the easiest chips to remove and re-install once you have reprogrammed them

Okay, no problem, I'll desolder the chip and read it in again.

@corty8 It will not be possible to find the corresponding password for your model. Just clear the NVRAM.

Okay and now clearing the NVRAM means what exactly? What do I have to watch out for?

I hope for a bad or wrong dump and next time I will unsolder the IC and re-read it.

Hi max,
i would guess that a bad dump is unlikely, since you were able to find AMITSESetup.
Maybe the following issues apply:

  • UEFI tool sometimes does not show the content of the variables, if you are using the current version. Use the older "a51" release and see if the content changes.
  • If this does not help you can try search for the last few hex characters of the key "B1 AA 44 05 D8 60 6B" by opening the bios with a raw hex editor. For short passwords or the 20 bytes hash these should stay the same. But there are potentially multiple matches.
  • Panasonic might have changed the way that the password is stored.

Best, Benjamin

I will search in Hex Editor for these Hex characters, maybe i will have success.

Thank you guys for your help.

best wishes

For what it's worth, I've done at least 50 FZ-G1's of various generations (amongst many other Panasonic models) and have read the chip on the board every time. It's a game of trial and error. Remove the battery, attach the charger - try to read. If that fails, leave the battery connected, with the charger connected. Or try turning the device on, with battery and charger connected and then switch off, leave all connected and then try to read. Sometimes you have to enter the bios and then power off. It's usually a combination of these things AND, sometimes the same device will perform differently to another of the same model. I also have a fair amount of luck using a bench power supply for powering the eeprom, this way I'm not relying on the fluctuating power supply of a cheap programmer. TL866ii is also a good programmer, but I have a CH341a which I modified to not supply 5v to the chip (as these have a design flaw - google CH341a 3.3v mod).

If you get one successful dump, dump again and then compare the two files with HxD for any differences. If they are identical, you are good to go.

Good luck!

@satorisage
Copy link

Hi - Trying to understand fully what you've shared here.

The HEX I retrieve from the rom is:
5B 46 B6 48 11 E2 6C 70 C7 9D 22 B1 7D 43 D8 2E 33 B8 8E D7 E9 5C 44 DA 9F 8A FA FE 55 D8 B0 7F 0B E0 66 C8 C1 FF 1C A6 77 16 D2 A9 2D 3D 88 D0 E3 63 3E F7 99 8A F4 1D 4F B1 AA 44 05 D8 60 6B

In your example you said you "xor" that with the other 64 bytes (the second 32 being the same as the first set) - but where did that part come from? Is that applied across all cf-53 models or did you need to retrieve that out of the rom?

Also how can I "xor" the HEX values? Is is an operation I can write in Python?

Thanks in advance for your time and assistance - I love reverse engineering and learning

@userx14
Copy link

userx14 commented Sep 9, 2022

Hi satorisage,

but where did that part come from?

See the secton "1337 encryption" of en4rab's original post. The key can generated in 16 bytes increments because it is
0x935b * (currentIteration + 1),
when you only use the lower 16 bytes of the result. This seems to be the same across many different toughbook models.

Is is an operation I can write in Python?

Yes, see following code using your rom data.

show code for panasoHardcoded.py python3
import binascii

def hexPrettyPrint(bytesStr):
    print(binascii.hexlify(bytesStr, sep=" "))

def generatePanaXorSequence(numOfBytes):
    if(numOfBytes%2):
        raise ValueError("Only even number of bytes supported")
    key = int("0x935b", 16)
    numOfInt16 = numOfBytes//2
    generatedKey = bytes()
    for i in range(numOfInt16):
        keyForThisInt16 = key*(i+1) 
        keyForThisInt16 = keyForThisInt16 & int("0xffff", 16)   #only keep the lower 2 bytes
        keyForThisInt16 = keyForThisInt16.to_bytes(2, 'little') 
        generatedKey = generatedKey + keyForThisInt16
    return generatedKey
    
def xorByteStrings(bytesStr1, bytesStr2):
    if(len(bytesStr1) != len(bytesStr2)):
        raise ValueError("Xor needs same length of byteStrings")
    byteStringResult = bytes()
    for i in range(len(bytesStr1)):
        byteStringResult += bytes([bytesStr1[i] ^ bytesStr2[i]])
    return byteStringResult
    
def getSHA1ifExist(bytesStr):
    sha1 = bytes()
    for i in range(20):                 #sha1 is 20 bytes
        if(bytesStr[2*i] != 0):         #check if the upper bytes is always zero of each int16
            return None
        sha1 += bytes([bytesStr[2*i + 1]])
    for i in range(40, len(bytesStr)):
        if(bytesStr[i] != 0):           #all bytes after the first 40 bytes should be zero
            return None
    return sha1

def getASCIIifExist(bytesStr):
    asciiBytes = bytes()
    for i in range(len(bytesStr)//2):
        if(bytesStr[2*i+1] != 0):        #check if the lower bytes is always zero of each int16
            return None
        if(bytesStr[2*i]):
            asciiBytes += bytes([bytesStr[2*i]])
    return asciiBytes.decode("ascii")

#calculation
yourValueFromNvRam = "5B 46 B6 48 11 E2 6C 70 C7 9D 22 B1 7D 43 D8 2E 33 B8 8E D7 E9 5C 44 DA 9F 8A FA FE 55 D8 B0 7F 0B E0 66 C8 C1 FF 1C A6 77 16 D2 A9 2D 3D 88 D0 E3 63 3E F7 99 8A F4 1D 4F B1 AA 44 05 D8 60 6B"
yourValueFromNvRam = yourValueFromNvRam.replace(" ", "")                        #remove whitespaces
yourValueFromNvRam = binascii.unhexlify(yourValueFromNvRam)                     #to bytes
generatedKeyWithSameLength = generatePanaXorSequence(len(yourValueFromNvRam))
resultOfXor = xorByteStrings(yourValueFromNvRam, generatedKeyWithSameLength)

#analysis
sha1 = getSHA1ifExist(resultOfXor)
if(sha1 == None):
    asciiString = getASCIIifExist(resultOfXor)
    if(asciiString):
        print(f"here is you password:\n{asciiString}")
    print("here is you xored sequence:")
    hexPrettyPrint(resultOfXor)
else:
    print("the xored sequence is likeley the following sha1 hash:")
    hexPrettyPrint(sha1)

(edit 04.01.23: add ascii conversion)

Please let me known if you have any additional questions.

One interesting thing I hadn't had time to implement yet is to open the dumped hex file, and search for occurences fo the last few bytes of the xor sequence for the length 64 bytes.
Since the password or hash is likely to be relatively short <40 bytes the last few bytes are most likely equal to the xor sequence.
Then derive the start of the sequence an overwrite all 64 bytes with zeros to generate a flashable image without password protection.

Maybe a check if the bios dump is complete (includes the intel me section, ...) would be important, because flashing back a partial modified dump will result in a "dead" device. Finding a complete dump online to recover from this state might be difficult.

Best,
Benjamin

@satorisage
Copy link

Hi satorisage,

but where did that part come from?

See the secton "1337 encryption" of en4rab's original post. The key can generated in 16 bytes increments because it is 0x935b * (currentIteration + 1), when you only use the lower 16 bytes of the result. This seems to be the same across many different toughbook models.

Is is an operation I can write in Python?

Yes, see following code using your rom data.

show code for panasoHardcoded.py python3
Please let me known if you have any additional questions.

One interesting thing I hadn't had time to implement yet is to open the dumped hex file, and search for occurences fo the last few bytes of the xor sequence for the length 64 bytes. Since the password or hash is likely to be relatively short <40 bytes the last few bytes are most likely equal to the xor sequence. Then derive the start of the sequence an overwrite all 64 bytes with zeros to generate a flashable image without password protection.

Maybe a check if the bios dump is complete (includes the intel me section, ...) would be important, because flashing back a partial modified dump will result in a "dead" device. Finding a complete dump online to recover from this state might be difficult.

Best, Benjamin

Thanks for the reply! Seems like for the CF54's I have this key could be incorrect - or maybe there is something else going on. When I extracted and calculated the result I got d56e583d7dc544b496160832f1f07a4a29941025 as the sha1. But the password is "tsipub" and as a sha1 hash it calculates to 48d87741220aa2a705005a01bbbcdb1c858eae41. Any thoughts on what could be going on there?

@userx14
Copy link

userx14 commented Sep 9, 2022

Seems like for the CF54's I have this key could be incorrect

If the code says that the xored result is likeley a sha1 hash then the xor-key part is working / the generated key from panaXorSequence is correct. It is basically impossible to get the these zero valued bytes every second character for a non matching key (just add hexPrettyPrint(resultOfXor) in the else case and you will see these zeros). If you look closely at your valueFromNvram you can see that many bytes (those that are zero after performing the xor) are equal to the output of the generatePanaXorSequence function.

But the password is "tsipub" and as a sha1 hash it calculates to 48d87741220aa2a705005a01bbbcdb1c858eae41. Any thoughts on what could be going on there?

I would have two possible explanations for this behavior:

  • instead of the password in ascii they could have hashed the scancodes. I suspect this because they also stored the scancodes for the non hashed password see first post of en4rab.
  • they could have added some constant extra bytes at the end of the password like a constant salt

I have to admit that I didn't really looked into this, and just replaced the section with zeros and called it a day.

I guess that trying one letter passwords, reading the hash, and then trying to brute force the hash could lead to some insight.

Best,
Benjamin

@maxtheobald
Copy link

Hello folks,
what can I say? The tip from @userx14 to simply overwrite the affected bit combination with 0 worked! Apparently the supervisor password is only stored once in the chip of the FZ-G1 MK4. Interestingly, the operating hours counter was also set to 0.
By the way, flashing also worked when installed.
Thanks again for your help.

@Randname666
Copy link

Hello. So I tried this on a Panasonic FZ-G1 MK2 and seems went further than the guy with a FZ-G1 MK4. It doesn't contain an item with guid "C811FA38-42C8-4579-A9BB-60E94EDDFB34" but the one with name "AmiTseSetupGuid" and also text "AMITSESetup".
The content read as :
5b7db609112d6c18c7bc22b37d2fd8b0334e8e26e9a244339fb9fafd55eeb0520b286641c1251c427716d2a92d3d88d0e3633ef7998af41d4fb1aa4405d8606b and after Xoring, it comes with such a result:
ee002f00970055005c00c70028002a006000e700f600db00c200f3004c006700e1001d00ca00c1000000000000000000000000000000000000000000000000
Which the 80s that should be showing up are instead coming up with 00s and other bytes doesn't seems to be either valid EFI scancodes or ASCII codes. I wonder if some kind of masking or other procedure has been applied to them ?

@userx14
Copy link

userx14 commented Sep 17, 2022

Hi @Randname666, your result is most likely the sha1 of the password / keyboard scancodes and maybe some additional constant. (20 bytes = "sha1 length" and every second byte is zero padding).

@Randname666
Copy link

Hi @Randname666, your result is most likely the sha1 of the password / keyboard scancodes and maybe some additional constant. (20 bytes = "sha1 length" and every second byte is zero padding).

Well, tried hashcating that sha1 and it exhausted 8 bytes of a-z, A-Z, 0~9 combinations. Either that's not the right direction, or just unfortunate enough to come into a guy who's really serious about device security.

@userx14
Copy link

userx14 commented Sep 18, 2022

Well, tried hashcating that sha1 and it exhausted 8 bytes of a-z, A-Z, 0~9 combinations. Either that's not the right direction, or just unfortunate enough to come into a guy who's really serious about device security.

Most likeley they are not ascii characters but key scancodes and there could be some additional constant added to the end.

It is possible to just overwrite the xored hash with zeros and flash the modified image back. But there is the risk that if you only have a partial bios backup / the bios chip is write protected, that you can brick the device when using a software flash tool. (See some of the earlier posts)

@Randname666
Copy link

Randname666 commented Sep 19, 2022

But there is the risk that if you only have a partial bios backup / the bios chip is write protected, that you can brick the device when using a software flash tool.

So, things like AFUWINGUI won't generate a full BIOS backup sometimes? Also, I am not sure if I got the idea of "write protected" here but I attempted a BIOS upgrade with the program provided by Panasonic, as on some "consumer level" laptops upgrading, downgrading, or "upgrading" to the same version of the current BIOS could get the password wiped, but not the case here: The FZ-G1 MK2 accepted and successfully finished the BIOS update, but the password is still kept. Luckily that the schema of the password storage is not changed.

I'm in lack of the tool and the skills to do it the hardware way if something goes wrong so I'd rather let the password stay there at least at the moment.

@satorisage
Copy link

satorisage commented Sep 19, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment