Verizon Fios G3100 and E3200 Research
#1
I recently discovered how easy it was to crack my Netgear default password.  That thrill led me to turn my attention to my Fios G3100.  However, this has turned out to be a much worthier adversary.  Boredom and a bit of tenacity has led me down a winding path, but here is where I am at so far in my research.

[Image: attachment.php?aid=1237]

The G3100 and E3200 routers are distributed by Verizon.  Per usual, the sticker on the back of the unit has the necessary information.  I wrote a small python script to scrape Ebay and FB listings and collect all of the associated images.  A second script sorts the images using computer vision and OCR to detect the QR code or relevant text.  I then personally process the good images to collect the useful information, whenever possible I use the QR code as it is the most trustworthy data to read.  Thus far, I have collected over 230+ complete records, as well as saving the images for verification.


.xlsx   FiosG3100andE3200.xlsx (Size: 43.08 KB / Downloads: 12)  
Link to Ref_Images.zip
 (this is a temporary free file sharing link, dm me if it expires)

From this sample we can gain some info on the G3100 key space:
  • MAC address starting with 04.A2.22 are the oldest and have 16 character passwords
        SSID is Fios-XXXXX where X is any char <a-z><A-Z><0-9>   
        SSID Passwords follow <word><number><word><number><word> format (ex: met8sonata868elm)
        Admin Passwords are 16 characters and follow a <word><number><word> format (ex: stubble16crowded)
  • MAC address starting with B8:F8:53 are mixed and may have 15 or 16 character passwords
        SSID is Fios-XXXXX where X is any char <a-z><A-Z><0-9> 
        SSID Passwords follow <word><number><word><number><word> format (ex: moat288nit48pug)
        Admin Passwords are 16 characters and follow a <word><number><word> format (ex: chopper86notably)
  • MAC address starting with 3C.BD.C5 are the newest and have 15 character passwords
        SSID is Fios-XXXXX where X is any char <a-z><A-Z><0-9>
                 or Verizon_XXXXXX where X is any char <A-Z><0-9>     
        SSID Passwords for “Fios” networks follow <word><number><word><number><word> format (ex: range36vex77toy)
                 or “Verizon” networks follow <word>-<word>-<word> with a single digit at the end of one word (ex: miry9-elm-north)
  •     Admin Passwords for “Fios” network are 16 characters and follow a <word><number><word> format (ex: unusual53smelter)
                or “Verizon” networks are 9 characters that are <A-Z><0-9> (ex: Z79KGSX4T)
                Note: 0 and 1 are not seen in sample    

From this sample we can gain some info on the E3200 key space:
  • MAC address starting with 04.A2.22 are the oldest and have 16 character passwords
        SSID is E3200-XXXXX where X is any char <a-z><A-Z><0-9>   
        SSID Passwords follow <word><number><word><number><word> format (ex: nylon88wit657aye)
        Admin Passwords are 16 characters and follow a <word><number><word> format (ex: ritual236auction)
  • MAC address starting with B8:F8:53 are mixed and may have 15 or 16 character passwords
        SSID is E3200-XXXXX where X is any char <a-z><A-Z><0-9>
        SSID Passwords follow <word><number><word><number><word> format (ex: mach92see36flat)
        Admin Passwords are 16 characters and follow a <word><number><word> format (ex: seraph497lantern)
  • MAC address starting with 3C.BD.C5 have 15 character passwords
        SSID is Verizon_XXXXXX where X is any char <A-Z><0-9>
        SSID Passwords follow <word>-<word>-<word> with a single digit at the end of one word (ex: tenth-ben6-vend)    
        Admin Passwords are are 9 characters that are <A-Z><0-9> (ex: 3JB94H6CQ)        
        Note: 0 and 1 are not seen in sample  
  • MAC address starting with DC.F5.1B are the newest and have 15 character passwords
        SSID is Verizon_XXXXXX where X is any char <A-Z><0-9>
        SSID Passwords follow <word>-<word>-<word> with a single digit at the end of one word (ex: plush-fast3-con)    
        Admin Passwords are are 9 characters that are <A-Z><0-9> (ex: QVB734TKL)           
        Note: 0 and 1 are not seen in sample  

From this sample we can gain some other info:
  • Password <word> are between 3-7 characters for SSID Password
  • Password <number> are between 1-4 digits
  • There are 3 HW version (1102, 1103, 1104)
  • Serial #’s are 16 digits (except for the most recent E3200 which have 11)
  • Shipped firmware ranges from 1.3.5.1 to 3.1.1.16 
  • There are the 568 unique words extracted from the passwords:
Code:
add aft ago aim air ait alp ape ark art ash ask awe aye bat bay bed bee beg ben bet bid biz boa bog bot bow bug bun bus bye cat caw cif cob con cot cub cud cup cut dab dad dam daw day del dew dia did dig dit doe dos due dun ear eeg ego eke elk elm end fad fat fax fay fed fee fen few fez fib fig fin fir fit fob fog fop for fox fro gad gap gel gem gen gig gin gnp gnu got gut had han has hat hew hey hid hie him hin hit hod hub hue hum ice icy jab jag jam jaw jet jib jog joy jus lab law lay let mad may met mil mix mod mow mud mug mum nag naw new nib nip nit nod non not now oak oar odd ode oil one ope opt ork out owl pal paw pay pea pet pit pod pug pun pup put ram ran rap raw ray ree ret rid rna roe rug run rut rye sat say see set sew sir sit six sly sou sow soy spa sum sun sup tag tap tax tee too tot toy tun ush vex vie vim wad was wax web wed why wig win wit woe won woo wry yak yam yea yes yet yon you zap zoo abbe aery agog alas alga allo arms atom back bake beak been beep bits boar bolt bone book boss bred brew brow cafe cape cart cast cene cere cham char cloy copy crib cuff dark dear deny dewy dial dine dint dock doff dory doth drub dump dust each ever exam fade fame fare fast fawn feet felt fine flat flaw flit form fund fuss gage gain gall gate gent golf grab gray grey grim hair hake halt hasp have hawk held hide high holm hone hoot hour huff hung ibis iron jibe jill june kale kidd kirk knit knot lack lead lean lend lens less lump mach mama mass meat mica mint miry moat mood myth nail name nice nigh nite oboe oily ouch over paid pail pant pelf pell pelt pert plan plot plus pool pram push quiz raze rill ripe roar rome roof rook ruby rush sage sale self shed sign sill skim slop slue slug soap solo spin stir swam swap tare tele tell than then they tidy tier ting tout tram trod tron tune type upon vain vane vend vide vine wain wait wake wane want wash wavy what whom will wind wing wire wisp wood yard yeah yell yelp yond zest acute amaze angel apace basic begot bough brush camel carry chase clean clump coach cocky combe comet coney could crate creak credo cress crock crone demur deter divan douse drily eater elope enact endow favor fifth fifty finny flock floor floss flown focal focus forte froth fuzzy games gorse guise hoary hobby hutch inapt inner jewel mayor meant mense mixed moose muddy mulct niter north nylon order papal pivot plait plumy plush poser price quard quell quest range rapid rayon sales salon salty scend scope scour sense shack sixty smack snips snort spark spent steep stiff swell synod taper tarry tempt tenth thank tinge today trace track tract trade trawl trend tweet tyler vague verse vetch vital whose witty woman worse wrist behove bethel german iodine pallor remove sonata bloated sweater

Although there is a lot of useful information collected in the sample, it is still a fairly large key space.  With that in mind I decided to take my first dives into firmware analysis, which of course requires some firmware.  Looking online, I was able to find a single reddit post that linked to g3100 firmware version 3.2.0.15.  With a lot more digging, I was able to find posts with links to firmware for other devices.  Using this information I wrote another script to try to find additional firmware.  Here’s what I've found, many of these are the first time posted online I believe.

https://cpe-ems34.verizon.com/firmware/g....0.0.6.bin
https://cpe-ems34.verizon.com/firmware/g...1.1.17.bin
https://cpe-ems34.verizon.com/firmware/g...1.1.18.bin
https://cpe-ems34.verizon.com/firmware/g...2.0.11.bin
https://cpe-ems34.verizon.com/firmware/B...2.0.13.bin
https://cpe-ems34.verizon.com/firmware/B...2.0.14.bin
https://cpe-ems34.verizon.com/firmware/B...2.0.15.bin
https://cpe-ems34.verizon.com/firmware/B...loader.bin
https://cpe-ems34.verizon.com/firmware/B...loader.bin
https://cpe-ems34.verizon.com/firmware/B...loader.bin
https://cpe-ems34.verizon.com/firmware/B...loader.bin

All of the links I found online for Verizon G3100, E3200, and CR1000 all used the cpe-ems34 link.  I did find some other routers that were using different servers such as cpe-ems20 and cpe-ems31.  Further investigation lead to this site showing all of the Verizon subdomains, which there are a ton of cpe-ems domains.

I tried my script with a few such as 31, 33, 43, however nothing new was turned up.
https://cpe-ems33.verizon.com/firmware/g...1.1.17.bin
https://cpe-ems34.verizon.com/firmware/g...2.0.15.bin

I tried binwalk on the first firmware I found (3.2.0.15), and while it extracts the file system, none of the files were readable for me.  The entropy graph shows that only a small part is encrypted, so I am a bit confused.  My next step is to try to mount it in a VM Linux since I only have Mac and RPI for testing.

.png   g3100_fw_3.2.0.15.bin.png (Size: 75.17 KB / Downloads: 3)

This is what led me to looking for older firmware, however using binwalk on 2.0.0.6 gives me similar results.  I know that there should be at least 2 more older firmware 1.3.6.27 and 1.5.0.10 but I have not been able to locate them.  

.png   g3100_fw_2.0.0.6.bin.png (Size: 79.38 KB / Downloads: 1)

