Unpublished WPA key algorithms

FiosFiend

Active member
Feedback: 0 / 0 / 0
Joined
Apr 6, 2025
Messages
152
Reaction score
168
Credits
2,573
@drsnooker I need some help! I think I found something interesting in the /bin/flash of the wrc-1467ghbk-s firmware

Rich (BB code):
    iVar3 = strcmp(pcVar22,"reset");
    if (iVar3 == 0) {
      apmib_init();
      memset(local_521c,0,0x40);
      local_5318._0_4_ = 0;
      apmib_get(200,(tm *)local_5318);
      puVar24 = local_52c8 + 0x14;
      fprintf(stderr,"HW_BOARD_VER=%d\n",local_5318._0_4_);
      apmib_get(0xc9,puVar24);
      apmib_setDef(0xb6,"admin");
      apmib_setDef(0xb7,"");
      FUN_00402c38((char *)&DAT_004116ac);
      sprintf((char *)local_521c,"elecom2g-%02x%02x%02x",local_52b4 & 0xff,(uint)local_52b0._0_1_,
              (uint)(byte)local_52b0);
      apmib_setDef(1,local_521c);
      apmib_setDef(0x116,local_521c);
      puVar5 = FUN_00411254(puVar24,0xc,local_5318._0_4_);
      apmib_setDef(0x1e,puVar5);
      puVar5 = FUN_00411254(puVar24,0xc,local_5318._0_4_);
      apmib_setDef(0x115,puVar5);
      sprintf((char *)local_521c,"elecom5g-%02x%02x%02x",local_52b4 & 0xff,(uint)local_52b0._0_1_,
              (uint)(byte)local_52b0);
      FUN_00402c38("wlan0");
      apmib_setDef(1,local_521c);
      apmib_setDef(0x116,local_521c);
      puVar5 = FUN_00411254(puVar24,0xc,local_5318._0_4_);
      apmib_setDef(0x1e,puVar5);
      puVar5 = FUN_00411254(puVar24,0xc,local_5318._0_4_);
      apmib_setDef(0x115,puVar5);
      apmib_update(2);
      local_5318._4_4_ = (timeval *)0x0;
      iVar3 = open64("/dev/mtdblock0",2);
      apmib_sem_lock();
      pcVar22 = (char *)apmib_dsconf();
      if (pcVar22 == (char *)0x0) {
        puts("Default configuration invalid!");
        goto LAB_0040cbec;
      }
      i



Rich (BB code):
undefined1 * FUN_00411254(void *param_1,int param_2,int param_3)

{
  bool bVar1;
  int iVar2;
  int iVar3;
  int *piVar4;
  char *pcVar5;
  uint uVar6;
 
  memset(&DAT_0042dc80,0,0x40);
  memcpy(&DAT_0042dcc0,param_1,6);
  iVar2 = DAT_0042dc70;
  piVar4 = &DAT_004150c4;
  bVar1 = DAT_0042dc70 != 0;
  DAT_0042dc7c = param_3;
  for (iVar3 = 0; iVar3 < param_2; iVar3 = iVar3 + 1) {
    uVar6 = (int)DAT_0042dcc4 * *piVar4 + (int)DAT_0042dcc3 * (&DAT_004150c0)[iVar3] +
            (int)DAT_0042dcc5 * piVar4[1] + (uint)bVar1;
    if (param_3 == 2) {
      pcVar5 = "0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" + uVar6 % 0x3e;
    }
    else if (param_3 == 3) {
      pcVar5 = "9823456789a2cdef3hijk4mn5p6r7tuvwxy8a2cdef3hijk4mn5p6r7tuvwxy8" + uVar6 % 0x3e;
    }
    else if (param_3 == 1) {
      pcVar5 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + uVar6 % 0x3e;
    }
    else {
      pcVar5 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + uVar6 % 0x3e;
    }
    piVar4 = piVar4 + 1;
    (&DAT_0042dc80)[iVar3] = *pcVar5;
  }
  (&DAT_0042dc80)[param_2] = 0;
  if (iVar2 != 0) {
    DAT_0042dc70 = 0;
  }
  return &DAT_0042dc80;
}

WRC-1900.jpeg
 

drsnooker

Active member
Contributor
VIP Member
Feedback: 0 / 0 / 0
Joined
Aug 1, 2020
Messages
501
Reaction score
811
Credits
4,625
@FiosFiend I'm swamped at the moment. Hopefully my head will get above water in November.
You might want to try IDA or Cutter to look at the same code. Each decompiler interprets the source differently. One might more sense than the other!
 

FiosFiend

Active member
Feedback: 0 / 0 / 0
Joined
Apr 6, 2025
Messages
152
Reaction score
168
Credits
2,573
Ok, it turned out to be a little easier to feed the MAC than I thought. I just put the MAC in a file named flash in /tmp/ and ran this using the libraries from the firmware from inside the emulated environment.

PATH=/tmp:$PATH LD_LIBRARY_PATH=../lib ./wpakey2.4g

Here was my output based on the known MACs
bc5c4c2ced61:9152502417459
bc5c4c2d0085:6152490316548
bc5c4c2d016b:1681951111870

The binary produces the same generated key repeatedly, despite the rand(). Unfortunately there is no way for us to confirm these are “valid” keys, but I am fairly confident they are what the device would actually produce. I also don’t think these are ever used for this model, since there is only 1 key shown on the device (which is produced with wpakey5g). I also haven’t been able to figure out a python script that produces the same keys in my environment, so I haven’t tested any keys against the hash.

I was also able to find another keygen and confirmed the python script is working! This one was in WRC-X1500GS-B, a plain text file named mstc_ssidkeygen (attached below). To test it yourself use the MAC 3897A452D908 which matches the SSID.

==================================================
Elecom Default Credential Generator
==================================================
Base MAC: 3897a452d908

Derived MAC Addresses:
5G : 3897a452d90a
2G : 3897a452d909
WAN : 3897a452d90b

SSIDs:
2.4GHz Main: elecom-52d908
2.4GHz Alt: e-tomo-52d908
2.4GHz Secure: elecom-s-52d908
5GHz Main: elecom-52d908
5GHz Alt: e-tomo-52d908
5GHz Secure: elecom-s-52d908

Security Credentials:
WiFi Password: 47u44vt57e56
Guest Password: 27u24nt37854
Secure Key: p7u54ft37257
WPS PIN: 30295124
Web GUI Password: 9tu435u3
==================================================


WRC-X1500GS-B.jpeg
 

Attachments

  • mstc_ssidkeygen.txt
    8.2 KB · Views: 16
  • elecom_gen2.py.txt
    7.7 KB · Views: 16

mi_ol_yr_a

New member
Feedback: 0 / 0 / 0
Joined
Oct 20, 2025
Messages
1
Reaction score
0
Credits
10
Hey everyone! I'm interested in this topic about Rotek routers. There are about 10 Rotek access points near me. I was able to access two of them (their WPS PIN turned out to be universal). These two access points were the same model, RX-22300, with a MAC address of DC:E3:05. There are other access points with the same MAC address, but the WPS PIN no longer works. I may have misread the user posts, but could you please explain: given only the MAC address of the Rotek access point, can I find its exact password, or at least a limited number of password options (not a million, of course)? What keygen is available, and what program can I use to run it?
The access points are accessible.
ModelSSIDBSSIDpassword
RX-22300RT-WiFi-CB60DC:E3:05:F2:CB:61YfJke3uEaK
RX-22300RT-WiFi-8819DC:E3:05:F4:88:1A5Nie8NnbyB
These are the access points I'd like to access.
ModelSSIDBSSIDpassword
RX22312RT-WiFi-F909DC:E3:05:79:F9:0A
RX22312RT-WiFi-7537DC:E3:05:7A:75:38
RX23302RT-WiFi-9F7148:29:E4:33:9F:72
 

Nikolia

Active member
Feedback: 7 / 0 / 0
Joined
Sep 13, 2021
Messages
1,288
Reaction score
3,633
Credits
6,985
mi_ol_yr_a ↑

For an access point with a MAC address of 48:29:E4.... there is a dictionary of 917362584 words.
Hashcat program at a speed of 1100,000 x/sec. search for 15 minutes.
 

FiosFiend

Active member
Feedback: 0 / 0 / 0
Joined
Apr 6, 2025
Messages
152
Reaction score
168
Credits
2,573
Wahoo, found another! @drsnooker you might be interested in this one. This is the correct algorithm for SSID NetComm XXXX, Trustpower_2.4Ghz_XXXX, and Aussie Broadband XXXX and was found in the file libcms_core.so of the NF18MESH firmware listed on the Aussie Broadband website. The input uses the serial number, so it requires building a dictionary from the expected range. I have confirmed that the python script generates the proper key, and have already cracked several WPA-SEC entries :smile: .

AUB1.jpeg1760992202932.png

Enter Serial #: 096025212326138
WPA key : cazifarahu

Enter Serial #: 998825203305557
WPA key : cujoboluho


It also works for the serial/pass that I posted in the collected netcomm data a page back.

Aussie Broadband 3895 poduroziza 18F145C572E8 180909508834
Aussie Broadband 7302 lahapasabe F8CA597E87FD 998825204903465
Aussie Broadband 2985 wewidinawe F8CA59A790C0 998825210206411
NetComm 0155 Cedefuqide F8CA59AD7C73 210508501807
NetComm 8660 xoporewowe F85A59758092 201006501464
NetComm 8644 nizotaqiqe F85A59758092 201006501464
Trustpower_2.4Ghz_1495 hoboyerolo F8CA59883440 201102505055
 

Attachments

  • netcomm-AUB-gen.py.txt
    2.8 KB · Views: 13

FiosFiend

Active member
Feedback: 0 / 0 / 0
Joined
Apr 6, 2025
Messages
152
Reaction score
168
Credits
2,573
Ok based on my previous image scrapes and some new data from @Sparton we’ve identified some of the Serial Number ranges. The generator is currently only working for model NF18ACV/NF18MESH.

There is a large group that uses the format YYMMDD5#####, where YY is 2 digit year, MM is 2 digit month, DD is 2 digit day, 5 is always constant and ##### is between 00000 and 29999 (ex: 201006501464. I have generated a dictionary that covers all dates from 2017 to 2021 which is 54,780,000 candidates. This dictionary could be significantly reduced by only using confirmed date prefixes instead.

There is also another subset of serials from 998825200000000 → 998825250000000, which is another 50,000,000 candidates.

Another dictionary for serial # 096025200000000 to 096025229999999 is 50,000,000 candidates for Aussie Broadband and Origin Broadband. Using all of the dictionaries against the WPA-SEC hashes produced these results.

NetComm
OUI F8CA59 83/303 (27.39%) Salts
OUI 18F145 79/202 (39.11%) Salts

Trustpower
105/140 (75.00%) Salts

Aussie Broadband
184/319 (57.68%) Salts

Origin Broadband
10/23 (43.48%) Salts


It would be possible to brute force these passwords, however the total candidates for a brute force:
  • Consonants c = 21 choices
  • Vowels v = 5 choices (a, e, i, o, u).
  • Pattern c v c v c v c v c v has 5 consonant positions and 5 vowel positions.
Answer: 12,762,815,625 candidates (≈12.76 billion). The combined dictionary attack is 1.2% the size of the brute force.
 

FiosFiend

Active member
Feedback: 0 / 0 / 0
Joined
Apr 6, 2025
Messages
152
Reaction score
168
Credits
2,573
I think I’m getting the hang of this!

This time we have the algorithm for NetComm's NF1901ACV. The firmware is currently listed on the NetComm website but it’s encrypted. Fortunately for us, there was a link on the Wayback Machine to firmware that’s not encrypted. Once we have the file system, we know to check out our old friend lib/libcms_core.so. This time we get the password algorithm and SSID generation! @drsnooker you should check out the file, I think this will look VERY familiar to you :wink:


1761179703600.png


Again we use the serial as input. The serial number range seems to lie 94452520#######.

Enter device serial: 944525200400337

suffix=_117887, newline=True, discard=False ->
seed: '944525200400337_117887\n'
param2: E4K9M948UK
ssid: NetComm 0956
wpa: xexememumi


It’s a 2 for 1, this algorithm also works for NF10WV too!

1761180481132.png
Enter device serial: 200521509084

suffix=_117887, newline=True, discard=False ->
seed: '200521509084_117887\n'
param2: 2J45rSxe56
ssid: NetComm 7452
wpa: Zihixaguyu


This model uses the serial format YYMMDD5##### that we saw earlier, but seems to range from 2016 to at least 2022.

Now to see if they happened to leave the encryption key so that I can decrypt the NF20 firmware :geek:
 

Attachments

  • NetComm_gen3.py.txt
    6.4 KB · Views: 10

FiosFiend

Active member
Feedback: 0 / 0 / 0
Joined
Apr 6, 2025
Messages
152
Reaction score
168
Credits
2,573
Good news, @Sparton discovered that the new algorithm produces the correct keys for the NF18 5GHz network! There are only minor differences between the two algorithms, so I have combined them. I also realized now that we have the SSID generator, we can produce SSID:Key look up tables rather than running full dictionary attacks. There will be some overlap since the SSID only uses 4 unique digits, but it will reduce our dictionaries from 100 million+ to significantly fewer candidates that should finish in 1 second :cool:

NF18x2.jpeg
Enter device serial: 200506500985

=== Variant A (suffix _117887) ===
seed: '200506500985_117887\n'
param2: tEfPLLlx2t
SSID: NetComm 7899
WPA: Muzebanufa

=== Variant B (suffix _227887) ===
seed: '200506500985_227887\n'
param2: SYN8EbRUOu
SSID: NetComm 7645
WPA: Cepufusede

NF18TP.jpeg
Enter device serial: 201102505055

=== Variant A (suffix _117887) ===
seed: '201102505055_117887\n'
param2: T3tMfiYcz8
SSID: NetComm 2588
WPA: nedoviveco

=== Variant B (suffix _227887) ===
seed: '201102505055_227887\n'
param2: g1IiUwe4kM
SSID: NetComm 1495
WPA: hoboyerolo



An interesting tidbit.. as part of this research, I was looking for more ISPs that use NetComm and came across Orcon in New Zealand. They list "The default WiFi name for this modem is "Your new Wi-Fi, and the password is the modems serial number, as printed on your Wi-Fi access card.” (link)

Well we already know the serial numbers! Since the SSID are all the same, we can actually use -m 22001 on these. Running the date dictionary against the hashes, we clear a good many of these :) 76/92 (82.61%) Digests

