├── C-version ├── .gitignore ├── Makefile ├── README.md ├── drcom.c ├── login.c ├── md5.c └── md5.h ├── README.md ├── client.py ├── drcom-luci ├── README.md ├── controller │ └── drcom.lua └── model │ └── cbi │ └── drcom.lua └── for-OpenWRT ├── README.md ├── drcom.conf ├── install.sh ├── jludrcom.lua ├── lucijludrcom.lua └── wired.py /C-version/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !*.c 3 | !*.h 4 | !Makefile 5 | !README.md 6 | -------------------------------------------------------------------------------- /C-version/Makefile: -------------------------------------------------------------------------------- 1 | objects = drcom.o md5.o 2 | 3 | drcom: $(objects) 4 | gcc -o drcom $(objects) 5 | 6 | $(objects):md5.h 7 | 8 | .PHONY: clean 9 | clean: 10 | -rm $(objects) 11 | -------------------------------------------------------------------------------- /C-version/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ly0/jlu-drcom-client/457e2e04e741d57df5e2cd96eed4db8d4756aee4/C-version/README.md -------------------------------------------------------------------------------- /C-version/drcom.c: -------------------------------------------------------------------------------- 1 | /* 2 | * simple JLU drcom client 3 | * dirty hack version 4 | * 5 | */ 6 | 7 | /* 8 | * -- doc -- 9 | * 数据包类型表示 10 | * 0x01 challenge request 11 | * 0x02 challenge response 12 | * 0x03 login request 13 | * 0x04 login response 14 | * 0x07 keep_alive request 15 | * keep_alive response 16 | * logout request 17 | * logout response 18 | * change_pass request 19 | * change_pass response 20 | * 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #include "md5.h" 39 | 40 | // 必须修改,帐号密码和 mac 地址是绑定的 41 | char user[] = "change to your account name here"; 42 | char pass[] = "change to your password here"; 43 | uint64_t mac = 0x000000000000; // echo 0x`ifconfig eth | egrep -io "([0-9a-f]{2}:){5}[0-9a-f]{2}" | tr -d ":"` 44 | 45 | 46 | // 不一定要修改 47 | char host[] = "drcom"; 48 | char os[] = "drcom"; 49 | int user_len = sizeof(user) - 1; 50 | int pass_len = sizeof(pass) - 1; 51 | int host_len = sizeof(host) - 1; 52 | int os_len = sizeof(os) - 1; 53 | 54 | // TODO 增加从文件读取参数 55 | 56 | //SERVER_DOMAIN login.jlu.edu.cn 57 | #define SERVER_ADDR "10.100.61.3" 58 | #define SERVER_PORT 61440 59 | 60 | #define RECV_DATA_SIZE 1000 61 | #define SEND_DATA_SIZE 1000 62 | #define CHALLENGE_TRY 10 63 | #define LOGIN_TRY 5 64 | #define ALIVE_TRY 5 65 | 66 | /* infomation */ 67 | struct user_info_pkt { 68 | char *username; 69 | char *password; 70 | char *hostname; 71 | char *os_name; 72 | uint64_t mac_addr; 73 | int username_len; 74 | int password_len; 75 | int hostname_len; 76 | int os_name_len; 77 | }; 78 | 79 | /* signal process flag */ 80 | int logout_flag = 0; 81 | 82 | void get_user_info(struct user_info_pkt *user_info) 83 | { 84 | user_info->username = user; 85 | user_info->username_len = user_len; 86 | user_info->password = pass; 87 | user_info->password_len = pass_len; 88 | user_info->hostname = host; 89 | user_info->hostname_len = host_len; 90 | user_info->os_name = os; 91 | user_info->os_name_len = os_len; 92 | user_info->mac_addr = mac; 93 | } 94 | 95 | void set_challenge_data(unsigned char *clg_data, int clg_data_len, int clg_try_count) 96 | { 97 | /* set challenge */ 98 | int random = rand() % 0xF0 + 0xF; 99 | int data_index = 0; 100 | memset(clg_data, 0x00, clg_data_len); 101 | /* 0x01 challenge request */ 102 | clg_data[data_index++] = 0x01; 103 | /* clg_try_count first 0x02, then increment */ 104 | clg_data[data_index++] = 0x02 + (unsigned char)clg_try_count; 105 | /* two byte of challenge_data */ 106 | clg_data[data_index++] = (unsigned char)(random % 0xFFFF); 107 | clg_data[data_index++] = (unsigned char)((random % 0xFFFF) >> 8); 108 | /* end with 0x09 */ 109 | clg_data[data_index++] = 0x09; 110 | } 111 | 112 | void challenge(int sock, struct sockaddr_in serv_addr, unsigned char *clg_data, int clg_data_len, char *recv_data, int recv_len) 113 | { 114 | int ret; 115 | int challenge_try = 0; 116 | do { 117 | if (challenge_try > CHALLENGE_TRY) { 118 | close(sock); 119 | fprintf(stderr, "[drcom-challenge]: try challenge, but failed, please check your network connection.\n"); 120 | exit(EXIT_FAILURE); 121 | } 122 | set_challenge_data(clg_data, clg_data_len, challenge_try); 123 | challenge_try++; 124 | ret = sendto(sock, clg_data, clg_data_len, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 125 | if (ret != clg_data_len) { 126 | fprintf(stderr, "[drcom-challenge]: send challenge data failed.\n"); 127 | continue; 128 | } 129 | ret = recvfrom(sock, recv_data, recv_len, 0, NULL, NULL); 130 | if (ret < 0) { 131 | fprintf(stderr, "[drcom-challenge]: recieve data from server failed.\n"); 132 | continue; 133 | } 134 | if (*recv_data != 0x02) { 135 | if (*recv_data == 0x07) { 136 | close(sock); 137 | fprintf(stderr, "[drcom-challenge]: wrong challenge data.\n"); 138 | exit(EXIT_FAILURE); 139 | } 140 | fprintf(stderr, "[drcom-challenge]: challenge failed!, try again.\n"); 141 | } 142 | } while ((*recv_data != 0x02)); 143 | fprintf(stdout, "[drcom-challenge]: challenge success!\n"); 144 | } 145 | 146 | void set_login_data(struct user_info_pkt *user_info, unsigned char *login_data, int login_data_len, unsigned char *salt, int salt_len) 147 | { 148 | /* login data */ 149 | int i, j; 150 | unsigned char md5_str[16]; 151 | unsigned char md5_str_tmp[100]; 152 | int md5_str_len; 153 | 154 | int data_index = 0; 155 | 156 | memset(login_data, 0x00, login_data_len); 157 | 158 | /* magic 3 byte, username_len 1 byte */ 159 | login_data[data_index++] = 0x03; 160 | login_data[data_index++] = 0x01; 161 | login_data[data_index++] = 0x00; 162 | login_data[data_index++] = (unsigned char)(user_info->username_len + 20); 163 | 164 | /* md5 0x03 0x01 salt password */ 165 | md5_str_len = 2 + salt_len + user_info->password_len; 166 | memset(md5_str_tmp, 0x00, md5_str_len); 167 | md5_str_tmp[0] = 0x03; 168 | md5_str_tmp[1] = 0x01; 169 | memcpy(md5_str_tmp +2, salt, salt_len); 170 | memcpy(md5_str_tmp + 2 + salt_len, user_info->password, user_info->password_len); 171 | MD5(md5_str_tmp, md5_str_len, md5_str); 172 | memcpy(login_data + data_index, md5_str, 16); 173 | data_index += 16; 174 | 175 | /* user name 36 */ 176 | memcpy(login_data + data_index, user_info->username, user_info->username_len); 177 | data_index += user_info->username_len > 36 ? user_info->username_len : 36; 178 | 179 | /* 0x00 0x00 */ 180 | data_index += 2; 181 | 182 | /* (data[4:10].encode('hex'),16)^mac */ 183 | uint64_t sum = 0; 184 | for (i = 0; i < 6; i++) { 185 | sum = (int)md5_str[i] + sum * 256; 186 | } 187 | sum ^= user_info->mac_addr; 188 | for (i = 6; i > 0; i--) { 189 | login_data[data_index + i - 1] = (unsigned char)(sum % 256); 190 | sum /= 256; 191 | } 192 | data_index += 6; 193 | 194 | /* md5 0x01 pwd salt 0x00 0x00 0x00 0x00 */ 195 | md5_str_len = 1 + user_info->password_len + salt_len + 4; 196 | memset(md5_str_tmp, 0x00, md5_str_len); 197 | md5_str_tmp[0] = 0x01; 198 | memcpy(md5_str_tmp + 1, user_info->password, user_info->password_len); 199 | memcpy(md5_str_tmp + 1 + user_info->password_len, salt, salt_len); 200 | MD5(md5_str_tmp, md5_str_len, md5_str); 201 | memcpy(login_data + data_index, md5_str, 16); 202 | data_index += 16; 203 | 204 | /* 0x01 0x31 0x8c 0x21 0x28 0x00*12 */ 205 | login_data[data_index++] = 0x01; 206 | login_data[data_index++] = 0x31; 207 | login_data[data_index++] = 0x8c; 208 | login_data[data_index++] = 0x21; 209 | login_data[data_index++] = 0x28; 210 | data_index += 12; 211 | 212 | /* md5 login_data[0-data_index] 0x14 0x00 0x07 0x0b 8 bytes */ 213 | md5_str_len = data_index + 4; 214 | memset(md5_str_tmp, 0x00, md5_str_len); 215 | memcpy(md5_str_tmp, login_data, data_index); 216 | md5_str_tmp[data_index+0] = 0x14; 217 | md5_str_tmp[data_index+1] = 0x00; 218 | md5_str_tmp[data_index+2] = 0x07; 219 | md5_str_tmp[data_index+3] = 0x0b; 220 | MD5(md5_str_tmp, md5_str_len, md5_str); 221 | memcpy(login_data + data_index, md5_str, 8); 222 | data_index += 8; 223 | 224 | /* 0x01 0x00*4 */ 225 | login_data[data_index++] = 0x01; 226 | data_index += 4; 227 | 228 | /* hostname */ 229 | i = user_info->hostname_len > 71 ? 71 : user_info->hostname_len; 230 | memcpy(login_data + data_index, user_info->hostname, i); 231 | data_index += 71; 232 | 233 | /* 0x01 */ 234 | login_data[data_index++] = 0x01; 235 | 236 | /* osname */ 237 | i = user_info->os_name_len > 128 ? 128 : user_info->os_name_len; 238 | memcpy(login_data + data_index, user_info->os_name, i); 239 | data_index += 128; 240 | 241 | /* 0x6d 0x00 0x00 len(pass) */ 242 | login_data[data_index++] = 0x6d; 243 | login_data[data_index++] = 0x00; 244 | login_data[data_index++] = 0x00; 245 | login_data[data_index++] = (unsigned char)(user_info->password_len); 246 | 247 | /* ror (md5 0x03 0x01 salt pass) pass */ 248 | md5_str_len = 2 + salt_len + user_info->password_len; 249 | memset(md5_str_tmp, 0x00, md5_str_len); 250 | md5_str_tmp[0] = 0x03; 251 | md5_str_tmp[1] = 0x01; 252 | memcpy(md5_str_tmp +2, salt, salt_len); 253 | memcpy(md5_str_tmp + 2 + salt_len, user_info->password, user_info->password_len); 254 | MD5(md5_str_tmp, md5_str_len, md5_str); 255 | int ror_check = 0; 256 | for (i = 0; i < user_info->password_len; i++) { 257 | ror_check = (int)md5_str[i] ^ (int)(user_info->password[i]); 258 | login_data[data_index++] = (unsigned char)(((ror_check << 3) & 0xFF) + (ror_check >> 5)); 259 | } 260 | 261 | /* 0x02 0x0c */ 262 | login_data[data_index++] = 0x02; 263 | login_data[data_index++] = 0x0c; 264 | 265 | /* checksum point */ 266 | int check_point = data_index; 267 | login_data[data_index++] = 0x01; 268 | login_data[data_index++] = 0x26; 269 | login_data[data_index++] = 0x07; 270 | login_data[data_index++] = 0x11; 271 | 272 | /* 0x00 0x00 mac */ 273 | login_data[data_index++] = 0x00; 274 | login_data[data_index++] = 0x00; 275 | uint64_t mac = user_info->mac_addr; 276 | for (i = 0; i < 6; i++) { 277 | login_data[data_index + i - 1] = (unsigned char)(mac % 256); 278 | mac /= 256; 279 | } 280 | data_index += 6; 281 | 282 | /* 0x00 0x00 0x00 0x00 the last two byte I dont't know*/ 283 | login_data[data_index++] = 0x00; 284 | login_data[data_index++] = 0x00; 285 | login_data[data_index++] = 0x00; 286 | login_data[data_index++] = 0x00; 287 | 288 | /* checksum */ 289 | sum = 1234; 290 | uint64_t check = 0; 291 | for (i = 0; i < data_index; i += 4) { 292 | check = 0; 293 | for (j = 0; j < 4; j++) { 294 | check = check * 256 + (int)login_data[i+j]; 295 | } 296 | sum ^= check; 297 | } 298 | sum = (1968 * sum) & 0xFFFFFFFF; 299 | for (j = 0; j < 4; j++) { 300 | login_data[check_point+j] = (unsigned char)(sum >> (j*8) & 0x000000FF); 301 | } 302 | } 303 | 304 | void login(int sock, struct sockaddr_in serv_addr, unsigned char *login_data, int login_data_len, char *recv_data, int recv_len) 305 | { 306 | /* login */ 307 | int ret = 0; 308 | int login_try = 0; 309 | do { 310 | if (login_try > LOGIN_TRY) { 311 | close(sock); 312 | fprintf(stderr, "[drcom-login]: try login, but failed, something wrong.\n"); 313 | exit(EXIT_FAILURE); 314 | } 315 | login_try++; 316 | ret = sendto(sock, login_data, login_data_len, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 317 | if (ret != login_data_len) { 318 | fprintf(stderr, "[drcom-login]: send login data failed.\n"); 319 | continue; 320 | } 321 | ret = recvfrom(sock, recv_data, recv_len, 0, NULL, NULL); 322 | if (ret < 0) { 323 | fprintf(stderr, "[drcom-login]: recieve data from server failed.\n"); 324 | continue; 325 | } 326 | if (*recv_data != 0x04) { 327 | if (*recv_data == 0x05) { 328 | close(sock); 329 | fprintf(stderr, "[drcom-login]: wrong password or username!\n\n"); 330 | exit(EXIT_FAILURE); 331 | } 332 | fprintf(stderr, "[drcom-login]: login failed!, try again\n"); 333 | } 334 | } while ((*recv_data != 0x04)); 335 | fprintf(stdout, "[drcom-login]: login success!\n"); 336 | } 337 | 338 | void set_alive_data(unsigned char *alive_data, int alive_data_len, unsigned char *tail, int tail_len, int alive_count, int random) 339 | { 340 | // 0: 84 | 1: 82 | 2: 82 341 | int i = 0; 342 | memset(alive_data, 0x00, alive_data_len); 343 | alive_data[i++] = 0x07; 344 | alive_data[i++] = (unsigned char)alive_count; 345 | alive_data[i++] = 0x28; 346 | alive_data[i++] = 0x00; 347 | alive_data[i++] = 0x0b; 348 | alive_data[i++] = (unsigned char)(alive_count * 2 + 1); 349 | // if (alive_count) { 350 | alive_data[i++] = 0xdc; 351 | alive_data[i++] = 0x02; 352 | // } else { 353 | // alive_data[i++] = 0x0f; 354 | // alive_data[i++] = 0x27; 355 | // } 356 | random += rand() % 10; 357 | for (i = 9 ; i > 7; i--) { 358 | alive_data[i] = random % 256; 359 | random /= 256; 360 | } 361 | memcpy(alive_data+16, tail, tail_len); 362 | i = 25; 363 | // if (alive_count && alive_count % 3 == 0) { 364 | // /* crc */ 365 | // memset(alive_data, 0xFF, 16); 366 | // } 367 | } 368 | 369 | void set_logout_data(unsigned char *logout_data, int logout_data_len) 370 | { 371 | memset(logout_data, 0x00, logout_data_len); 372 | // TODO 373 | 374 | } 375 | 376 | void logout(int sock, struct sockaddr_in serv_addr, unsigned char *logout_data, int logout_data_len, char *recv_data, int recv_len) 377 | { 378 | set_logout_data(logout_data, logout_data_len); 379 | // TODO 380 | 381 | close(sock); 382 | exit(EXIT_SUCCESS); 383 | } 384 | 385 | void logout_signal(int signum) 386 | { 387 | logout_flag = 1; 388 | } 389 | 390 | int main(int argc, char **argv) 391 | { 392 | int sock, ret; 393 | unsigned char send_data[SEND_DATA_SIZE]; 394 | char recv_data[RECV_DATA_SIZE]; 395 | struct sockaddr_in serv_addr; 396 | struct user_info_pkt user_info; 397 | 398 | sock = socket(AF_INET, SOCK_DGRAM, 0); 399 | if (sock < 0) { 400 | fprintf(stderr, "[drcom]: create sock failed.\n"); 401 | exit(EXIT_FAILURE); 402 | } 403 | serv_addr.sin_family = AF_INET; 404 | serv_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR); 405 | serv_addr.sin_port = htons(SERVER_PORT); 406 | 407 | // get user information 408 | get_user_info(&user_info); 409 | 410 | // challenge data length 20 411 | challenge(sock, serv_addr, send_data, 20, recv_data, RECV_DATA_SIZE); 412 | 413 | // login data length 338, salt length 4 414 | set_login_data(&user_info, send_data, 338, (unsigned char *)(recv_data + 4), 4); 415 | memset(recv_data, 0x00, RECV_DATA_SIZE); 416 | login(sock, serv_addr, send_data, 338, recv_data, RECV_DATA_SIZE); 417 | 418 | // daemon process 419 | switch (fork()) { 420 | case -1: 421 | close(sock); 422 | fprintf(stderr, "[drcom-keep-alive]: drcom failed to run in daemon.\n"); 423 | exit(EXIT_FAILURE); 424 | case 0: 425 | break; 426 | default: 427 | fprintf(stdout, "[drcom-keep-alive]: drcom running in daemon!\n"); 428 | exit(EXIT_SUCCESS); 429 | } 430 | if (setsid() < 0) { 431 | exit(EXIT_FAILURE); 432 | } 433 | umask(0); 434 | if (chdir("/tmp/") < 0) { 435 | exit(EXIT_FAILURE); 436 | } 437 | close(STDIN_FILENO); 438 | close(STDOUT_FILENO); 439 | close(STDERR_FILENO); 440 | 441 | signal(SIGINT, logout_signal); 442 | 443 | // keep alive alive data length 42 or 40 444 | unsigned char tail[4]; 445 | int tail_len = 4; 446 | memset(tail, 0x00, tail_len); 447 | int random = rand() % 0xFFFF; 448 | 449 | int alive_data_len = 0; 450 | int alive_count = 0; 451 | int alive_fail_count = 0; 452 | do { 453 | if (alive_fail_count > ALIVE_TRY) { 454 | close(sock); 455 | // fprintf(stderr, "[drcom-keep-alive]: couldn't connect to network, check please.\n"); 456 | exit(EXIT_FAILURE); 457 | } 458 | alive_data_len = alive_count > 0 ? 40 : 42; 459 | set_alive_data(send_data, alive_data_len, tail, tail_len, alive_count, random); 460 | ret = sendto(sock, send_data, alive_data_len, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 461 | if (ret != alive_data_len) { 462 | alive_fail_count++; 463 | // fprintf(stderr, "[drcom-keep-alive]: send keep-alive data failed.\n"); 464 | continue; 465 | } else { 466 | alive_fail_count = 0; 467 | } 468 | memset(recv_data, 0x00, RECV_DATA_SIZE); 469 | ret = recvfrom(sock, recv_data, RECV_DATA_SIZE, 0, NULL, NULL); 470 | if (ret < 0 || *recv_data != 0x07) { 471 | alive_fail_count++; 472 | // fprintf(stderr, "[drcom-keep-alive]: recieve keep-alive response data from server failed.\n"); 473 | continue; 474 | } else { 475 | alive_fail_count = 0; 476 | } 477 | if (alive_count > 1) memcpy(tail, recv_data+16, tail_len); 478 | sleep(15); 479 | // fprintf(stdout, "[drcom-keep-alive]: keep alive.\n"); 480 | alive_count = (alive_count + 1) % 3; 481 | } while (logout_flag != 1); 482 | 483 | // logout, data_length 80 or ? 484 | memset(recv_data, 0x00, RECV_DATA_SIZE); 485 | logout(sock, serv_addr, send_data, 80, recv_data, RECV_DATA_SIZE); 486 | 487 | return 0; 488 | } 489 | -------------------------------------------------------------------------------- /C-version/login.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "md5.h" 5 | 6 | /* 7 | Author: latyas@gmail.com 8 | Incomplete. 9 | */ 10 | enum { 11 | EUSR_TOO_LONG = 10, 12 | EHOSTNAME_TOO_LONG 13 | }; 14 | 15 | extern void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ); 16 | struct login_packet 17 | { 18 | unsigned char magic[3]; 19 | unsigned char username_len[1]; 20 | unsigned char md5_1[16]; 21 | unsigned char username[36]; 22 | unsigned char delimiter_1[2]; 23 | unsigned char encrypted_1[6]; 24 | unsigned char md5_2[16]; 25 | unsigned char delimiter_2[17]; /* '\x01\x31\x8c\x31\x4e' + '\00'*12 */ 26 | unsigned char md5_3[16]; 27 | unsigned char delimeter_2_1[5]; /* \x01\x00\x00\x00\x00*/ 28 | unsigned char host_name[71]; 29 | unsigned char delimiter_3[1]; /* \0x01*/ 30 | unsigned char host_os[128]; 31 | unsigned char delimiter_4[3]; /*'\x6d\x00\x00'*/ 32 | unsigned char password_len[1]; 33 | unsigned char ror_md5[16]; 34 | unsigned char delimiter_4[2]; 35 | unsigned char verifier[4]; 36 | unsigned char delimiter_5[2]; 37 | unsigned char mac[6]; 38 | 39 | 40 | }; 41 | 42 | struct login_packet *login_verifier(struct login_packet *pkt) 43 | { 44 | return pkt; 45 | } 46 | struct login_packet *login_init(struct login_packet *pkt) 47 | { 48 | memset(pkt, 0, sizeof(*pkt)); 49 | strcpy(pkt->magic, "\x03\x01\x00"); 50 | 51 | return pkt; 52 | } 53 | struct login_packet *login_sign(char *username, char *password, char* mac, char* hostname, char* salt, struct login_packet *pkt) 54 | { 55 | unsigned char* md5_buffer[16]; 56 | 57 | /* username length*/ 58 | pkt->username_len[0] = strlen(username) + 20; 59 | /* calculate password md5*/ 60 | _get_salted_password_1(password, salt, md5_buffer); 61 | memcpy(pkt->md5_1,md5_1,16); 62 | 63 | /* username */ 64 | if (strlen(username) > 36) exit(EUSR_TOO_LONG); 65 | memcpy(pkt->username, username, strlen(username)); 66 | 67 | /* delimeter_1*/ 68 | memset(pkt->delimiter_1,0,2); 69 | 70 | 71 | /*encrypted_1*/ 72 | for(int i=0; i<6; i++) 73 | { 74 | pkt->encrypted_1[i] = pkt->md5_1[i] ^ mac[i]; 75 | } 76 | 77 | /* salted password md5_2*/ 78 | _get_salted_password_2(password, salt, md5_buffer); 79 | memcpy(pkt->md5_2,md5_buffer,16); 80 | 81 | /* delimeter 2 */ 82 | memcpy(pkt->delimiter_2,"\x01\x31\x8c\x31\x4e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",17); 83 | 84 | /* md5_2 */ 85 | 86 | /* hostname */ 87 | if (strlen(hostname) > 71) exit(EHOSTNAME_TOO_LONG); 88 | 89 | /**/ 90 | /* 91 | data += dump(int(data[4:10].encode('hex'),16)^mac).rjust(6,'\x00') 92 | first 6 bytes of md5_1 93 | */ 94 | 95 | /* set mac*/ 96 | memcpy(pkt->mac, mac, 6); 97 | } 98 | char *_get_salted_password_1(char *password, char* salt, char md5_buffer[16]) 99 | { 100 | unsigned int salt_len = strlen(salt); 101 | unsigned int password_len = strlen(password); 102 | char *buffer = malloc(2 + salt_len + password_len); 103 | strcpy(buffer, "\x03\x01"); 104 | memcpy(buffer+2, salt, salt_len); 105 | memcpy(buffer+2+salt_len, password, password_len); 106 | 107 | md5(buffer, 2 + salt_len + password_len, md5_buffer) 108 | return md5_buffer; 109 | } 110 | char *_get_salted_password_2(char *password, char* salt, char md5_buffer[16]) 111 | { 112 | unsigned int salt_len = strlen(salt); 113 | unsigned int password_len = strlen(password); 114 | char *buffer = malloc(5 + salt_len + password_len); 115 | 116 | strcpy(buffer, "\x01"); 117 | memcpy(buffer+1, password, password_len); 118 | memcpy(buffer+1+password_len, salt, salt_len); 119 | memset(buffer+1+password_len+salt_len,0,4); 120 | 121 | md5(buffer, 5 + salt_len + password_len, md5_buffer) 122 | return md5_buffer; 123 | } 124 | int _ror(int value, int places) 125 | { 126 | return (value>>places)|(value<. Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order 41 | either statically or dynamically; added missing #include 42 | in library. 43 | 2002-03-11 lpd Corrected argument list for main(), and added int return 44 | type, in test program and T value program. 45 | 2002-02-21 lpd Added missing #include in test program. 46 | 2000-07-03 lpd Patched to eliminate warnings about "constant is 47 | unsigned in ANSI C, signed in traditional"; made test program 48 | self-checking. 49 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 50 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 51 | 1999-05-03 lpd Original version. 52 | */ 53 | 54 | #include "md5.h" 55 | #include 56 | 57 | #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ 58 | #ifdef ARCH_IS_BIG_ENDIAN 59 | # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) 60 | #else 61 | # define BYTE_ORDER 0 62 | #endif 63 | 64 | #define T_MASK ((md5_word_t)~0) 65 | #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) 66 | #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) 67 | #define T3 0x242070db 68 | #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) 69 | #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) 70 | #define T6 0x4787c62a 71 | #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) 72 | #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) 73 | #define T9 0x698098d8 74 | #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) 75 | #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) 76 | #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) 77 | #define T13 0x6b901122 78 | #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) 79 | #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) 80 | #define T16 0x49b40821 81 | #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) 82 | #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) 83 | #define T19 0x265e5a51 84 | #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) 85 | #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) 86 | #define T22 0x02441453 87 | #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) 88 | #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) 89 | #define T25 0x21e1cde6 90 | #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) 91 | #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) 92 | #define T28 0x455a14ed 93 | #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) 94 | #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) 95 | #define T31 0x676f02d9 96 | #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) 97 | #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) 98 | #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) 99 | #define T35 0x6d9d6122 100 | #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) 101 | #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) 102 | #define T38 0x4bdecfa9 103 | #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) 104 | #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) 105 | #define T41 0x289b7ec6 106 | #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) 107 | #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) 108 | #define T44 0x04881d05 109 | #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) 110 | #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) 111 | #define T47 0x1fa27cf8 112 | #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) 113 | #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) 114 | #define T50 0x432aff97 115 | #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) 116 | #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) 117 | #define T53 0x655b59c3 118 | #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) 119 | #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) 120 | #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) 121 | #define T57 0x6fa87e4f 122 | #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) 123 | #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) 124 | #define T60 0x4e0811a1 125 | #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) 126 | #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) 127 | #define T63 0x2ad7d2bb 128 | #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) 129 | 130 | 131 | static void 132 | md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) 133 | { 134 | md5_word_t 135 | a = pms->abcd[0], b = pms->abcd[1], 136 | c = pms->abcd[2], d = pms->abcd[3]; 137 | md5_word_t t; 138 | #if BYTE_ORDER > 0 139 | /* Define storage only for big-endian CPUs. */ 140 | md5_word_t X[16]; 141 | #else 142 | /* Define storage for little-endian or both types of CPUs. */ 143 | md5_word_t xbuf[16]; 144 | const md5_word_t *X; 145 | #endif 146 | 147 | { 148 | #if BYTE_ORDER == 0 149 | /* 150 | * Determine dynamically whether this is a big-endian or 151 | * little-endian machine, since we can use a more efficient 152 | * algorithm on the latter. 153 | */ 154 | static const int w = 1; 155 | 156 | if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ 157 | #endif 158 | #if BYTE_ORDER <= 0 /* little-endian */ 159 | { 160 | /* 161 | * On little-endian machines, we can process properly aligned 162 | * data without copying it. 163 | */ 164 | if (!((data - (const md5_byte_t *)0) & 3)) { 165 | /* data are properly aligned */ 166 | X = (const md5_word_t *)data; 167 | } else { 168 | /* not aligned */ 169 | memcpy(xbuf, data, 64); 170 | X = xbuf; 171 | } 172 | } 173 | #endif 174 | #if BYTE_ORDER == 0 175 | else /* dynamic big-endian */ 176 | #endif 177 | #if BYTE_ORDER >= 0 /* big-endian */ 178 | { 179 | /* 180 | * On big-endian machines, we must arrange the bytes in the 181 | * right order. 182 | */ 183 | const md5_byte_t *xp = data; 184 | int i; 185 | 186 | # if BYTE_ORDER == 0 187 | X = xbuf; /* (dynamic only) */ 188 | # else 189 | # define xbuf X /* (static only) */ 190 | # endif 191 | for (i = 0; i < 16; ++i, xp += 4) 192 | xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); 193 | } 194 | #endif 195 | } 196 | 197 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 198 | 199 | /* Round 1. */ 200 | /* Let [abcd k s i] denote the operation 201 | a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ 202 | #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) 203 | #define SET(a, b, c, d, k, s, Ti)\ 204 | t = a + F(b,c,d) + X[k] + Ti;\ 205 | a = ROTATE_LEFT(t, s) + b 206 | /* Do the following 16 operations. */ 207 | SET(a, b, c, d, 0, 7, T1); 208 | SET(d, a, b, c, 1, 12, T2); 209 | SET(c, d, a, b, 2, 17, T3); 210 | SET(b, c, d, a, 3, 22, T4); 211 | SET(a, b, c, d, 4, 7, T5); 212 | SET(d, a, b, c, 5, 12, T6); 213 | SET(c, d, a, b, 6, 17, T7); 214 | SET(b, c, d, a, 7, 22, T8); 215 | SET(a, b, c, d, 8, 7, T9); 216 | SET(d, a, b, c, 9, 12, T10); 217 | SET(c, d, a, b, 10, 17, T11); 218 | SET(b, c, d, a, 11, 22, T12); 219 | SET(a, b, c, d, 12, 7, T13); 220 | SET(d, a, b, c, 13, 12, T14); 221 | SET(c, d, a, b, 14, 17, T15); 222 | SET(b, c, d, a, 15, 22, T16); 223 | #undef SET 224 | 225 | /* Round 2. */ 226 | /* Let [abcd k s i] denote the operation 227 | a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ 228 | #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) 229 | #define SET(a, b, c, d, k, s, Ti)\ 230 | t = a + G(b,c,d) + X[k] + Ti;\ 231 | a = ROTATE_LEFT(t, s) + b 232 | /* Do the following 16 operations. */ 233 | SET(a, b, c, d, 1, 5, T17); 234 | SET(d, a, b, c, 6, 9, T18); 235 | SET(c, d, a, b, 11, 14, T19); 236 | SET(b, c, d, a, 0, 20, T20); 237 | SET(a, b, c, d, 5, 5, T21); 238 | SET(d, a, b, c, 10, 9, T22); 239 | SET(c, d, a, b, 15, 14, T23); 240 | SET(b, c, d, a, 4, 20, T24); 241 | SET(a, b, c, d, 9, 5, T25); 242 | SET(d, a, b, c, 14, 9, T26); 243 | SET(c, d, a, b, 3, 14, T27); 244 | SET(b, c, d, a, 8, 20, T28); 245 | SET(a, b, c, d, 13, 5, T29); 246 | SET(d, a, b, c, 2, 9, T30); 247 | SET(c, d, a, b, 7, 14, T31); 248 | SET(b, c, d, a, 12, 20, T32); 249 | #undef SET 250 | 251 | /* Round 3. */ 252 | /* Let [abcd k s t] denote the operation 253 | a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ 254 | #define H(x, y, z) ((x) ^ (y) ^ (z)) 255 | #define SET(a, b, c, d, k, s, Ti)\ 256 | t = a + H(b,c,d) + X[k] + Ti;\ 257 | a = ROTATE_LEFT(t, s) + b 258 | /* Do the following 16 operations. */ 259 | SET(a, b, c, d, 5, 4, T33); 260 | SET(d, a, b, c, 8, 11, T34); 261 | SET(c, d, a, b, 11, 16, T35); 262 | SET(b, c, d, a, 14, 23, T36); 263 | SET(a, b, c, d, 1, 4, T37); 264 | SET(d, a, b, c, 4, 11, T38); 265 | SET(c, d, a, b, 7, 16, T39); 266 | SET(b, c, d, a, 10, 23, T40); 267 | SET(a, b, c, d, 13, 4, T41); 268 | SET(d, a, b, c, 0, 11, T42); 269 | SET(c, d, a, b, 3, 16, T43); 270 | SET(b, c, d, a, 6, 23, T44); 271 | SET(a, b, c, d, 9, 4, T45); 272 | SET(d, a, b, c, 12, 11, T46); 273 | SET(c, d, a, b, 15, 16, T47); 274 | SET(b, c, d, a, 2, 23, T48); 275 | #undef SET 276 | 277 | /* Round 4. */ 278 | /* Let [abcd k s t] denote the operation 279 | a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ 280 | #define I(x, y, z) ((y) ^ ((x) | ~(z))) 281 | #define SET(a, b, c, d, k, s, Ti)\ 282 | t = a + I(b,c,d) + X[k] + Ti;\ 283 | a = ROTATE_LEFT(t, s) + b 284 | /* Do the following 16 operations. */ 285 | SET(a, b, c, d, 0, 6, T49); 286 | SET(d, a, b, c, 7, 10, T50); 287 | SET(c, d, a, b, 14, 15, T51); 288 | SET(b, c, d, a, 5, 21, T52); 289 | SET(a, b, c, d, 12, 6, T53); 290 | SET(d, a, b, c, 3, 10, T54); 291 | SET(c, d, a, b, 10, 15, T55); 292 | SET(b, c, d, a, 1, 21, T56); 293 | SET(a, b, c, d, 8, 6, T57); 294 | SET(d, a, b, c, 15, 10, T58); 295 | SET(c, d, a, b, 6, 15, T59); 296 | SET(b, c, d, a, 13, 21, T60); 297 | SET(a, b, c, d, 4, 6, T61); 298 | SET(d, a, b, c, 11, 10, T62); 299 | SET(c, d, a, b, 2, 15, T63); 300 | SET(b, c, d, a, 9, 21, T64); 301 | #undef SET 302 | 303 | /* Then perform the following additions. (That is increment each 304 | of the four registers by the value it had before this block 305 | was started.) */ 306 | pms->abcd[0] += a; 307 | pms->abcd[1] += b; 308 | pms->abcd[2] += c; 309 | pms->abcd[3] += d; 310 | } 311 | 312 | void 313 | md5_init(md5_state_t *pms) 314 | { 315 | pms->count[0] = pms->count[1] = 0; 316 | pms->abcd[0] = 0x67452301; 317 | pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; 318 | pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; 319 | pms->abcd[3] = 0x10325476; 320 | } 321 | 322 | void 323 | md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) 324 | { 325 | const md5_byte_t *p = data; 326 | int left = nbytes; 327 | int offset = (pms->count[0] >> 3) & 63; 328 | md5_word_t nbits = (md5_word_t)(nbytes << 3); 329 | 330 | if (nbytes <= 0) 331 | return; 332 | 333 | /* Update the message length. */ 334 | pms->count[1] += nbytes >> 29; 335 | pms->count[0] += nbits; 336 | if (pms->count[0] < nbits) 337 | pms->count[1]++; 338 | 339 | /* Process an initial partial block. */ 340 | if (offset) { 341 | int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); 342 | 343 | memcpy(pms->buf + offset, p, copy); 344 | if (offset + copy < 64) 345 | return; 346 | p += copy; 347 | left -= copy; 348 | md5_process(pms, pms->buf); 349 | } 350 | 351 | /* Process full blocks. */ 352 | for (; left >= 64; p += 64, left -= 64) 353 | md5_process(pms, p); 354 | 355 | /* Process a final partial block. */ 356 | if (left) 357 | memcpy(pms->buf, p, left); 358 | } 359 | 360 | void 361 | md5_finish(md5_state_t *pms, md5_byte_t digest[16]) 362 | { 363 | static const md5_byte_t pad[64] = { 364 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 365 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 366 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 367 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 368 | }; 369 | md5_byte_t data[8]; 370 | int i; 371 | 372 | /* Save the length before padding. */ 373 | for (i = 0; i < 8; ++i) 374 | data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); 375 | /* Pad to 56 bytes mod 64. */ 376 | md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); 377 | /* Append the length. */ 378 | md5_append(pms, data, 8); 379 | for (i = 0; i < 16; ++i) 380 | digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); 381 | } 382 | 383 | unsigned char * 384 | MD5(const unsigned char *d, int n, unsigned char *md) 385 | { 386 | md5_state_t state; 387 | md5_byte_t digest[16]; 388 | 389 | md5_init(&state); 390 | md5_append(&state, d, n); 391 | md5_finish(&state, digest); 392 | 393 | memcpy(md, digest, 16); 394 | 395 | return md; 396 | } 397 | 398 | -------------------------------------------------------------------------------- /C-version/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.h is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Removed support for non-ANSI compilers; removed 41 | references to Ghostscript; clarified derivation from RFC 1321; 42 | now handles byte order either statically or dynamically. 43 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 44 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); 45 | added conditionalization for C++ compilation from Martin 46 | Purschke . 47 | 1999-05-03 lpd Original version. 48 | */ 49 | 50 | #ifndef md5_INCLUDED 51 | # define md5_INCLUDED 52 | 53 | /* 54 | * This package supports both compile-time and run-time determination of CPU 55 | * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 56 | * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 57 | * defined as non-zero, the code will be compiled to run only on big-endian 58 | * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 59 | * run on either big- or little-endian CPUs, but will run slightly less 60 | * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 61 | */ 62 | 63 | typedef unsigned char md5_byte_t; /* 8-bit byte */ 64 | typedef unsigned int md5_word_t; /* 32-bit word */ 65 | 66 | /* Define the state of the MD5 Algorithm. */ 67 | typedef struct md5_state_s { 68 | md5_word_t count[2]; /* message length in bits, lsw first */ 69 | md5_word_t abcd[4]; /* digest buffer */ 70 | md5_byte_t buf[64]; /* accumulate block */ 71 | } md5_state_t; 72 | 73 | #ifdef __cplusplus 74 | extern "C" 75 | { 76 | #endif 77 | 78 | /* Initialize the algorithm. */ 79 | void md5_init(md5_state_t *pms); 80 | 81 | /* Append a string to the message. */ 82 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); 83 | 84 | /* Finish the message and return the digest. */ 85 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); 86 | 87 | unsigned char *MD5(const unsigned char *d, int n, unsigned char *md); 88 | 89 | #ifdef __cplusplus 90 | } /* end extern "C" */ 91 | #endif 92 | 93 | #endif /* md5_INCLUDED */ 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DrCOM Client for jilin university 2 | ------------- 3 | 4 | 本项目已 fork 到 https://github.com/drcoms/jlu-drcom-client , 该 repo 停止更新。 5 | 6 | 有关其他学校 7 | ------------- 8 | HITwh的Shindo酱优秀的项目,u62R0(理论上u64也是可以的),带802.1x
9 | https://github.com/coverxit/EasyDrcom/ 10 | 11 | U62R0-u64不带802.1x的版本, 主要用于debug, 实际使用(尤其是放在路由器里)还需要另作修改
12 | https://github.com/drcoms/generic 13 | 14 | Openwrt下一个图形界面的版本
15 | http://github.com/drcoms/openwrt 16 | 17 | 代码是很久以前由两个 Python 初学者写的,质量糟糕,不过用起来舒适,将就一下或者仅使用代码中的***mkpkt***函数和***keep_alive_package_builder***函数然后重构它吧! 18 | 19 | 配置文件说明 20 | ``` 21 | server = "10.100.61.3" #认证服务器,可以使用域名auth.jlu.edu.cn 22 | username = "" #用户名,和客户端一样 23 | password = "" #密码,和客户端一样 24 | host_name = "liyuanyuan" #计算机名,不要超过71个字符 25 | host_os = "Windows 4.0" #操作系统,不要超过128个字符 26 | mac = 0x888888888888 #网络中心上注册时IP对应的MAC 27 | ``` 28 | -------------------------------------------------------------------------------- /client.py: -------------------------------------------------------------------------------- 1 | import socket, struct, time 2 | from hashlib import md5 3 | import sys 4 | import urllib2 5 | 6 | class ChallengeException (Exception): 7 | def __init__(self): 8 | pass 9 | 10 | class LoginException (Exception): 11 | def __init__(self): 12 | pass 13 | 14 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 15 | s.bind(("0.0.0.0", 61440)) 16 | 17 | s.settimeout(3) 18 | SALT = '' 19 | UNLIMITED_RETRY = True 20 | EXCEPTION = False 21 | DEBUG = True 22 | server = "10.100.61.3" # "auth.jlu.edu.cn" 23 | username = "YOURUSERNAME" 24 | password = "YOURPASSWORD" 25 | host_name = "LIYUANYUAN" 26 | host_os = "8089D" 27 | mac = 0xffffffffffff 28 | 29 | def challenge(svr,ran): 30 | while True: 31 | t = struct.pack(">5)) 67 | return ret 68 | 69 | def keep_alive_package_builder(number,random,tail,type=1,first=False): 70 | data = '\x07'+ chr(number) + '\x28\x00\x0b' + chr(type) 71 | if first : 72 | data += '\x0f\x27' 73 | else: 74 | data += '\xdc\02' 75 | data += random + '\x00' * 6 76 | data += tail 77 | data += '\x00' * 4 78 | #data += struct.pack("!H",0xdc02) 79 | if type == 3: 80 | foo = '\x31\x8c\x21\x3e' #CONSTANT 81 | #CRC 82 | crc = packet_CRC(data+foo) 83 | data += struct.pack("!I",crc) + foo + '\x00' * 8 84 | else: #packet type = 1 85 | data += '\x00' * 16 86 | return data 87 | 88 | def packet_CRC(s): 89 | ret = 0 90 | for i in re.findall('..', s): 91 | ret ^= struct.unpack('>h', i)[0] 92 | ret &= 0xFFFF 93 | ret = ret * 0x2c7 94 | return ret 95 | 96 | def keep_alive2(): 97 | #first keep_alive: 98 | #number = number (mod 7) 99 | #status = 1: first packet user sended 100 | # 2: first packet user recieved 101 | # 3: 2nd packet user sended 102 | # 4: 2nd packet user recieved 103 | # Codes for test 104 | tail = '' 105 | packet = '' 106 | svr = server 107 | import random 108 | ran = random.randint(0,0xFFFF) 109 | ran += random.randint(1,10) 110 | packet = keep_alive_package_builder(0,dump(ran),'\x00'*4,1,True) 111 | s.sendto(packet, (svr, 61440)) 112 | data, address = s.recvfrom(1024) 113 | 114 | ran += random.randint(1,10) 115 | packet = keep_alive_package_builder(1,dump(ran),'\x00'*4,1,False) 116 | s.sendto(packet, (svr, 61440)) 117 | data, address = s.recvfrom(1024) 118 | tail = data[16:20] 119 | 120 | 121 | ran += random.randint(1,10) 122 | packet = keep_alive_package_builder(2,dump(ran),tail,3,False) 123 | s.sendto(packet, (svr, 61440)) 124 | data, address = s.recvfrom(1024) 125 | tail = data[16:20] 126 | print "[keep-alive2] keep-alive2 loop was in daemon." 127 | 128 | i = 1 129 | while True: 130 | try: 131 | time.sleep(5) 132 | ran += random.randint(1,10) 133 | packet = keep_alive_package_builder(2,dump(ran),tail,1,False) 134 | #print 'DEBUG: keep_alive2,packet 4\n',packet.encode('hex') 135 | s.sendto(packet, (svr, 61440)) 136 | data, address = s.recvfrom(1024) 137 | tail = data[16:20] 138 | #print 'DEBUG: keep_alive2,packet 4 return\n',data.encode('hex') 139 | 140 | ran += random.randint(1,10) 141 | packet = keep_alive_package_builder(2,dump(ran),tail,3,False) 142 | #print 'DEBUG: keep_alive2,packet 5\n',packet.encode('hex') 143 | s.sendto(packet, (svr, 61440)) 144 | data, address = s.recvfrom(1024) 145 | tail = data[16:20] 146 | #print 'DEBUG: keep_alive2,packet 5 return\n',data.encode('hex') 147 | i = i+1 148 | i = i % (0xFF) 149 | 150 | check_online = urllib2.urlopen('http://10.100.61.3') 151 | foo = check_online.read() 152 | if 'login.jlu.edu.cn' in foo: 153 | print '[keep_alive2] offline.relogin...' 154 | break; 155 | #MODIFIED END 156 | ''' 157 | if i % 10 == 0: 158 | check_online = urllib2.urlopen('http://10.100.61.3') 159 | foo = check_online.read() 160 | if 'login.jlu.edu.cn' in foo: 161 | print '[keep_alive2] offline.relogin...' 162 | break; 163 | ''' 164 | except: 165 | pass 166 | 167 | 168 | import re 169 | def checksum(s): 170 | ret = 1234 171 | for i in re.findall('....', s): 172 | ret ^= int(i[::-1].encode('hex'), 16) 173 | ret = (1968 * ret) & 0xffffffff 174 | return struct.pack('= 5 and UNLIMITED_RETRY == False: 217 | print '[login] wrong password, retried ' + str(i) +' times.' 218 | sys.exit(1) 219 | elif data[0] == '\x05': 220 | print "[login] wrong password." 221 | i = i + 1 222 | time.sleep(i*1.618) 223 | elif data[0] != '\x02': 224 | print "[login] server return exception.retry" 225 | if DEBUG: 226 | print '[login] last packet server returned:\n' + data.encode('hex') 227 | time.sleep(1) 228 | raise LoginException 229 | continue; 230 | break; 231 | else: 232 | if i >= 5 and UNLIMITED_RETRY == False : 233 | print '[login] packet received error, maybe you are under attacking' 234 | sys.exit(1) 235 | else: 236 | i = i + 1 237 | print '[login] package error, retrying...' 238 | 239 | print '[login] login sent' 240 | return data[-22:-6] 241 | 242 | import httplib 243 | def info(ip): 244 | c = httplib.HTTPConnection(ip, 80, timeout=10) 245 | c.request("GET", "") 246 | r = c.getresponse() 247 | if r.status != 200: 248 | return None 249 | s = r.read() 250 | data = dict() 251 | data["flux"] = int(s[s.index("flow='")+6:s.index("';fsele=")]) 252 | data["time"] = int(s[s.index("time='")+6:s.index("';flow")]) 253 | return data 254 | def keep_alive1(salt,tail,pwd,svr): 255 | foo = struct.pack('!H',int(time.time())%0xFFFF) 256 | data = '\xff' + md5sum('\x03\x01'+salt+pwd) + '\x00\x00\x00' 257 | data += tail 258 | data += foo + '\x00\x00\x00\x00' 259 | print '[keep_alive1] keep_alive1,sent' 260 | s.sendto(data, (svr, 61440)) 261 | try: 262 | data, address = s.recvfrom(1024) 263 | print '[keep_alive1] keep_alive1,server received' 264 | except: 265 | print '[keep_alive1] Timeout!' 266 | pass 267 | 268 | def main(): 269 | print "auth svr:"+server+"\nusername:"+username+"\npassword:"+"********"+"\nmac:"+str(hex(mac)) 270 | print "os:MSDOS 8.0"+"\nhostname: localhost" 271 | print "DrCOM Auth Router Ver 1.2" 272 | print "Version feature:\n[1] Auto Anti droping connection\n[2] Stronger exception handling." 273 | while True: 274 | try: 275 | package_tail = login(username, password, server) 276 | except LoginException: 277 | continue 278 | keep_alive2() 279 | if __name__ == "__main__": 280 | main() 281 | 282 | 283 | 284 | -------------------------------------------------------------------------------- /drcom-luci/README.md: -------------------------------------------------------------------------------- 1 | DrCOM GUI for luci 2 | --------------------- 3 | 由于各种版本情况不一样,需要自行整合 4 | 5 | 在第一次保存了配置以后试试 `uci show drcom.config` 6 | 7 | 可以使用 `uci get drcom.config.username` 这样的语句来获取 *luci* 的数据 8 | 9 | 使用 10 | ----------- 11 | 对 `wired.py` 的修改: 12 | 13 | 1. 名字修改为 `drcom` 14 | 2. 在头部加入 `#!/usr/bin/python` 15 | 3. 在第一个 `import` 语句后加入 `import subprocess` 16 | 4. 加入函数 17 | 18 | ```python 19 | def init(): 20 | global username, password, mac, host_name, host_os, server 21 | username = subprocess.check_output(['uci','get','drcom.config.username']).strip() 22 | password = subprocess.check_output(['uci','get','drcom.config.password']).strip() 23 | mac = int(subprocess.check_output(['uci','get','drcom.config.mac']).strip().replace(':', ''), base=16) 24 | host_name = subprocess.check_output(['uci','get','drcom.config.host_name']).strip() 25 | host_os = subprocess.check_output(['uci','get','drcom.config.host_os']).strip() 26 | server = subprocess.check_output(['uci','get','drcom.config.remote_server']).strip() 27 | ``` 28 | 5. `execfile(CONF, globals())` 替换为 `init()` 29 | -------------------------------------------------------------------------------- /drcom-luci/controller/drcom.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | RA-MOD 3 | ]]-- 4 | 5 | module("luci.controller.drcom", package.seeall) 6 | 7 | function index() 8 | 9 | if not nixio.fs.access("/etc/config/drcom") then 10 | return 11 | end 12 | 13 | local page 14 | 15 | page = entry({"admin", "services", "DrCOM"}, cbi("drcom"), _("DrCOM"), 45) 16 | page.i18n = "DrCOM" 17 | page.dependent = true 18 | end 19 | -------------------------------------------------------------------------------- /drcom-luci/model/cbi/drcom.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright reserved by latyas 3 | ]]-- 4 | 5 | local fs = require "nixio.fs" 6 | local nixio = require "nixio" 7 | 8 | local drcom_running =(luci.sys.call("pidof drcom > /dev/null") == 0) 9 | local client_status 10 | if drcom_running then 11 | client_status = "客户端运行中" 12 | else 13 | client_status = "客户端未运行" 14 | end 15 | 16 | m = Map("drcom", translate("DrCOM"), translate(client_status)) 17 | 18 | server = m:section(TypedSection, "drcom", translate("客户端配置")) 19 | server.anonymous = true 20 | 21 | remote_server = server:option(Value, "remote_server", translate("认证服务器地址")) 22 | remote_server.datatype = "ip4addr" 23 | 24 | username = server:option(Value, "username", translate("用户名")) 25 | 26 | password = server:option(Value, "password", translate("密码")) 27 | password.datatype = "maxlength(16)" 28 | password.password = true 29 | 30 | host_name = server:option(Value, "host_name", translate("主机名")) 31 | host_name.datatype = "maxlength(16)" 32 | host_name.default = "NOKIA" 33 | 34 | host_os = server:option(Value, "host_os", translate("主机操作系统")) 35 | host_os.datatype = "maxlength(32)" 36 | host_os.default = "DOS" 37 | 38 | mac = server:option(Value, "mac", translate("绑定MAC地址"), translate("如果不绑定mac可以保持默认")) 39 | mac.default = "11:22:33:44:55:66" 40 | 41 | --[[ 42 | dhcp_server = server:option(Value, "dhcp_server", translate("DHCP服务器"), translate("DHCP服务器")) 43 | dhcp_server.datatype = "ip4addr" 44 | dhcp_server.default = "0.0.0.0" 45 | 46 | 47 | version = server:option(ListValue, "version", translate("客户端版本"), translate("版本号请参考原版客户端的关于界面,有类似0.8 u62R0这一类的")) 48 | version:value("u60") 49 | version:value("u60R0") 50 | version:value("u62") 51 | version:value("u62R0") 52 | version:value("u64") 53 | version:value("u64R0") 54 | 55 | version_type = server:option(ListValue, "version_type", translate("客户端类型"), translate("协议类型请看客户端版本最后一个字符,如5.2.0(d) 则类型为d")) 56 | version_type:value("d") 57 | version_type:value("p") 58 | version_type:value("x") 59 | 60 | iface = server:option(ListValue, "iface", translate("网络接口")) 61 | for k, v in ipairs(nixio.getifaddrs()) do 62 | if v.family == "packet" then 63 | iface:value(v.name) 64 | end 65 | end 66 | ]]-- 67 | 68 | return m -------------------------------------------------------------------------------- /for-OpenWRT/README.md: -------------------------------------------------------------------------------- 1 | 安装说明 2 | --------------- 3 | * 将所有文件上传至路由器上 4 | * 运行 *install.sh* 5 | * 在 *Luci* 界面 *Services* 菜单中找到 *DrCOM for JLU* 6 | * 修改 *username* 和 *password*, 注意不要出现语法错误 7 | 8 | 9 | 已知BUG 10 | --------------- 11 | 程序本该 *fork* ,但是由于完成它的时候实在太菜了,根本没想那么多,而且由于个人的傻逼个性能用则用的性格导致实在不想弄它。 12 | 所以主线程不返回,这就导致了这个插件有个 BUG, 在点了连接按钮以后,提示文字会出现,但是页面一直在加载,其实这时候程序已经启动了,可以不用管 (实在没查着Lua用什么函数可以不用管返回)。 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /for-OpenWRT/drcom.conf: -------------------------------------------------------------------------------- 1 | server = "10.100.61.3" 2 | username = "qianbf2111" 3 | password = "579946" 4 | host_name = "liyuanyuan" 5 | host_os = "Windows 4.0" 6 | mac = 0xdc0ea1218ad6 -------------------------------------------------------------------------------- /for-OpenWRT/install.sh: -------------------------------------------------------------------------------- 1 | cp ./drcom.conf /etc 2 | cp ./wired.py /usr/bin 3 | cp ./lucijludrcom.lua /usr/lib/lua/luci/controller/jludrcom.lua 4 | cp ./jludrcom.lua /usr/lib/lua/luci/model/cbi/ 5 | -------------------------------------------------------------------------------- /for-OpenWRT/jludrcom.lua: -------------------------------------------------------------------------------- 1 | local sys = require "luci.sys" 2 | local fs = require "nixio.fs" 3 | 4 | m = SimpleForm("jludrcom", translate("DrCOM Client"), 5 | translate("DrCOM Client for Jilin Univ.")) 6 | 7 | m.submit = translate("Connect") 8 | m.reset = false 9 | 10 | local o = m:field(Value, "conf") 11 | o.template = "cbi/tvalue" 12 | o.rows = 20 13 | o.rmempty = true 14 | 15 | ori = fs.readfile("/etc/drcom.conf") 16 | 17 | local update = luci.http.formvalue("cbi.submit") 18 | if update then 19 | luci.sys.call("killall python") 20 | luci.sys.call("python /usr/bin/wired.py & > /dev/null") 21 | local msg = "JLUDrCOM service rebooted successfully." 22 | if m.message == nil then 23 | m.message = msg 24 | else 25 | m.message = m.message .. msg 26 | end 27 | end 28 | 29 | function o.cfgvalue(self, section) 30 | return fs.readfile("/etc/drcom.conf") 31 | end 32 | 33 | 34 | function o.write(self, s, val) 35 | local msg 36 | fs.writefile("/etc/drcom.conf", val) 37 | msg = "

Configuration updated.

" 38 | m.message = m.message .. msg 39 | end 40 | 41 | return m 42 | 43 | 44 | -------------------------------------------------------------------------------- /for-OpenWRT/lucijludrcom.lua: -------------------------------------------------------------------------------- 1 | module("luci.controller.jludrcom", package.seeall) 2 | 3 | function index() 4 | require("luci.i18n") 5 | luci.i18n.loadc("jludrcom") 6 | 7 | if nixio.fs.access("/etc/drcom.conf") then 8 | local page 9 | page = entry({"admin", "services", "jludrcom"}, cbi("jludrcom"), _("DrCOM for JLU"), 10) 10 | page.i18n = "jludrcom" 11 | page.dependent = true 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /for-OpenWRT/wired.py: -------------------------------------------------------------------------------- 1 | # This code was written by two newbies of Python. 2 | # Please forgive damn style of the code 3 | # It works fine, although maybe crashes sometime, when this happens, 4 | # restarting the program and it would work fine again. 5 | 6 | import socket, struct, time 7 | from hashlib import md5 8 | import sys 9 | import urllib2 10 | 11 | class ChallengeException (Exception): 12 | def __init__(self): 13 | pass 14 | 15 | class LoginException (Exception): 16 | def __init__(self): 17 | pass 18 | 19 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 20 | s.bind(("0.0.0.0", 61440)) 21 | 22 | s.settimeout(3) 23 | SALT = '' 24 | CONF = "/etc/drcom.conf" 25 | UNLIMITED_RETRY = True 26 | EXCEPTION = False 27 | DEBUG = True 28 | 29 | def challenge(svr,ran): 30 | while True: 31 | t = struct.pack(">5)) 67 | return ret 68 | 69 | def keep_alive_package_builder(number,random,tail,type=1,first=False): 70 | data = '\x07'+ chr(number) + '\x28\x00\x0b' + chr(type) 71 | if first : 72 | data += '\x0f\x27' 73 | else: 74 | data += '\xdc\02' 75 | data += random + '\x00' * 6 76 | data += tail 77 | data += '\x00' * 4 78 | #data += struct.pack("!H",0xdc02) 79 | if type == 3: 80 | foo = '\x31\x8c\x21\x3e' #CONSTANT 81 | checksum1 = packet_checksum1(data+foo) 82 | data += struct.pack("!I",checksum1) + foo + '\x00' * 8 83 | else: #packet type = 1 84 | data += '\x00' * 16 85 | return data 86 | 87 | def packet_checksum1(s): 88 | ret = 0 89 | for i in re.findall('..', s): 90 | ret ^= struct.unpack('>h', i)[0] 91 | ret &= 0xFFFF 92 | ret = ret * 0x2c7 93 | return ret 94 | 95 | def keep_alive2(): 96 | #first keep_alive: 97 | #number = number (mod 7) 98 | #status = 1: first packet that user sended 99 | # 2: first packet that user recieved 100 | # 3: 2nd packet that user sended 101 | # 4: 2nd packet that user recieved 102 | # Codes for test 103 | tail = '' 104 | packet = '' 105 | svr = server 106 | import random 107 | ran = random.randint(0,0xFFFF) 108 | ran += random.randint(1,10) 109 | packet = keep_alive_package_builder(0,dump(ran),'\x00'*4,1,True) 110 | s.sendto(packet, (svr, 61440)) 111 | data, address = s.recvfrom(1024) 112 | 113 | ran += random.randint(1,10) 114 | packet = keep_alive_package_builder(1,dump(ran),'\x00'*4,1,False) 115 | s.sendto(packet, (svr, 61440)) 116 | data, address = s.recvfrom(1024) 117 | tail = data[16:20] 118 | 119 | 120 | ran += random.randint(1,10) 121 | packet = keep_alive_package_builder(2,dump(ran),tail,3,False) 122 | s.sendto(packet, (svr, 61440)) 123 | data, address = s.recvfrom(1024) 124 | tail = data[16:20] 125 | print "[keep-alive2] keep-alive2 loop was in daemon." 126 | 127 | i = 1 128 | while True: 129 | try: 130 | time.sleep(5) 131 | ran += random.randint(1,10) 132 | packet = keep_alive_package_builder(2,dump(ran),tail,1,False) 133 | #print 'DEBUG: keep_alive2,packet 4\n',packet.encode('hex') 134 | s.sendto(packet, (svr, 61440)) 135 | data, address = s.recvfrom(1024) 136 | tail = data[16:20] 137 | #print 'DEBUG: keep_alive2,packet 4 return\n',data.encode('hex') 138 | 139 | ran += random.randint(1,10) 140 | packet = keep_alive_package_builder(2,dump(ran),tail,3,False) 141 | #print 'DEBUG: keep_alive2,packet 5\n',packet.encode('hex') 142 | s.sendto(packet, (svr, 61440)) 143 | data, address = s.recvfrom(1024) 144 | tail = data[16:20] 145 | #print 'DEBUG: keep_alive2,packet 5 return\n',data.encode('hex') 146 | i = i+1 147 | 148 | check_online = urllib2.urlopen('http://10.100.61.3') 149 | foo = check_online.read() 150 | if 'login.jlu.edu.cn' in foo: 151 | print '[keep_alive2] offline.relogin...' 152 | break; 153 | #MODIFIED END 154 | ''' 155 | if i % 10 == 0: 156 | check_online = urllib2.urlopen('http://10.100.61.3') 157 | foo = check_online.read() 158 | if 'login.jlu.edu.cn' in foo: 159 | print '[keep_alive2] offline.relogin...' 160 | break; 161 | ''' 162 | except: 163 | pass 164 | 165 | 166 | import re 167 | def checksum(s): 168 | ret = 1234 169 | for i in re.findall('....', s): 170 | ret ^= int(i[::-1].encode('hex'), 16) 171 | ret = (1968 * ret) & 0xffffffff 172 | return struct.pack('= 5 and UNLIMITED_RETRY == False: 215 | print '[login] wrong password, retried ' + str(i) +' times.' 216 | sys.exit(1) 217 | elif data[0] == '\x05': 218 | print "[login] wrong password." 219 | i = i + 1 220 | time.sleep(i*1.618) 221 | elif data[0] != '\x02': 222 | print "[login] server return exception.retry" 223 | if DEBUG: 224 | print '[login] last packet server returned:\n' + data.encode('hex') 225 | time.sleep(1) 226 | raise LoginException 227 | continue; 228 | break; 229 | else: 230 | if i >= 5 and UNLIMITED_RETRY == False : 231 | print '[login] packet received error, maybe you are under attacking' 232 | sys.exit(1) 233 | else: 234 | i = i + 1 235 | print '[login] package error, retrying...' 236 | 237 | print '[login] login sent' 238 | return data[-22:-6] 239 | 240 | def keep_alive1(salt,tail,pwd,svr): 241 | foo = struct.pack('!H',int(time.time())%0xFFFF) 242 | data = '\xff' + md5sum('\x03\x01'+salt+pwd) + '\x00\x00\x00' 243 | data += tail 244 | data += foo + '\x00\x00\x00\x00' 245 | print '[keep_alive1] keep_alive1,sent' 246 | s.sendto(data, (svr, 61440)) 247 | try: 248 | data, address = s.recvfrom(1024) 249 | print '[keep_alive1] keep_alive1,server received' 250 | except: 251 | print '[keep_alive1] Timeout!' 252 | pass 253 | 254 | def main(): 255 | execfile(CONF, globals()) 256 | print "config path:"+CONF+"\nauth svr:"+server+"\nusername:"+username+"\npassword:"+"********"+"\nmac:"+str(hex(mac)) 257 | print "os:MSDOS 8.0"+"\nhostname: localhost" 258 | print "DrCOM Auth Router Ver 1.2" 259 | print "Version feature:\n[1] Auto Anti droping connection\n[2] Stronger exception handling." 260 | while True: 261 | try: 262 | package_tail = login(username, password, server) 263 | except LoginException: 264 | continue 265 | #print 'Tail: ',package_tail.encode('hex') 266 | #keep_alive1(SALT,package_tail,password,server) 267 | #inf = info(server) 268 | #print "\nflow:"+str(inf['flux']/1024)+" MB \nused time:"+str(inf['time'])+" Min \nauth svr:"+server 269 | keep_alive2() 270 | #time.sleep(2) 271 | #print alive1 272 | if __name__ == "__main__": 273 | main() 274 | 275 | 276 | --------------------------------------------------------------------------------