The possibility of firmware encryption led me to look at physical access of the device.  After some quick soldering, I connected to the UART.  Unfortunately this did not lead to a shell either, but did provide a bit more information.  Referencing some of the output online, I found someone else who also connected this way and had a longer output (possibly because of older firmware?).
Code:
BTRM V1.0 R1.0 L1CD MMUI MMU9 DATA ZBBS MAIN OTP? REF? REFP RTF? RTFP OTPP FSBT NAND IMG? IMGL UHD? UHDP RLO? RLOP AHD? ROT? ROTA MID? MIDP AHDP SBI? SBIA PASS ---- U-Boot SPL 2019.07 (Oct 31 2023 - 03:52:42 -0400) Strap register: 0x53008176 Board is FLD secure $SPL: 5.04L.02@419765 $ nand flash device id 0x98d39126, total size 1024MB block size 256KB, page size 4096 bytes, spare area 216 bytes ECC BCH-8 FFinit done find magic number 0x75456e76 at address 0x100000 FFinit find magic number 0xcb00cb at address 0x114000 reading blob from 0x114000 offset 0x26c len 608 digest sha256 OK FFinit find magic number 0x64447233 at address 0x105000 reading blob from 0x105000 offset 0xc len 59888 digest sha256 OK mcb selector 0x1427 checksum 0x722c322d safe_mode 0 U-Boot DDR standalone 2019.07 (Jul 25 2021 - 18:43:37 -0700) Build: 5.04L.02@348603 MemsysInit hpg0_generic_aarch64 3.5.1.1 20171009 DDR3 8267D980 80180000 801A0000 00000000 00000000 0020476E MCB rev=0x00000501 Ref ID=0x0476E Sub Bld=0x002 Dram Timing 11-11-11 start of memsys_begin mc_cfg_init(): Initialize the default values on mc_cfg init_memc_dram_profile(): Initializing MEMC DRAM profile --------------------------------------------------------------- MEMC DRAM profile (memc_dram_profile_struct) values:   dram_type    = DDR3 ==================================================== PART values:   part_speed_grade    = 1600 CL11   part_size_Mbits    = 4096 (DRAM size in MegaBits)   part_row_bits      = 15 (number of row bits)   part_col_bits      = 10 (number of column bits)   part_ba_bits        = 3 (number of bank bits)   part_width_bits    = 16 (DRAM width in bits) NUMER OF PARTS:   part_num            = 1 (Number of parts) TOTAL values:   total_size_Mbits    = 4096 (DRAM size in MegaBits)   total_cs_bits      = 0 (number of cs bits, for dual_rank mode)   total_width_bits    = 16 (DRAM width in bits)   total_burst_bytes  = 16 (Number of bytes per DRAM access)   total_max_byte_addr = 0x1fffffff (Maximum/last DRAM byte address)                         (Number of bits in total_max_byte_addr is 29)                         (i.e. total_max_byte_addr goes from bit 0 to bit 28)   ddr_2T_mode        = 0   ddr_hdp_mode        = 1   large_page          = 1   ddr_dual_rank      = 0   cs_mode            = 0 MEMC timing (memc_dram_timing_cfg_struct) values: ====================================================   MC_CHN_TIM_TIM1_0 register fields:     tCwl  = 8     tRP    = 11     tCL    = 11     tRCD  = 11   MC_CHN_TIM_TIM1_1 register fields:     tCCD_L = 4     tCCD  = 4     tRRD_L = 6     tRRD  = 6   MC_CHN_TIM_TIM1_2 register fields:     tFAW  = 32     tRTP  = 6     tRCr  = 39   MC_CHN_TIM_TIM1_3 register fields:     tWTR_L = 6     tWTR  = 6     tWR_L  = 12     tWR    = 12   MC_CHN_TIM_TIM2 register fields:     tR2R  = 0     tR2W  = 2     tW2R  = 2     tW2W  = 0     tAL    = 0     tRFC  = 208 ==================================================== %1 SSC enabled Poll PHY Status register PHY Status= 1 Disable Auto-Refresh [0000000080180200] = 0x00000305 End of memsys_begin Add/Ctl Alignment Coarse Adj=0x087 deg, cmd steps=0x0DC reg 0x801A0090 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A0094 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A0098 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A009C set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00A0 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00A4 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00A8 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00AC set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00B0 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00B4 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00B8 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00BC set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00C0 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00C4 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00C8 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00CC set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00D0 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00D4 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00D8 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00DC set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00E0 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00E4 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00E8 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00EC set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00F0 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00F4 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00F8 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A00FC set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A0100 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A0108 set to VDL 0x054 with Fine Adj=0x01 deg reg 0x801A010C set to VDL 0x054 with Fine Adj=0x01 deg HP RX TRIM itrim = 0x0 lstrim = 0x9 ZQ Cal HP PHY R in Ohm P: Finger=0x318 Term=0x71 Drv=0x28 N: Finger=0x2A6 Term=0x71 Drv=0x28 PLL Ref(Hz)=0x02FAF080 UI STEPS=0x06E DDR CLK(MHz)=0x31B WL CLK dly(ps)=0x0C8 bitT(ps)=0x274 VDLsize(fs)=0x164D CLK_VDL=0x023 start of memc_init [0000000080180004] = 0x0110061f [0000000080180234] = 0x00001101 Enable Auto-Refresh [0000000080180110] = 0x11100f0e [0000000080180114] = 0x15141312 [0000000080180118] = 0x19181716 [000000008018011c] = 0x001c1b1a [0000000080180124] = 0x04000000 [0000000080180128] = 0x08070605 [000000008018012c] = 0x00000a09 [0000000080180134] = 0x000d0c0b Writing to MC_CHN_CFG_CNFG reg; data=0x00000000 [0000000080180100] = 0x00000000 cfg_memc_timing_ctrl() Called [0000000080180214] = 0x080b0b0b [0000000080180218] = 0x04040606 [000000008018021c] = 0x20000627 [0000000080180220] = 0x06060c0c [0000000080180224] = 0x120000d0 End of memc_init start of pre_shmoo [0000000080180004] = 0xc110071f end of pre_shmoo SHMOO 28nm 801A0000 80180800 00000000 00020000 00000000 Shmoo WL One UI Steps : 0x7B auto-clk result = 01B (filter=0C steps) initial CLK shift = 023 final CLK shift  = 01B   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111   000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222   012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 00 S-------------------X------------------------------------------------------------------------------------------------------ 01 S-----------X-------------------------------------------------------------------------------------------------------------- Shmoo RD En FORCED WR ODT = 0x00001800 DQSN DRIVE PAD CONTROL (from) (to) B0 00039A91 00079A91 B1 00039A91 00079A91 B0 RISE UI=1 VDL=1B PICK UI=2 VDL=1B B1 RISE UI=1 VDL=28 PICK UI=2 VDL=28   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111   000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222   012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 00 --S-----------------+---+++X+++++++++++++++-------------------------------------------------------------------------------- 01 --S-----------------------------+----++-X+++++++++++++++------------------------------------------------------------------- Shmoo RD DQ NP DQS : B0 VDL=6E ok B1 VDL=6E ok   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111   000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222   012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 00 ---------------------+++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++------- 01 ---------------+++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++--------- 02 ------------------+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++--------- 03 ----------+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++----------------- 04 --------------+++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++----------------- 05 ------------+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++--------------- 06 ------------++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++------------- 07 --------+++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++-------------------- 08 ------------------------+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++--- 09 -----------------------++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++--- 10 -------------------+++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++----- 11 --------------------+++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++++--- 12 -----------------+++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++++------ 13 ----------------++++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++++----- 14 --------------++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++----------- 15 ------------------++++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++++--- Shmoo RD DQ P   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111   000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222   012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 00 ---------------------+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++------ 01 ---------------+++++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++++----- 02 -------------------++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++------ 03 ---------++++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++++------------- 04 --------------+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++------------- 05 ------------+++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++++----------- 06 ------------++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++------------- 07 --------++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++----------------- 08 ------------------------++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++- 09 -----------------------++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++--- 10 -------------------+++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++----- 11 --------------------+++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++++--- 12 -----------------+++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++------- 13 ---------------++++++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++++++--- 14 --------------++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++----------- 15 -----------------+++++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++++--- Shmoo RD DQ N   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111   000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222   012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 00 ------------------+-+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++------- 01 ----------------++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++--------- 02 ------------------+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++--------- 03 ---------+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++------------------ 04 ------------++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++----------------- 05 -----------++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++-------------- 06 -----------+++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++------------- 07 -----++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++-------------------- 08 ------------------------++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++-- 09 ---------------------++++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++++- 10 ------------------+++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++++----- 11 ------------------+++++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++++-- 12 ---------------++++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++++------ 13 ----------------++++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++++----- 14 ------------++++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++++---------- 15 ------------------++++++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++++++--- RD DQS adjustments : BL0: Start: 0x6E Final: 0x6E BL1: Start: 0x6E Final: 0x6E Shmoo WR DQ   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111   000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222   012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 00 ------------+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++--------------- 01 ----------+++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++--------------------- 02 ------------+++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++---------------- 03 ---+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++------------------------ 04 ---------+++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++----------------------- 05 --------+++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++-------------------- 06 -----------++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++------------------ 07 ---+++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++----------------------------- 08 ---------------+++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++------------- 09 ---------------++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++--------------- 10 -----------+++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++---------------- 11 -----------+++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++----------------- 12 -----------+++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++-------------------- 13 -----------+++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++----------------- 14 ----+++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++------------------------ 15 ------------+++++++++++++++++++++++++++++++++++++++++++++++X+++++++++++++++++++++++++++++++++++++++++++++++---------------- Shmoo WR DM WR DM   000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111   000000000011111111112222222222333333333344444444445555555555666666666677777777778888888888999999999900000000001111111111222   012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 00 -------++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++----------------------- 01 --------++++++++++++++++++++++++++++++++++++++++++++++++X++++++++++++++++++++++++++++++++++++++++++++++++------------------ start of memsys_end [0000000080180004] = 0x8110071f [0000000080180010] = 0x00000009 end of memsys_end DDR test done successfully FFinit find magic number 0x75456e76 at address 0x100000 FFinit find magic number 0x74506c21 at address 0x140000 reading blob from 0x140000 offset 0xc len 163741 digest sha256 OK U-Boot TPL 2019.07 (Oct 31 2023 - 03:52:39 -0400) Board is FLD secure $TPL: 5.04L.02@419765 $ CPU Clock: 1500MHz IMAGE is NAND Trying to boot from NAND nand flash device id 0x98d39126, total size 1024MB block size 256KB, page size 4096 bytes, spare area 216 bytes ECC BCH-8 image from 2097152 to 315621376 brcmnand_read_buf(): Attempt to read bad nand block 760 brcmnand_read_buf(): Attempt to read bad nand block 762 brcmnand_read_buf(): Attempt to read bad nand block 768 brcmnand_read_buf(): Attempt to read bad nand block 770 brcmnand_read_buf(): Attempt to read bad nand block 772 brcmnand_read_buf(): Attempt to read bad nand block 780 brcmnand_read_buf(): Attempt to read bad nand block 782 RESET STATUS is 0x80000000 SELECTED Image 1 FIT_VOL_ID is 3 brcmnand_read_buf(): Attempt to read bad nand block 760 brcmnand_read_buf(): Attempt to read bad nand block 762 brcmnand_read_buf(): Attempt to read bad nand block 768 brcmnand_read_buf(): Attempt to read bad nand block 770 brcmnand_read_buf(): Attempt to read bad nand block 772 brcmnand_read_buf(): Attempt to read bad nand block 780 brcmnand_read_buf(): Attempt to read bad nand block 782 Found FIT format U-Boot tpl_load_read: sector 7000000, count 3194, buf 0000000007000000 tpl_load_read: sector 7000000, count 4192, buf 0000000007000000 fit read sector 7000000, sectors=16786, dst=0000000007000000, count=16786, size=0x4192 FIT Header Authentication Successfull! INFO: Found disabled /trust/anti-rollback node! INFO: Found /trust/hw_state node in fit tpl_load_read: sector 7003680, count 8028, buf 0000000000004000 ## Checking hash(es) for Image atf ... sha256+ OK tpl_load_read: sector 700b680, count 27fc80, buf 0000000001000000 ## Checking hash(es) for Image uboot ... sha256+ OK tpl_load_read: sector 76ea1c0, count c5be, buf 000000000127fc80 ## Checking hash(es) for Image fdt_VERIZON-G3100 ... sha256+ OK INFO: Creating //trust INFO: Creating /trust/antirollback_lvl INFO: Adding exported item node antirollback_lvl to dtb, size:4 INFO: Creating /trust/brcm_pub_key INFO: Adding exported item node brcm_pub_key to dtb, size:256 U-Boot 2019.07 (Oct 31 2023 - 03:52:45 -0400), Build: 5.04L.02@419765 Model: VERIZON-G3100 DRAM:  512 MiB max supported leds 32[32] Serial LED interface found num shifters 2 [2] serial data polarity low 0 BCA LED Controller initialized HW led 3 registered HW led 4 registered HW led 5 registered HW led 6 registered HW led 7 registered HW led 8 registered HW led 9 registered HW led 10 registered SW led 0 registered SW led 1 registered SW led 2 registered SW led 11 registered SW led 12 registered SW led 13 registered SW led 14 registered SW led 15 registered Dump Current setting of SWREGs 1.0D, reg=0x00, val=0xc690 1.0D, reg=0x01, val=0x0d06 1.0D, reg=0x02, val=0xcb12 1.0D, reg=0x03, val=0x5372 1.0D, reg=0x04, val=0x0000 1.0D, reg=0x05, val=0x0702 1.0D, reg=0x06, val=0xb000 1.0D, reg=0x07, val=0x0029 1.0D, reg=0x08, val=0x0c02 1.0D, reg=0x09, val=0x0071 1.8 , reg=0x00, val=0xc690 1.8 , reg=0x01, val=0x0d06 1.8 , reg=0x02, val=0xcb12 1.8 , reg=0x03, val=0x5370 1.8 , reg=0x04, val=0x0000 1.8 , reg=0x05, val=0x0702 1.8 , reg=0x06, val=0xb000 1.8 , reg=0x07, val=0x0029 1.8 , reg=0x08, val=0x0c02 1.8 , reg=0x09, val=0x0071 1.5 , reg=0x00, val=0xc690 1.5 , reg=0x01, val=0x0d06 1.5 , reg=0x02, val=0xcb12 1.5 , reg=0x03, val=0x5370 1.5 , reg=0x04, val=0x0000 1.5 , reg=0x05, val=0x0702 1.5 , reg=0x06, val=0xb000 1.5 , reg=0x07, val=0x0029 1.5 , reg=0x08, val=0x0c02 1.5 , reg=0x09, val=0x0071 1.0A, reg=0x00, val=0xc690 1.0A, reg=0x01, val=0x0d06 1.0A, reg=0x02, val=0xcb12 1.0A, reg=0x03, val=0x5370 1.0A, reg=0x04, val=0x0000 1.0A, reg=0x05, val=0x0702 1.0A, reg=0x06, val=0xb000 1.0A, reg=0x07, val=0x0029 1.0A, reg=0x08, val=0x0c02 1.0A, reg=0x09, val=0x0071 Take PMC out of reset waiting for PMC finish booting PMC rev: 3.4.1.427360 running pmc_init:PMC using DQM mode Chip ID: BCM68369_B1 Broadcom B53 Dual Core: 1500MHz RDP: 1400MHz $Uboot: 5.04L.02@419765 $ WDT:  Started with servicing (80s timeout) NAND:  1024 MiB MMC:  sdhci: 0 Loading Environment from BOOT_MAGIC... ENV_BOOT_MAGIC_LOAD found magic at 100000 good crc resize from 16384 to 8192 OK In:    serial0 Out:  serial0 Err:  serial0 Board is FLD secure INFO: Can't find /trust/fit-aes1 node in boot DTB! Now we are in UBOOT proper HTTPD: ready for starting boot_device is NAND Net:  Using MAC Address b8:f8:53:0b:1d:01 eth0: switch0 No size specified -> Using max size (7300992) Read 7300992 bytes from volume bootfs1 to 0000000002000000 FIT Header Authentication Successfull! Read 4 bytes from volume rootfs1 to 000000001dd40664 ## Loading kernel from FIT Image at 02000000 ...   Using 'conf_lx_VERIZON-G3100' configuration   Verifying Hash Integrity ... OK   Trying 'kernel' kernel subimage     Description:  4.19 kernel     Type:        Kernel Image     Compression:  lzma compressed     Data Start:  0x0228c800     Data Size:    3461392 Bytes = 3.3 MiB     Architecture: AArch64     OS:          Linux     Load Address: 0x00100000     Entry Point:  0x00100000     Hash algo:    sha256     Hash value:  77e40836ec218fa969f9d2bd572115ed9a7ef008cc75bfec4912354ce78a6349   Verifying Hash Integrity ... sha256+ OK ## Loading fdt from FIT Image at 02000000 ...   Using 'conf_lx_VERIZON-G3100' configuration   Verifying Hash Integrity ... OK   Trying 'fdt_VERIZON-G3100' fdt subimage     Description:  dtb     Type:        Flat Device Tree     Compression:  uncompressed     Data Start:  0x026ea1c4     Data Size:    50618 Bytes = 49.4 KiB     Architecture: AArch64     Hash algo:    sha256     Hash value:  c50470d2e693ebcd7dd68e42cc1de0ace24ccc30766e9c36d08c6b4462fa2e53   Verifying Hash Integrity ... sha256+ OK   Booting using the fdt blob at 0x26ea1c4 ARCADYAN: Authenticating vmlinux ... ARCADYAN: Authenticating vmlinux pass ARCADYAN: Decrypting kernel image ... ARCADYAN: Decrypting kernel image done   Uncompressing Kernel Image ... OK ERROR: reserving fdt memory region failed (addr=1b400000 size=4c00000)   Loading Device Tree to 0000000007f73000, end 0000000007fff5b9 ... OK RSVD: not found enrty for adsl RSVD: not found enrty for bufmem RSVD: not found enrty for rnrmem RSVD: Allocated for rdp1    64MB RSVD: Allocated for rdp2    8MB RSVD: Allocated for dhd0    11MB RSVD: Allocated for dhd1    11MB RSVD: Allocated for dhd2    11MB RSVD: Total 0x06c00000 bytes CMA reserved memory @ 0x19400000 appending extra boot args to linux boot command line:   mtdparts=brcmnand.0:2097152(loader),313524224@2097152(image),8388608@315621376(misc1),1048576@324009984(misc3),709885952@325058560(data),28311552@1034944512(owl),1048576@1063256064(mtdoops),2097152@1064304640(license),2097152@1066401792(certificate),1048576@1068498944(pri Starting kernel ... D%G