Example:
Your new Wi-Fi:171227505158
Your new Wi-Fi:180928510894
Your new Wi-Fi:191028500706
Your new Wi-Fi:191028503632
Your new Wi-Fi:200707502047
 

Attachments

  • NetComm_fullgen.py.txt
    4.3 KB · Views: 11

FiosFiend

Active member
Feedback: 0 / 0 / 0
Joined
Apr 6, 2025
Messages
152
Reaction score
168
Credits
2,573
phish.jpg

Check it out, I caught another one! This one was found in the TM3200M GPL source code (bcm963xx_31.164l.04_gpl_consumer_release) on the Actiontec website. Yet again, we find the algorithm lurking in the depths of /lib/libcms_core.so. The decompiled algorithm accepts serial number or MAC address as input, so it likely covers multiple devices. I have confirmed it works for Actiontec PK5000 using the SSID myqwest. Right now, my script recognizes the MAC prefix 00247B subtracts 1, and outputs an uppercase key. This matches what I’ve observed on the sticker, but was not part of the original algorithm. The rest of the code is unchanged so that we can find other devices. @Sparton I could use some help finding the other devices this covers.

PK5000.jpeg

Enter device Serial number or MAC address: 00247B60F64F
[!] Detected 00247B prefix — adjusting MAC (-1)

