commit 13a3f55bf82a911190e92e67466ddd4f4aefd47a Author: Nulo Date: Sun Oct 9 20:15:56 2022 -0300 Peronismo.exe diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8e0b8a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +libpcap-1.10.1 +libpcap-1.10.1.tar.gz +zig-cache +zig-out + diff --git a/build-pcap.sh b/build-pcap.sh new file mode 100644 index 0000000..21a8ae2 --- /dev/null +++ b/build-pcap.sh @@ -0,0 +1,15 @@ +#!/bin/sh +test -f libpcap-1.10.1.tar.gz || wget https://www.tcpdump.org/release/libpcap-1.10.1.tar.gz +tar xf libpcap-1.10.1.tar.gz +cd libpcap-1.10.1 +# export ZIG=~/.local/zig-linux-x86_64-0.10.0-dev.2836+2360f8c49/zig +export ZIG=zig # 0.9.1 +export CC="$ZIG cc -target mips-linux-musl" +export CFLAGS='-Os' +# https://jensd.be/1126/linux/cross-compiling-for-arm-or-aarch64-on-debian-or-ubuntu +# https://old.reddit.com/r/Zig/comments/lzqgxf/trying_to_crosscompile_to_mips_with_zig_cc/ +make clean +./configure \ + --host=mips-unknown-linux-musl \ + --with-pcap=linux LDFLAGS="-static" +make diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..b1046e0 --- /dev/null +++ b/build.zig @@ -0,0 +1,47 @@ +const std = @import("std"); + +pub fn build(b: *std.build.Builder) void { + // Standard target options allows the person running `zig build` to choose + // what target to build for. Here we do not override the defaults, which + // means any target is allowed, and the default is native. Other options + // for restricting supported target set are available. + const target = b.standardTargetOptions(.{}); + + // Standard release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("wifi-spammer", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.linkLibC(); + exe.linkSystemLibrary("pcap"); + + // exe.setTarget(.{ + // .cpu_arch = .mips, + // // .cpu_model = .{ .explicit = &std.Target.mips.cpu.mips32r2 }, + // .os_tag = .linux, + // .abi = .musl, + // }); + // exe.addLibPath("./libpcap-1.10.1/"); + // exe.addObjectFile("./libpcap-1.10.1/libpcap.a"); + // exe.addIncludeDir("./libpcap-1.10.1/"); + // exe.strip = true; + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); + + const exe_tests = b.addTest("src/main.zig"); + exe_tests.setTarget(target); + exe_tests.setBuildMode(mode); + + const test_step = b.step("test", "Run unit tests"); + test_step.dependOn(&exe_tests.step); +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..869297a --- /dev/null +++ b/readme.md @@ -0,0 +1,26 @@ +# wifi-spammer + +Anuncia redes inexistentes con los mensajes que quieras. + +Inspirado en [esp8266_beaconSpam](https://github.com/spacehuhn/esp8266_beaconSpam). Originalmente escrito en C, porteado y limpiado a Zig. + +## Bugs + +- Por alguna razón no siempre aparecen todas las redes, y gradualmente van apareciendo menos +- No pude cross-compilar a un router MIPS. Estuve varias horas. Queda, en build.zig, build-pcap.sh y upload.sh, mis intentos. + +## Empezar + +Poner tarjeta en monitor mode (no entiendo bien si es necesario porque no estamos monitoreando, pero por las dudas) + +```sh +doas ip link set wlan0 down && \ +doas iw wlan0 set monitor control && \ +doas ip link set wlan0 up +``` + +Compilar y ejecutar como root. Actualmente asume que tu placa de red es `wlan0`. + +```sh +zig build && doas ./zig-out/bin/wifi-spammer +``` diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 0000000..1994e4f --- /dev/null +++ b/src/main.zig @@ -0,0 +1,172 @@ +const std = @import("std"); +const c = @cImport({ + @cInclude("pcap/pcap.h"); +}); + +const ByteList = std.ArrayList(u8); + +// https://www.devdungeon.com/content/using-libpcap-c#sending-packets +// https://mrncciew.com/2014/10/08/802-11-mgmt-beacon-frame/ +// https://github.com/spacehuhn/esp8266_beaconSpam/blob/master/esp8266_beaconSpam/esp8266_beaconSpam.ino + +fn radioTapHeader(list: *ByteList) !void { + try list.appendSlice(&[_]u8{ + 0x00, 0x00, 0x12, 0x00, 0x2e, 0x48, 0x00, 0x00, 0x10, 0x02, 0x6c, 0x09, 0xa0, 0x00, 0xbe, 0x07, + 0x00, 0x00, + }); +} +fn macHeader(list: *ByteList, srcAddress: [6]u8, seq_ctl: u16) !void { + try list.appendSlice(&[_]u8{ + // zig fmt: off + 0x80, 0x00, 0x00, 0x00, // Type/Subtype: managment beacon frame + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // Destination: broadcast + }); + // zig fmt: on + try list.appendSlice(&srcAddress); + try list.appendSlice(&srcAddress); + try list.appendSlice(std.mem.asBytes(&seq_ctl)); +} +fn frameHeader(list: *ByteList) !void { + try list.appendSlice(&[_]u8{ + // timestamp + 0x83, 0x51, 0xf7, 0x8f, 0x0f, 0x00, 0x00, 0x00, + // Interval: 0x64, 0x00 => every 100ms - 0xe8, 0x03 => every 1s + 0x64, 0x00, + // Capability info + 0x21, 0x00, + }); +} +fn ssidTag(list: *ByteList, ssid: []const u8) !void { + try list.append(0x00); // type + std.debug.assert(ssid.len < 256); + try list.append(@intCast(u8, ssid.len)); + try list.appendSlice(ssid); +} +fn otherTags(list: *ByteList) !void { + try list.appendSlice(&[_]u8{ + // Supported Rates + 0x01, 0x08, // Tag: Supported Rates, Tag length: 8 + 0x82, // 1(B) + 0x84, // 2(B) + 0x8b, // 5.5(B) + 0x96, // 11(B) + 0x24, // 18 + 0x30, // 24 + 0x48, // 36 + 0x6c, // 54 + + // Current Channel + 0x03, 0x01, // Channel set, length + 0x01, // Current Channel + + // RSN information + // 0x30, + // 0x18, + // 0x01, + // 0x00, + // 0x00, + // 0x0f, + // 0xac, + // 0x02, + // 0x02, + // 0x00, + // 0x00, 0x0f, 0xac, 0x04, 0x00, 0x0f, 0xac, 0x04, //Fix: changed 0x02(TKIP) to 0x04(CCMP) is default. WPA2 with TKIP not supported by many devices + // 0x01, 0x00, 0x00, 0x0f, 0xac, 0x02, 0x00, 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + }); +} + +fn buildPacket(allocator: std.mem.Allocator, ssid: []const u8, mac: [6]u8, seq_ctl: u16) ![]const u8 { + var list = ByteList.init(allocator); + errdefer list.deinit(); + + try radioTapHeader(&list); + try macHeader(&list, mac, seq_ctl); + try frameHeader(&list); + try ssidTag(&list, ssid); + try otherTags(&list); + + // std.mem.bytesAsValue(u32, packet[packet.len - 4 .. packet.len]).* = std.hash.Crc32.hash(packet[18 .. packet.len - 18 - 4]); + + try list.appendSlice(std.mem.asBytes(&std.hash.Crc32.hash( + // exclude Radiotap header + list.items[18 .. list.items.len - 18]))); + + return list.toOwnedSlice(); +} + +pub fn main() anyerror!void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + + var error_buffer: [c.PCAP_ERRBUF_SIZE:0]u8 = undefined; + var alldevsp: ?*c.pcap_if_t = undefined; + if (c.pcap_findalldevs(&alldevsp, &error_buffer) != 0) { + std.log.err("Error finding device: {s}", .{error_buffer}); + return error.FindingDevice; + } + if (alldevsp == null) { + std.log.err("No devices", .{}); + return error.NoDevices; + } + defer c.pcap_freealldevs(alldevsp); + + var device: ?*c.pcap_if_t = alldevsp; + var handle: ?*c.pcap_t = null; + while (device != null) { + if (std.mem.eql(u8, std.mem.span(device.?.name), "wlan0")) { + std.log.info("Network device found: {s}", .{device.?.name}); + handle = c.pcap_open_live(device.?.name, c.BUFSIZ, 0, 10000, &error_buffer); + if (handle == null) { + std.log.err("Error opening device: {s}", .{error_buffer}); + return error.OpeningDevice; + } + break; + } + device = device.?.next; + } + if (handle == null) { + std.log.err("Didn't find interface", .{}); + return error.NoInterface; + } + + var prng = std.rand.DefaultPrng.init(@intCast(u64, std.time.timestamp())); + var base_mac: [5]u8 = undefined; + prng.fill(&base_mac); + + var seq: u12 = 0; + while (true) : (seq +|= 1) { + for (ssids) |ssid, index| { + const mac = [6]u8{ base_mac[0], base_mac[1], base_mac[2], base_mac[3], base_mac[4], @intCast(u8, index) }; + + var packet_n: usize = 0; + std.log.info("Advertising {s}", .{ssid}); + while (packet_n < 1) : (packet_n += 1) { + const seq_ctl: u16 = @as(u16, seq) << 4; + const packet = try buildPacket(allocator, ssid, mac, seq_ctl); + defer allocator.free(packet); + + if (c.pcap_sendpacket(handle, packet.ptr, @intCast(c_int, packet.len)) != 0) { + std.log.err("Error sending packet: {s}", .{error_buffer}); + return error.SendingPacket; + } + std.time.sleep(1 * std.time.ns_per_ms); + } + } + std.time.sleep(100 * std.time.ns_per_ms); + } + + std.log.info("All your codebase are belong to us.", .{}); +} + +const ssids = [_][]const u8{ + // "viva peron!!", "viva evita!!", "viva aaron!!", + // "antifascista", "4ntifascista", "antifasc1sta", + // "an7ifascista", + // "antifa5cista", + "!molestooo10", "!molestooo11", "!molestooo12", "!molestooo13", "!molestooo14", "!molestooo15", "!molestooo16", "!molestooo17", "!molestooo18", "!molestooo19", "!molestooo20", "!molestooo21", "!molestooo22", "!molestooo23", "!molestooo24", "!molestooo25", "!molestooo26", "!molestooo27", "!molestooo28", "!molestooo29", "!molestooo30", "!molestooo31", "!molestooo32", "!molestooo33", "!molestooo34", "!molestooo35", "!molestooo36", "!molestooo37", "!molestooo38", "!molestooo39", "!molestooo40", "!molestooo41", "!molestooo42", "!molestooo43", "!molestooo44", "!molestooo45", "!molestooo46", "!molestooo47", "!molestooo48", "!molestooo49", "!molestooo50", // "!molestooo51", "!molestooo52", "!molestooo53", "!molestooo54", "!molestooo55", "!molestooo56", "!molestooo57", "!molestooo58", "!molestooo59", "!molestooo60", "!molestooo61", "!molestooo62", "!molestooo63", "!molestooo64", "!molestooo65", "!molestooo66", "!molestooo67", "!molestooo68", "!molestooo69", "!molestooo70", "!molestooo71", "!molestooo72", "!molestooo73", "!molestooo74", "!molestooo75", "!molestooo76", "!molestooo77", "!molestooo78", "!molestooo79", "!molestooo80", "!molestooo81", "!molestooo82", "!molestooo83", "!molestooo84", "!molestooo85", "!molestooo86", "!molestooo87", "!molestooo88", "!molestooo89", "!molestooo90", "!molestooo91", "!molestooo92", "!molestooo93", "!molestooo94", "!molestooo95", "!molestooo96", "!molestooo97", "!molestooo98", "!molestooo99", +}; diff --git a/upload.sh b/upload.sh new file mode 100644 index 0000000..79df01f --- /dev/null +++ b/upload.sh @@ -0,0 +1,4 @@ +#!/bin/sh +#~/.local/zig-linux-x86_64-0.10.0-dev.2836+2360f8c49/zig build +zig build +ssh root@192.168.1.1 'cat - > /tmp/wifi-spammer' < zig-out/bin/wifi-spammer