My device is currently running firmware 3.4.0.9, which I tried to revert to any previous version.  I found a reference to a “hidden” admin page to update firmware at https://192.168.1.1/#/firmware_upgrade, but none of the firmware I downloaded would work (I think due to anti rollback).

So this is where I am currently stuck.  I doubt that the key generation algorithm is on the device.  However, if anyone is able to make sense of the serial output that might help unlock the firmware, I would love to just have a look around for curiosity sake.  I will try to periodically scrape and update the password file, I originally thought it would have more entries by now.

Next Steps:
  • Analyze the data set to try to reduce key space (unused characters, common words, find the wordlist?)
  • Collect more complete entries for the dataset
  • Try to mount file system (ubi.img) in a proper Linux environment
  • Try to find older firmware


Attached Files
.jpeg   Backref.jpeg (Size: 50 KB / Downloads: 260)
Reply
#2
I forgot to post the E3200 Firmware links I discovered.  The single mention I found previously was for the 3.2.0.11.trapeze.bin

https://cpe-ems34.verizon.com/firmware/e...1.1.17.bin
https://cpe-ems34.verizon.com/firmware/e...1.1.18.bin
https://cpe-ems34.verizon.com/firmware/e....2.0.1.bin
https://cpe-ems34.verizon.com/firmware/B...rapeze.bin
https://cpe-ems34.verizon.com/firmware/B...rapeze.bin
https://cpe-ems34.verizon.com/firmware/B...rapeze.bin
https://cpe-ems34.verizon.com/firmware/B...2.0.11.bin
https://cpe-ems34.verizon.com/firmware/B...2.0.12.bin
https://cpe-ems34.verizon.com/firmware/B...loader.bin
https://cpe-ems34.verizon.com/firmware/B...loader.bin

Code:
https://cpe-ems34.verizon.com/firmware/e3200_fw_3.1.1.17.bin https://cpe-ems34.verizon.com/firmware/e3200_fw_3.1.1.18.bin https://cpe-ems34.verizon.com/firmware/e3200_fw_3.2.0.1.bin https://cpe-ems34.verizon.com/firmware/BHRx_Ext/e3200_fw_3.2.0.11.trapeze.bin https://cpe-ems34.verizon.com/firmware/BHRx_Ext/e3200_fw_3.2.0.12.trapeze.bin https://cpe-ems34.verizon.com/firmware/BHRx_Ext/e3200_fw_3.4.0.8.trapeze.bin https://cpe-ems34.verizon.com/firmware/BHRx_Ext/e3200_fw_3.2.0.11.bin https://cpe-ems34.verizon.com/firmware/BHRx_Ext/e3200_fw_3.2.0.12.bin https://cpe-ems34.verizon.com/firmware/BHRx_Ext/e3200_fw_3.4.0.7_loader.bin https://cpe-ems34.verizon.com/firmware/BHRx_Ext/e3200_fw_3.4.0.8_loader.bin

and the G3100 for readability.
Code:
https://cpe-ems34.verizon.com/firmware/g3100_fw_2.0.0.6.bin https://cpe-ems34.verizon.com/firmware/g3100_fw_3.1.1.17.bin https://cpe-ems34.verizon.com/firmware/g3100_fw_3.1.1.18.bin https://cpe-ems34.verizon.com/firmware/g3100_fw_3.2.0.11.bin https://cpe-ems34.verizon.com/firmware/BHRx/g3100_fw_3.2.0.13.bin https://cpe-ems34.verizon.com/firmware/BHRx/g3100_fw_3.2.0.14.bin https://cpe-ems34.verizon.com/firmware/BHRx/g3100_fw_3.2.0.15.bin https://cpe-ems34.verizon.com/firmware/BHRx/g3100_fw_3.4.0.4_loader.bin https://cpe-ems34.verizon.com/firmware/BHRx/g3100_fw_3.4.0.6_loader.bin https://cpe-ems34.verizon.com/firmware/BHRx/g3100_fw_3.4.0.8_loader.bin https://cpe-ems34.verizon.com/firmware/BHRx/g3100_fw_3.4.0.9_loader.bin <Mirrors> https://cpe-ems33.verizon.com/firmware/g3100_fw_3.1.1.17.bin https://cpe-ems33.verizon.com/firmware/g3100_fw_3.2.0.15.bin
Reply
#3
Nicely done. Not sure if this will be helpful, but PSKracker has a couple of netgear wordlists that might come in handy
https://github.com/andrewjlamarche/PSKracker
Reply
#4
Interesting research. We've looked at these and sadly couldn't find anything, which can limit the keyspace, which is really enormous. We have a lot of uncracked Fios networks in wpa-sec. We've got only these:
Code:
b8f853eb8962 Fios-6MSdq arc53dock735wry b8f85362dec2 Fios-DMG5b palmy82out76arc 04a222f1f9da Fios-9ZfGv tag828pun44snail b8f85337fb06 Fios-fq8ZT zoo343owl289crow
As always, the BSSID may be fake.
Reply
#5
Yeah I have come across the wordlists for 3-7 letter words that could be combined to create a dictionary, however as others have discovered the possible keyspace is still huge.  I had a bit of time over the weekend to play with the data, and I am happy to report that I made some progress!  With a little more data collection/processing I should be able to generate all of the Serial numbers based on MAC address.  Without an algorithm, it isn’t super exciting... but it does allow me to at least validate the MAC and serials I collect are accurate since the characters 0 8 B all look similar in blurry photos.  If we ever do discover the algorithm, the serial number could likely be part of it.


Here’s my analysis...

I noticed that there seemed to be a pattern in the last digit of the MAC address, with many ending in 0/8, or 4/C especially when grouped together by serial number.  So I separated the data by MAC address using the first 3 octets (ie B8.F8.53.XX.XX.XX), and then combined the last 3 octets (ie DD.4A.98) removed the decimals (DD4A98) and converted the hex to decimal value (14502552).  This gave me a numerical value for the MAC that I could plot vs the serial number.  We can see there is a very strong correlation, but we can’t accurately calculate the serial number. 

[Image: attachment.php?aid=1242]

To try to determine the relationship, I kept the serial numbers sorted in order.  Then I took the hex2dec and serial number of one entry, and subtracted it from the next.  I then took the (Mac difference / Serial difference). Seeing the same whole digit pop up several times gives us a clue that we’re on to something!

[Image: attachment.php?aid=1243]

However, there are still several entries that don’t make any sense at all.  I tried to look at the serial numbers individually, but there were huge jumps that didn’t seem explainable.  I fed the data to our favorite AI, and it couldn’t make much sense of it either.  However, it did suggest that perhaps the digits 21 in all of the serial numbers (E302120090812958) was a date code.  I investigated this a little bit, but it didn’t seem to work out.  Eventually I broke the digits into smaller numbers, which then allowed me to recognize there is a date code, just in a slightly different spot!  The format is 2-digit year, 2 digit month, 2 digit day starting on the 6th character (E302120090812958 = 09/08/2020).  I was able to verify this because the month spot is never greater than 12, the day spot is never greater than 31 and is only 31 on months that have that many days, and the years are between 19-23.  The first 5 characters in the serial always stay the same, so that leaves us with the last 5 digits as the incremental serial (E302120090812958).  With this information in hand, I sorted the list by date codes, and everything starts to line up more.  The number 8 that shows up is how many steps there are between MAC addresses, so if the MAC is 3C.BD.C5.42.22.50, the next address in the sequence will be 3C.BD.C5.42.22.58.  Using this information, I can actually back calculate the starting MAC address for each date code if we assume each block starts @ 00000 serial.  Once all of the starting blocks are calculated, we can calculate the end of the previous block by subtracting 1 step.  The E3200 MACS step by 6 digits instead of 8, some of the earlier g3100 jump by 11.  Several of the ending blocks stop on seemingly non-random numbers, which is another clue that we're on the right track.  I have gone though and done this for the 3C.BD.C5 MACs I have on hand, and ended up covering most of the address space.  I was also able to identify and correct several places where the MAC or Serial was slightly off in my original data set (and validated using the saved photos)

[Image: attachment.php?aid=1244]

With this bit of success, I created a python script to calculate the serial based on a given MAC.  There are still a few “UNKNOWN” blocks when there seems to be a large gap of MACs between blocks.  I will work on adding the other MAC prefixes, so that we can enumerate all possible devices.  I also stopped on serial 00001 earlier instead of 00000.  I am still not sure which is correct honestly.  Eventually I will correct them all to 00000 add code to detect these edges and give you both Serials.  If you test the code, please report back.  If you want to give me a MAC address and have me try to guess the serial I can.  Otherwise, I have another batch of recently scraped images that I still need to validate and add to the database.  I will be testing these on the script.  My next post should have an updated data set!