Generated Qwest SSID and WPA Key
--------------------------------
SSID: QWEST604E
WPA Key: FF9F2E2BFFCFA953E7E6E71ACA

*Note: the generated SSID doesn’t match for this device.
 

Attachments

  • qwest_gen.py.txt
    4.7 KB · Views: 13

JustGuardian

Active member
Feedback: 0 / 0 / 0
Joined
Feb 2, 2022
Messages
80
Reaction score
48
Credits
547
Looks like we got Home&Life for the older models with a SN that starts with 'S' Zykgen(SN,'m',16) I'm guessing the newer models start with 'W'. Doesn't like look the algo works for those.
Same with WIND3. Zyxel must have updated their algo at some point.
Did you ever found the firmware of those types of modems? maybe even analyzed it. Btw I noticed that in the infamous firmware from VMG8823, VMG8825 in the libzcfg_be.so there is a function named zcfgBeWlanGenDefaultSSID that is the one who is responsible for generating the suffix in the name. Like "Home&Life SuperWiFi-XXXX". If the suffix is 4 chars long it is extracted from the mac, if the suffix is more than 4 chars and it is numerical it is generated in another way, based on the serial. The way they decide which method to use to generate the suffix is by using the function
zcfgBwWlanChkSSIDGenBySN(pvVar2,extraout_r1,extraout_r2).
C-like:
undefined4 zcfgBwWlanChkSSIDGenBySN(undefined4 param_1,undefined4 param_2,undefined4 param_3)


