├── src ├── tunnel.h ├── client.h ├── raw.h ├── tunnel.c ├── raw.c └── client.c ├── client.exe ├── WpdPack └── required.txt ├── Makefile ├── LICENSE └── README /src/tunnel.h: -------------------------------------------------------------------------------- 1 | void tunnel_start(char * targetip, char * localip, int port); 2 | -------------------------------------------------------------------------------- /client.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/Layer2-Pivoting-Client/master/client.exe -------------------------------------------------------------------------------- /WpdPack/required.txt: -------------------------------------------------------------------------------- 1 | To build this VPN client, you will need the WinPcap Developer's Pack. 2 | 3 | http://www.winpcap.org/devel.htm 4 | 5 | Download it and make sure its contents extract to this folder. 6 | 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=i686-w64-mingw32-gcc 2 | LIB_WPCAP=./WpdPack/Lib 3 | INC_WPCAP=./WpdPack/Include 4 | 5 | client.exe: src/client.c src/raw.c src/tunnel.c 6 | $(CC) -I $(INC_WPCAP) -L $(LIB_WPCAP) src/*.c -o client.exe -lws2_32 -lwpcap 7 | 8 | clean: 9 | rm -f client.exe 10 | -------------------------------------------------------------------------------- /src/client.h: -------------------------------------------------------------------------------- 1 | /* receive an ethernet frame [size][buffer] */ 2 | int client_recv_frame(SOCKET ch, void * buffer, int maxlength); 3 | 4 | /* send an ethernet frame */ 5 | void client_send_frame(SOCKET ch, void * buffer, int len); 6 | 7 | /* Construct a TCP channel */ 8 | SOCKET client_connect(char * targetip, int port); 9 | -------------------------------------------------------------------------------- /src/raw.h: -------------------------------------------------------------------------------- 1 | pcap_t * raw_start(char * localip, char * filterme); 2 | void raw_loop(pcap_t * adhandle, void (*packet_handler)(u_char *, const struct pcap_pkthdr *, const u_char *)); 3 | 4 | /* list all of the interfaces to stdout */ 5 | void raw_list(); 6 | 7 | /* adjust the BPF associated with the device */ 8 | void raw_filter(pcap_t * handle, char * localip, char * targetip, char * filter); 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Strategic Cyber LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those 25 | of the authors and should not be interpreted as representing official policies, 26 | either expressed or implied, of the FreeBSD Project. 27 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | .------------------------. 2 | | Layer-2 Pivoting Client >------------------------------------------------------- 3 | `------------------------' 4 | 5 | This code is a simple client to demonstrate Layer-2 pivoting* with the Windows 6 | PCAP library. It's designed to connect to the simpletun.c server by Davide Brini. 7 | 8 | http://backreference.org/2010/03/26/tuntap-interface-tutorial/ 9 | 10 | The simpletun.c server may crash, occasionally, if you leave BUFSIZE at line 11 | 42 set to the default. Consider setting it to a higher value (e.g., 8192). 12 | 13 | The tutorial that accompanies this code is at: 14 | 15 | http://blog.cobaltstrike.com/2014/10/14/how-vpn-pivoting-works-with-source-code/ 16 | 17 | Build 18 | ~~~~~ 19 | Before you can build the layer-2 pivoting client, you must download the WinPCAP 20 | Developer's Kit. This doesn't change too often. Just download the ZIP file 21 | and unzip into this folder [such that there's a ./WpdPack folder in the same 22 | folder as this README]. 23 | 24 | http://www.winpcap.org/devel.htm 25 | 26 | The Makefile is setup to build the Layer-2 client on Kali Linux [I know, right?]. 27 | To build it, type 'make'. 28 | 29 | Use 30 | ~~~ 31 | 32 | 1. Start a server with simpletun: 33 | 34 | ./simpletun -i [interface] -s -p [port] -a 35 | 36 | 2. Install WinPcap on client system 37 | 38 | http://www.winpcap.org/install/default.htm 39 | 40 | 3. Start the client 41 | 42 | client.exe [server] [port] [localip] 43 | 44 | 4. On the server system, configure an IP address: 45 | 46 | ifconfig [interface] [target net IP] [mask] 47 | 48 | or request an IP address with a DHCP client: 49 | 50 | dhclient [interface] 51 | 52 | Author? 53 | ~~~~~~~ 54 | (c) 2014 Raphael Mudge, Strategic Cyber LLC 55 | http://www.advancedpentest.com/ 56 | 57 | See LICENSE for license information. 58 | -------------------------------------------------------------------------------- /src/tunnel.c: -------------------------------------------------------------------------------- 1 | #include "pcap.h" 2 | #include "client.h" 3 | #include "raw.h" 4 | 5 | /* prototype of the packet handler */ 6 | void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); 7 | 8 | /* make this global */ 9 | static SOCKET server; 10 | static pcap_t * sniffer; 11 | 12 | DWORD ThreadProc(LPVOID parm); 13 | 14 | void tunnel_start(char * targetip, int port, char * localip) { 15 | 16 | /* first... connect to our VPN server */ 17 | server = client_connect(targetip, port); 18 | 19 | /* makes the specified interface start sniffing */ 20 | sniffer = raw_start(localip, targetip); 21 | 22 | /* start reading stuff */ 23 | CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ThreadProc, (LPVOID) NULL, 0, NULL); 24 | 25 | /* start looping... */ 26 | raw_loop(sniffer, packet_handler); 27 | } 28 | 29 | DWORD ThreadProc(LPVOID param) { 30 | char * buffer = malloc(sizeof(char) * 65536); 31 | int len, result; 32 | unsigned short action; 33 | 34 | while (TRUE) { 35 | len = client_recv_frame(server, buffer, 65536); 36 | 37 | /* inject the frame we received onto the wire directly */ 38 | result = pcap_sendpacket(sniffer, (u_char *)buffer, len); 39 | if (result == -1) { 40 | printf("Send packet failed: %d\n", len); 41 | } 42 | } 43 | } 44 | 45 | /* Callback function invoked by libpcap for every incoming packet */ 46 | void packet_handler(u_char * param, const struct pcap_pkthdr * header, const u_char * pkt_data) { 47 | /* send the raw frame to our server */ 48 | client_send_frame(server, (void *)pkt_data, header->len); 49 | } 50 | 51 | int main(int argc, char * argv[]) { 52 | /* check the args.. */ 53 | if (argc != 4) { 54 | printf("%s [remote ip] [port] [local ip]\n", argv[0]); 55 | return 0; 56 | } 57 | 58 | tunnel_start(argv[1], atoi(argv[2]), argv[3]); 59 | return 0; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /src/raw.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Code for managing raw access to network resources 3 | */ 4 | #include 5 | #include 6 | #include "pcap/pcap.h" 7 | #define PCAP_OPENFLAG_PROMISCUOUS 1 8 | #define PCAP_OPENFLAG_NOCAPTURE_LOCAL 8 9 | #include "client.h" 10 | 11 | /* filter out a host */ 12 | void raw_filter_internal(pcap_t * handle, pcap_if_t * device, char * targetip, char * filter) { 13 | u_int netmask; 14 | char packet_filter[256]; 15 | struct bpf_program fcode; 16 | 17 | /* setup our BPF filter */ 18 | if (filter == NULL) { 19 | _snprintf(packet_filter, 256, "not host %s", targetip); 20 | } 21 | else { 22 | _snprintf(packet_filter, 256, "(%s) && not host %s", targetip, filter); 23 | } 24 | 25 | /* try to determine the netmask of our device */ 26 | if (device->addresses != NULL) 27 | netmask = ((struct sockaddr_in*)(device->addresses->netmask))->sin_addr.S_un.S_addr; 28 | else 29 | netmask = 0xffffff; 30 | 31 | /* compile our pcap filter */ 32 | if (pcap_compile(handle, &fcode, packet_filter, 1, netmask)) { 33 | printf("Could not compile the filter: %s\n", targetip); 34 | return; 35 | } 36 | 37 | /* set it up */ 38 | if (pcap_setfilter(handle, &fcode) < 0) { 39 | printf("Could not set the filter\n"); 40 | } 41 | } 42 | 43 | pcap_if_t * find_interface(pcap_if_t ** alldevs, char * localip) { 44 | pcap_if_t * d; 45 | char errbuf[PCAP_ERRBUF_SIZE + 128]; 46 | struct pcap_addr * addr; 47 | 48 | /* Retrieve the device list on the local machine */ 49 | if (pcap_findalldevs_ex("rcap://", NULL, alldevs, errbuf) == -1) { 50 | printf("Error in pcap_findalldevs: %s\n", errbuf); 51 | exit(1); 52 | } 53 | 54 | for (d = *alldevs; d; d = d->next) { 55 | for (addr = d->addresses; addr; addr = addr->next) { 56 | char * checkme = inet_ntoa(((struct sockaddr_in *)addr->addr)->sin_addr); 57 | if (strcmp(checkme, localip) == 0) 58 | return d; 59 | } 60 | } 61 | 62 | printf("Interface for '%s' not found\n", localip); 63 | exit(0); 64 | } 65 | 66 | pcap_t * raw_start(char * localip, char * filterip) { 67 | pcap_t * adhandle = NULL; 68 | pcap_if_t * d = NULL; 69 | pcap_if_t * alldevs = NULL; 70 | char errbuf[PCAP_ERRBUF_SIZE]; 71 | 72 | /* find out interface */ 73 | d = find_interface(&alldevs, localip); 74 | 75 | /* Open the device */ 76 | adhandle = (pcap_t *)pcap_open(d->name, 65536, PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_NOCAPTURE_LOCAL, 1, NULL, errbuf); 77 | if (adhandle == NULL) { 78 | printf("\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name); 79 | return NULL; 80 | } 81 | 82 | /* filter out the specified host */ 83 | raw_filter_internal(adhandle, d, filterip, NULL); 84 | 85 | /* ok, now we can free out list of interfaces */ 86 | pcap_freealldevs(alldevs); 87 | 88 | return adhandle; 89 | } 90 | 91 | void raw_loop(pcap_t * adhandle, void (*packet_handler)(u_char *, const struct pcap_pkthdr *, const u_char *)) { 92 | pcap_loop(adhandle, 0, packet_handler, NULL); 93 | } 94 | -------------------------------------------------------------------------------- /src/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "client.h" 4 | 5 | static int is_winsock_initialized = 0; 6 | 7 | /* 8 | * Initialize Winsock. This only needs to happen once. 9 | */ 10 | void client_winsock_init() { 11 | WSADATA wsaData; 12 | WORD wVersionRequested; 13 | 14 | if (is_winsock_initialized == 1) 15 | return; 16 | 17 | wVersionRequested = MAKEWORD(2, 2); 18 | 19 | /* try to init winsock library */ 20 | if (WSAStartup(wVersionRequested, &wsaData) < 0) { 21 | printf("ws2_32.dll is out of date.\n"); 22 | WSACleanup(); 23 | exit(1); 24 | } 25 | 26 | is_winsock_initialized = 1; 27 | } 28 | 29 | /* recv all with some other data */ 30 | int recv_all(SOCKET MySock, char * buffer, int len) { 31 | int tret = 0; 32 | int nret = 0; 33 | char * startb = buffer; 34 | while (tret < len) { 35 | nret = recv(MySock, (char *)startb, len - tret, 0); 36 | startb += nret; 37 | tret += nret; 38 | 39 | if (nret == SOCKET_ERROR) { 40 | closesocket(MySock); 41 | WSACleanup(); 42 | printf("Attempt to receive %d/%d bytes FAILED!\n", tret, len); 43 | exit(1); 44 | } 45 | } 46 | return tret; 47 | } 48 | 49 | /* receive a frame from the wire */ 50 | /* post a frame to the wire */ 51 | int client_recv_frame(SOCKET MySock, void * buffer, int maxlength) { 52 | int nret; 53 | unsigned short len; 54 | 55 | /* read a 2 byte short indicating size of frame to read */ 56 | nret = recv_all(MySock, (char *)&len, sizeof(unsigned short)); 57 | len = ntohs(len); 58 | 59 | /* do the standard error checking */ 60 | if (nret == SOCKET_ERROR) { 61 | printf("Size receive corrupt\n"); 62 | } 63 | 64 | /* sanity check for the length value */ 65 | if (len > maxlength) { 66 | printf("Read len is too large\n"); 67 | closesocket(MySock); 68 | WSACleanup(); 69 | exit(1); 70 | } 71 | 72 | /* read the actual frame into our buffer */ 73 | //printf("Will read: %d (was %d) from wire\n", len, htons(len)); 74 | nret = recv_all(MySock, (char *)buffer, len); 75 | 76 | return nret; 77 | } 78 | 79 | void client_send_frame(SOCKET MySock, void * buffer, int len) { 80 | unsigned short sz; 81 | int nret; 82 | 83 | /* convert our 2-byte value to network byte order */ 84 | sz = htons(len); 85 | 86 | /* write a 2 byte short indicating size of frame to read */ 87 | nret = send(MySock, (char *)&sz, sizeof(unsigned short), 0); 88 | 89 | /* do the standard error checking */ 90 | if (nret == SOCKET_ERROR) { 91 | printf("send is corrupt!\n"); 92 | closesocket(MySock); 93 | WSACleanup(); 94 | exit(1); 95 | } 96 | 97 | /* write the actual frame to the network */ 98 | nret = send(MySock, (char *)buffer, len, 0); 99 | 100 | if (nret == SOCKET_ERROR) { 101 | printf("Attempt to write data FAILED!\n"); 102 | } 103 | } 104 | 105 | SOCKET client_connect(char * targetip, int port) { 106 | struct hostent * pTarget; 107 | struct sockaddr_in sock; 108 | SOCKET MySock; 109 | 110 | /* initialize the winsock library */ 111 | client_winsock_init(); 112 | 113 | /* setup our socket */ 114 | MySock = socket(AF_INET, SOCK_STREAM, 0); 115 | if (MySock == INVALID_SOCKET) { 116 | printf("Socket error\r\n"); 117 | closesocket(MySock); 118 | WSACleanup(); 119 | exit(1); 120 | } 121 | 122 | /* resolve our target */ 123 | pTarget = gethostbyname(targetip); 124 | if (pTarget == NULL) { 125 | printf("Could not resolve %s\n", targetip); 126 | closesocket(MySock); 127 | WSACleanup(); 128 | exit(1); 129 | } 130 | 131 | /* copy our target information into the sock */ 132 | memcpy(&sock.sin_addr.s_addr, pTarget->h_addr, pTarget->h_length); 133 | sock.sin_family = AF_INET; 134 | sock.sin_port = htons(port); 135 | 136 | /* issue our connection */ 137 | if ( connect(MySock, (struct sockaddr *)&sock, sizeof(sock)) ) { 138 | printf("Couldn't connect to host.\n"); 139 | closesocket(MySock); 140 | WSACleanup(); 141 | exit(1); 142 | } 143 | 144 | return MySock; 145 | } 146 | --------------------------------------------------------------------------------