Code:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import re from datetime import datetime # Your MAC ranges data mac_data = """ 3C.BD.C5.00.00.00:3C.BD.C5.01.F5.6A,G3100,8,Unknown 3C.BD.C5.01.F5.70:3C.BD.C5.09.3B.F8,G3100,8,121011516659 3C.BD.C5.09.3C.00:3C.BD.C5.0C.30.38,G3100,8,121030100001 3C.BD.C5.0C.30.40:3C.BD.C5.16.4A.C8,G3100,8,121021700001 3C.BD.C5.16.4A.D0:3C.BD.C5.1C.C1.58,G3100,8,121031200001 3C.BD.C5.1C.C1.5E:3C.BD.C5.22.C3.EA,G3100,8,Unknown 3C.BD.C5.22.C3.F0:3C.BD.C5.2B.5B.E8,G3100,8,121033100001 3C.BD.C5.2B.5B.F0:3C.BD.C5.31.1E.60,G3100,8,121041400001 3C.BD.C5.31.1E.66:3C.BD.C5.37.5C.92,G3100,8,Unknown 3C.BD.C5.37.5C.98:3C.BD.C5.3D.D3.40,G3100,8,121051800001 3C.BD.C5.3D.D3.48:3C.BD.C5.42.22.58,G3100,8,121060700001 3C.BD.C5.42.22.60:3C.BD.C5.46.3E.C4,G3100,8,121062200000 3C.BD.C5.46.3E.CC:3C.BD.C5.47.F6.C4,G3100,8,121071300000 3C.BD.C5.47.F6.CC:3C.BD.C5.49.AE.C4,G3100,8,121072100000 3C.BD.C5.49.AE.CC:3C.BD.C5.50.05.44,G3100,8,121070100000 3C.BD.C5.50.05.4C:3C.BD.C5.56.95.D4,G3100,8,121072000000 3C.BD.C5.56.95.DA:3C.BD.C5.60.3B.72,E3200,6,121072000000 3C.BD.C5.60.3B.74:3C.BD.C5.69.B8.CC,G3100,8,121081100000 3C.BD.C5.69.B8.D4:3C.BD.C5.71.07.FC,G3100,8,121082000000 3C.BD.C5.71.08.00:3C.BD.C5.76.8D.C8,G3100,8,121082600000 3C.BD.C5.76.8D.CC:3C.BD.C5.7D.27.9C,G3100,8,121090800000 3C.BD.C5.7D.27.A2:3C.BD.C5.85.4C.98,G3100,8,Unknown 3C.BD.C5.83.03.D4:3C.BD.C5.85.4C.9E,E3200,6,121091600001 3C.BD.C5.85.4C.A4:3C.BD.C5.8C.CB.C6,E3200,6,Unknown 3C.BD.C5.8C.CB.CC:3C.BD.C5.93.FF.8C,G3100,8,121101500000 3C.BD.C5.93.FF.92:BD.C5.93.9B.67.6C,G3100,8,Unknown 3C.BD.C5.9B.67.72:3C.BD.C5.A1.71.B2,G3100,8,121110500000 3C.BD.C5.A1.71.BA:3C.BD.C5.A3.FE.1C,E3200,6,121110500001 3C.BD.C5.A3.FE.22:3C.BD.C5.AD.16.64,E3200,6,Unknown 3C.BD.C5.AD.16.6A:3C.BD.C5.AE.AE.2E,E3200,6,122010100001 3C.BD.C5.AE.AE.34:3C.BD.C5.B4.2D.5E,E3200,6,121122100000 3C.BD.C5.B4.2D.62:3C.BD.C5.B5.09.9A,G3100,8,122021400000 3C.BD.C5.B5.09.A2:3C.BD.C5.B5.E5.9A,G3100,8,122031000000 3C.BD.C5.B5.E5.A2:3C.BD.C5.B8.0B.9A,G3100,8,122031100000 3C.BD.C5.B8.0B.A2:3C.BD.B8.C1.ED.A2,G3100,8,122031500000 3C.BD.C5.C1.ED.A4:3C.BD.C5.C2.40.1E,E3200,6,122031300000 3C.BD.C5.C2.40.24:3C.BD.C5.C2.89.E0,E3200,6,122031400000 3C.BD.C5.C2.89.E6:3C.BD.C5.CD.A1.1A,E3200,6,Unknown 3C.BD.C5.CD.A1.20:3C.BD.C5.CF.39.86,E3200,6,122052200000 3C.BD.C5.CF.39.8C:3C.BD.C5.D2.C8.06,E3200,6,122091400000 3C.BD.C5.D2.C8.0C:3C.BD.C5.D3.41.F2,E3200,6,122091500000 3C.BD.C5.D3.41.F8:3C.BD.C5.DA.E1.12,E3200,6,Unknown 3C.BD.C5.DA.E1.18:3C.BD.C5.DD.EE.80,E3200,6,122110900000 3C.BD.C5.DD.EE.86:3C.BD.C5.E5.83.8A,E3200,6,Unknown 3C.BD.C5.E5.83.90:3C.BD.C5.E8.44.B0,E3200,6,123011000000 3C.BD.C5.E8.34.96:3C.BD.C5.E8.44.B6,E3200,6,123030400000 3C.BD.C5.E8.44.BC:3C.BD.C5.F1.11.4A,E3200,6,Unknown 3C.BD.C5.F1.11.50:3C.BD.C5.F1.E1.E2,E3200,6,123042100000 3C.BD.C5.F1.E1.E8:3C.BD.C5.F4.B3.C2,E3200,6,123042600000 3C.BD.C5.F4.B3.C8:3C.BD.C5.F8.7A.CA,E3200,6,123052000000 3C.BD.C5.F8.7A.D0:3C.BD.C5.F9.F9.FE,E3200,6,123080600000 """.strip().splitlines() # Helper to convert MAC string to integer def mac_to_int(mac):     return int(mac.replace(".", ""), 16) # Helper to extract the last 3 octets as integer def last_3_octets_to_int(mac):     return int(mac.replace(".", "")[-6:], 16) def format_date_from_serial(serial):     if serial.lower() == 'unknown' or not serial.isdigit():         return "Unknown"     try:         year = int(serial[1:3])         month = int(serial[3:5])         day = int(serial[5:7])         # Normalize year         year += 2000 if year < 100 else 0         date = datetime(year, month, day)         return date.strftime("%m-%d-%y")     except Exception:         return "Invalid" def calculate_serial(mac_input):     mac_input_clean = mac_input.upper().replace(":", ".").replace("-", ".")     mac_value = mac_to_int(mac_input_clean)     mac_last = last_3_octets_to_int(mac_input_clean)     for line in mac_data:         mac_range, model, step_str, serial_start = line.split(",")         mac_start_str, mac_end_str = mac_range.split(":")         step = int(step_str)                 mac_start_val = mac_to_int(mac_start_str)         mac_end_val = mac_to_int(mac_end_str)         if mac_start_val <= mac_value <= mac_end_val and serial_start != "Unknown":             mac_start_last = last_3_octets_to_int(mac_start_str)             delta = (mac_last - mac_start_last) // step             calculated_serial = str(int(serial_start) + delta).zfill(12)             date_str = format_date_from_serial(calculated_serial)             return {                 "Given MAC": mac_input_clean,                 "Start MAC": mac_start_str,                 "Calculated Serial": calculated_serial,                 "Model": model,                 "Date": date_str             }     return {"error": "MAC not found in any known range or serial unknown."} # Main loop if __name__ == "__main__":     user_mac = input("Enter a MAC address (e.g., 3C:BD:C5:09:3C:12): ")     result = calculate_serial(user_mac)         if "error" in result:         print(result["error"])     else:         for k, v in result.items():             print(f"{k}: {v}")


Attached Files
.png   B8F853.png (Size: 63.26 KB / Downloads: 153)
.png   Example MACs.png (Size: 291.94 KB / Downloads: 148)
.png   Date Block Example.png (Size: 256.76 KB / Downloads: 146)
Reply
#6
I wanted to mention that I know the posted data set and python code both contain minor errors. 

For the data set: I will be posting a new data set with revalidated data, additional columns, and new entries.
For the python code: I realized since the info in the date blocks is the same, we can output a lot of details about a specific device, including the correct keyspace for a dictionary attack based on MAC. I will also be sharing the various scripts that I’ve discussed once I clean them up a little bit.

For now if anyone can help with the firmware it would be greatly appreciated. Here is a bit more info in that regard.

I found a nice teardown of the device here: https://fccid.io/RAXG3100/Internal-Photo...330446.pdf

Here we see the CPU chip is a BROADCOM BCM43684KRFBG. (product page)
[Image: attachment.php?aid=1245]

From the UART output posted previously we know that it is running AArch64 Linux. Is the sha256 hash value just a check, or something that can be cracked?

Code:
## Loading kernel from FIT Image at 02000000 ...   Using 'conf_lx_VERIZON-G3100' configuration   Verifying Hash Integrity ... OK   Trying 'kernel' kernel subimage     Description:  4.19 kernel     Type:        Kernel Image     Compression:  lzma compressed     Data Start:  0x0228c800     Data Size:    3461392 Bytes = 3.3 MiB     Architecture: AArch64     OS:          Linux     Load Address: 0x00100000     Entry Point:  0x00100000     Hash algo:    sha256     Hash value:  77e40836ec218fa969f9d2bd572115ed9a7ef008cc75bfec4912354ce78a6349   Verifying Hash Integrity ... sha256+ OK

The memory is TOSHIBA TH58NVG3S0HTA10 (data sheet). It looks like there test are pads to access the memory. Figuring out the layout, and dump directly from the chip is probably a bit above my skillset currently.
[Image: attachment.php?aid=1246]

Part of the UART output posted earlier:

Code:
MEMC DRAM profile (memc_dram_profile_struct) values:   dram_type    = DDR3 ==================================================== PART values:   part_speed_grade    = 1600 CL11   part_size_Mbits    = 4096 (DRAM size in MegaBits)   part_row_bits      = 15 (number of row bits)   part_col_bits      = 10 (number of column bits)   part_ba_bits        = 3 (number of bank bits)   part_width_bits    = 16 (DRAM width in bits) NUMER OF PARTS:   part_num            = 1 (Number of parts) TOTAL values:   total_size_Mbits    = 4096 (DRAM size in MegaBits)   total_cs_bits      = 0 (number of cs bits, for dual_rank mode)   total_width_bits    = 16 (DRAM width in bits)   total_burst_bytes  = 16 (Number of bytes per DRAM access)   total_max_byte_addr = 0x1fffffff (Maximum/last DRAM byte address)                         (Number of bits in total_max_byte_addr is 29)                         (i.e. total_max_byte_addr goes from bit 0 to bit 28)

There are 2 boards inside the device. Each has an obvious UART, however I was only able to get output from 1. Unfortunately I don’t remember the pin layout, but I used a multimeter to find (+) and (-). I think RX/TX were right my first try, otherwise swap them. There is also possibly a JTAG connector, but I don’t have much experience with that.

Bad UART: Board without COAX connector.
[Image: attachment.php?aid=1248]

Good UART: Board with the COAX connector
[Image: attachment.php?aid=1247]

There are several other chips on the boards such as, ZM5101A-CME3, Broadcom B50212E, ERF32, SEC 907(?), MXL3711 which I know very little about.


Attached Files
.png   G3100 Chip.png (Size: 402.8 KB / Downloads: 141)
.png   G3100 Memory.png (Size: 422.62 KB / Downloads: 141)
.png   Good UART.png (Size: 487.98 KB / Downloads: 153)
.png   Bad UART.png (Size: 412.96 KB / Downloads: 153)
Reply
#7
Awesome work but it seems the firmware links are now not respond. You don't by chance have a different source for them do you?
Reply
#8
(04-10-2025, 08:44 PM)textile302 Wrote: Awesome work but it seems the firmware links are now not respond. You don't by chance have a different source for them do you?

Thanks for your interest in this!  Unfortunately I think you need to be on Fios network for the download links to work.  However I have already downloaded all of the linked firmware.  I just sent you a DM with the link.  

Stay tuned... I will post an updated data set and python code sometime this weekend.
Reply
#9
Hey all, it’s the weekend and here is that Python script that I promised!  I worked on calculating the Start/End of the known Date Code blocks in the data set. I had a script to help with the actual calculations, but I did each one individually to oversee how everything was lining up. 

Here’s the code I ended up with, I have named it Fios-F1nDr as a play on their SSID 😀