{
  void *__ptr;
  int iVar1;
  undefined4 uStack_14;
  undefined4 uStack_10;
  void *local_c;


  local_c = (void *)0x0;
  uStack_14 = param_2;
  uStack_10 = param_3;
  memset(&uStack_14,0,7);
  iVar1 = zcfgBeObjGetWithoutUpdate(0xd02c,&uStack_14,&local_c);
  __ptr = local_c;
  if ((iVar1 == 0) && (iVar1 = strcmp((char *)((int)local_c + 0x10),"SN"), iVar1 == 0)) {
    free(__ptr);
    return 1;
  }
  free(local_c);
  return 0;
}

That appears to check in the configuration(maybe) if "SN" is present.
If "SN" is present it returns 1 else 0.
Then if that function returned 0 it generates the suffix using the mac, else it generates it using the serial number like this:

C:
else {   
    memset(__dest,0,0x10);
    iVar3 = zyUtilIGetSerialNumber(__dest);
    if ((iVar3 != 0) || (local_40[0] == 0)) {
      strcpy((char *)__dest,"S090Y00000000");
    }
    sVar4 = strlen((char *)__dest);
    if (-1 < (int)(sVar4 - param_3)) {
      __dest = __dest + (sVar4 - param_3);
    }
  }
  strncpy(local_60,(char *)__dest,param_3);
  for (iVar3 = 0; iVar3 < (int)param_3; iVar3 = iVar3 + 1) {
    cVar6 = local_60[iVar3];
    if ((byte)(cVar6 + 0x9fU) < 0x1a) {
      cVar6 = cVar6 + -0x20;
    }
    local_60[iVar3] = cVar6;
  }
  local_60[param_3] = '\0';
  sprintf(param_1,"%s%s",param_2,local_60);

