1 /* 2 * Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 // A Simple Windows Debug Server. 26 // 27 // This software provides a socket-based debug server which uses 28 // mostly ASCII protocols to communicate with its clients. Since the 29 // Windows security model is largely based around being able to run 30 // programs on the machine, this server only accepts connections 31 // coming from localhost. 32 // 33 // When run as a service (under Windows NT), this software provides 34 // clients the ability to attach to and detach from processes without 35 // killing those processes. Ordinarily this is forbidden by the 36 // Windows debugging APIs (although more recent debugging environments 37 // from Microsoft seem to have circumvented this restriction, perhaps 38 // in a different way). This is achieved by forking a persistent 39 // subprocess for each debugging session which remains alive as long 40 // as the target process is. 41 // 42 // At this point the client can read information out of the target 43 // process's address space. Future work includes exposing more 44 // functionality like writing to the remote address space and 45 // suspending and resuming threads. 46 47 #include <iostream> 48 #include <vector> 49 #include <stdlib.h> 50 // Must come before everything else 51 #include <winsock2.h> 52 #include <assert.h> 53 #include "Dispatcher.hpp" 54 #include "Handler.hpp" 55 #include "initWinsock.hpp" 56 #include "ioUtils.hpp" 57 #include "isNT4.hpp" 58 #include "Message.hpp" 59 #include "nt4internals.hpp" 60 #include "ports.h" 61 #include "procList.hpp" 62 #include "serverLists.hpp" 63 #include "Reaper.hpp" 64 65 // Uncomment the #define below to get messages on stderr 66 // #define DEBUGGING 67 68 using namespace std; 69 70 static ChildList childList; 71 static ClientList clientList; 72 static Reaper* reaper = NULL; 73 74 // Needed prototypes 75 void shutdownChild(ChildInfo* childInfo); 76 void detachClient(ClientInfo* clientInfo); 77 void shutdownClient(ClientInfo* clientInfo); 78 79 char * 80 longToDotFormat(long addr) 81 { 82 char *temp_s = new char[20]; 83 84 sprintf(temp_s, "%d.%d.%d.%d", ((addr & 0xff000000) >> 24), 85 ((addr & 0x00ff0000) >> 16), ((addr & 0x0000ff00) >> 8), 86 (addr & 0x000000ff)); 87 88 return temp_s; 89 } 90 91 // NOTE that we do this query every time. It is a bad idea to cache IP 92 // addresses. For example, we might be hosted on a machine using DHCP 93 // and the connection addresses might change over time. (Yes, this 94 // actually happened.) 95 bool 96 isConnectionOkay(ULONG connAddr) { 97 if (connAddr == INADDR_LOOPBACK) { 98 return true; 99 } 100 101 const int MAXNAME = 1024; 102 char myname[MAXNAME]; 103 gethostname(myname, MAXNAME); 104 struct hostent* myInfo = gethostbyname(myname); 105 if (myInfo == NULL) { 106 #ifdef DEBUGGING 107 cerr << "My host information was null" << endl; 108 #endif 109 } else { 110 // Run down the list of IP addresses for myself 111 assert(myInfo->h_length == sizeof(ULONG)); 112 #ifdef DEBUGGING 113 cerr << "My known IP addresses: " << endl; 114 #endif 115 for (char** pp = myInfo->h_addr_list; *pp != NULL; pp++) { 116 char* p = *pp; 117 ULONG altAddr = ntohl(*((ULONG*) p)); 118 #ifdef DEBUGGING 119 char* name = longToDotFormat(altAddr); 120 cerr << name << endl; 121 delete[] name; 122 #endif 123 if (altAddr == connAddr) { 124 #ifdef DEBUGGING 125 cerr << "FOUND" << endl; 126 #endif 127 return true; 128 } 129 } 130 #ifdef DEBUGGING 131 cerr << "Done." << endl; 132 #endif 133 } 134 135 return false; 136 } 137 138 SOCKET 139 setupListeningSocket(short port) { 140 SOCKET listening = socket(AF_INET, SOCK_STREAM, 0); 141 if (listening == INVALID_SOCKET) { 142 cerr << "Error creating listening socket" << endl; 143 exit(1); 144 } 145 146 int reuseAddress = 1; 147 if (setsockopt(listening, SOL_SOCKET, SO_REUSEADDR, 148 (char *)&reuseAddress, sizeof(reuseAddress)) == -1) { 149 cerr << "Error reusing address" << endl; 150 exit(1); 151 } 152 153 struct sockaddr_in serverInfo; 154 155 memset((char *)&serverInfo, 0, sizeof(serverInfo)); 156 serverInfo.sin_addr.s_addr = INADDR_ANY; 157 serverInfo.sin_family = AF_INET; 158 serverInfo.sin_port = htons(port); 159 160 if (bind(listening, (struct sockaddr *) &serverInfo, sizeof(serverInfo)) < 0) { 161 cerr << "Error binding socket" << endl; 162 exit(1); 163 } 164 165 if (listen(listening, 5) < 0) { 166 cerr << "Error listening" << endl; 167 exit(1); 168 } 169 170 return listening; 171 } 172 173 /** Accepts a connection from the given listening socket, but only if 174 the connection came from localhost. Returns INVALID_SOCKET if the 175 connection came from any other IP address or if an error occurred 176 during the call to accept(). */ 177 SOCKET 178 acceptFromLocalhost(SOCKET listening) { 179 struct sockaddr_in peerAddr; 180 int peerAddrLen = sizeof(peerAddr); 181 SOCKET fd = accept(listening, (sockaddr*) &peerAddr, &peerAddrLen); 182 if (fd == INVALID_SOCKET) { 183 return fd; 184 } 185 186 if (!isConnectionOkay(ntohl(peerAddr.sin_addr.s_addr))) { 187 // Reject connections from other machines for security purposes. 188 // The Windows security model seems to assume one user per 189 // machine, and that security is compromised if another user is 190 // able to run executables on the given host. (If these 191 // assumptions are not strict enough, we will have to change 192 // this.) 193 shutdown(fd, SD_BOTH); 194 closesocket(fd); 195 return INVALID_SOCKET; 196 } 197 198 // Disable TCP buffering on all sockets. We send small amounts of 199 // data back and forth and don't want buffering. 200 int buffer_val = 1; 201 if (setsockopt(fd, IPPROTO_IP, TCP_NODELAY, 202 (char *) &buffer_val, sizeof(buffer_val)) < 0) { 203 shutdown(fd, SD_BOTH); 204 closesocket(fd); 205 } 206 207 return fd; 208 } 209 210 void 211 reapCB(void* arg) { 212 ChildInfo* info = (ChildInfo*) arg; 213 ListsLocker ll; 214 DWORD pid = info->getPid(); 215 shutdownChild(info); 216 #ifdef DEBUGGING 217 cerr << "Reaped child for process " << pid << endl; 218 #endif 219 } 220 221 /** Starts a child process with stdin and stdout redirected to pipes, 222 handles to which are returned. auxHandle1 and auxHandle2 should be 223 closed as well when the child process exits. Returns false if 224 process creation failed. */ 225 bool 226 startChildProcess(DWORD pidToDebug, 227 DWORD childStdinBufSize, 228 DWORD childStdoutBufSize, 229 LPHANDLE childProcessHandle, 230 LPHANDLE writeToStdinHandle, 231 LPHANDLE readFromStdoutHandle, 232 LPHANDLE auxHandle1, 233 LPHANDLE auxHandle2) { 234 // Code adapted from Microsoft example 235 // "Creating a Child Process with Redirected Input and Output" 236 237 SECURITY_ATTRIBUTES saAttr; 238 BOOL fSuccess; 239 240 HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, 241 hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, 242 hSaveStdin, hSaveStdout; 243 244 // Set the bInheritHandle flag so pipe handles are inherited. 245 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 246 saAttr.bInheritHandle = TRUE; 247 saAttr.lpSecurityDescriptor = NULL; 248 249 // The steps for redirecting child process's STDOUT: 250 // 1. Save current STDOUT, to be restored later. 251 // 2. Create anonymous pipe to be STDOUT for child process. 252 // 3. Set STDOUT of the parent process to be write handle to 253 // the pipe, so it is inherited by the child process. 254 // 4. Create a noninheritable duplicate of the read handle and 255 // close the inheritable read handle. 256 257 // Save the handle to the current STDOUT. 258 hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE); 259 // Create a pipe for the child process's STDOUT. 260 if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, childStdoutBufSize)) { 261 return false; 262 } 263 // Set a write handle to the pipe to be STDOUT. 264 if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr)) { 265 return false; 266 } 267 // Create noninheritable read handle and close the inheritable read 268 // handle. 269 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, 270 GetCurrentProcess(), &hChildStdoutRdDup, 271 0, FALSE, 272 DUPLICATE_SAME_ACCESS); 273 if( !fSuccess ) { 274 return false; 275 } 276 CloseHandle(hChildStdoutRd); 277 278 // The steps for redirecting child process's STDIN: 279 // 1. Save current STDIN, to be restored later. 280 // 2. Create anonymous pipe to be STDIN for child process. 281 // 3. Set STDIN of the parent to be the read handle to the 282 // pipe, so it is inherited by the child process. 283 // 4. Create a noninheritable duplicate of the write handle, 284 // and close the inheritable write handle. 285 // Save the handle to the current STDIN. 286 hSaveStdin = GetStdHandle(STD_INPUT_HANDLE); 287 // Create a pipe for the child process's STDIN. 288 if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, childStdinBufSize)) { 289 return false; 290 } 291 // Set a read handle to the pipe to be STDIN. 292 if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) { 293 return false; 294 } 295 // Duplicate the write handle to the pipe so it is not inherited. 296 fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, 297 GetCurrentProcess(), &hChildStdinWrDup, 0, 298 FALSE, // not inherited 299 DUPLICATE_SAME_ACCESS); 300 if (! fSuccess) { 301 return false; 302 } 303 CloseHandle(hChildStdinWr); 304 305 // Create the child process 306 char cmdLine[256]; 307 sprintf(cmdLine, "SwDbgSub.exe %u", pidToDebug); 308 PROCESS_INFORMATION procInfo; 309 STARTUPINFO startInfo; 310 memset((char*) &startInfo, 0, sizeof(startInfo)); 311 startInfo.cb = sizeof(startInfo); 312 BOOL res = CreateProcess(NULL, 313 cmdLine, 314 NULL, 315 NULL, 316 TRUE, // inherit handles: important 317 0, 318 NULL, 319 NULL, 320 &startInfo, 321 &procInfo); 322 if (!res) { 323 return false; 324 } 325 // After process creation, restore the saved STDIN and STDOUT. 326 if (! SetStdHandle(STD_INPUT_HANDLE, hSaveStdin)) { 327 return false; 328 } 329 if (! SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout)) { 330 return false; 331 } 332 333 // hChildStdinWrDup can be used to write to the child's stdin 334 // hChildStdoutRdDup can be used to read from the child's stdout 335 336 // NOTE: example code closes hChildStdoutWr before reading from 337 // hChildStdoutRdDup. "Close the write end of the pipe before 338 // reading from the read end of the pipe"??? Looks like this is 339 // example-specific. 340 341 // Set up return arguments 342 // hChildStdoutRd and hChildStdinWr are already closed at this point 343 *childProcessHandle = procInfo.hProcess; 344 *writeToStdinHandle = hChildStdinWrDup; 345 *readFromStdoutHandle = hChildStdoutRdDup; 346 *auxHandle1 = hChildStdinRd; 347 *auxHandle2 = hChildStdoutWr; 348 return true; 349 } 350 351 /** Clears the event and writes the message to the child process */ 352 bool 353 sendMessage(ChildInfo* child, Message* message) { 354 DWORD numBytesWritten; 355 if (!WriteFile(child->getWriteToStdinHandle(), 356 message, sizeof(Message), &numBytesWritten, NULL)) { 357 return false; 358 } 359 if (numBytesWritten != sizeof(Message)) { 360 return false; 361 } 362 // Follow up "poke" messages with the raw data 363 if (message->type == Message::POKE) { 364 if (!WriteFile(child->getWriteToStdinHandle(), 365 message->pokeArg.data, message->pokeArg.numBytes, &numBytesWritten, NULL)) { 366 return false; 367 } 368 if (numBytesWritten != message->pokeArg.numBytes) { 369 return false; 370 } 371 } 372 return true; 373 } 374 375 /** Copies data from child's stdout to the client's IOBuf and sends it 376 along */ 377 bool 378 forwardReplyToClient(ChildInfo* child, ClientInfo* client) { 379 DWORD total = 0; 380 IOBuf::FillState ret; 381 382 do { 383 DWORD temp; 384 ret = client->getIOBuf()->fillFromFileHandle(child->getReadFromStdoutHandle(), 385 &temp); 386 if (ret == IOBuf::DONE || ret == IOBuf::MORE_DATA_PENDING) { 387 if (!client->getIOBuf()->flush()) { 388 #ifdef DEBUGGING 389 cerr << "Forward failed because flush failed" << endl; 390 #endif 391 return false; 392 } 393 total += temp; 394 } 395 } while (ret == IOBuf::MORE_DATA_PENDING); 396 397 return (ret == IOBuf::FAILED) ? false : true; 398 } 399 400 //---------------------------------------------------------------------- 401 // Server Handler 402 // 403 404 class ServerHandler : public Handler { 405 public: 406 ServerHandler(); 407 408 // Starts up in Unicode mode by default 409 bool getASCII(); 410 411 void setIOBuf(IOBuf* ioBuf); 412 413 void procList(char* arg); 414 415 // Must be called before calling one of the routines below 416 void setClientInfo(ClientInfo* info); 417 418 // Indicates to outer loop that exit was called or that an error 419 // occurred and that the client exited. 420 bool exited(); 421 // Clears this state 422 void clearExited(); 423 424 void ascii(char* arg); 425 void unicode(char* arg); 426 void attach(char* arg); 427 void detach(char* arg); 428 void libInfo(char* arg); 429 void peek(char* arg); 430 void poke(char* arg); 431 void threadList(char* arg); 432 void dupHandle(char* arg); 433 void closeHandle(char* arg); 434 void getContext(char* arg); 435 void setContext(char* arg); 436 void selectorEntry(char* arg); 437 void suspend(char* arg); 438 void resume(char* arg); 439 void pollEvent(char* arg); 440 void continueEvent(char* arg); 441 void exit(char* arg); 442 443 // This is pretty gross. Needed to make the target process know 444 // about clients that have disconnected unexpectedly while attached. 445 friend void shutdownClient(ClientInfo*); 446 private: 447 // Writes: charSize <space> numChars <space> <binary string> 448 // Handles both ASCII and UNICODE modes 449 void writeString(USHORT len, WCHAR* str); 450 451 // Handles only ASCII mode 452 void writeString(USHORT len, char* str); 453 454 ClientInfo* clientInfo; 455 IOBuf* ioBuf; 456 bool _exited; 457 bool _ascii; 458 }; 459 460 static ServerHandler* handler; 461 462 ServerHandler::ServerHandler() { 463 _exited = false; 464 _ascii = false; 465 ioBuf = NULL; 466 } 467 468 bool 469 ServerHandler::getASCII() { 470 return _ascii; 471 } 472 473 void 474 ServerHandler::setIOBuf(IOBuf* buf) { 475 ioBuf = buf; 476 } 477 478 void 479 ServerHandler::setClientInfo(ClientInfo* info) { 480 clientInfo = info; 481 } 482 483 bool 484 ServerHandler::exited() { 485 return _exited; 486 } 487 488 void 489 ServerHandler::clearExited() { 490 _exited = false; 491 } 492 493 void 494 ServerHandler::ascii(char* arg) { 495 _ascii = true; 496 } 497 498 void 499 ServerHandler::unicode(char* arg) { 500 _ascii = false; 501 } 502 503 void 504 ServerHandler::procList(char* arg) { 505 #ifdef DEBUGGING 506 cerr << "proclist" << endl; 507 #endif 508 509 ProcEntryList processes; 510 ::procList(processes); 511 512 ioBuf->writeInt(processes.size()); 513 514 for (ProcEntryList::iterator iter = processes.begin(); 515 iter != processes.end(); iter++) { 516 ProcEntry& entry = *iter; 517 ioBuf->writeSpace(); 518 ioBuf->writeUnsignedInt(entry.getPid()); 519 ioBuf->writeSpace(); 520 writeString(entry.getNameLength(), entry.getName()); 521 } 522 523 ioBuf->writeEOL(); 524 ioBuf->flush(); 525 } 526 527 void 528 ServerHandler::attach(char* arg) { 529 // If the client is already attached to a process, fail. 530 if (clientInfo->getTarget() != NULL) { 531 ioBuf->writeBoolAsInt(false); 532 ioBuf->writeEOL(); 533 ioBuf->flush(); 534 return; 535 } 536 537 // Try to get pid 538 DWORD pid; 539 if (!scanUnsignedLong(&arg, &pid)) { 540 ioBuf->writeBoolAsInt(false); 541 ioBuf->writeEOL(); 542 ioBuf->flush(); 543 return; 544 } 545 546 // See whether this pid is already forked 547 ListsLocker ll; 548 ChildInfo* childInfo = childList.getChildByPid(pid); 549 if (childInfo != NULL) { 550 // If this child already has a client, return false 551 if (childInfo->getClient() != NULL) { 552 ioBuf->writeBoolAsInt(false); 553 ioBuf->writeEOL(); 554 ioBuf->flush(); 555 return; 556 } 557 558 // Otherwise, can associate this client with this child process 559 childInfo->setClient(clientInfo); 560 clientInfo->setTarget(childInfo); 561 562 // Tell the child we are attaching so it can suspend the target 563 // process 564 Message msg; 565 msg.type = Message::ATTACH; 566 sendMessage(childInfo, &msg); 567 568 ioBuf->writeBoolAsInt(true); 569 ioBuf->writeEOL(); 570 ioBuf->flush(); 571 return; 572 } else { 573 // Have to fork a new child subprocess 574 HANDLE childProcessHandle; 575 HANDLE writeToStdinHandle; 576 HANDLE readFromStdoutHandle; 577 HANDLE auxHandle1; 578 HANDLE auxHandle2; 579 if (!startChildProcess(pid, 580 32768, 581 131072, 582 &childProcessHandle, 583 &writeToStdinHandle, 584 &readFromStdoutHandle, 585 &auxHandle1, 586 &auxHandle2)) { 587 ioBuf->writeBoolAsInt(false); 588 ioBuf->writeEOL(); 589 ioBuf->flush(); 590 return; 591 } 592 593 // See whether the child succeeded in attaching to the process 594 char res; 595 DWORD numRead; 596 if (!ReadFile(readFromStdoutHandle, 597 &res, 598 sizeof(char), 599 &numRead, 600 NULL)) { 601 ioBuf->writeBoolAsInt(false); 602 ioBuf->writeEOL(); 603 ioBuf->flush(); 604 return; 605 } 606 607 if (!res) { 608 ioBuf->writeBoolAsInt(false); 609 ioBuf->writeEOL(); 610 ioBuf->flush(); 611 return; 612 } 613 614 // OK, success. 615 childInfo = new ChildInfo(pid, childProcessHandle, 616 writeToStdinHandle, readFromStdoutHandle, 617 auxHandle1, auxHandle2); 618 childList.addChild(childInfo); 619 reaper->registerProcess(childProcessHandle, childInfo); 620 // Associate this client with this child process 621 childInfo->setClient(clientInfo); 622 clientInfo->setTarget(childInfo); 623 624 // Tell the child process to actually suspend the target process 625 Message msg; 626 msg.type = Message::ATTACH; 627 sendMessage(childInfo, &msg); 628 629 // Write result to client 630 ioBuf->writeBoolAsInt(true); 631 ioBuf->writeEOL(); 632 ioBuf->flush(); 633 return; 634 } 635 } 636 637 void 638 ServerHandler::detach(char* arg) { 639 // If the client is not attached, fail. 640 if (clientInfo->getTarget() == NULL) { 641 ioBuf->writeBoolAsInt(false); 642 ioBuf->writeEOL(); 643 ioBuf->flush(); 644 return; 645 } 646 647 detachClient(clientInfo); 648 649 ioBuf->writeBoolAsInt(true); 650 ioBuf->writeEOL(); 651 ioBuf->flush(); 652 } 653 654 void 655 ServerHandler::libInfo(char* arg) { 656 ListsLocker ll; 657 ChildInfo* child = clientInfo->getTarget(); 658 if (child == NULL) { 659 ioBuf->writeInt(0); 660 ioBuf->writeEOL(); 661 ioBuf->flush(); 662 return; 663 } 664 665 // Send message to child 666 Message msg; 667 msg.type = Message::LIBINFO; 668 sendMessage(child, &msg); 669 670 // Forward reply to client 671 forwardReplyToClient(child, clientInfo); 672 } 673 674 void 675 ServerHandler::peek(char* arg) { 676 ListsLocker ll; 677 ChildInfo* child = clientInfo->getTarget(); 678 if (child == NULL) { 679 ioBuf->writeString("B"); 680 ioBuf->writeBinChar(0); 681 ioBuf->flush(); 682 return; 683 } 684 685 // Try to get address 686 DWORD address; 687 if (!scanAddress(&arg, &address)) { 688 ioBuf->writeString("B"); 689 ioBuf->writeBinChar(0); 690 ioBuf->flush(); 691 return; 692 } 693 694 // Try to get number of bytes 695 DWORD numBytes; 696 if (!scanUnsignedLong(&arg, &numBytes)) { 697 ioBuf->writeString("B"); 698 ioBuf->writeBinChar(0); 699 ioBuf->flush(); 700 return; 701 } 702 703 // Send message to child 704 Message msg; 705 msg.type = Message::PEEK; 706 msg.peekArg.address = address; 707 msg.peekArg.numBytes = numBytes; 708 sendMessage(child, &msg); 709 710 // Forward reply to client 711 forwardReplyToClient(child, clientInfo); 712 } 713 714 void 715 ServerHandler::poke(char* arg) { 716 #ifdef DEBUGGING 717 cerr << "ServerHandler::poke" << endl; 718 #endif 719 ListsLocker ll; 720 ChildInfo* child = clientInfo->getTarget(); 721 if (child == NULL) { 722 ioBuf->writeBoolAsInt(false); 723 ioBuf->flush(); 724 return; 725 } 726 727 // Try to get address 728 DWORD address; 729 if (!scanAddress(&arg, &address)) { 730 ioBuf->writeBoolAsInt(false); 731 ioBuf->flush(); 732 return; 733 } 734 735 // Try to get number of bytes 736 if (!scanAndSkipBinEscapeChar(&arg)) { 737 ioBuf->writeBoolAsInt(false); 738 ioBuf->flush(); 739 return; 740 } 741 DWORD numBytes; 742 if (!scanBinUnsignedLong(&arg, &numBytes)) { 743 ioBuf->writeBoolAsInt(false); 744 ioBuf->flush(); 745 return; 746 } 747 748 // Raw data is now in "arg" 749 // Send message to child 750 Message msg; 751 msg.type = Message::POKE; 752 msg.pokeArg.address = address; 753 msg.pokeArg.numBytes = numBytes; 754 msg.pokeArg.data = arg; 755 sendMessage(child, &msg); 756 757 // Forward reply to client 758 forwardReplyToClient(child, clientInfo); 759 } 760 761 void 762 ServerHandler::threadList(char* arg) { 763 ListsLocker ll; 764 ChildInfo* child = clientInfo->getTarget(); 765 if (child == NULL) { 766 ioBuf->writeBoolAsInt(false); 767 ioBuf->flush(); 768 return; 769 } 770 771 // Send message to child 772 Message msg; 773 msg.type = Message::THREADLIST; 774 sendMessage(child, &msg); 775 776 // Forward reply to client 777 forwardReplyToClient(child, clientInfo); 778 } 779 780 void 781 ServerHandler::dupHandle(char* arg) { 782 ListsLocker ll; 783 ChildInfo* child = clientInfo->getTarget(); 784 if (child == NULL) { 785 ioBuf->writeBoolAsInt(false); 786 ioBuf->flush(); 787 return; 788 } 789 790 // Try to get handle 791 DWORD address; 792 if (!scanAddress(&arg, &address)) { 793 ioBuf->writeBoolAsInt(false); 794 ioBuf->flush(); 795 } 796 797 // Send message to child 798 Message msg; 799 msg.type = Message::DUPHANDLE; 800 msg.handleArg.handle = (HANDLE) address; 801 sendMessage(child, &msg); 802 803 // Forward reply to client 804 forwardReplyToClient(child, clientInfo); 805 } 806 807 void 808 ServerHandler::closeHandle(char* arg) { 809 ListsLocker ll; 810 ChildInfo* child = clientInfo->getTarget(); 811 if (child == NULL) { 812 return; 813 } 814 815 // Try to get handle 816 DWORD address; 817 if (!scanAddress(&arg, &address)) { 818 return; 819 } 820 821 // Send message to child 822 Message msg; 823 msg.type = Message::CLOSEHANDLE; 824 msg.handleArg.handle = (HANDLE) address; 825 sendMessage(child, &msg); 826 827 // No reply 828 } 829 830 void 831 ServerHandler::getContext(char* arg) { 832 ListsLocker ll; 833 ChildInfo* child = clientInfo->getTarget(); 834 if (child == NULL) { 835 ioBuf->writeBoolAsInt(false); 836 ioBuf->flush(); 837 return; 838 } 839 840 // Try to get handle 841 DWORD address; 842 if (!scanAddress(&arg, &address)) { 843 ioBuf->writeBoolAsInt(false); 844 ioBuf->flush(); 845 return; 846 } 847 848 // Send message to child 849 Message msg; 850 msg.type = Message::GETCONTEXT; 851 msg.handleArg.handle = (HANDLE) address; 852 sendMessage(child, &msg); 853 854 // Forward reply to client 855 forwardReplyToClient(child, clientInfo); 856 } 857 858 void 859 ServerHandler::setContext(char* arg) { 860 ListsLocker ll; 861 ChildInfo* child = clientInfo->getTarget(); 862 if (child == NULL) { 863 ioBuf->writeBoolAsInt(false); 864 ioBuf->flush(); 865 return; 866 } 867 868 // Try to get handle 869 DWORD address; 870 if (!scanAddress(&arg, &address)) { 871 ioBuf->writeBoolAsInt(false); 872 ioBuf->flush(); 873 return; 874 } 875 876 // Try to get context 877 DWORD regs[NUM_REGS_IN_CONTEXT]; 878 for (int i = 0; i < NUM_REGS_IN_CONTEXT; i++) { 879 if (!scanAddress(&arg, ®s[i])) { 880 ioBuf->writeBoolAsInt(false); 881 ioBuf->flush(); 882 return; 883 } 884 } 885 886 // Send message to child 887 Message msg; 888 msg.type = Message::SETCONTEXT; 889 msg.setContextArg.handle = (HANDLE) address; 890 msg.setContextArg.Eax = regs[0]; 891 msg.setContextArg.Ebx = regs[1]; 892 msg.setContextArg.Ecx = regs[2]; 893 msg.setContextArg.Edx = regs[3]; 894 msg.setContextArg.Esi = regs[4]; 895 msg.setContextArg.Edi = regs[5]; 896 msg.setContextArg.Ebp = regs[6]; 897 msg.setContextArg.Esp = regs[7]; 898 msg.setContextArg.Eip = regs[8]; 899 msg.setContextArg.Ds = regs[9]; 900 msg.setContextArg.Es = regs[10]; 901 msg.setContextArg.Fs = regs[11]; 902 msg.setContextArg.Gs = regs[12]; 903 msg.setContextArg.Cs = regs[13]; 904 msg.setContextArg.Ss = regs[14]; 905 msg.setContextArg.EFlags = regs[15]; 906 msg.setContextArg.Dr0 = regs[16]; 907 msg.setContextArg.Dr1 = regs[17]; 908 msg.setContextArg.Dr2 = regs[18]; 909 msg.setContextArg.Dr3 = regs[19]; 910 msg.setContextArg.Dr6 = regs[20]; 911 msg.setContextArg.Dr7 = regs[21]; 912 sendMessage(child, &msg); 913 914 // Forward reply to client 915 forwardReplyToClient(child, clientInfo); 916 } 917 918 void 919 ServerHandler::selectorEntry(char* arg) { 920 ListsLocker ll; 921 ChildInfo* child = clientInfo->getTarget(); 922 if (child == NULL) { 923 ioBuf->writeBoolAsInt(false); 924 ioBuf->flush(); 925 return; 926 } 927 928 // Try to get thread handle 929 DWORD address; 930 if (!scanAddress(&arg, &address)) { 931 ioBuf->writeBoolAsInt(false); 932 ioBuf->flush(); 933 return; 934 } 935 936 // Try to get selector 937 DWORD selector; 938 if (!scanUnsignedLong(&arg, &selector)) { 939 ioBuf->writeBoolAsInt(false); 940 ioBuf->flush(); 941 return; 942 } 943 944 // Send message to child 945 Message msg; 946 msg.type = Message::SELECTORENTRY; 947 msg.selectorArg.handle = (HANDLE) address; 948 msg.selectorArg.selector = selector; 949 sendMessage(child, &msg); 950 951 // Forward reply to client 952 forwardReplyToClient(child, clientInfo); 953 } 954 955 void 956 ServerHandler::suspend(char* arg) { 957 ListsLocker ll; 958 ChildInfo* child = clientInfo->getTarget(); 959 if (child == NULL) { 960 return; 961 } 962 963 // Send message to child 964 Message msg; 965 msg.type = Message::SUSPEND; 966 sendMessage(child, &msg); 967 968 // No reply 969 } 970 971 void 972 ServerHandler::resume(char* arg) { 973 ListsLocker ll; 974 ChildInfo* child = clientInfo->getTarget(); 975 if (child == NULL) { 976 return; 977 } 978 979 // Send message to child 980 Message msg; 981 msg.type = Message::RESUME; 982 sendMessage(child, &msg); 983 984 // No reply 985 } 986 987 void 988 ServerHandler::pollEvent(char* arg) { 989 ListsLocker ll; 990 ChildInfo* child = clientInfo->getTarget(); 991 if (child == NULL) { 992 ioBuf->writeBoolAsInt(false); 993 ioBuf->flush(); 994 return; 995 } 996 997 // Send message to child 998 Message msg; 999 msg.type = Message::POLLEVENT; 1000 sendMessage(child, &msg); 1001 1002 // Forward reply to client 1003 forwardReplyToClient(child, clientInfo); 1004 } 1005 1006 void 1007 ServerHandler::continueEvent(char* arg) { 1008 ListsLocker ll; 1009 ChildInfo* child = clientInfo->getTarget(); 1010 if (child == NULL) { 1011 ioBuf->writeBoolAsInt(false); 1012 ioBuf->flush(); 1013 return; 1014 } 1015 1016 // Try to get bool arg 1017 int passEventToClient; 1018 if (!scanInt(&arg, &passEventToClient)) { 1019 ioBuf->writeBoolAsInt(false); 1020 ioBuf->flush(); 1021 return; 1022 } 1023 1024 // Send message to child 1025 Message msg; 1026 msg.type = Message::CONTINUEEVENT; 1027 msg.boolArg.val = ((passEventToClient != 0) ? true : false); 1028 sendMessage(child, &msg); 1029 1030 // Forward reply to client 1031 forwardReplyToClient(child, clientInfo); 1032 } 1033 1034 void 1035 ServerHandler::exit(char* arg) { 1036 shutdownClient(clientInfo); 1037 _exited = true; 1038 } 1039 1040 void 1041 ServerHandler::writeString(USHORT len, WCHAR* str) { 1042 if (_ascii) { 1043 char* cStr = new char[len + 1]; 1044 sprintf(cStr, "%.*ls", len, str); 1045 writeString(len, cStr); 1046 delete[] cStr; 1047 } else { 1048 ioBuf->writeInt(sizeof(unsigned short)); 1049 ioBuf->writeSpace(); 1050 ioBuf->writeInt(len); 1051 ioBuf->writeSpace(); 1052 for (int i = 0; i < len; i++) { 1053 ioBuf->writeBinUnsignedShort(str[i]); 1054 } 1055 } 1056 } 1057 1058 void 1059 ServerHandler::writeString(USHORT len, char* str) { 1060 ioBuf->writeInt(1); 1061 ioBuf->writeSpace(); 1062 ioBuf->writeInt(len); 1063 ioBuf->writeSpace(); 1064 ioBuf->writeString(str); 1065 } 1066 1067 // 1068 //---------------------------------------------------------------------- 1069 1070 //---------------------------------------------------------------------- 1071 // Shutdown routines 1072 // 1073 1074 void 1075 shutdownChild(ChildInfo* childInfo) { 1076 childList.removeChild(childInfo); 1077 childInfo->closeAll(); 1078 if (childInfo->getClient() != NULL) { 1079 shutdownClient(childInfo->getClient()); 1080 } 1081 delete childInfo; 1082 } 1083 1084 void 1085 detachClient(ClientInfo* info) { 1086 ListsLocker ll; 1087 // May have been dissociated while not under cover of lock 1088 if (info->getTarget() == NULL) { 1089 return; 1090 } 1091 1092 // Tell the child that we have detached to let the target process 1093 // continue running 1094 Message msg; 1095 msg.type = Message::DETACH; 1096 sendMessage(info->getTarget(), &msg); 1097 1098 // Dissociate the client and the target 1099 info->getTarget()->setClient(NULL); 1100 info->setTarget(NULL); 1101 } 1102 1103 void 1104 shutdownClient(ClientInfo* clientInfo) { 1105 #ifdef DEBUGGING 1106 cerr << "Shutting down client" << endl; 1107 #endif 1108 1109 // If we're connected, inform the target process that we're 1110 // disconnecting 1111 detachClient(clientInfo); 1112 1113 // Remove this client from the list and delete it 1114 clientList.removeClient(clientInfo); 1115 if (clientInfo->getTarget() != NULL) { 1116 clientInfo->getTarget()->setClient(NULL); 1117 } 1118 clientInfo->closeAll(); 1119 delete clientInfo; 1120 } 1121 1122 // 1123 //---------------------------------------------------------------------- 1124 1125 1126 /** Main dispatcher for client commands. NOTE: do not refer to this 1127 clientInfo data structure after calling this routine, as it may be 1128 deleted internally. */ 1129 void 1130 readAndDispatch(ClientInfo* clientInfo) { 1131 IOBuf::ReadLineResult res; 1132 IOBuf* ioBuf = clientInfo->getIOBuf(); 1133 unsigned long howMany; 1134 ioctlsocket(clientInfo->getDataSocket(), FIONREAD, &howMany); 1135 if (howMany == 0) { 1136 // Client closed down. 1137 shutdownClient(clientInfo); 1138 return; 1139 } 1140 // Read and process as much data as possible 1141 do { 1142 res = ioBuf->tryReadLine(); 1143 if (res == IOBuf::RL_ERROR) { 1144 #ifdef DEBUGGING 1145 cerr << "Error while reading line" << endl; 1146 #endif 1147 shutdownClient(clientInfo); 1148 return; 1149 } else if (res == IOBuf::RL_GOT_DATA) { 1150 #ifdef DEBUGGING 1151 cerr << "Got data: \"" << ioBuf->getLine() << "\"" << endl; 1152 #endif 1153 handler->setIOBuf(ioBuf); 1154 handler->setClientInfo(clientInfo); 1155 handler->clearExited(); 1156 Dispatcher::dispatch(ioBuf->getLine(), handler); 1157 } 1158 } while (res == IOBuf::RL_GOT_DATA && (!handler->exited())); 1159 #ifdef DEBUGGING 1160 cerr << "Exiting readAndDispatch" << endl; 1161 #endif 1162 } 1163 1164 int 1165 main(int argc, char **argv) 1166 { 1167 initWinsock(); 1168 1169 if (isNT4()) { 1170 loadPSAPIDLL(); // Will exit if not present 1171 } 1172 1173 SOCKET clientListeningSock = setupListeningSocket(CLIENT_PORT); 1174 1175 handler = new ServerHandler(); 1176 Lists::init(); 1177 1178 reaper = new Reaper(&reapCB); 1179 if (!reaper->start()) { 1180 exit(1); 1181 } 1182 1183 while (true) { 1184 // Select on all sockets: 1185 // - client listening socket 1186 // - sockets for all client connections 1187 1188 // When one of the client connections closes, close its socket 1189 // handles. 1190 1191 fd_set set; 1192 SOCKET maxSock = 0; 1193 1194 // Set up fd_set 1195 { 1196 int i; 1197 FD_ZERO(&set); 1198 FD_SET(clientListeningSock, &set); 1199 if (clientListeningSock > maxSock) { 1200 maxSock = clientListeningSock; 1201 } 1202 for (i = 0; i < clientList.size(); i++) { 1203 ClientInfo* info = clientList.get(i); 1204 if (info->getDataSocket() > maxSock) { 1205 maxSock = info->getDataSocket(); 1206 } 1207 FD_SET(info->getDataSocket(), &set); 1208 } 1209 } 1210 struct timeval timeout; 1211 timeout.tv_sec = 300; // 5 minutes 1212 timeout.tv_usec = 0; 1213 int res = select(maxSock, &set, NULL, NULL, &timeout); 1214 if (res > 0) { 1215 1216 //////////////// 1217 // New client // 1218 //////////////// 1219 if (FD_ISSET(clientListeningSock, &set)) { 1220 SOCKET fd = acceptFromLocalhost(clientListeningSock); 1221 if (fd != INVALID_SOCKET) { 1222 // Create new client information object 1223 ClientInfo* info = new ClientInfo(fd); 1224 // Add to list of clients 1225 clientList.addClient(info); 1226 #ifdef DEBUGGING 1227 cerr << "New client" << endl; 1228 #endif 1229 } 1230 } 1231 1232 /////////////////////////// 1233 // Commands from clients // 1234 /////////////////////////// 1235 ClientInfo* clientInfo; 1236 if (clientList.isAnyDataSocketSet(&set, &clientInfo)) { 1237 readAndDispatch(clientInfo); 1238 } 1239 } else if (res < 0) { 1240 // Looks like one of the clients was killed. Try to figure out which one. 1241 bool found = false; 1242 fd_set set; 1243 struct timeval timeout; 1244 timeout.tv_sec = 0; 1245 timeout.tv_usec = 0; 1246 for (int i = 0; i < clientList.size(); i++) { 1247 ClientInfo* info = clientList.get(i); 1248 FD_ZERO(&set); 1249 FD_SET(info->getDataSocket(), &set); 1250 if (select(1 + info->getDataSocket(), &set, NULL, NULL, &timeout) < 0) { 1251 found = true; 1252 clientList.removeClient(info); 1253 info->closeAll(); 1254 delete info; 1255 break; 1256 } 1257 } 1258 if (!found) { 1259 // This indicates trouble -- one of our listening sockets died. 1260 exit(1); 1261 } 1262 } 1263 } 1264 1265 return 0; 1266 }