seemoo-lab / nexmon

The C-based Firmware Patching Framework for Broadcom/Cypress WiFi Chips that enables Monitor Mode, Frame Injection and much more
GNU General Public License v3.0
2.4k stars 450 forks source link

Removing firmware channel restrictions #443

Open bm16ton opened 3 years ago

bm16ton commented 3 years ago

Hello, I see that the modified driver no longer shows the channels restrictions IE no IR, radar detection but they still exist in firmware. Im running a patched driver which also removes those flags, if I start an AP on a "no IR, radar detection" instead of immediately starting it takes a min...but it does start! The second machine connecting to the raspberry pi 4 has no restrictions so is doing active scans on that channel. I dont believe that is supposed to be enuff to allow the pi4 to start transmitting on those freqs. Im not sure if its just a bug or poor checking. What would be great is if we could remove those flags from the firmware!? Also maybe enable channels 12 13 14. I looked at the code here and is waay above my head. Old intel/atheros/realtek cards I was able to hack the firmware on to remove channels restrictions almost always was a very small change usually located after each channel in a table. Any help would be greatly appreciated. Thank you for your awesome work!

matthiasseemoo commented 3 years ago

did you take a look into the restrictions.c file from our other nexmon based projects? such as the jammer? Did you read our paper on reactive jamming or my phd thesis? there you see what is possible with nexmon. you can even define non-standard channels, such as those with 80 MHz bandwidth in the 2.4 GHz band.

On 14. Nov 2020, at 22:54, bm16ton notifications@github.com wrote:

Hello, I see that the modified driver no longer shows the channels restrictions IE no IR, radar detection but they still exist in firmware. Im running a patched driver which also removes those flags, if I start an AP on a "no IR, radar detection" instead of immediately starting it takes a min...but it does start! The second machine connecting to the raspberry pi 4 has no restrictions so is doing active scans on that channel. I dont believe that is supposed to be enuff to allow the pi4 to start transmitting on those freqs. Im not sure if its just a bug or poor checking. What would be great is if we could remove those flags from the firmware!? Also maybe enable channels 12 13 14. I looked at the code here and is waay above my head. Old intel/atheros/realtek cards I was able to hack the firmware on to remove channels restrictions almost always was a very small change usually located after each channel in a table. Any help would be greatly appreciated. Thank you for your awesome work!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/seemoo-lab/nexmon/issues/443, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACZ773URC56MOTXYFQIPWS3SP34DDANCNFSM4TVZCHOQ.

bm16ton commented 3 years ago

Oh my god! you my good sir are a genius! Thank you again for your awesome work. ill hafta put some time aside to do some reading

On Mon, Nov 16, 2020, 3:11 PM Matthias Schulz notifications@github.com wrote:

did you take a look into the restrictions.c file from our other nexmon based projects? such as the jammer? Did you read our paper on reactive jamming or my phd thesis? there you see what is possible with nexmon. you can even define non-standard channels, such as those with 80 MHz bandwidth in the 2.4 GHz band.

On 14. Nov 2020, at 22:54, bm16ton notifications@github.com wrote:

Hello, I see that the modified driver no longer shows the channels restrictions IE no IR, radar detection but they still exist in firmware. Im running a patched driver which also removes those flags, if I start an AP on a "no IR, radar detection" instead of immediately starting it takes a min...but it does start! The second machine connecting to the raspberry pi 4 has no restrictions so is doing active scans on that channel. I dont believe that is supposed to be enuff to allow the pi4 to start transmitting on those freqs. Im not sure if its just a bug or poor checking. What would be great is if we could remove those flags from the firmware!? Also maybe enable channels 12 13 14. I looked at the code here and is waay above my head. Old intel/atheros/realtek cards I was able to hack the firmware on to remove channels restrictions almost always was a very small change usually located after each channel in a table. Any help would be greatly appreciated. Thank you for your awesome work!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub < https://github.com/seemoo-lab/nexmon/issues/443>, or unsubscribe < https://github.com/notifications/unsubscribe-auth/ACZ773URC56MOTXYFQIPWS3SP34DDANCNFSM4TVZCHOQ .

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/seemoo-lab/nexmon/issues/443#issuecomment-728297541, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADAWMP72DIIXBLHIHLU3G43SQGBPVANCNFSM4TVZCHOQ .

salomoneli commented 3 years ago

Hi, I managed to remove the restrictions for the DFS channels in the 5 GHz band on the Raspberry Pi 4 (bcm43455c0). I found the following functions by reverse-engineering the firmware, which took me quite some time. So hopefully my solutions can help you.