I wonder if this could be useful, but I dont think so...
 

drsnooker

Active member
Contributor
VIP Member
Feedback: 0 / 0 / 0
Joined
Aug 1, 2020
Messages
501
Reaction score
811
Credits
4,625
There's light at the end of the tunnel and I don't think it's a train this time!
Fantastic work by @FiosFiend and also the colab with @Sparton and his encyclopedic knowledge of world wide wifi passwords.
Not sure if @wizardhat is still around but a buddy of mine picked up some e-waste in the emerald isles. Not sure if it'll lead to anything, but interesting to poke around in.
Anyway, after this weekend I'll get back into this thread and read all of your updates.

eircom.jpg
 

drsnooker

Active member
Contributor
VIP Member
Feedback: 0 / 0 / 0
Joined
Aug 1, 2020
Messages
501
Reaction score
811
Credits
4,625
@drsnooker I need some help! I think I found something interesting in the /bin/flash of the wrc-1467ghbk-s firmware
Actually had a few minutes today. Quite a few folks are leaving early this Friday to go trick'r'treating which leaves me a quite a few distractions.
I don't want to steal your credit nor the pleasure of you solving another keygen, plus you seem well versed in Python, so I thought I'd write a qiling script to execute the /bin/flash with a given MAC
This can serve as an example to running other functions as well as an intro to dynamic reverse engineering.
It'll spit out the correct password for mac+1 (see SSID)
Upto you to remove the comment # in front of the ql.debug statement in the flash1900.py and step through the code!

wrc1467png.png
 

Attachments

  • flash1900.zip
    36.8 KB · Views: 5

drsnooker