Code:
import pandas as pd import os from tabulate import tabulate def parse_ref_data(ref_data_lines):     ref_data = []     for line in ref_data_lines:         parts = line.split(',')                 # Ensure parts has enough elements         if len(parts) < 11:             print(f"Skipping line due to insufficient data: {line}")             continue                 ref_data.append({             'MAC_start': parts[0],             'MAC_end': parts[1],             'Serial_start': parts[2],             'Serial_end': parts[3],             'M2HR': parts[4] if parts[4] else "Unknown",             'W_format': int(parts[5]) if parts[5].isdigit() else None,             'W_len': int(parts[6]) if parts[6].isdigit() else None,             'A_format': int(parts[7]) if parts[7].isdigit() else None,             'A_len': int(parts[8]) if parts[8].isdigit() else None,             'Date': parts[9] if len(parts) > 9 else '',             'HW': parts[10] if len(parts) > 10 else '',             'Model': parts[11] if len(parts) > 11 else ''         })     return ref_data def mac_to_hex(mac):     # Strip separators and convert to lowercase     mac = mac.replace(':', '').replace('.', '').lower()     return int(mac[-6:], 16) def process_single_mac(mac, ref_data):     # Strip separators and convert to lowercase     mac_cleaned = mac.replace(':', '').replace('.', '').replace('-', '').lower()         # Check for valid prefix     valid_prefixes = ["04a222", "b8f853", "3cbdc5", "dcf51b"]     if mac_cleaned[:6] not in valid_prefixes:         return {"Model": "Unknown Device", "Calculated Serial": "Unknown Device"}     # Skip calculation for DCF51B prefix     if mac_cleaned[:6] == "dcf51b":         return {"Calculated Serial": "Not enough data", "Model": "E3200", "HW": 1104,                 "W_format": 2, "W_len": "15", "A_format": 2, "A_len": 9}                 # Find the relevant block     for block in ref_data:         mac_start_cleaned = block['MAC_start'].replace(':', '').replace('.', '').replace('-', '').lower()         mac_end_cleaned = block['MAC_end'].replace(':', '').replace('.', '').replace('-', '').lower()                       # Compare cleaned MAC addresses         if mac_start_cleaned <= mac_cleaned <= mac_end_cleaned:             if block['Serial_start'] == "Unknown Block":                 return {"Calculated Serial": "Unknown Block", "Model": block['Model'], "Hardware": block['HW'],                         "W_format": block['W_format'], "W_len": block['W_len'], "A_format": block['A_format'], "A_len": block['A_len']}                                   # Skip calculation if M2HR is unknown             if block['M2HR'] == "Unknown":                 return {"Calculated Serial": "Unknown", "M2HR": "Unknown", "Model": block['Model'], "HW": block['HW'],                         "W_format": block['W_format'], "W_len": block['W_len'], "A_format": block['A_format'], "A_len": block['A_len']}                         # Calculate Serial             serial_prefix = block['Serial_start'][0]             serial_start_cleaned = block['Serial_start'][1:]                         mac_dec = mac_to_hex(mac)             mac_start_dec = mac_to_hex(block['MAC_start'])             serial_difference = (mac_dec - mac_start_dec) / int(block['M2HR'])             calculated_serial = serial_prefix + str(int(serial_start_cleaned) + serial_difference)             calculated_serial = calculated_serial[:16]                         return {"MAC_start": block['MAC_start'], "MAC_end": block['MAC_end'], "M2HR": block['M2HR'], "Calculated Serial": calculated_serial,                     "W_format": block['W_format'], "W_len": block['W_len'], "A_format": block['A_format'], "A_len": block['A_len'],                     "Model": block['Model'], "Date": block['Date'], "HW": block['HW']}         return {"Model": "Unknown Device", "Calculated Serial": "Unknown Device"} def process_csv_file(file_path, ref_data, save_location):     # Read the CSV file containing MAC addresses     df = pd.read_csv(file_path)     # Define the column titles for the output CSV     columns = ["MAC_input", "MAC_start", "MAC_end", "M2HR", "Calculated Serial", "W_format", "W_len", "A_format", "A_len", "Model", "Date Code (YYMMDD)", "HW"]     # Prepare a list to hold results     results = []     # Process each MAC address     for mac in df:         result = process_single_mac(mac.strip(), ref_data)  # Ensure whitespace is stripped         result['MAC'] = mac  # Include the original MAC address         # Format W_len and A_len using format_description         W_format = format_description(result.get("W_format", ""), is_wifi=True)         A_format = format_description(result.get("A_format", ""), is_wifi=False)                 # Append the values in the order of the defined columns         results.append([             result.get("MAC", ""),             result.get("MAC_start", ""),             result.get("MAC_end", ""),             result.get("M2HR", ""),             result.get("Calculated Serial", ""),             W_format,             result.get("W_len", ""),             A_format,             result.get("A_len", ""),             result.get("Model", ""),             result.get("Date", ""),             result.get("HW", "")         ])     # Convert results to DataFrame     results_df = pd.DataFrame(results, columns=columns)         # Save the DataFrame to a CSV file     results_df.to_csv(save_location, index=False)     print(str(len(results_df)) + " MACs proccessed, saved to " + save_location) def format_description(format_type, is_wifi=True):     if is_wifi:         return "wnwnw" if format_type == 1 else "w?-w?-w? " if format_type == 2 else ""     else:         return "wnw" if format_type == 1 else "<A-Z><0-9>" if format_type == 2 else "" def print_formatted_table(result):         print("                      Fios-F1NdR")     # Organize the data into a table     table_data = [         ["MAC Input", result.get("MAC", "")],         ["MAC Block Start", result.get("MAC_start", "")],         ["MAC Block End", result.get("MAC_end", "")],         ["MAC 2 Hex Ratio", result.get("M2HR", "")],         ["Calculated Serial", result.get("Calculated Serial", "")],         ["Keyspace", "w = <word>  n = <number>\n? = single digit at end of random word"],         ["WiFi Pass Format", format_description(result.get("W_format", ""), is_wifi=True)],         ["WiFi Pass Length", result.get("W_len", "")],         ["Admin Pass Format", format_description(result.get("A_format", ""), is_wifi=False)],         ["Admin Pass Length", result.get("A_len", "")],         ["Model Type", result.get("Model", "")],         ["Date Code (YYMMDD)", result.get("Date", "")],         ["Hardware", result.get("HW", "")]     ]     formatted_table = tabulate(table_data, tablefmt="grid")     print(formatted_table)     def main():     ref_data_lines = [ "04.A2.22.00.00.00,04.A2.22.AE.B8.7E,0,0,Unknown,1,0,1,0,0,0,Unknown", "04.A2.22.AE.B8.89,04.A2.22.BA.30.A2,G401119042900000,G401119042968331,11,1,16,1,16,190429,1102,G3100", "04.A2.22.BA.30.A6,04.A2.22.C3.3A.BB,G401119061100000,G401119061153855,11,1,16,1,16,190611,1103,G3100", "04.A2.22.C3.3A.C6,04.A2.22.CB.A8.3C,G401119061800000,G401119061850210,11,1,16,1,16,190618,1103,G3100", "04.A2.22.CB.5B.F0,04.A2.22.CB.5B.F2,E301119062000000,0,Unknown,1,16,1,16,190620,1102,E3200", "04.A2.22.CB.E9.6C,04.A2.22.DB.74.3E,G401119062600000,G40111906292598,11,1,16,1,16,190626,1103,G3100", "04.A2.22.D3.FF.3A,04.A2.22.DC.D2.DE,G401119071600000,G401119071652588,11,1,16,1,16,190716,1103,G3100", "04.A2.22.DC.D2.E0,04.A2.22.DC.D2.E2,E301119072900000,0,Unknown,1,16,1,16,190729,1102,E3200", "04.A2.22.DF.45.32,04.A2.22.DF.45.34,E301119073010000,0,Unknown,1,16,1,16,190730,1102,E3200", "04.A2.22.DF.DB.E0,04.A2.22.DF.DB.E2,E301119073000000,0,Unknown,1,16,1,16,190730,1102,E3200", "04.A2.22.E1.1D.12,04.A2.22.EA.27.27,G401119081000000,G401119081053855,11,1,16,1,16,190810,1103,G3100", "04.A2.22.E2.B5.72,04.A2.22.E5.5E.A1,G401119073100000,G401119073115853,11,1,16,1,16,190731,1103,G3100", "04.A2.22.E5.5E.A2,04.A2.22.F3.31.E2,G401119081300000,G401119081382368,11,1,16,1,16,190813,1103,G3100", "04.A2.22.F3.31.E2,04.A2.22.F8.0B.14,G401119082300000,G401119082328886,11,1,16,1,16,190823,1103,G3100", "04.A2.22.F8.0B.1F,04.A2.22.F8.3E.DB,G401119081300000,G401119081396619,0.000115284648277019,1,16,1,16,190813,1103,G3100", "04.A2.22.F8.3E.DC,04.A2.22.FA.2B.90,0,0,Unknown,1,0,1,0,0,0,Unknown", "04.A2.22.FA.2B.9A,04.A2.22.FB.F4.BF,G401119092000000,G401119092010639,11,1,16,1,16,190920,1103,G3100", "04.A2.22.FB.F4.CA,04.A2.22.FF.FF.FF,0,0,Unknown,1,0,1,0,0,0,Unknown", "B8.F8.53.00.00.00,B8.F8.53.02.AD.9B,0,0,Unknown,1,0,,0,0,0,Unknown", "B8.F8.53.02.8D.41,B8.F8.53.05.93.61,G401119092620000,G401119092638016,11,1,16,1,16,190926,1103,G3100", "B8.F8.53.05.93.61,B8.F8.53.07.27.6A,G401119101100000,G401119101109403,11,1,16,1,16,191011,1103,G3100", "B8.F8.53.07.27.75,B8.F8.53.08.BF.CA,G401119101400000,G401119101409503,11,1,16,1,16,191014,1103,G3100", "B8.F8.53.08.BF.D5,B8.F8.53.09.CF.B2,G401119101600000,G401119101606327,11,1,16,1,16,191016,1103,G3100", "B8.F8.53.09.D0.15,B8.F8.53.0A.B2.DF,G401119101700000,G401119101705278,11,1,16,1,16,191017,1103,G3100", "B8.F8.53.0A.B2.D6,B8.F8.53.0A.E0.54,0,0,Unknown,1,0,1,0,0,0,Unknown", "B8.F8.53.0A.E0.55,B8.F8.53.0B.49.17,G401119101800000,G401119101802438,11,1,16,1,16,191018,1103,G3100", "B8.F8.53.0B.49.0E,B8.F8.53.1C.67.5C,0,0,Unknown,1,0,1,0,0,0,Unknown", "B8.F8.53.1C.67.5D,B8.F8.53.20.20.3D,G401119111200000,G401119111222176,11,1,16,1,16,191112,1103,G3100", "B8.F8.53.20.20.3D,B8.F8.53.24.7C.D3,G401119110800000,G401119110825986,11,1,16,1,16,191108,1104,G3100", "B8.F8.53.25.5A.AF,B8.F8.53.25.5A.BB,E301119111100000,0,Unknown,1,16,1,16,191111,1102,E3200", "B8.F8.53.25.C1.09,B8.F8.53.28.DC.42,G401119111500000,G401119111518507,11,1,16,1,16,191115,1103,G3100", "B8.F8.53.28.DC.49,B8.F8.53.2C.FC.75,G401119120200000,G401119120224580,11,1,16,1,16,191202,1103,G3100", "B8.F8.53.2C.FC.75,B8.F8.53.2F.1D.C6,G401119120500000,G401119120512691,11,1,16,1,16,191205,1103,G3100", "B8.F8.53.2F.1D.CD,B8.F8.53.34.F7.22,G401119120700000,G401119120734848,11,1,16,1,16,191207,1103,G3100", "B8.F8.53.34.F7.2D,B8.F8.53.35.B1.B4,G401119121700000,G401119121704341,11,1,16,1,16,191217,1103,G3100", "B8.F8.53.35.B1.BD,B8.F8.53.3B.0B.27,G401119120900000,G401119120931870,11,1,16,1,16,191209,1103,G3100", "B8.F8.53.3B.0B.31,B8.F8.53.3C.A3.86,G401120010700000,G401120010709503,11,1,16,1,16,200107,1103,G3100", "B8.F8.53.3C.A3.8B,B8.F8.53.3E.3B.EB,G401120010900000,G401120010909504,11,1,16,1,16,200109,1103,G3100", "B8.F8.53.3E.3B.F1,B8.F8.53.40.1F.62,G401120011000000,G401120011011251,11,1,16,1,16,200110,1103,G3100", "B8.F8.53.40.1F.65,B8.F8.53.43.05.09,G401120011300000,G401120011317260,11,1,16,1,16,200113,1103,G3100", "B8.F8.53.43.05.11,B8.F8.53.44.90.98,G401120011600000,G401120011609205,11,1,16,1,16,200116,1103,G3100", "B8.F8.53.44.90.9F,B8.F8.53.4C.AE.CE,G401120010200000,G401120010248365,11,1,16,1,16,200102,1103,G3100", "B8.F8.53.4C.AE.D6,B8.F8.53.51.F0.93,G402120021000000,0,Unknown,1,16,1,16,200210,1104,G3100", "B8.F8.53.51.B9.01,B8.F8.53.51.F7.F2,G402120022400000,0,Unknown,1,16,1,16,200224,1104,G3100", "B8.F8.53.52.19.01,B8.F8.53.52.9E.82,G402120022500000,0,Unknown,1,16,1,16,200225,1104,G3100", "B8.F8.53.52.E2.01,B8.F8.53.52.F7.12,G402120022600000,0,Unknown,1,16,1,16,200226,1104,G3100", "B8.F8.53.54.6E.01,B8.F8.53.54.B6.FA,G402120022900000,0,Unknown,1,16,1,16,200229,1104,G3100", "B8.F8.53.55.34.01,B8.F8.53.55.58.52,G402120030300000,0,Unknown,1,16,1,16,200303,1104,G3100", "B8.F8.53.57.8C.41,B8.F8.53.57.D8.C2,G402120031000000,0,Unknown,1,15,1,16,200310,1104,G3100", "B8.F8.53.59.7B.41,B8.F8.53.59.87.62,G402120031300000,0,Unknown,1,16,1,16,200313,1104,G3100", "B8.F8.53.5A.41.41,B8.F8.53.5A.8A.C0,G402120031400000,0,Unknown,1,16,1,16,200314,1004,G3100", "B8.F8.53.5B.CD.41,B8.F8.53.5F.4B.89,G402120031800000,G402120031828617,8,1,15,1,16,200318,1104,G3100", "B8.F8.53.5F.4B.90,B8.F8.53.60.11.88,G402120040800000,G402120040806335,8,1,15,1,16,200408,1104,G3100", "B8.F8.53.60.11.90,B8.F8.53.62.00.88,G402120040900000,G402120040915839,8,1,15,1,16,200409,1104,G3100", "B8.F8.53.62.00.90,B8.F8.53.62.C6.88,G402120041200000,G402120041206335,8,1,15,1,16,200412,1104,G3100", "B8.F8.53.62.C6.90,B8.F8.53.67.0D.C8,G402120032500000,G402120032535047,8,1,15,1,16,200325,1104,G3100", "B8.F8.53.67.0D.D0,B8.F8.53.67.D3.C8,G402120050600000,G402120050606336,8,1,15,1,16,200506,1104,G3100", "B8.F8.53.67.D3.D0,B8.F8.53.69.5F.C8,G402120050800000,G402120050812671,8,1,15,1,16,200508,1104,G3100", "B8.F8.53.68.99.D0,B8.F8.53.68.B8.B1,G402120050900000,G402120050900989,8,1,15,1,16,200509,1104,G3100", "B8.F8.53.69.5F.D0,B8.F8.53.6D.80.88,G402120051100000,G402120051133816,8,1,15,1,16,200511,1104,G3100", "B8.F8.53.6D.80.90,B8.F8.53.70.35.88,G402120060600000,G402120060622176,8,1,15,1,16,200606,1104,G3100", "B8.F8.53.70.35.90,B8.F8.53.72.0F.59,G402120052600000,G402120052634649,8,1,15,1,16,200526,1104,G3100", "B8.F8.53.73.AA.58,B8.F8.53.73.B9.F9,G402120070200000,G402120070200501,8,1,15,1,16,200702,1104,G3100", "B8.F8.53.74.70.58,B8.F8.53.75.36.50,G402120070300000,G402120070306335,8,1,15,1,16,200703,1104,G3100", "B8.F8.53.75.36.58,B8.F8.53.77.52.70,G402120070500000,G402120070517284,8,1,15,1,16,200705,1104,G3100", "B8.F8.53.77.52.78,B8.F8.53.7D.EB.B0,G402120062600000,G402120062654056,8,1,15,1,16,200626,1104,G3100", "B8.F8.53.7D.EB.B8,B8.F8.53.7F.14.B0,G402120072300000,G402120072309503,8,1,15,1,16,200723,1104,G3100", "B8.F8.53.7F.14.B8,B8.F8.53.85.C5.38,G402120071800000,G402120071854800,8,1,15,1,16,200718,1104,G3100", "B8.F8.53.85.C5.40,B8.F8.53.8B.AB.A8,G402120081100000,G402120081148333,8,1,15,1,16,200811,1104,G3100", "B8.F8.53.8B.AB.B0,B8.F8.53.95.FB.A8,G402120081200000,G402120081284479,8,1,15,1,16,200812,1104,G3100", "B8.F8.53.95.FB.B0,B8.F8.53.9E.AF.28,G402120082000000,G402120082071279,8,1,15,1,16,200820,1104,G3100", "B8.F8.53.9E.AF.32,B8.F8.53.A0.F4.30,E302120082400000,E302120082424789,6,1,15,1,16,200824,1103,E3200", "B8.F8.53.A0.F4.34,B8.F8.53.A1.62.2C,G402120082800000,G402120082803519,8,1,15,1,16,200828,1104,G3100", "B8.F8.53.A1.62.34,B8.F8.53.AA.85.1C,G402120083000000,G402120083074845,8,1,15,1,16,200830,1104,G3100", "B8.F8.53.AA.85.1E,B8.F8.53.AD.F8.DA,E302120090800000,E302120090837706,6,1,15,1,16,200908,1103,E3200", "B8.F8.53.AD.F8.DC,B8.F8.53.B6.85.24,G402120091500000,G402120091570025,8,1,15,1,16,200915,1104,G3100", "B8.F8.53.B6.85.26,B8.F8.53.B7.01.8E,E302120091500000,E302120091505308,6,1,15,1,16,200915,1103,E3200", "B8.F8.53.B7.01.8F,B8.F8.53.B7.98.C3,0,0,Unknown,1,0,1,0,0,0,Unknown", "B8.F8.53.B7.98.C4,B8.F8.53.B8.06.BC,G402120101500000,G402120101503519,8,1,15,1,16,201015,1104,G3100", "B8.F8.53.B8.06.C4,B8.F8.53.BB.08.BC,G402120101600000,G402120101624639,8,1,15,1,16,201016,1104,G3100", "B8.F8.53.BB.08.C4,B8.F8.53.BB.76.BC,G402120101800000,G402120101803519,8,1,15,1,16,201018,1104,G3100", "B8.F8.53.BB.76.C4,B8.F8.53.C0.9E.BC,G402120101900000,G402120101942240,8,1,15,1,16,201019,1104,G3100", "B8.F8.53.C0.9E.C4,B8.F8.53.C2.56.C4,G402120102400000,G402120102414080,8,1,15,1,16,201024,1104,G3100", "B8.F8.53.C2.56.C4,B8.F8.53.C5.D1.1C,G402120102500000,G402120102528491,8,1,15,1,16,201025,1104,G3100", "B8.F8.53.C5.D1.20,B8.F8.53.CD.91.D0,G402120100700000,G402120100763510,8,1,15,1,16,201007,1104,G3100", "B8.F8.53.CD.91.D2,B8.F8.53.CE.C3.5A,E302120100700000,0,6,1,15,1,16,201007,1103,E3200", "B8.F8.53.CE.C3.60,B8.F8.53.B7.98.BE,0,0,Unknown,1,0,1,0,0,0,Unknown", "B8.F8.53.CE.D4.C8,B8.F8.53.D3.58.68,G402120101300000,G402120101336980,8,1,15,1,16,201013,1104,G3100", "B8.F8.53.D3.58.6A,B8.F8.53.D5.EC.64,E302120101500000,E302120101528159,6,1,15,1,16,201015,1103,E3200", "B8.F8.53.D5.EC.68,B8.F8.53.D7.36.60,G402120111200000,G402120111210559,8,1,15,1,16,201112,1104,G3100", "B8.F8.53.D7.36.68,B8.F8.53.DA.38.60,G402120111300000,G402120111324640,8,1,15,1,16,201113,1104,G3100", "B8.F8.53.DA.38.68,B8.F8.53.DC.01.D0,G402120111700000,G402120111714637,8,1,15,1,16,201117,1104,G3100", "B8.F8.53.DC.01.D2,B8.F8.53.DC.6F.CA,E302120111300000,E302120111304693,6,1,15,1,16,201113,1103,E3200", "B8.F8.53.DC.6F.D0,B8.F8.53.E3.C6.D8,G402120111300000,G402120111360129,8,1,15,1,16,201113,1104,G3100", "B8.F8.53.E3.C6.E0,B8.F8.53.EB.14.D8,G402120120200000,G402120120259839,8,1,15,1,16,201202,1104,G3100", "B8.F8.53.EB.14.E0,B8.F8.53.F3.08.C8,G402120121000000,G402120121065150,8,1,15,1,16,201210,1104,G3100", "B8.F8.53.F3.08.D0,B8.F8.53.F8.30.C8,G402120122300000,G402120122342240,8,1,15,1,16,201223,1104,G3100", "B8.F8.53.F8.30.D0,B8.F8.53.FA.C4.C8,G402121011800000,G402121011821120,8,1,15,1,16,210118,1104,G3100", "B8.F8.53.FA.C4.D0,B8.F8.53.FF.BF.F8,G402121010600000,G402121010640805,8,1,15,1,16,210106,1104,G3100", "B8.F8.53.FF.BF.F9,B8.F8.53.FF.FF.FF,0,0,Unknown,1,0,1,0,0,0,Unknown", "3C.BD.C5.00.00.00,3C.BD.C5.01.25.57,0,0,Unknown,1,0,1,0,0,0,Unknown", "3C.BD.C5.01.25.58,3C.BD.C5.01.F5.78,G402121011510000,G402121011516660,8,1,15,1,16,210115,1104,G3100", "3C.BD.C5.09.3B.F8,3C.BD.C5.0B.B4.78,G402121030100000,G402121030120240,8,1,15,1,16,210301,1104,G3100", "3C.BD.C5.0B.B4.7A,3C.BD.C5.0B.BC.FD,E302121030300000,E302121030300364,6,1,15,1,16,210303,1103,E3200", "3C.BD.C5.0C.30.38,3C.BD.C5.16.4A.C0,G402121021700000,G402121021782769,8,1,15,1,16,210217,1104,G3100", "3C.BD.C5.16.4A.C8,3C.BD.C5.22.55.E0,G402121031200000,G402121031298659,8,1,15,1,16,210312,1104,G3100", "3C.BD.C5.1E.E5.EA,3C.BD.C5.22.55.E6,E302121031200000,E302121031237546,6,1,15,1,16,210312,1103,E3200", "3C.BD.C5.22.55.E8,3C.Bd.C5.2B.5B.E0,G402121033100000,G402121033173919,8,1,15,1,16,210331,1104,G3100", "3C.BD.C5.2B.5B.E8,3C.BD.C5.31.1E.68,G402121041400000,G402121041447184,8,1,15,1,16,210414,1104,G3100", "3C.BD.C5.31.1E.69,3C.BD.C5.35.36.88,0,0,Unknown,1,0,1,0,0,0,Unknown", "3C.BD.C5.35.36.90,3C.BD.C5.3C.6B.58,G402121051500000,G402121051559033,8,1,15,1,16,210515,1104,G3100", "3C.BD.C5.3C.6B.59,3C.BD.C5.37.5C.88,0,0,Unknown,1,0,1,0,0,0,Unknown", "3C.BD.C5.37.5C.90,3C.BD.C5.3D.D3.38,G402121051800000,G402121051852950,8,1,15,1,16,210518,1104,G3100", "3C.BD.C5.3D.D3.40,3C.BD.C5.42.27.40,G402121060700000,G402121060735456,8,1,15,1,16,210607,1104,G3100", "3C.BD.C5.42.27.4C,3C.BD.C5.46.3E.C4,G402121062200000,G402121062233519,8,1,15,1,16,210622,1104,G3100", "3C.BD.C5.46.3E.CC,3C.BD.C5.47.F6.C4,G402121071300000,G402121071314079,8,1,15,1,16,210713,1104,G3100", "3C.BD.C5.47.F6.CC,3C.BD.C5.49.AE.C4,G402121072100000,G402121072114079,8,1,15,1,16,210721,1104,G3100", "3C.BD.C5.49.AE.CC,3C.BD.C5.50.05.4C,G402121070100000,G402121070151920,8,1,15,1,16,210701,1104,G3100", "3C.BD.C5.50.05.4C,3C.BD.C5.57.37.CC,G402121072000000,G402121072058960,8,2,15,2,9,210720,1104,G3100", "3C.BD.C5.57.37.CE,3C.BD.C5.59.22.C0,E302121072000000,E302121072020947,6,2,15,2,9,210720,1103,E3200", "3C.BD.C5.59.24.74,3C.BD.C5.60.3B.6C,G402121080200000,G402121080258079,8,2,15,2,9,210802,1104,G3100", "3C.BD.C5.60.3B.74,3C.BD.C5.67.20.6C,G402121081100000,G402121081156479,8,2,15,2,9,210811,1104,G3100", "3C.BD.C5.67.20.74,3C.BD.C5.69.B8.CC,G402121081160000,G402121081181259,8,2,15,2,9,210811,1104,G3100", "3C.BD.C5.69.B8.D4,3C.BD.C5.71.07.FC,G402121082000000,G402121082059877,8,2,15,2,9,210820,1104,G3100", "3C.BD.C5.71.08.00,3C.BD.C5.76.8D.C8,G402121082600000,G402121082645241,8,2,15,2,9,210826,1104,G3100", "3C.BD.C5.76.8D.CD,3C.BD.C5.7D.27.A5,G402121090800000,G402121090854075,8,2,15,2,9,210908,1104,G3100", "3C.BD.C5.7D.27.A6,3C.BD.C5.83.03.C6,0,0,Unknown,2,0,2,0,0,0,Unknown", "3C.BD.C5.7E.9C.4C,3C.BD.C5.83.03.CC,G402121091600000,G402121091636080,8,2,15,2,9,210916,1104,G3100", "3C.BD.C5.83.03.CE,3C.BD.C5.85.4C.A4,E302121091600000,E302121091624953,6,2,15,2,9,210916,1103,E3200", "3C.BD.C5.85.4C.AA,3C.BD.C5.8C.CB.CB,0,0,Unknown,2,0,2,0,0,0,Unknown", "3C.BD.C5.8C.CB.CC,3C.BD.C5.93.FF.94,G402121101500000,G402121101559001,8,2,15,2,9,211015,1104,G3100", "3C.BD.C5.93.FF.9C,3C.BD.C5.9B.67.71,0,0,Unknown,2,0,2,0,0,0,Unknown", "3C.BD.C5.9B.67.72,3C.BD.C5.A1.71.B2,G402121110500000,G402121110549480,8,2,15,2,9,211105,1104,G3100", "3C.BD.C5.A1.71.B4,3C.BD.C5.A3.FE.22,E302121110500000,E302121110527837,6,2,15,2,9,211105,1103,E3200", "3C.BD.C5.A3.FE.28,3C.BD.C5.AD.16.63,0,0,Unknown,2,0,2,0,0,0,Unknown", "3C.BD.C5.AD.16.64,3C.BD.C5.AE.AE.34,E302122010100000,E30212201017400,6,2,15,2,9,220101,1103,E3200", "3C.BD.C5.AE.AE.34,3C.BD.C5.B4.2D.5E,E302121122100000,E302121122160039,6,2,15,2,9,211221,1103,E3200", "3C.BD.C5.B4.2D.62,3C.BD.C5.B5.09.9A,G402122021400000,G402122021407047,8,2,15,2,9,220214,1104,G3100", "3C.BD.C5.B5.09.A2,3C.BD.C5.B5.E5.9A,G402122031000000,G402122031007039,8,2,15,2,9,220310,1104,G3100", "3C.BD.C5.B5.E5.A2,3C.BD.C5.B8.0B.9A,G402122031100000,G402122031117599,8,2,15,2,9,220311,1104,G3100", "3C.BD.C5.B8.0B.A2,3C.BD.C5.C1.ED.A2,G402122031500000,G402122031580960,8,2,15,2,9,220315,1104,G3100", "3C.BD.C5.C1.ED.A4,3C.BD.C5.C2.40.1E,E302122031300000,E302122031303519,6,2,15,2,9,220313,1103,E3200", "3C.BD.C5.C2.40.24,3C.BD.C5.C2.89.E6,E302122031400000,E302122031403147,6,2,15,2,9,220314,1103,E3200", "3C.BD.C5.C2.89.EC,3C.BD.C5.CD.A1.19,0,0,Unknown,2,0,2,0,0,0,Unknown", "3C.BD.C5.CD.A1.20,3C.BD.C5.CF.39.86,E302122052200000,E302122052217426,6,2,15,2,9,220522,1103,E3200", "3C.BD.C5.CF.39.8C,3C.BD.C5.D2.C8.06,E302122091400000,E302122091438847,6,2,15,2,9,220914,1103,E3200", "3C.BD.C5.D2.C8.0C,3C.BD.C5.DA.E1.12,E302122091500000,E302122091588450,6,2,15,2,9,220915,1103,E3200", "3C.BD.C5.DA.E1.18,3C.BD.C5.DD.EE.86,E302122110900000,E302122110933341,6,2,15,2,9,221109,1103,E3200", "3C.BD.C5.DD.EE.8C,3C.BD.C5.E5.83.97,0,0,Unknown,2,0,2,0,0,0,Unknown", "3C.BD.C5.E5.83.98,3C.BD.C5.E8.34.8A,E302123011000000,E302123011029396,6,2,15,2,9,230110,1103,E3200", "3C.BD.C5.E8.34.90,3C.BD.C5.F1.11.4A,E302123030400000,E302123030496800,6,2,15,2,9,230304,1103,E3200", "3C.BD.C5.F1.11.50,3C.BD.C5.F1.E1.E2,E302123042100000,E302123042108899,6,2,15,2,9,230421,1103,E3200", "3C.BD.C5.F1.E1.E8,3C.BD.C5.F4.B3.C2,E302123042600000,E302123042630800,6,2,15,2,9,230426,1103,E3200", "3C.BD.C5.F4.B3.C8,3C.BD.C5.F8.7A.CA,E302123052000000,E302123052041260,6,2,15,2,9,230520,1103,E3200", "3C.BD.C5.F8.7A.D0,3C.BD.C5.F8.A3.63,E302123080600000,E302123080601732,6,2,15,2,9,230806,1103,E3200", "3C.BD.C5.F8.A3.64,3C.BD.C5.FF.FF.FF,0,0,Unknown,2,0,2,0,0,0,Unknown", "DC.F5.1B.5F.EA.4F,DC.F5.1B.64.2B.10,Unknown,Unknown,0,2,16,2,9,223550,1103,Unknown", "DC.F5.1B.64.2B.1A,DC.F5.1B.64.34.D5,E302123103100000,0,6,2,15,2,9,231031,1103,E3200", "DC.F5.1B.64.54.5A,DC.F5.1B.64.57.B5,E302123110200000,0,6,2,15,2,9,231102,1103,E3200", "DC.F5.1B.67.F4.7A,DC.F5.1B.68.6F.Ff,E302123113000000,0,6,2,15,2,9,231130,1103,E3200", "DC.F5.1B.5D.64.60,DC.F5.1B.60.14.57,AA63332935300000,0,6,2,15,2,9,329353,1103,Unknown",     ]         ref_data = parse_ref_data(ref_data_lines)         user_input = input("Enter one or more MAC addresses (comma-separated) or the path to a.csv file: ")         if user_input.lower().endswith('.csv'):         while not os.path.isfile(user_input) or not user_input.lower().endswith('.csv'):             user_input = input("Please enter a valid.csv file path: ")                 save_location = input("Enter the save location for the output.csv file: ")         process_csv_file(user_input, ref_data, save_location)     else:         mac_addresses = user_input.split(',')         for mac in mac_addresses:             mac = mac.strip()  # Remove any leading/trailing whitespace             result = process_single_mac(mac, ref_data)             result['MAC'] = mac  # Include the original MAC address             # Print the result in a formatted table             print_formatted_table(result)         if __name__ == "__main__":     main()