There are two possibilities:

  1. You can simply call the function wlc_bmac_mute() in sendframe() before wlc_sendctl() is called.

    sendframe(struct wlc_info *wlc, struct sk_buff *p, unsigned int fifo, unsigned int rate)
    {
    char ret;
    
    // this unmutes the currently used channel and allows to send on "quiet/passive" channels
    wlc_bmac_mute(wlc->hw, 0, 0);
    
    if (wlc->band->bandtype == WLC_BAND_5G && rate < RATES_RATE_6M) {
        rate = RATES_RATE_6M;
    }
    
    if (wlc->hw->up) {
        ret = wlc_sendctl(wlc, p, wlc->active_queue, wlc->band->hwrs_scb, fifo, rate, 0);
    } else {
        ret = wlc_sendctl(wlc, p, wlc->active_queue, wlc->band->hwrs_scb, fifo, rate, 1);
    }
    return ret;
    }
  2. Or you can use my patch which avoids that channel restrictions are set during the initialization process at system startup. In this case you don't have to call the function as it is called automatically. I added the patch to the regulations.c file.
    // Overwrite the call to wlc_valid_chanspec_db() in wlc_radar_chanspec():
    //      - clear "quiet" setting for the channel (so that it doesn't get muted)
    //      - returns 0 to signal that it is not a radar sensitive channel
    int
    wlc_radar_chanspec_hook(void* wlc_cmi, unsigned short chanspec)
    {
    printf("%s: Hook successful!\n", __FUNCTION__);
    wlc_clr_quiet_chanspec(wlc_cmi, chanspec);
    return 0;
    }
    __attribute__((at(0x58a0e, "flashpatch", CHIP_VER_BCM43455c0, FW_VER_7_45_189)))
    BLPatch(wlc_valid_chanspec_db, wlc_radar_chanspec_hook);

Here are the addresses where I found the functions. Simply add the following lines to the local_wrapper.c or wrapper.c file:

AT(CHIP_VER_BCM43455c0, FW_VER_7_45_189, 0x49874)
void
wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool on, uint32 flags)
VOID_DUMMY

AT(CHIP_VER_BCM43455c0, FW_VER_7_45_189, 0x57b70)
void
wlc_clr_quiet_chanspec(void *wlc_cmi, unsigned short chanspec)
VOID_DUMMY
bm16ton commented 3 years ago

Im speechless! Thank you my friend. I envy your skills. I will test as soon as possible.

On Wed, Dec 16, 2020 at 12:47 PM Elli notifications@github.com wrote:

Hi, I managed to remove the restrictions for the DFS channels in the 5 GHz band on the Raspberry Pi 4 (bcm43455c0). I found the following functions by reverse-engineering the firmware, which took me quite some time. So hopefully my solutions can help you.

There are two possibilities:

  1. You can simply call the function wlc_bmac_mute() in sendframe() before wlc_sendctl() is called.

sendframe(struct wlc_info wlc, struct sk_buff p, unsigned int fifo, unsigned int rate) { char ret;

// this unmutes the currently used channel and allows to send on "quiet/passive" channels
wlc_bmac_mute(wlc->hw, 0, 0);

if (wlc->band->bandtype == WLC_BAND_5G && rate < RATES_RATE_6M) {
    rate = RATES_RATE_6M;
}

if (wlc->hw->up) {
    ret = wlc_sendctl(wlc, p, wlc->active_queue, wlc->band->hwrs_scb, fifo, rate, 0);
} else {
    ret = wlc_sendctl(wlc, p, wlc->active_queue, wlc->band->hwrs_scb, fifo, rate, 1);
}
return ret;

}

  1. Or you can use my patch which avoids that channel restrictions are set during the initialization process at system startup. In this case you don't have to call the function as it is called automatically. I added the patch to the regulations.c file.

// Overwrite the call to wlc_valid_chanspec_db() in wlc_radar_chanspec(): // - clear "quiet" setting for the channel (so that it doesn't get muted) // - returns 0 to signal that it is not a radar sensitive channel int wlc_radar_chanspec_hook(void* wlc_cmi, unsigned short chanspec) { printf("%s: Hook successful!\n", FUNCTION); wlc_clr_quiet_chanspec(wlc_cmi, chanspec); return 0; } attribute((at(0x58a0e, "flashpatch", CHIP_VER_BCM43455c0, FW_VER_7_45_189))) BLPatch(wlc_valid_chanspec_db, wlc_radar_chanspec_hook);

Here are the addresses where I found the functions. Simply add the following lines to the local_wrapper.c or wrapper.c file:

AT(CHIP_VER_BCM43455c0, FW_VER_7_45_189, 0x49874) void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool on, uint32 flags) VOID_DUMMY

AT(CHIP_VER_BCM43455c0, FW_VER_7_45_189, 0x57b70) void wlc_clr_quiet_chanspec(void *wlc_cmi, unsigned short chanspec) VOID_DUMMY

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/seemoo-lab/nexmon/issues/443#issuecomment-746715730, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADAWMP6T4OH5KMYBSO2NO4LSVDXERANCNFSM4TVZCHOQ .