Active member
Contributor
VIP Member
Feedback: 0 / 0 / 0
Joined
Aug 1, 2020
Messages
501
Reaction score
811
Credits
4,625
Hey everyone! I'm interested in this topic about Rotek routers. There are about 10 Rotek access points near me. I was able to access two of them (their WPS PIN turned out to be universal). These two access points were the same model, RX-22300, with a MAC address of DC:E3:05. There are other access points with the same MAC address, but the WPS PIN no longer works. I may have misread the user posts, but could you please explain: given only the MAC address of the Rotek access point, can I find its exact password, or at least a limited number of password options (not a million, of course)? What keygen is available, and what program can I use to run it?

We don't know how the MAC relates to the seeds. All we have right now is generating the dictionaries and running them against the caps.
 

drsnooker

Active member
Contributor
VIP Member
Feedback: 0 / 0 / 0
Joined
Aug 1, 2020
Messages
501
Reaction score
811
Credits
4,625
@FiosFiend not to burst your bubble with the actiontec keygen but...
@Dawbs with all of fiosfiend recent additions we probably should add a non-zyxel keygen table in the default-wpa-keyspace-work-in-progress thread.
Not sure if @Plum wants to host the newly discovered keygens, or perhaps @FiosFiend can start a github repository. Attachments in this forum expire so when somebody comes across this thread in a few years it might be less useful.
 

Dawbs

Super Moderator
Staff member
Super Moderator
Trusted
Feedback: 3 / 0 / 0
Joined
Dec 30, 2019
Messages
4,275
Reaction score
3,579
Credits
19,186
That's a good idea. we'll work on a non-Zyxel list.

As for attachments, they should be fine here & never expire, Any missing attachments should pre-date the forum switch over. But having them on a github is definitely the standard way to host.
 

FiosFiend

Active member
Feedback: 0 / 0 / 0
Joined
Apr 6, 2025
Messages
152
Reaction score
168
Credits
2,573
@drsnooker glad you got some free time to play around! Yeah @RealEnder had informed me that you already found the actiontec/qwest keygen. The good news is @Sparton, @RealEnder and I finally put it to use and cleared a bunch of myqwest keys :smile: . I am not sure if you knew that it also generated the PK5000 keys too (just needs uppercased)

@Plum or whomever else wants to secure these scripts is welcome to do so, I share them here so that they can benefit the community.

@drsnooker great idea emulating flash! I did that for the wpa2.4key, but absolutely didn’t even consider doing it this time. I had never used qiling before, but your script was super helpful to figure out what was going on. Thanks for showing me a new trick. Please don’t ever worry about stealing credit, I asked for help and you solved the problem! My original decompile didn’t fully show how the math was being done (32 bit wrap around). but thanks to the emulation debug we now have a working python script that works for

WRC-1467GHBK
WRC-1467GHBK.jpeg
MAC (12 hex digits or colon form): BC5C4C70BBF9
Mode (1=default, 2 or 3) [default 1]:

SSID: elecom2g-70bbf9
Key : I4kEoISGQOa4


WRC-1900
WRC-1900_2.jpeg
MAC (12 hex digits or colon form): BC:5C:4C:77:63:81
Mode (1=default, 2 or 3) [default 1]:

SSID: elecom2g-776381
Key : xdDnr3znDLRL

WRC-1900-GHBK-S (MODE 2)
1762023552164.png
MAC (12 hex digits or colon form): BC5C4CC3AC49
Mode (1=default, 2 or 3) [default 1]: 2

SSID: elecom2g-c3ac49
Key : ekggcu40owsq
 

Attachments

  • WRC-1900.jpeg
    WRC-1900.jpeg
    45.2 KB · Views: 6

FiosFiend

Active member
Feedback: 0 / 0 / 0
Joined
Apr 6, 2025
Messages
152
Reaction score
168
Credits
2,573
Whoops I forgot to post the script. @Dawbs please add this to my previous post.
 

Attachments

  • elecom_flash_gen.py.txt
    2.1 KB · Views: 12

Plum

Moderator
Staff member
Moderator
Trusted
Contributor
Feedback: 11 / 0 / 0
Joined
Dec 30, 2019
Messages
4,439
Reaction score
5,284
Credits
13,186
I don't mind hosting any new algs on my github if needed.
 
Top