Output:
Code:
                      Fios-F1NdR +--------------------+----------------------------------------+ | MAC Input          | B8.F8.53.E2.EC.60                      | +--------------------+----------------------------------------+ | MAC Block Start    | B8.F8.53.DC.6F.D0                      | +--------------------+----------------------------------------+ | MAC Block End      | B8.F8.53.E3.C6.D8                      | +--------------------+----------------------------------------+ | MAC 2 Hex Ratio    | 8                                      | +--------------------+----------------------------------------+ | Calculated Serial  | G402120111353138                      | +--------------------+----------------------------------------+ | Keyspace          | w = <word>  n = <number>              | |                    | ? = single digit at end of random word | +--------------------+----------------------------------------+ | WiFi Pass Format  | wnwnw                                  | +--------------------+----------------------------------------+ | WiFi Pass Length  | 15                                    | +--------------------+----------------------------------------+ | Admin Pass Format  | wnw                                    | +--------------------+----------------------------------------+ | Admin Pass Length  | 16                                    | +--------------------+----------------------------------------+ | Model Type        | G3100                                  | +--------------------+----------------------------------------+ | Date Code (YYMMDD) | 201113                                | +--------------------+----------------------------------------+ | Hardware          | 1104                                  | +--------------------+----------------------------------------+

