Created
April 12, 2024 14:14
-
-
Save sgarwood/c60883ad2921893d1e9def4bd22b0728 to your computer and use it in GitHub Desktop.
vigor_130_dsl_broadcast_parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <openssl/sha.h> | |
| #include "stdio.h" | |
| #include <string.h> | |
| #include <linux/ip.h> | |
| #include "lib/tiny-AES-c/aes.h" | |
| #include <netinet/in.h> | |
| #include <sys/socket.h> | |
| #include <unistd.h> | |
| #include <arpa/inet.h> | |
| #include "net/ethernet.h" | |
| #include "netinet/ether.h" | |
| #include "arpa/inet.h" | |
| #include <stdio.h> | |
| #include <assert.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <sys/types.h> | |
| #include <linux/in.h> | |
| #include <sys/socket.h> | |
| #include <sys/select.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <openssl/sha.h> | |
| #include <netinet/in.h> | |
| #include <malloc.h> | |
| #include <stdio.h> /* for printf() and fprintf() */ | |
| #include <sys/socket.h> /* for socket(), connect(), sendto(), and recvfrom() */ | |
| #include <arpa/inet.h> /* for sockaddr_in and inet_addr() */ | |
| #include <stdlib.h> /* for atoi() and exit() */ | |
| #include <string.h> /* for memset() */ | |
| #include <unistd.h> /* for close() */ | |
| #define MAXRECVSTRING 116 /* Longest string to receive */ | |
| struct DSBuffer { | |
| uint32_t wanIdx; // 0 idx of WAN? | |
| uint32_t vdslupspeed; // 4 | |
| uint32_t vdsldownspeed; // 8 | |
| uint32_t adsltxcell; // 12 | |
| uint32_t adslrxcell; // 16 | |
| uint32_t adsltxcrce; // 20 | |
| uint32_t adslrxcrce; // 24 | |
| uint32_t dsltype; // 28 | |
| uint32_t timestamp; // 32 | |
| uint32_t vdslsnrup; // 36 | |
| uint32_t vdslsnrdown; // 40 | |
| uint32_t adslloop; // 44 | |
| uint32_t adslsnrm; // 48 | |
| char fw_ver[20]; // 52 | |
| char profile[4]; // 72 --vdslprofile or adslmode | |
| char pad[14]; // | |
| char state[14]; // 90 | |
| // 94 total bytes | |
| // 116 - 104 = bytes left of space | |
| uint8_t a[12]; | |
| }; | |
| void print_upspeed(struct DSBuffer *dslBuffer) { | |
| printf("Upspeed: %u(Kbps)\n", ntohl(dslBuffer->vdslupspeed) / 1000); | |
| } | |
| void print_downspeed(struct DSBuffer *dslBuffer) { | |
| printf("Downspeed: %u(Kbps)\n", ntohl(dslBuffer->vdsldownspeed) / 1000); | |
| } | |
| void print_snrdown(struct DSBuffer *dslBuffer) { | |
| printf("SNR Down: %d\n", ntohl(dslBuffer->vdslsnrdown)); | |
| } | |
| void print_snrup(struct DSBuffer *dslBuffer) { | |
| printf("SNR Up: %d\n", ntohl(dslBuffer->vdslsnrup)); | |
| } | |
| void print_downspeed_in_mbps(struct DSBuffer *dslBuffer) { | |
| // Convert from network byte order (big-endian) to host byte order (assumed LSB) | |
| uint32_t downspeed_host_order = ntohl(dslBuffer->vdsldownspeed); | |
| // Extract the actual download speed in bits per second (bps) | |
| uint32_t downspeed_bps = downspeed_host_order; | |
| // Integer division for Mbps (rounded down) | |
| uint32_t mbps_integer = downspeed_bps / 1000000; // Division by 1 million for Mbps | |
| // Print the download speed in Mbps (rounded down) | |
| printf("Download speed: %u Mbps\n", mbps_integer); | |
| } | |
| void print_dsltype(struct DSBuffer *dslBuffer) { | |
| printf("xDSL Type: %u (6 = vdsl, 1 = adsl)\n", ntohl(dslBuffer->dsltype)); | |
| } | |
| void print_wan(struct DSBuffer *dslBuffer) { | |
| printf("WAN IDX: %u\n", dslBuffer->wanIdx); | |
| } | |
| void print_timestamp(struct DSBuffer *dslBuffer) { | |
| printf("Timestamp: %u\n", ntohl(dslBuffer->timestamp)); | |
| } | |
| void print_fwver(struct DSBuffer *dsBuffer) { | |
| printf("fwver: %.*s\n", 19, dsBuffer->fw_ver); | |
| } | |
| void print_vdslprf(struct DSBuffer *dsBuffer) { | |
| printf("vdsl profile: %s\n", dsBuffer->profile); | |
| } | |
| void print_vdslstate(struct DSBuffer *dsBuffer) { | |
| printf("vdsl state: %s\n", dsBuffer->state); | |
| } | |
| int decryptDslBuffer( | |
| uint8_t *encryptedBuffer, | |
| struct DSBuffer *dsBuffer, | |
| const struct ether_addr *macAddr | |
| ) { | |
| const unsigned char magicref[4] = {0x20, 0x52, 0x05, 0x20}; | |
| if (memcmp((unsigned char *) encryptedBuffer, magicref, 4) != 0) { | |
| return -2; | |
| printf("Incorrect magic byte"); | |
| } | |
| uint8_t messageDigest[SHA_DIGEST_LENGTH]; | |
| uint8_t key[SHA_DIGEST_LENGTH * 2]; | |
| uint8_t iv[24]; | |
| memset(key, 0x0, 17); | |
| memset(iv, 0x0, 17); | |
| SHA1((uint8_t *) macAddr, ETH_ALEN, messageDigest); | |
| int i; | |
| int j = 0; | |
| for (i = 0; (j < SHA_DIGEST_LENGTH && i < 10); i += 2) { | |
| sprintf((char *) &key[i], "%02X", messageDigest[j]); | |
| j++; | |
| } | |
| // Use first 17 bytes of SHA1 as IV, 16th byte is null terminator | |
| memcpy(iv, key, 17); | |
| // printf("%s\n", iv); | |
| // printf("%s\n", key); | |
| memcpy(dsBuffer, encryptedBuffer, 116); | |
| struct AES_ctx aesCtx; | |
| AES_init_ctx_iv(&aesCtx, key, iv); | |
| // Skip first 4 bytes (magic bytes) | |
| AES_CBC_decrypt_buffer(&aesCtx, ((uint8_t *) dsBuffer) + sizeof(magicref), 112); | |
| return 0; | |
| } | |
| _Noreturn void handleSocket(char *macAddress) { | |
| int sock; /* Socket */ | |
| struct sockaddr_in broadcastAddr; /* Broadcast Address */ | |
| unsigned short broadcastPort; /* Port */ | |
| unsigned char recvString[MAXRECVSTRING + 1]; /* Buffer for received string */ | |
| size_t recvStringLen; /* Length of received string */ | |
| fd_set readfd; | |
| int ret; | |
| struct sockaddr_in client_addr; | |
| struct sockaddr_in server_addr; | |
| socklen_t addr_len; | |
| struct DSBuffer dslData; | |
| struct ether_addr macAddr; | |
| ether_aton_r(macAddress, &macAddr); | |
| broadcastPort = 4944; | |
| /* Create a best-effort datagram socket using UDP */ | |
| if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) | |
| printf("socket() failed"); | |
| /* Construct bind structure */ | |
| memset(&broadcastAddr, 0, sizeof(broadcastAddr)); /* Zero out structure */ | |
| broadcastAddr.sin_family = AF_INET; /* Internet address family */ | |
| broadcastAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ | |
| broadcastAddr.sin_port = htons(broadcastPort); /* Broadcast port */ | |
| /* Bind to the broadcast port */ | |
| if (bind(sock, (struct sockaddr *) &broadcastAddr, sizeof(broadcastAddr)) < 0) | |
| printf("bind() failed"); | |
| while (1) { | |
| FD_ZERO(&readfd); | |
| FD_SET(sock, &readfd); | |
| ret = select(sock + 1, &readfd, NULL, NULL, 0); | |
| if (ret > 0) { | |
| if (FD_ISSET(sock, &readfd)) { | |
| recvStringLen = recvfrom( | |
| sock, | |
| recvString, | |
| MAXRECVSTRING, | |
| 0, | |
| (struct sockaddr *) &client_addr, | |
| &addr_len | |
| ); | |
| if (recvStringLen != 116) { | |
| printf("Incorrect number of bytes recvd!"); | |
| continue; | |
| } | |
| printf( | |
| "Received UDP Datagram of correct size: using Key %s to decrypt contents\n", | |
| ether_ntoa(&macAddr) | |
| ); | |
| decryptDslBuffer(recvString, &dslData, &macAddr); | |
| // printf("Size of DSLBuffer: %lu\n", sizeof(struct DSBuffer)); | |
| assert(sizeof(struct DSBuffer) == 116); | |
| print_dsltype(&dslData); | |
| print_downspeed(&dslData); | |
| print_downspeed_in_mbps(&dslData); | |
| print_upspeed(&dslData); | |
| print_snrdown(&dslData); | |
| print_snrup(&dslData); | |
| print_wan(&dslData); | |
| print_timestamp(&dslData); | |
| print_fwver(&dslData); | |
| print_vdslprf(&dslData); | |
| print_vdslstate(&dslData); | |
| printf("=================================================================\n"); | |
| } | |
| } | |
| } | |
| } | |
| int main(int argn, char *argv[]) { | |
| if (argn != 2) { | |
| printf("Usage:\n"); | |
| printf("%s <mac address of Vigor 130 DSL Modem>\n", argv[0]); | |
| printf("e.g. %s aa:bb:cc:dd:ee:ff\n", argv[0]); | |
| return 1; | |
| } | |
| handleSocket(argv[1]); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Added some validation as well as other features (support for signal handling, negative values, key debugging printing, DSL type detection, buffer overflow security features and allowing multiple instances) and improvements (also published at https://github.com/Matthew1471/DrayTek-Tools/blob/main/C/):