bm16ton commented 3 years ago

Im sorry it took me so long to respond, IT WORKS GREAT! The channels are all open now (except the ones that are disabled) and the card can goto 31db tho it appears to have a lot of clipping at 31db which is way to high anyway. Iw still says max 20db, Tho im not currently using your kernel driver so maybe that reports correctly. I did have cfg80211 msgs saying having troubles setting txpower but that message and all others are now gone after switching to kernel 5.10. This is amazing. I know this must have taken a lot of time, and I truly appreciate it. Will you be adding this to the repo? If not I could throw it up on my github, tho i doubt anyone would find it. Lol. This is an amazing project. I think i saw something about using this on bluetooth Im curious as all hell about what projects that is/was being used on. I look forwarding to reading all about it

salomoneli commented 3 years ago

Hi, I'm very happy that it also works for you! I will add it to my repository, hopefully until next week. :)

and you're right, this project is really amazing!

bm16ton commented 3 years ago

So the jammer and sdr restrictions.c has what looks like a patch to add chspec's. Im not a programmer at all but it looks like the driver just compares the chspec's from firmware to in driver channel list and sets disabled to each channel without a chspec, this seems to be confirmed by adding printk in driver for the list of chspecs. So in theory i could change his 5339 patch for adding channels; unsigned short additional_valid_chanspecs[] = { CH20MHZ_CHSPEC(12), CH20MHZ_CHSPEC(13), CH20MHZ_CHSPEC(14), CH20MHZ_CHSPEC(34), };

int wlc_valid_chanspec_ext_hook(void *wlc_cm, unsigned short chanspec, int dualband) { int valid = wlc_valid_chanspec_ext(wlc_cm, chanspec, dualband); int i;

if (!valid && dualband == 1) for (i = 0; i < sizeof(additional_valid_chanspecs)/sizeof(additional_valid_chanspecs[0]); i++) valid |= additional_valid_chanspecs[i] == chanspec;

return valid;

}

attribute((at(0x5BA28, "flashpatch", CHIP_VER_BCM43455c0, FW_VER_7_45_189))) BPatch(wlc_valid_chanspec_ext, wlc_valid_chanspec_ext_hook)

