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

Example of promiscuous mode #4

Closed
redfast00 opened this issue Mar 30, 2017 · 15 comments
Closed

Example of promiscuous mode #4

redfast00 opened this issue Mar 30, 2017 · 15 comments

Comments

@redfast00
Copy link
Contributor

Hi, it seems that there is no example code of the ESP8266 in promiscuous mode, so I have a few questions:

  • Is this code able to capture packets of any size (>112 bytes)?
  • If so, how can you know the length of a packet?
  • Can you please supply some example code?
@ernacktob
Copy link
Owner

In the README I added an update explaining that the code does not enter true promiscuous mode (as with wifi_enable_promiscuous(1)), because I was unable to catch frames with MAC addresses not matching the devices' own address, or the broadcast address. I didn't make further research to find if that is possible without further reverse engineering efforts.

What it can do, is capture packets addressed to the device or broadcast. At the time when I wrote this, if I remember correctly, there was a limitation in the official sniffer API that allowed only less than 112 bytes to be sniffed. But I was able to get the full packet by tapping into more low-level functions and parsing the headers.

For example code, you can look in user_main.c, in the init_done() function. There is this function call: wifi_raw_set_recv_cb(my_recv_cb);

The wifi_raw_set_recv_cb just sets the rx_func callback (in wifi_raw.c) to point to the my_recv_cb function. The prototype for this callback is void ICACHE_FLASH_ATTR my_recv_cb(struct RxPacket *pkt). The struct RxPacket (defined in wifi_raw.h) contains the information on packet, as well as the data. The length is stored in the rx_ctl.legacy_length field.

The current example my_recv_cb just prints the full packet in hex and ascii format (like in the xxd dump format).

I haven't been able to test this further anymore because I don't have access to esp8266 device.

@redfast00
Copy link
Contributor Author

Just a quick follow-up question: what sdk version does this use?

@ernacktob
Copy link
Owner

ernacktob commented Mar 30, 2017

I don't remember on the top of my head, I'll get back to you later today when I get the chance to check. I really should have written this in the README, but apparently I forgot... sorry about that :S

@redfast00
Copy link
Contributor Author

I haven't been able to get it to receive anything. How does aaEnqueueRxq get called? After setup, I ran strings on the libraries and it doesn't contain aaEnqueueRxq, but it does contain ppEnqueueRxq. Should I also replace that? The README isn't really clear on that one.

@ernacktob
Copy link
Owner

ernacktob commented Mar 30, 2017

The original libraries have a ppEnqueueRxq symbol which is the one I was hooking into. The initial way I implemented the hooking was to create a copy of the libpp library (called libpp2.a). I explain this in the NOTES section of the README. The libpp2 has the symbol for ppEnqueueRxq replaced by symbol aaEnqueueRxq (a copy of this patched library is provided in the lib/ folder).

@tgoddard proposed a better way to hook into ppEnqueueRxq by using a linker option LD_FLAGS = ... -Wl,-wrap=ppEnqueueRxq. See this issue: #1
I have not implemented it myself but that might be an easier way to get this callback rather than patching the libraries like I was doing.

If you use the patched library, you have to also link against it instead of the original library. I have a Makefile2 that does this, so you can use make -f Makefile2 instead of make -f Makefile.

If you want to try tgoddard's method instead, you can use the original Makefile, but with appending to LDFLAGS that -Wl,-wrap=ppEnqueueRxq flag (and change the wifi_raw.c function aaEnqueueRxq to be called __wrap_ppEnqueueRxq.

@redfast00
Copy link
Contributor Author

I modified the libraries with the commands in the README and used the modified Makefile. When that failed, I tried to copy the included libraries, but that failed (I think it might be because of a version mismatch). Will definitely try out the mentioned alternative and maybe open a PR if it works.

@ernacktob
Copy link
Owner

ernacktob commented Mar 30, 2017

By curiosity, what kind of failure was it? Segfault? Or just the callback not getting called? But yeah, I would not be surprised if using different libraries than the version I have causes problems, because they might have changed the way binaries interface between each other, or changed the internal packet processing structures.

@redfast00
Copy link
Contributor Author

I finally got the receiving part working! 😄 Will submit a PR later on, but in short: I switched from modifying the libraries to adding a wrapper function as @tgoddard described. This is way cleaner, since we now don't have to worry about library versions (for others reading this, I am using v0.9.3). I'll have to check out the sending possibilities later, but I don't think it's much different from wifi_send_pkt_freedom() for the earlier versions of the SDK (pre-1.3.0). This also has the benefit that we don't have to change opmodes every time we want to send a packet (I don't know if this causes packetloss or performance issues, but it looks cleaner).

(BTW, the failure was basically that it wouldn't let me compile)

@ernacktob
Copy link
Owner

I am glad this worked out, and thankful for your efforts in actually trying this out.

@ernacktob
Copy link
Owner

ernacktob commented Mar 30, 2017

By the way, I suspect the compilation error you had was due to a missing reference to ppEnqueueRxq (which would be the case if you have overwritten all references to aaEnqueueRxq in libpp.a). But one of them must be kept to ppEnqueueRxq because it exports the real ppEnqueueRxq symbol that I call from the wrapper in wifi_raw.c. The other two symbols were, I think, some kinds of indirect GOT entries or something of that sort, and were those I had to overwrite to point to the aaEnqueueRxq.

But yeah, that thing was really kludgy and tgoddard's solution is much easier to implement, and probably much more portable.

Also another note, I earlier said that the length is in the rx_ctl.legacy_length field. I think this actually depends on the packet type. I read the official sniffer API docs where they describe the sniffer_buf and RxControl structs, and there is also the HT_length field which is used instead for some other kinds of packets. I don't know what was the distinction anymore though.

@ernacktob
Copy link
Owner

By the way, just so you know, the version of the SDK I was using is esp_iot_sdk_v1.2.0.
I will update the README to mention this clearly in case anyone else needs to know.

@redfast00
Copy link
Contributor Author

redfast00 commented Mar 31, 2017

I just tested my latest version (see #5) against v1.3.0. I am able to receive, and wifi_send_pkt_freedom works! This means that we are now able to send "arbitrary" packets (duration bytes still get zeroed, but we can send non-beacon packets) without changing mode. Will maybe open a PR later (maybe a c preprocessor thing and non-default).

I wonder how wifi_send_pkt_freedom works and if the duration bytes are set via hardware or software...

@redfast00
Copy link
Contributor Author

Also, is it currently possible to send shorter packets (no full 802.11 header)?

@ernacktob
Copy link
Owner

When you refer to wifi_send_pkt_freedom, is that the official packet injection API they offered in that one SDK version? I haven't played around with that.

But no even with the ppTxPkt wrapper, I haven't been able to send packets shorter than 19 bytes, and also the Duration ID always got set to 0. It's strange that wifi_set_pkt_freedom would do that too...

@redfast00
Copy link
Contributor Author

Yes, I meant wifi_send_pkt_freedom from sdk v1.3.0 (it got nerfed in the versions after that to only be able to send beacon packets ).

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

2 participants