Using the script is pretty simple, just run it! The script will prompt you to "Enter one or more MAC addresses (comma-separated) or the path to a.csv file:”. As it says, it will accept a variety of inputs. You can type a single MAC address, a few MACs separated by a comma, or feed it a list of MACs from a comma separated .csv file. The script strips out the characters . - : so it will accept a variety of formats. If you give it a .csv file, it will prompt you for a save path, which will be something like "/path/fiender.csv”. The script will then use “ref_data_lines” as the data to calculate the information. Everything should be human readable and commented, but let me know if you have any questions. For future updates I will only post the new ref_data_lines because that should be all that needs changed.

Once I had the data and the script, I collected 25 new entries for the data base and checked them against the script. How did we do? OOF, only 36% of the new entries were calculated correctly. At least the correct hits show that we’re on the right path...  

Correct = 9 (36%) 
Incorrect = 10 (40%)
Unknown Block = 4 (16%)
Unknown Device = 1 (4%) 
Not Enough data = 1 (4%)  

This actually isn’t a bad thing though, the script is making some assumptions about each MAC block, and these entries provide us with new date codes. After working the new entries into the data, we test the script again. Much better, with 80% of the hits correct. The ones we’re missing are because we don’t have enough information to calculate the block space just yet. Sometimes just a single entry can remove a bunch of the unknown, which means that continuing to collect data will continue to improve the script. The good news is that this only really pertains to calculating the correct Serial Number, which doesn’t matter much at this point without a keygen algorithm. The script will still output everything we know, including the Password Keyspace as this info doesn’t actually change too much across devices. I will keep track of these stats as I continue to update the data base to see how close we’re getting to finding all of the blocks. Although we don’t have the algorithm, all we need to do is drop it into the script and we have a complete recovery tool!  

Correct = 20 (80%)
Incorrect = 0 (0%)
Unknown Block = 4 (16%)
Unknown Device = 0 (0%)
Not Enough data = 1 (4%)

Some other fun stats:
We have discovered 145 unique date codes.  Here the date codes and the # of devices currently believed to be in each block.  On average, a block contains 29336 devices, so a usually high number of devices could indicate that there is at least 1 missing date code.  0 devices means that we don’t know enough about that block yet.  Current calculations predict ~4165721 devices total.

Code:
190429 68331 190611 53855 190618 50210 190620 0 190626 92598 190716 52588 190729 0 190730 0 190730 0 190810 53855 190731 15853 190813 82368 190823 28886 190813 96619 190920 10639 190926 38016 191011 09403 191014 09503 191016 06327 191017 05278 191018 02438 191112 22176 191108 25986 191111 0 191115 18507 191202 24580 191205 12691 191207 34848 191217 04341 191209 31870 200107 09503 200109 09504 200110 11251 200113 17260 200116 09205 200102 48365 200210 0 200224 0 200225 0 200226 0 200229 0 200303 0 200310 0 200313 0 200314 0 200318 28617 200408 06335 200409 15839 200412 06335 200325 35047 200506 06336 200508 12671 200509 00989 200511 33816 200606 22176 200526 34649 200702 00501 200703 06335 200705 17284 200626 54056 200723 09503 200718 54800 200811 48333 200812 84479 200820 71279 200824 24789 200828 03519 200830 74845 200908 37706 200915 70025 200915 05308 201015 03519 201016 24639 201018 03519 201019 42240 201024 14080 201025 28491 201007 63510 201007 0 201013 36980 201015 28159 201112 10559 201113 24640 201117 14637 201113 04693 201113 60129 201202 59839 201210 65150 201223 42240 210118 21120 210106 40805 210115 16660 210301 20240 210303 00364 210217 82769 210312 98659 210312 37546 210331 73919 210414 47184 210515 59033 210518 52950 210607 35456 210622 33519 210713 14079 210721 14079 210701 51920 210720 58960 210720 20947 210802 58079 210811 56479 210811 81259 210820 59877 210826 45241 210908 54075 210916 36080 210916 24953 211015 59001 211105 49480 211105 27837 220101 17400 211221 60039 220214 07047 220310 07039 220311 17599 220315 80960 220313 03519 220314 03147 220522 17426 220914 38847 220915 88450 221109 33341 230110 29396 230304 96800 230421 08899 230426 30800 230520 41260 230806 01732 223550 0 231031 0 231102 0 231130 0 329353 0
Reply
#10
I am happy to say I have added another 59 entries to the dataset, which added to the 25 that I collected in the previous post brings us to 84 new entries!  I was hoping for 100, but that is close enough for me.  There are now 313 complete entries.  

Dataset:  
.xlsx   g3100_E3200_04_16_24.xlsx (Size: 331.59 KB / Downloads: 3)
Reference Images: Ref_images.zip

Let’s see what we’ve learned...

First, we test the new entries against the Fios-F1nDr database.  We test 58 entries, since 1 was actually missing the serial.  Again it doesn’t look good at first, but all it really means is that we’ve collected a bunch of new Date Codes!  After working all of the new entries into the proper place and recalculating everything, we retest against the updated database.

Before:
Correct - 12  (~20.5%)
Incorrect - 23  (~40.5%)
unknown block - 12  (~20.5%)
Unknown device - 9  (~15.5%)
Not Enough Data - 2 (~3%)

After:
Correct - 44  (~75.9%)
Incorrect - 3 (~5%)
unknown block - 0 (0%)
Unknown Device 9  (~15.5%)
Not enough data 2  (~3%)

Much Better!  The 3 incorrect are outliers in the dataset, that don’t calculate correctly at the moment.  The Unknown devices are showing up because they are either in the DC.F5.1B block or new block 74.90.BC.  We are starting to gather a bit more info about both of these, but we need more entries to better understand what’s going on there.