and besides adding more then 20mhz I need to find the address for where to place the hook at, and change attribute((at(0x5BA28 to the correct address? Im a complete noob but if I open up the 5339 firmware and goto address 0x5BA28 is their any chance I will find something unique that I could search for in the 43455c0 firmware to get the address? I currently only have arm64 PC's so any suggestions for opensource decompilers would be much appreciated.

bm16ton commented 3 years ago

ops I see

attribute((weak)) attribute((at(0x0005ba28, "flashpatch"))) BPatch(flash_patch_83, 0x001adbb4);

in the bcm4339 firmware folder so i guess ill need something like that for the 43455c0. Hrm itcomplicates things but i found some reading on this and will hopefully have a grasp on that second part shortly.

bm16ton commented 3 years ago

im an idiot, everything is all there already I just need to make the patch.

bm16ton commented 3 years ago

The below patch work on raspi4 BCM43455c0, FW_VER_7_45_189. To add extra channels and enable the currently disabled ones in firmware.

pragma NEXMON targetregion "patch"

include

include

include

include

include

unsigned short additional_valid_chanspecs[] = { CH80MHZ_CHSPEC(6, WL_CHANSPEC_CTL_SB_L), CH20MHZ_CHSPEC(7), CH40MHZ_CHSPEC(7, WL_CHANSPEC_CTL_SB_L), CH80MHZ_CHSPEC(7, WL_CHANSPEC_CTL_SB_L), CH20MHZ_CHSPEC(7), CH40MHZ_CHSPEC(7, WL_CHANSPEC_CTL_SB_U), CH80MHZ_CHSPEC(7, WL_CHANSPEC_CTL_SB_U), CH20MHZ_CHSPEC(9), CH40MHZ_CHSPEC(9, WL_CHANSPEC_CTL_SB_L), CH80MHZ_CHSPEC(9, WL_CHANSPEC_CTL_SB_L), CH20MHZ_CHSPEC(12), CH40MHZ_CHSPEC(12, WL_CHANSPEC_CTL_SB_L), CH80MHZ_CHSPEC(12, WL_CHANSPEC_CTL_SB_L), CH20MHZ_CHSPEC(13), CH40MHZ_CHSPEC(13, WL_CHANSPEC_CTL_SB_L), CH80MHZ_CHSPEC(13, WL_CHANSPEC_CTL_SB_L), CH20MHZ_CHSPEC(14), CH40MHZ_CHSPEC(14, WL_CHANSPEC_CTL_SB_L), CH80MHZ_CHSPEC(14, WL_CHANSPEC_CTL_SB_L), CH20MHZ_CHSPEC(32), CH20MHZ_CHSPEC(34), CH40MHZ_CHSPEC(34, WL_CHANSPEC_CTL_SB_U), CH80MHZ_CHSPEC(34, WL_CHANSPEC_CTL_SB_U), CH20MHZ_CHSPEC(38), CH40MHZ_CHSPEC(38, WL_CHANSPEC_CTL_SB_U), CH80MHZ_CHSPEC(38, WL_CHANSPEC_CTL_SB_U), CH20MHZ_CHSPEC(42), CH40MHZ_CHSPEC(42, WL_CHANSPEC_CTL_SB_U), CH80MHZ_CHSPEC(42, WL_CHANSPEC_CTL_SB_U), CH20MHZ_CHSPEC(46), CH40MHZ_CHSPEC(46, WL_CHANSPEC_CTL_SB_U), CH80MHZ_CHSPEC(46, WL_CHANSPEC_CTL_SB_U), CH20MHZ_CHSPEC(106), CH40MHZ_CHSPEC(106, WL_CHANSPEC_CTL_SB_L), CH80MHZ_CHSPEC(106, WL_CHANSPEC_CTL_SB_L), CH20MHZ_CHSPEC(116), CH40MHZ_CHSPEC(118, WL_CHANSPEC_CTL_SB_L), CH80MHZ_CHSPEC(138, WL_CHANSPEC_CTL_SB_L), CH80MHZ_CHSPEC(122, WL_CHANSPEC_CTL_SB_L), CH20MHZ_CHSPEC(120),

if (NEXMON_CHIP == CHIP_VER_BCM43455c0)

0xe02a, // 36/80
0xe29b, // 157/80

endif

};

int wlc_valid_chanspec_ext_hook(void *wlc_cm, unsigned short chanspec, int dualband) { int valid = wlc_valid_chanspec_ext(wlc_cm, chanspec, dualband); int i;

if (!valid && dualband == 1)
    for (i = 0; i < sizeof(additional_valid_chanspecs)/sizeof(additional_valid_chanspecs[0]); i++)
        valid |= additional_valid_chanspecs[i] == chanspec;

return valid;

}

attribute((at(0x58eb6, "flashpatch", CHIP_VER_BCM43455c0, FW_VER_7_45_189))) attribute((at(0x5BA28, "flashpatch", CHIP_VER_BCM4339, FW_VER_6_37_32_RC23_34_43_r639704))) BPatch(wlc_valid_chanspec_ext, wlc_valid_chanspec_ext_hook)

// Overwrite the call to wlc_valid_chanspec_db() in wlc_radar_chanspec(): // - clear "quiet" setting for the channel (so that it doesn't get muted) // - returns 0 to signal that it is not a radar sensitive channel int wlc_radar_chanspec_hook(void* wlc_cmi, unsigned short chanspec) { printf("%s: Hook successful!\n", FUNCTION); wlc_clr_quiet_chanspec(wlc_cmi, chanspec); return 0; } attribute((at(0x58a0e, "flashpatch", CHIP_VER_BCM43455c0, FW_VER_7_45_189))) BLPatch(wlc_valid_chanspec_db, wlc_radar_chanspec_hook)

The kernel driver needs channels added to list as well, in drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c

static struct ieee80211_channel __wl_5ghz_channels[] = { CHAN5G(32), CHAN5G(34), CHAN5G(36), CHAN5G(38), CHAN5G(40), CHAN5G(42), CHAN5G(44), CHAN5G(46), CHAN5G(48), CHAN5G(52), CHAN5G(56), CHAN5G(60), CHAN5G(64), CHAN5G(100), CHAN5G(104), CHAN5G(108), CHAN5G(106), CHAN5G(112), CHAN5G(116), CHAN5G(120), CHAN5G(124), CHAN5G(128), CHAN5G(132), CHAN5G(136), CHAN5G(140), CHAN5G(144), CHAN5G(149), CHAN5G(153), CHAN5G(157), CHAN5G(161), CHAN5G(165) };

Depending on what channels you enable with this the REG_RULES also may need to be updated, in brcfmac/crda/and net.

I patched this kernel 5.10 with the following brcmfmac; Max txpower set to 31db (waay to high) Reg_rules opened up module param dump_chspec to dump chspec/flags to syslog nexmon patches

cfg80211/mac80211 removed built-in radar/no-ir restrictions removed lowering tx-power based off AP hints opened up built in reg_rules to be much more permissive kali monitor mode patches

userland regulatory.bin wireless_regdb and crda will probly need to be updated as well.

master branch; https://github.com/bm16ton/raspberrypi-kernel/