We now have 166 Unique Date codes.  There is now a second sheet named “Date Codes” in the dataset that has each of the blocks separated.  This eventually gets collapsed into that data_ref_lines that the Fios-F1nDr code uses, which is also included with the dataset.  Sorting the entries by the date codes allows us to see devices that are in the same block possibly removing some of the overall randomness.  There are quite a few blocks that we have 4-7 entries for.

Also added to the dataset is a new column named “QR”, which indicates if the QR data was read from the reference image.  The QR data either reads or it doesn’t, so it is the most accurate and therefore preferred source of the data.  This is the script that I am using to sort the scraped images into “found” and “not found”.  Found images contain either a QR code, or some part of the back label we are looking for (WIFI, Serial, Password, etc).  The script is adapted from code found here, and uses apple vision for the text and zbarimg for the QR code.  The script might only work on an Apple devices, but I am not sure.  The script will output “imagedata.csv” at the end, that contains all of the info that it finds.  The script works great to sort the images, but unfortunately the extracted text is rarely complete or correct, but it’s fun to see what the computer picks up.

Code:
""" Use Apple's Vision Framework via PyObjC to detect text in images modified code from: https://gist.github.com/RhetTbull/1c34fc07c95733642cffcd1ac587fc4c Necessary Dependencies: python3 -m pip install pyobjc-core pyobjc-framework-Quartz pyobjc-framework-Vision wurlitzer brew install zbar This script process all of the images in folder_path using apple vision to extract text. It checks to see if any of the keywords are found in the image, and extracts the relevent info All of the info is saved to <file name> and relevent photos are moved to the "found" folder in case they need to be referenced later.  Any photos without keywords are deleted. """ import pathlib import sys import Quartz import Vision import os import shutil import pandas as pd from Cocoa import NSURL from Foundation import NSDictionary # needed to capture system-level stderr from wurlitzer import pipes import subprocess import re from pyzbar.pyzbar import decode, ZBarSymbol from PIL import Image sys.path.append(r'/opt/homebrew/Cellar/zbar')  #tell the script where to find zbarimg KEYWORDS = ["Wi-Fi Name:", "Wi-Fi Password:", "Admin URL:", "Admin Password:",             "Model Number:", "Serial #.", "WAN MAC:", "HW ver.:", "Shipped FW ver.:"] # Define the keyword mappings qr_to_keyword_map = {         "WIFI:S:": "Wi-Fi Name:",         "T:WPA;P:": "Wi-Fi Password:",         "ROUTER:M:": "Model Number:",         "S:": "Serial #.",         "W:": "WAN MAC:",         "I:admin;P:": "Admin Password:", } QRKEYWORDS = ["WIFI:S:", "T:WPA;P:", "I:admin;P:", "ROUTER:M:", "S:"] KEYWORDS = ["Wi-Fi Name:", "Wi-Fi Password:", "Admin URL:", "Admin Password:",             "Model Number:", "Serial #.", "WAN MAC:", "HW ver.:", "Shipped FW ver.:"] keywords_lower = [keyword.lower() for keyword in KEYWORDS]  #makes keywords lowercase(case insensitive) for better matching global qr_found def image_to_text(img_path, lang="eng"):     input_url = NSURL.fileURLWithPath_(img_path)     with pipes() as (out, err):     # capture stdout and stderr from system calls     # otherwise, Quartz.CIImage.imageWithContentsOfURL_     # prints to stderr something like:     # 2020-09-20 20:55:25.538 python[73042:5650492] Creating client/daemon connection: B8FE995E-3F27-47F4-9FA8-559C615FD774     # 2020-09-20 20:55:25.652 python[73042:5650492] Got the query meta data reply for: com.apple.MobileAsset.RawCamera.Camera, response: 0         input_image = Quartz.CIImage.imageWithContentsOfURL_(input_url)     vision_options = NSDictionary.dictionaryWithDictionary_({})     vision_handler = Vision.VNImageRequestHandler.alloc().initWithCIImage_options_(         input_image, vision_options     )     results = []     handler = make_request_handler(results)     vision_request = Vision.VNRecognizeTextRequest.alloc().initWithCompletionHandler_(handler)     error = vision_handler.performRequests_error_([vision_request], None)     return results def scan_qr(image_path, img_name):     qr_read = pd.DataFrame()     global qr_found     qr_found = False         try:         # Run zbarimg command on the image         #qimage_path = '/Users/Brian/Downloads/Routers/Fios-3100/ebay_images/found/image_702.webp'         img = Image.open(image_path)  # Replace with your file         decoded_objects = decode(img)                 if decoded_objects:                     qr_read = pd.DataFrame(decoded_objects)           #print(decoded_objects)             #print(f"✅ QR Code Found:" + str(decoded_objects))             #qr_codes = [line.split(": ", 1)[1] for line in result.stdout.strip().split("\n") if ": " in line]             #qr_read = pd.DataFrame(qr_codes)    # Create a DataFrame             qr_read["QR_read"] = "Yes"             #df = pd.DataFrame(qr_codes, columns=["QR Code Data"])             qr_found = True         #else:             #print(f"❌ No QR code detected in", img_name)         except FileNotFoundError:         print("Error: zbarimg is not installed or not found in PATH.")         #return qr_read     return decoded_objects def make_request_handler(results):     """ results: list to store results """     if not isinstance(results, list):         raise ValueError("results must be a list")     def handler(request, error):         if error:             print(f"Error! {error}")         else:             observations = request.results()             for text_observation in observations:                 recognized_text = text_observation.topCandidates_(1)[0]                 results.append([recognized_text.string(), recognized_text.confidence()])     return handler def extract_values(qrcodes, results, QRKEYWORDS, KEYWORDS):     global match_found     match_found = False         extracted_data = {key: "" for key in KEYWORDS}  # Initialize a dictionary with empty values         # Convert QRKEYWORDS to KEYWORDS mapping     qr_to_keyword_map = {         "WIFI:S:": "Wi-Fi Name:",         "T:WPA;P:": "Wi-Fi Password:",         "I:admin;P:": "Admin Password:",         "ROUTER:M:": "Model Number:",         ";S:": "Serial #."     }         # **Step 1: Search QR Code Data**     for qr_entry in qrcodes:         data_str = str(qr_entry)  # Decode bytes to string         for qr_key, keyword in qr_to_keyword_map.items():             match = re.search(fr'{qr_key}([^;]+)', data_str)             if match:                 extracted_data[keyword] = match.group(1).split("'")[0]  # Remove trailing artifacts                 match_found = True                 extracted_data["QR_found"] = "Yes"     # **Step 2: Search OCR Text (Only if not found in QR)**     for text_entry in results:         text = str(text_entry)                 for keyword in KEYWORDS:             if extracted_data[keyword]:  # Skip if already filled by QR                 continue             match = re.search(fr'{keyword}([^;]+)', text, re.IGNORECASE)             if match:                 extracted_data[keyword] = match.group(1).split("'")[0]  # Extract OCR value                 match_found = True     # Convert to DataFrame     extract_df = pd.DataFrame([extracted_data])     return extract_df folder_path = input("Please enter the file path to folder with the images: ") folder_path = (folder_path + "/") folder_contents = os.listdir(folder_path) os.makedirs(folder_path +"found/", exist_ok=True) os.makedirs(folder_path +"not_found/", exist_ok=True) global match_found match_found = False matched_text = pd.DataFrame()  #the dataframe where well store all of oure matched text clean_list = pd.DataFrame() for imgs in folder_contents:     if not imgs.lower().endswith((".png", ".jpg", ".jpeg", ".webp", ".tiff")):  #.lower makes the comparison case-insensitive         continue     match_found = False     print ("Processing: " + imgs)     img_path = (folder_path + imgs)     qrcodes = scan_qr(img_path, imgs)     results = image_to_text(img_path)         # Extract values from QR and OCR results     if qrcodes:         #qr_data = extract_values(qrcodes)         print("QR Code Found: " + str(qrcodes))     if results:         #ocr_data = extract_values(results)         print ("OCR Text Found: " + str(results))         if qrcodes or results:         img_data = extract_values(qrcodes, results, QRKEYWORDS, KEYWORDS)         img_data['IMG'] = imgs #add the image name to the info               if match_found == True:         print(f"✅ Match found! Moving: {imgs}")         matched_text = pd.concat([matched_text, img_data], ignore_index=True)  #add the extracted info to our dataframe         shutil.move(folder_path + imgs, folder_path + "found/" + imgs)    #moves the images to a folder named "found"     else:         print(f"❌ No match. Moving: {imgs}")         shutil.move(folder_path + imgs, folder_path + "not_found/" + imgs)    #moves the images to a folder named "found"         #os.remove(img_path)  #delete files where no info is found #Now to do some cleaning to our matched_text #clean_list['Duplicates'] = 0 if not matched_text.empty:     clean_list = matched_text #copy the matched text into a new dataframe     clean_list = clean_list.fillna("") #remove any nan     clean_list = clean_list.map(lambda x: x.replace(" ", "") if isinstance(x, str) else x)     #clean_list = clean_list.map(lambda x: x.replace("', 0.5]", "") if isinstance(x, str) else x)     img_column = clean_list.pop('IMG')  # Removes "IMG" column but keeps it in memory     clean_list["duplicates"] = clean_list.duplicated(keep="first").astype(int)  #adds a column "duplicates" and denotes duplicate with 0 or 1     clean_list["duplicates"] = clean_list.groupby(clean_list.columns.drop(["duplicates"]).tolist())["duplicates"].transform("sum") #count the number of duplicates     clean_list = clean_list.drop_duplicates() #.reset_index(drop=True)  # Drop duplicate rows and keep the first occurrence     clean_list.insert(0, "IMG", img_column)     clean_list = clean_list[["IMG"] + [col for col in clean_list.columns if col != "IMG"]] # ensures "IMG" is first column, while preserving the rest of the order     clean_list = clean_list.sort_values(by="IMG").reset_index(drop=True) #Arranges list in alphabetical order based on image name         clean_list = clean_list.reset_index(drop=True)     clean_list.to_csv(folder_path + "/imagedata.csv") else:     print("No matched images found!") # the number in the results is the confidence score, It's important to note that a lower confidence score doesn't #necessarily mean the recognized text is incorrect, but it does suggest that the system is less certain about #its accuracy. In such cases, manual verification or additional processing might be warranted to ensure the information's correctness.


Unfortunately, the script is not very good at reading the QR code.  Running the script against all of the reference images only yields 38/313 QR codes.  Using my phone, with a QR reader app is how I actually collect the QR codes.  Using this method I’ve read 133/313 codes, but it takes much longer.  If I could somehow get the script to read the QR with the same effectiveness as my phone it would make the scraping process so much faster and simpler!  The good news is now that we have the QR column, we actually can separate the reference images into a “Read” and “Unread”, and perhaps use this to train the image processing to better recognize our QR codes.  Furthermore, we are looking for a specific format to the QR code, so hopefully this can better inform the script too?  Here is what an example read looks like.

Code:
WIFI:S:Verizon_ZFBX9P;T:WPA;P:bread-veto6-ode;;ROUTER:M:G3100;S:G402121090810583;W:3CBDC577D884;I:admin;P:KT7XFBH3D;;4

If you want to see if your phone is any better at reading images, I can read the first image but not the second.

[Image: attachment.php?aid=1254][Image: attachment.php?aid=1256]

Despite everything that I’ve been able to accomplish, I am very much new to all this.  This is my first foray into hardware hacking, and I am working mostly off of tutorials found online.  I was able to get binwalk to run, and I can get it loaded into Ghidra, but I honestly have no clue what the next steps should be.  I believe it is encrypted, possibly with LUKS.  I found an awesome post on the openwrt forums discussing the CR1000A which is a similar device.  The post is an exciting read, but quickly got over my head.  I also found a nice teardown of the E3200, which seems to be very similar to the G3100 internally.  Looks like the embedded processor of choice is a Broadcom BCM68369KFEBG, which is a Dual Core 1.5 GHz ARM v8 processor featuring 4x GbE PHYs, 1x USB 3.0, DDR 800MHz support, 4ch VoIP.

"Looks like the embedded processor of choice is a Broadcom BCM68369KFEBG, which is a Dual Core 1.5 GHz ARM v8 processor featuring 4x GbE PHYs, 1x USB 3.0, DDR 800MHz support, 4ch VoIP."

I hope that my posts show that I am putting a lot of effort into this, and willing to share my ideas openly.  I don’t really expect to find the keygen algorithm, but it’s enough of a carrot to keep me going.  I will continue to drudge along by myself, but if you, or anyone you know may be interested in furthering this research please let me know.  I have all of the listed firmware downloaded and I’m happy to pass it along.


Attached Files
.jpg   image_25060.jpg (Size: 327 KB / Downloads: 96)
.jpeg   image_28001.jpeg (Size: 81.2 KB / Downloads: 95)
Reply